diff --git a/lib/circuit_gas_meter.ts b/lib/circuit_gas_meter.ts new file mode 100644 index 00000000..6fb3d122 --- /dev/null +++ b/lib/circuit_gas_meter.ts @@ -0,0 +1,4 @@ +export function trackScriptExecutionGas(opCount: number, gasLimit = 100000): boolean { + if (opCount > gasLimit) throw new Error('Gas limit exceeded'); + return true; +} diff --git a/lib/gas_meter.ts b/lib/gas_meter.ts new file mode 100644 index 00000000..4f6b25c7 --- /dev/null +++ b/lib/gas_meter.ts @@ -0,0 +1,4 @@ +export function calculateCircuitEvalGas(opCount: number, memoryBytes: number): number { + const baseGas = 100; + return baseGas + opCount * 2 + Math.floor(memoryBytes / 1024); +} diff --git a/lib/ledResistorEval.ts b/lib/ledResistorEval.ts new file mode 100644 index 00000000..a79e9c4f --- /dev/null +++ b/lib/ledResistorEval.ts @@ -0,0 +1,4 @@ +/** + * tscircuit - led-ballast-resistor + */ +export function calcLedResistor(vSupply: number, vForward: number, iAmps: number = 0.02): number { return Math.max(0, (vSupply - vForward) / iAmps); } diff --git a/lib/macroCycleDetector.ts b/lib/macroCycleDetector.ts new file mode 100644 index 00000000..5d382fc7 --- /dev/null +++ b/lib/macroCycleDetector.ts @@ -0,0 +1,31 @@ +/** + * tscircuit/eval - Macro Cycle Detector + */ +export function detectMacroCycles(graph: Record): { hasCycle: boolean; cyclePath?: string[] } { + const visited = new Set(); + const recursionStack = new Set(); + + function dfs(node: string, path: string[]): boolean { + visited.add(node); + recursionStack.add(node); + + for (const neighbor of graph[node] || []) { + if (!visited.has(neighbor)) { + if (dfs(neighbor, [...path, neighbor])) return true; + } else if (recursionStack.has(neighbor)) { + return true; + } + } + + recursionStack.delete(node); + return false; + } + + for (const node of Object.keys(graph)) { + if (!visited.has(node)) { + if (dfs(node, [node])) return { hasCycle: true }; + } + } + + return { hasCycle: false }; +} diff --git a/lib/rcFilterEval.ts b/lib/rcFilterEval.ts new file mode 100644 index 00000000..a4da1112 --- /dev/null +++ b/lib/rcFilterEval.ts @@ -0,0 +1,4 @@ +/** + * tscircuit - rc-time-constant + */ +export function calcRcCutoff(r: number, c: number): number { return 1 / (2 * Math.PI * r * c); } diff --git a/lib/regexExecutionGuard.ts b/lib/regexExecutionGuard.ts new file mode 100644 index 00000000..a0c25d9c --- /dev/null +++ b/lib/regexExecutionGuard.ts @@ -0,0 +1,11 @@ +/** + * tscircuit/eval - Safe Regex Execution Guard + */ +export function safeRegexTest(pattern: RegExp, input: string, timeoutMs: number = 50): boolean { + const start = Date.now(); + const res = pattern.test(input); + if (Date.now() - start > timeoutMs) { + throw new Error('Regex execution exceeded execution time budget'); + } + return res; +} diff --git a/lib/stack_guard.ts b/lib/stack_guard.ts new file mode 100644 index 00000000..5cbab06a --- /dev/null +++ b/lib/stack_guard.ts @@ -0,0 +1,5 @@ +export function checkCallStackDepth(currentDepth: number, maxDepth: number = 250): void { + if (currentDepth > maxDepth) { + throw new Error(`Maximum schematic expansion depth of ${maxDepth} exceeded`); + } +} diff --git a/lib/thermalEval.ts b/lib/thermalEval.ts new file mode 100644 index 00000000..5fa88f16 --- /dev/null +++ b/lib/thermalEval.ts @@ -0,0 +1,4 @@ +/** + * tscircuit - thermal-dissipation-eval + */ +export function calcJunctionTemp(pWatts: number, rThetaJA: number, ambient: number = 25): number { return ambient + (pWatts * rThetaJA); } diff --git a/lib/timeout_guard.ts b/lib/timeout_guard.ts new file mode 100644 index 00000000..a5d16cd9 --- /dev/null +++ b/lib/timeout_guard.ts @@ -0,0 +1,7 @@ +export function enforceEvalTimeout(promise: Promise, timeoutMs: number = 5000): Promise { + let timer: NodeJS.Timeout; + const timeoutPromise = new Promise((_, reject) => { + timer = setTimeout(() => reject(new Error('Circuit eval timeout exceeded')), timeoutMs); + }); + return Promise.race([promise, timeoutPromise]).finally(() => clearTimeout(timer)); +} diff --git a/lib/voltageDividerEval.ts b/lib/voltageDividerEval.ts new file mode 100644 index 00000000..f60ad6b6 --- /dev/null +++ b/lib/voltageDividerEval.ts @@ -0,0 +1,4 @@ +/** + * tscircuit - resistor-divider-calc + */ +export function calcDivider(vin: number, r1: number, r2: number): number { return vin * (r2 / (r1 + r2)); } diff --git a/lib/wireGaugeEval.ts b/lib/wireGaugeEval.ts new file mode 100644 index 00000000..1a3db60c --- /dev/null +++ b/lib/wireGaugeEval.ts @@ -0,0 +1,4 @@ +/** + * tscircuit - wire-gauge-voltage-drop + */ +export function calcWireDrop(current: number, lengthM: number, ohmsPerM: number): number { return current * lengthM * ohmsPerM; }