tjs-lang 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTEXT.md +594 -0
- package/LICENSE +190 -0
- package/README.md +220 -0
- package/bin/benchmarks.ts +351 -0
- package/bin/dev.ts +205 -0
- package/bin/docs.js +170 -0
- package/bin/install-cursor.sh +71 -0
- package/bin/install-vscode.sh +71 -0
- package/bin/select-local-models.d.ts +1 -0
- package/bin/select-local-models.js +28 -0
- package/bin/select-local-models.ts +31 -0
- package/demo/autocomplete.test.ts +232 -0
- package/demo/docs.json +186 -0
- package/demo/examples.test.ts +598 -0
- package/demo/index.html +91 -0
- package/demo/src/autocomplete.ts +482 -0
- package/demo/src/capabilities.ts +859 -0
- package/demo/src/demo-nav.ts +2097 -0
- package/demo/src/examples.test.ts +161 -0
- package/demo/src/examples.ts +476 -0
- package/demo/src/imports.test.ts +196 -0
- package/demo/src/imports.ts +421 -0
- package/demo/src/index.ts +639 -0
- package/demo/src/module-store.ts +635 -0
- package/demo/src/module-sw.ts +132 -0
- package/demo/src/playground.ts +949 -0
- package/demo/src/service-host.ts +389 -0
- package/demo/src/settings.ts +440 -0
- package/demo/src/style.ts +280 -0
- package/demo/src/tjs-playground.ts +1605 -0
- package/demo/src/ts-examples.ts +478 -0
- package/demo/src/ts-playground.ts +1092 -0
- package/demo/static/favicon.svg +30 -0
- package/demo/static/photo-1.jpg +0 -0
- package/demo/static/photo-2.jpg +0 -0
- package/demo/static/texts/ai-history.txt +9 -0
- package/demo/static/texts/coffee-origins.txt +9 -0
- package/demo/static/texts/renewable-energy.txt +9 -0
- package/dist/index.js +256 -0
- package/dist/index.js.map +37 -0
- package/dist/tjs-batteries.js +4 -0
- package/dist/tjs-batteries.js.map +15 -0
- package/dist/tjs-full.js +256 -0
- package/dist/tjs-full.js.map +37 -0
- package/dist/tjs-transpiler.js +220 -0
- package/dist/tjs-transpiler.js.map +21 -0
- package/dist/tjs-vm.js +4 -0
- package/dist/tjs-vm.js.map +14 -0
- package/docs/CNAME +1 -0
- package/docs/favicon.svg +30 -0
- package/docs/index.html +91 -0
- package/docs/index.js +10468 -0
- package/docs/index.js.map +92 -0
- package/docs/photo-1.jpg +0 -0
- package/docs/photo-1.webp +0 -0
- package/docs/photo-2.jpg +0 -0
- package/docs/photo-2.webp +0 -0
- package/docs/texts/ai-history.txt +9 -0
- package/docs/texts/coffee-origins.txt +9 -0
- package/docs/texts/renewable-energy.txt +9 -0
- package/docs/tjs-lang.svg +31 -0
- package/docs/tosijs-agent.svg +31 -0
- package/editors/README.md +325 -0
- package/editors/ace/ajs-mode.js +328 -0
- package/editors/ace/ajs-mode.ts +269 -0
- package/editors/ajs-syntax.ts +212 -0
- package/editors/build-grammars.ts +510 -0
- package/editors/codemirror/ajs-language.js +287 -0
- package/editors/codemirror/ajs-language.ts +1447 -0
- package/editors/codemirror/autocomplete.test.ts +531 -0
- package/editors/codemirror/component.ts +404 -0
- package/editors/monaco/ajs-monarch.js +243 -0
- package/editors/monaco/ajs-monarch.ts +225 -0
- package/editors/tjs-syntax.ts +115 -0
- package/editors/vscode/language-configuration.json +37 -0
- package/editors/vscode/package.json +65 -0
- package/editors/vscode/syntaxes/ajs-injection.tmLanguage.json +107 -0
- package/editors/vscode/syntaxes/ajs.tmLanguage.json +252 -0
- package/editors/vscode/syntaxes/tjs.tmLanguage.json +333 -0
- package/package.json +83 -0
- package/src/cli/commands/check.ts +41 -0
- package/src/cli/commands/convert.ts +133 -0
- package/src/cli/commands/emit.ts +260 -0
- package/src/cli/commands/run.ts +68 -0
- package/src/cli/commands/test.ts +194 -0
- package/src/cli/commands/types.ts +20 -0
- package/src/cli/create-app.ts +236 -0
- package/src/cli/playground.ts +250 -0
- package/src/cli/tjs.ts +166 -0
- package/src/cli/tjsx.ts +160 -0
- package/tjs-lang.svg +31 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/lang/parser.ts", "../src/lang/types.ts", "../src/lang/inference.ts", "../src/lang/emitters/ast.ts", "../src/lang/core.ts", "../src/lang/emitters/js.ts", "../src/lang/tests.ts", "../src/lang/schema.ts", "../node_modules/acorn-walk/dist/walk.mjs", "../src/lang/linter.ts", "../src/lang/runtime.ts", "../src/types/Type.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Acorn parser wrapper for Agent99 JavaScript\n *\n * Handles parsing of \"Better JavaScript\" including custom syntax extensions\n * like the colon shorthand for required parameters.\n */\n\nimport * as acorn from 'acorn'\nimport type { Program, FunctionDeclaration } from 'acorn'\nimport { SyntaxError } from './types'\n\n/** Parser options */\nexport interface ParseOptions {\n /** Filename for error messages */\n filename?: string\n /** Enable colon shorthand syntax preprocessing */\n colonShorthand?: boolean\n /**\n * Target is the VM (AJS code).\n * When true, skips == to Is() transformation since the VM handles == correctly.\n */\n vmTarget?: boolean\n}\n\n/**\n * A WASM block extracted from source\n *\n * Simple form (body is both WASM source and JS fallback):\n * wasm {\n * for (let i = 0; i < arr.length; i++) { arr[i] *= 2 }\n * }\n *\n * With explicit fallback (when WASM and JS need different code):\n * wasm {\n * // WASM-optimized path\n * } fallback {\n * // JS fallback using different approach\n * }\n *\n * Variables are captured from scope automatically.\n */\nexport interface WasmBlock {\n /** Unique ID for this block */\n id: string\n /** The body (JS subset that compiles to WASM, also used as fallback) */\n body: string\n /** Explicit fallback body (only if different from body) */\n fallback?: string\n /** Variables captured from enclosing scope (auto-detected) */\n captures: string[]\n /** Start position in original source */\n start: number\n /** End position in original source */\n end: number\n}\n\n/**\n * A test block extracted from source\n *\n * Syntax:\n * test { body }\n * test 'description' { body }\n *\n * Tests run at transpile time and are stripped from output.\n */\nexport interface TestBlock {\n /** Optional description */\n description?: string\n /** The test body code */\n body: string\n /** Start position in original source */\n start: number\n /** End position in original source */\n end: number\n}\n\n/**\n * Preprocess options\n */\nexport interface PreprocessOptions {\n /** Skip test execution (tests still stripped from output) */\n dangerouslySkipTests?: boolean\n /**\n * Skip == to Is() transformation.\n * Set to true for AJS code that runs in the VM, which already handles == correctly.\n * Default: false (transform == to Is() for TJS code running in regular JS)\n */\n vmTarget?: boolean\n}\n\n/**\n * Tokenizer state for tracking context during source transformation\n */\ntype TokenizerState =\n | 'normal'\n | 'single-string'\n | 'double-string'\n | 'template-string'\n | 'line-comment'\n | 'block-comment'\n | 'regex'\n\n/**\n * Structural context for tracking where we are in the code\n * This enables proper handling of class methods vs function calls\n */\ntype StructuralContext = 'top-level' | 'class-body' | 'function-body' | 'block'\n\ninterface ContextFrame {\n type: StructuralContext\n braceDepth: number // The brace depth when we entered this context\n}\n\n/**\n * Unified paren expression transformer using state machine tokenizer\n *\n * Model: opening paren can be ( or (? or (!, closing can be ) or )->type or )-?type or )-!type\n *\n * This unifies handling of:\n * - Function declaration params: function foo(x: type) -> returnType { }\n * - Arrow function params: (x: type) => expr\n * - Safe/unsafe markers: function foo(?) or function foo(!)\n * - Return type annotations: ) -> type or ) -? type or ) -! type\n *\n * @param source The source code to transform\n * @param ctx Context for tracking required params, safe/unsafe functions, etc.\n * @returns Transformed source and extracted metadata\n */\nfunction transformParenExpressions(\n source: string,\n ctx: {\n originalSource: string\n requiredParams: Set<string>\n unsafeFunctions: Set<string>\n safeFunctions: Set<string>\n }\n): {\n source: string\n returnType?: string\n returnSafety?: 'safe' | 'unsafe'\n} {\n let result = ''\n let i = 0\n let firstReturnType: string | undefined\n let firstReturnSafety: 'safe' | 'unsafe' | undefined\n\n // State machine for tokenizing\n let state: TokenizerState = 'normal'\n // Stack for template string interpolation depth (each entry is brace depth within that interpolation)\n const templateStack: number[] = []\n\n // Structural context tracking - know if we're in a class body, function body, etc.\n const contextStack: ContextFrame[] = [{ type: 'top-level', braceDepth: 0 }]\n let braceDepth = 0\n\n // Helper to get current structural context (reserved for future use)\n const _currentContext = (): StructuralContext =>\n contextStack[contextStack.length - 1]?.type || 'top-level'\n\n // Helper to check if we're directly in a class body (not nested in a function/block inside it)\n const isInClassBody = (): boolean => {\n const frame = contextStack[contextStack.length - 1]\n return frame?.type === 'class-body' && braceDepth === frame.braceDepth + 1\n }\n\n while (i < source.length) {\n const char = source[i]\n const nextChar = source[i + 1]\n\n // Handle state transitions based on current state\n switch (state) {\n case 'single-string':\n result += char\n if (char === '\\\\' && i + 1 < source.length) {\n result += nextChar\n i += 2\n continue\n }\n if (char === \"'\") {\n state = 'normal'\n }\n i++\n continue\n\n case 'double-string':\n result += char\n if (char === '\\\\' && i + 1 < source.length) {\n result += nextChar\n i += 2\n continue\n }\n if (char === '\"') {\n state = 'normal'\n }\n i++\n continue\n\n case 'template-string':\n result += char\n if (char === '\\\\' && i + 1 < source.length) {\n result += nextChar\n i += 2\n continue\n }\n if (char === '$' && nextChar === '{') {\n // Enter template expression\n result += nextChar\n i += 2\n templateStack.push(1) // Start with brace depth 1\n state = 'normal' // Back to normal parsing inside ${}\n continue\n }\n if (char === '`') {\n state = 'normal'\n }\n i++\n continue\n\n case 'line-comment':\n result += char\n if (char === '\\n') {\n state = 'normal'\n }\n i++\n continue\n\n case 'block-comment':\n result += char\n if (char === '*' && nextChar === '/') {\n result += nextChar\n i += 2\n state = 'normal'\n continue\n }\n i++\n continue\n\n case 'regex':\n result += char\n if (char === '\\\\' && i + 1 < source.length) {\n result += nextChar\n i += 2\n continue\n }\n if (char === '[') {\n // Character class - read until ]\n i++\n while (i < source.length && source[i] !== ']') {\n result += source[i]\n if (source[i] === '\\\\' && i + 1 < source.length) {\n result += source[i + 1]\n i += 2\n } else {\n i++\n }\n }\n if (i < source.length) {\n result += source[i]\n i++\n }\n continue\n }\n if (char === '/') {\n // End of regex, consume flags\n i++\n while (i < source.length && /[gimsuy]/.test(source[i])) {\n result += source[i]\n i++\n }\n state = 'normal'\n continue\n }\n i++\n continue\n\n case 'normal':\n // Handle template stack - track braces inside template expressions\n if (templateStack.length > 0) {\n if (char === '{') {\n templateStack[templateStack.length - 1]++\n } else if (char === '}') {\n templateStack[templateStack.length - 1]--\n if (templateStack[templateStack.length - 1] === 0) {\n // Exiting template expression, back to template string\n templateStack.pop()\n result += char\n i++\n state = 'template-string'\n continue\n }\n }\n }\n\n // Check for string/comment/regex start\n if (char === \"'\") {\n result += char\n i++\n state = 'single-string'\n continue\n }\n if (char === '\"') {\n result += char\n i++\n state = 'double-string'\n continue\n }\n if (char === '`') {\n result += char\n i++\n state = 'template-string'\n continue\n }\n if (char === '/' && nextChar === '/') {\n result += char + nextChar\n i += 2\n state = 'line-comment'\n continue\n }\n if (char === '/' && nextChar === '*') {\n result += char + nextChar\n i += 2\n state = 'block-comment'\n continue\n }\n\n // Check for regex literal\n if (char === '/') {\n const before = result.trimEnd()\n const lastChar = before[before.length - 1]\n const isRegexContext =\n !lastChar ||\n /[=(!,;:{[&|?+\\-*%<>~^]$/.test(before) ||\n /\\b(return|case|throw|in|of|typeof|instanceof|new|delete|void)\\s*$/.test(\n before\n )\n if (isRegexContext) {\n result += char\n i++\n state = 'regex'\n continue\n }\n }\n\n // Now handle TJS-specific transformations in normal state\n break\n }\n\n // We're in normal state - look for TJS patterns\n\n // Track braces for structural context\n if (char === '{') {\n braceDepth++\n result += char\n i++\n continue\n }\n if (char === '}') {\n braceDepth--\n // Pop context if we're exiting it\n const frame = contextStack[contextStack.length - 1]\n if (frame && braceDepth === frame.braceDepth) {\n contextStack.pop()\n }\n result += char\n i++\n continue\n }\n\n // Look for class declarations: class Name { or class Name extends Base {\n const classMatch = source\n .slice(i)\n .match(/^class\\s+\\w+(?:\\s+extends\\s+\\w+)?\\s*\\{/)\n if (classMatch) {\n // Output everything up to but not including the {\n const classHeader = classMatch[0].slice(0, -1)\n result += classHeader\n i += classHeader.length\n // Push class-body context (will be entered when we see the {)\n contextStack.push({ type: 'class-body', braceDepth })\n continue\n }\n\n // Look for function declarations: function name( or function name (\n const funcMatch = source.slice(i).match(/^function\\s+(\\w+)\\s*\\(/)\n if (funcMatch) {\n const funcName = funcMatch[1]\n const matchLen = funcMatch[0].length\n\n // Check for safety marker right after opening paren: (? or (!\n const afterParen = source[i + matchLen]\n let safetyMarker: '?' | '!' | null = null\n let paramStart = i + matchLen\n\n if (afterParen === '?' || afterParen === '!') {\n safetyMarker = afterParen\n paramStart++\n if (safetyMarker === '!') {\n ctx.unsafeFunctions.add(funcName)\n } else {\n ctx.safeFunctions.add(funcName)\n }\n }\n\n result += `function ${funcName}(`\n i = paramStart\n\n // Find matching ) using balanced counting\n const paramsResult = extractBalancedContent(source, i, '(', ')')\n if (!paramsResult) {\n // Unbalanced - just copy character and continue\n result += source[i]\n i++\n continue\n }\n\n const { content: params, endPos } = paramsResult\n i = endPos\n\n // Process the params (transform : to = for required params, handle nested arrows)\n const processedParams = processParamString(params, ctx, true)\n result += processedParams + ')'\n\n // Check what follows the closing paren: whitespace then -> or -? or -! (return type)\n let j = i\n while (j < source.length && /\\s/.test(source[j])) j++\n\n const returnArrow = source.slice(j, j + 2)\n if (\n returnArrow === '->' ||\n returnArrow === '-?' ||\n returnArrow === '-!'\n ) {\n // Extract return type\n j += 2\n // Skip whitespace after arrow\n while (j < source.length && /\\s/.test(source[j])) j++\n\n const typeResult = extractReturnTypeValue(source, j)\n if (typeResult) {\n const { type, endPos: typeEnd } = typeResult\n // Record first return type for metadata\n if (firstReturnType === undefined) {\n firstReturnType = type\n if (returnArrow === '-?') {\n firstReturnSafety = 'safe'\n } else if (returnArrow === '-!') {\n firstReturnSafety = 'unsafe'\n }\n }\n i = typeEnd\n }\n }\n continue\n }\n\n // Look for class method syntax: constructor(, methodName(, get name(, set name(\n // These appear inside class bodies and need param transformation\n // Only match if we're actually in a class body (proper context tracking)\n const methodMatch = source\n .slice(i)\n .match(/^(constructor|(?:get|set)\\s+\\w+|async\\s+\\w+|\\w+)\\s*\\(/)\n if (methodMatch && isInClassBody()) {\n // We're actually in a class body - this is a method definition\n const methodPart = methodMatch[1]\n const matchLen = methodMatch[0].length\n const paramStart = i + matchLen\n\n result += methodPart + '('\n i = paramStart\n\n // Find matching )\n const paramsResult = extractBalancedContent(source, i, '(', ')')\n if (!paramsResult) {\n result += source[i]\n i++\n continue\n }\n\n const { content: params, endPos } = paramsResult\n i = endPos\n\n // Process the params (transform : to = for TJS types)\n const processedParams = processParamString(params, ctx, true)\n result += processedParams + ')'\n\n // Check for return type annotation: ) -> type or ): type\n let j = i\n while (j < source.length && /\\s/.test(source[j])) j++\n\n // Handle -> return type (TJS style)\n const returnArrow = source.slice(j, j + 2)\n if (returnArrow === '->') {\n j += 2\n while (j < source.length && /\\s/.test(source[j])) j++\n const typeResult = extractReturnTypeValue(source, j)\n if (typeResult) {\n i = typeResult.endPos\n }\n }\n // Handle : return type (TS style) - just strip it\n else if (source[j] === ':') {\n j++\n while (j < source.length && /\\s/.test(source[j])) j++\n const typeResult = extractReturnTypeValue(source, j)\n if (typeResult) {\n i = typeResult.endPos\n }\n }\n\n continue\n }\n\n // Look for arrow function params: (params) =>\n // We need to be careful to only transform when followed by =>\n if (source[i] === '(') {\n // First, find the matching ) without consuming any safety marker\n // We'll check for safety marker only if this is actually an arrow function\n const fullParamsResult = extractBalancedContent(source, i + 1, '(', ')')\n if (!fullParamsResult) {\n result += source[i]\n i++\n continue\n }\n\n const fullContent = fullParamsResult.content\n const endPos = fullParamsResult.endPos\n\n // Check what follows: whitespace then => (arrow function) or -> (return type on arrow)\n let j = endPos\n while (j < source.length && /\\s/.test(source[j])) j++\n\n // Check for return type annotation on arrow function: ) -> type =>\n let arrowReturnType: string | undefined\n const returnArrow = source.slice(j, j + 2)\n if (\n returnArrow === '->' ||\n returnArrow === '-?' ||\n returnArrow === '-!'\n ) {\n j += 2\n while (j < source.length && /\\s/.test(source[j])) j++\n const typeResult = extractReturnTypeValue(source, j)\n if (typeResult) {\n arrowReturnType = typeResult.type\n j = typeResult.endPos\n while (j < source.length && /\\s/.test(source[j])) j++\n }\n }\n\n if (source.slice(j, j + 2) === '=>') {\n // This IS an arrow function - now check for safety marker\n let safetyMarker: '?' | '!' | null = null\n let params = fullContent\n\n // Check if content starts with safety marker (? or !) followed by whitespace\n const trimmedContent = fullContent.trimStart()\n if (\n trimmedContent.startsWith('?') &&\n (trimmedContent.length === 1 || /\\s/.test(trimmedContent[1]))\n ) {\n safetyMarker = '?'\n params = trimmedContent.slice(1)\n } else if (\n trimmedContent.startsWith('!') &&\n (trimmedContent.length === 1 || /\\s/.test(trimmedContent[1]))\n ) {\n safetyMarker = '!'\n params = trimmedContent.slice(1)\n }\n\n // Process the params\n const processedParams = processParamString(params, ctx, false)\n // Add safety marker as comment for arrow functions (since we can't track them by name)\n const safetyComment =\n safetyMarker === '?'\n ? '/* safe */ '\n : safetyMarker === '!'\n ? '/* unsafe */ '\n : ''\n result += `(${safetyComment}${processedParams})`\n // Skip the return type annotation (we extracted it but don't emit it)\n i = endPos\n // Skip to just before the =>\n while (i < j && /\\s/.test(source[i])) {\n result += source[i]\n i++\n }\n // If there was a return type, we need to skip past it to =>\n if (arrowReturnType) {\n i = j\n }\n } else {\n // Not an arrow function - recursively transform the content for nested arrows\n // but don't process as param declarations (no colon-to-equals transform)\n const transformed = transformParenExpressions(fullContent, ctx)\n result += `(${transformed.source})`\n i = endPos\n }\n continue\n }\n\n result += source[i]\n i++\n }\n\n return {\n source: result,\n returnType: firstReturnType,\n returnSafety: firstReturnSafety,\n }\n}\n\n/**\n * Extract balanced content between delimiters\n * @param source The source string\n * @param start Position after the opening delimiter\n * @param open Opening delimiter character (for depth counting of nested structures)\n * @param close Closing delimiter character\n * @returns The content between delimiters and position after closing delimiter, or null if unbalanced\n */\nfunction extractBalancedContent(\n source: string,\n start: number,\n open: string,\n close: string\n): { content: string; endPos: number } | null {\n let depth = 1\n let i = start\n let inString = false\n let stringChar = ''\n\n while (i < source.length && depth > 0) {\n const char = source[i]\n\n // Handle string literals\n if (!inString && (char === \"'\" || char === '\"' || char === '`')) {\n inString = true\n stringChar = char\n } else if (inString && char === stringChar && source[i - 1] !== '\\\\') {\n inString = false\n } else if (!inString) {\n if (char === open) depth++\n else if (char === close) depth--\n }\n i++\n }\n\n if (depth !== 0) return null\n\n return {\n content: source.slice(start, i - 1),\n endPos: i,\n }\n}\n\n/**\n * Extract a JS value starting at a position in source.\n * Handles nested objects {}, arrays [], strings, numbers, booleans, null.\n * Uses state machine to properly track nesting.\n */\nfunction extractJSValue(\n source: string,\n start: number\n): { value: string; endPos: number } | null {\n let i = start\n\n // Skip leading whitespace\n while (i < source.length && /\\s/.test(source[i])) i++\n if (i >= source.length) return null\n\n const valueStart = i\n const firstChar = source[i]\n\n // Handle objects and arrays with balanced parsing\n if (firstChar === '{' || firstChar === '[') {\n const close = firstChar === '{' ? '}' : ']'\n const result = extractBalancedContent(source, i + 1, firstChar, close)\n if (!result) return null\n return {\n value: source.slice(valueStart, result.endPos),\n endPos: result.endPos,\n }\n }\n\n // Handle strings\n if (firstChar === \"'\" || firstChar === '\"' || firstChar === '`') {\n i++\n while (i < source.length) {\n if (source[i] === firstChar && source[i - 1] !== '\\\\') {\n i++\n return { value: source.slice(valueStart, i), endPos: i }\n }\n i++\n }\n return null // Unterminated string\n }\n\n // Handle numbers (including negative and decimals)\n if (/[-+\\d]/.test(firstChar)) {\n while (i < source.length && /[\\d.eE+-]/.test(source[i])) i++\n return { value: source.slice(valueStart, i), endPos: i }\n }\n\n // Handle keywords: true, false, null, undefined\n const keywordMatch = source.slice(i).match(/^(true|false|null|undefined)\\b/)\n if (keywordMatch) {\n return {\n value: keywordMatch[1],\n endPos: i + keywordMatch[1].length,\n }\n }\n\n return null\n}\n\n/**\n * Normalize union syntax in type strings\n * Converts single | to || for TJS consistency (needed for JS parsing)\n */\nfunction normalizeUnionSyntax(type: string): string {\n // Replace single | (not ||) with || for proper JS parsing\n // Use negative lookbehind and lookahead to avoid matching ||\n return type.replace(/(?<!\\|)\\|(?!\\|)/g, ' || ')\n}\n\n/**\n * Extract a return type value starting at the given position\n * Handles: simple types ('', 0, null), objects ({ }), arrays ([ ]), unions (| or ||)\n */\nfunction extractReturnTypeValue(\n source: string,\n start: number\n): { type: string; endPos: number } | null {\n let i = start\n let depth = 0\n let inString = false\n let stringChar = ''\n let sawContent = false\n\n // Helper to create result with normalized type\n const makeResult = (endPos: number) => ({\n type: normalizeUnionSyntax(source.slice(start, endPos).trim()),\n endPos,\n })\n\n while (i < source.length) {\n const char = source[i]\n\n // Handle string literals\n if (!inString && (char === \"'\" || char === '\"' || char === '`')) {\n inString = true\n stringChar = char\n sawContent = true\n i++\n continue\n }\n if (inString) {\n if (char === stringChar && source[i - 1] !== '\\\\') {\n inString = false\n i++ // Move past closing quote\n // Just finished a string at depth 0\n if (depth === 0) {\n // Check if next non-ws is function body { or union |\n let j = i\n while (j < source.length && /\\s/.test(source[j])) j++\n if (source[j] === '{') {\n // Check if it's object type or function body\n const afterBrace = source.slice(j + 1).match(/^\\s*(\\w+)\\s*:/)\n if (!afterBrace) {\n // Function body - type ends here\n return makeResult(i)\n }\n }\n if (source[j] !== '|' && source[j] !== '&') {\n // No union - type ends here\n return makeResult(i)\n }\n }\n continue\n }\n i++\n continue\n }\n\n // Track bracket depth\n if (char === '{' || char === '[' || char === '(') {\n depth++\n sawContent = true\n i++\n continue\n }\n if (char === '}' || char === ']' || char === ')') {\n depth--\n if (depth === 0) {\n i++\n // Check for union after closing bracket\n let j = i\n while (j < source.length && /\\s/.test(source[j])) j++\n if (source[j] === '|' || source[j] === '&') {\n continue // More type content\n }\n return makeResult(i)\n }\n i++\n continue\n }\n\n // At depth 0, check for function body\n if (depth === 0 && char === '{') {\n if (sawContent) {\n return makeResult(i)\n }\n // First { - check if object type or function body\n const afterBrace = source.slice(i + 1).match(/^\\s*(\\w+)\\s*:/)\n if (afterBrace) {\n depth++\n sawContent = true\n i++\n continue\n }\n return makeResult(i)\n }\n\n // Handle union/intersection at depth 0\n if (depth === 0 && (char === '|' || char === '&')) {\n i++\n if (i < source.length && source[i] === '|') i++ // Skip second | for ||\n while (i < source.length && /\\s/.test(source[i])) i++\n continue\n }\n\n // Handle numbers (including decimals like 14.5, -3.14)\n if (\n depth === 0 &&\n (/\\d/.test(char) || (char === '-' && /\\d/.test(source[i + 1])))\n ) {\n let j = i\n if (source[j] === '-') j++ // Skip negative sign\n while (j < source.length && /\\d/.test(source[j])) j++\n // Handle decimal part\n if (j < source.length && source[j] === '.' && /\\d/.test(source[j + 1])) {\n j++ // Skip decimal point\n while (j < source.length && /\\d/.test(source[j])) j++\n }\n // Handle exponent (1e10, 1.5e-3)\n if (j < source.length && (source[j] === 'e' || source[j] === 'E')) {\n j++\n if (j < source.length && (source[j] === '+' || source[j] === '-')) j++\n while (j < source.length && /\\d/.test(source[j])) j++\n }\n sawContent = true\n i = j\n // Check what's next\n while (i < source.length && /\\s/.test(source[i])) i++\n if (i < source.length && source[i] === '{') {\n // Function body - type ends here\n return {\n type: normalizeUnionSyntax(source.slice(start, j).trim()),\n endPos: j,\n }\n }\n if (source[i] !== '|' && source[i] !== '&') {\n return {\n type: normalizeUnionSyntax(source.slice(start, j).trim()),\n endPos: j,\n }\n }\n continue\n }\n\n // Handle identifiers (null, undefined, true, false, type names)\n if (depth === 0 && /[a-zA-Z_]/.test(char)) {\n let j = i\n while (j < source.length && /\\w/.test(source[j])) j++\n sawContent = true\n i = j\n // Check what's next\n while (i < source.length && /\\s/.test(source[i])) i++\n if (i < source.length && source[i] === '{') {\n // Check if function body\n const afterBrace = source.slice(i + 1).match(/^\\s*(\\w+)\\s*:/)\n if (!afterBrace) {\n // Function body - type ends before whitespace\n let typeEnd = j\n while (typeEnd > start && /\\s/.test(source[typeEnd - 1])) typeEnd--\n return {\n type: normalizeUnionSyntax(source.slice(start, typeEnd).trim()),\n endPos: j,\n }\n }\n }\n if (source[i] !== '|' && source[i] !== '&') {\n return {\n type: normalizeUnionSyntax(source.slice(start, j).trim()),\n endPos: j,\n }\n }\n continue\n }\n\n i++\n }\n\n // Reached end of source\n if (sawContent) {\n return makeResult(i)\n }\n return null\n}\n\n/**\n * Process a parameter string, transforming : to = for required params\n * and recursively handling nested arrow functions\n */\nfunction processParamString(\n params: string,\n ctx: {\n requiredParams: Set<string>\n unsafeFunctions: Set<string>\n safeFunctions: Set<string>\n },\n trackRequired: boolean\n): string {\n // First recursively process any nested arrow functions\n const withArrows = transformParenExpressions(params, {\n originalSource: params,\n requiredParams: ctx.requiredParams,\n unsafeFunctions: ctx.unsafeFunctions,\n safeFunctions: ctx.safeFunctions,\n }).source\n\n // Now split and process each parameter\n const paramList = splitParameters(withArrows)\n let sawOptional = false\n const seenNames = new Set<string>()\n\n // Helper to check for duplicate names\n const checkDuplicate = (name: string) => {\n if (trackRequired && /^\\w+$/.test(name)) {\n if (seenNames.has(name)) {\n throw new Error(`Duplicate parameter name '${name}'`)\n }\n seenNames.add(name)\n }\n }\n\n const processed = paramList.map((param) => {\n const trimmed = param.trim()\n if (!trimmed) return param\n\n // Handle destructured object parameters: { name: 'Clara', age = 30 }\n // Transform colons to equals inside the braces (recursive)\n // Order doesn't matter for objects, so don't enforce required-before-optional\n // ONLY do this when trackRequired is true - i.e., actual function parameters\n if (trackRequired && trimmed.startsWith('{') && trimmed.endsWith('}')) {\n const inner = trimmed.slice(1, -1)\n const processedInner = processDestructuredObjectParams(inner, ctx)\n return `{ ${processedInner} }`\n }\n\n // Handle destructured array parameters: [first: '', second: 0]\n // ONLY do this when trackRequired is true - i.e., actual function parameters\n if (trackRequired && trimmed.startsWith('[') && trimmed.endsWith(']')) {\n const inner = trimmed.slice(1, -1)\n const processedInner = processDestructuredObjectParams(inner, ctx)\n return `[ ${processedInner} ]`\n }\n\n // Handle optional param syntax: x?: type -> x = type (not required)\n const optionalMatch = trimmed.match(/^(\\w+)\\s*\\?\\s*:\\s*(.+)$/)\n if (optionalMatch) {\n const [, name, type] = optionalMatch\n checkDuplicate(name)\n sawOptional = true\n // Optional params are NOT tracked as required\n return `${name} = ${type}`\n }\n\n // Check if param already has a default value (x = value)\n if (!hasColonNotEquals(trimmed)) {\n // Has equals sign (default value) - this is optional\n // Extract name from \"name = value\" pattern\n const eqMatch = trimmed.match(/^(\\w+)\\s*=/)\n if (eqMatch) {\n checkDuplicate(eqMatch[1])\n }\n sawOptional = true\n return param\n }\n\n // Handle required param syntax: x: type -> x = type (tracked as required)\n const colonPos = findTopLevelColon(trimmed)\n if (colonPos !== -1) {\n const name = trimmed.slice(0, colonPos).trim()\n const type = trimmed.slice(colonPos + 1).trim()\n\n checkDuplicate(name)\n\n // Check for required param after optional - this is an error\n if (sawOptional && trackRequired && /^\\w+$/.test(name)) {\n throw new Error(\n `Required parameter '${name}' cannot follow optional parameter`\n )\n }\n\n if (trackRequired && /^\\w+$/.test(name)) {\n ctx.requiredParams.add(name)\n }\n return `${name} = ${type}`\n }\n\n return param\n })\n\n return processed.join(',')\n}\n\n/**\n * Process destructured object/array parameters\n *\n * In TJS destructuring patterns:\n * - `name: 'Clara'` means required param with example (transforms to `name = 'Clara'`)\n * - `age = 30` means optional param with default (stays as `age = 30`)\n * - Nested objects like `address: { street: '9 High St', zip = '0000' }` are tricky:\n * the inner object is a value (object literal), not a pattern, so we transform it back\n *\n * Key insight: In destructuring, `foo: value` at top level is a required param,\n * but at nested levels within an object value, `:` is normal object literal syntax.\n *\n * Order does NOT matter in objects (unlike positional function params).\n */\nfunction processDestructuredObjectParams(\n inner: string,\n ctx: {\n requiredParams: Set<string>\n unsafeFunctions: Set<string>\n safeFunctions: Set<string>\n }\n): string {\n // Split on commas at the top level (respecting nested braces)\n const parts = splitParameters(inner)\n\n const processed = parts.map((part) => {\n const trimmed = part.trim()\n if (!trimmed) return part\n\n // Check for nested destructured object: name: { ... }\n // The inner { ... } is an object literal value, not a destructuring pattern\n const nestedObjectMatch = trimmed.match(/^(\\w+)\\s*:\\s*(\\{[\\s\\S]*\\})$/)\n if (nestedObjectMatch) {\n const [, name, objectLiteral] = nestedObjectMatch\n ctx.requiredParams.add(name)\n // Process the inner object as an object literal (transform = to : for values)\n const processedLiteral = processObjectLiteralValue(objectLiteral)\n return `${name} = ${processedLiteral}`\n }\n\n // Check for nested destructured array: name: [ ... ]\n const nestedArrayMatch = trimmed.match(/^(\\w+)\\s*:\\s*(\\[[\\s\\S]*\\])$/)\n if (nestedArrayMatch) {\n const [, name, arrayLiteral] = nestedArrayMatch\n ctx.requiredParams.add(name)\n // Process the inner array as an array literal\n const processedLiteral = processArrayLiteralValue(arrayLiteral)\n return `${name} = ${processedLiteral}`\n }\n\n // Handle simple colon syntax: name: 'value' -> name = 'value' (required)\n const colonMatch = trimmed.match(/^(\\w+)\\s*:\\s*([\\s\\S]+)$/)\n if (colonMatch) {\n const [, name, value] = colonMatch\n ctx.requiredParams.add(name)\n return `${name} = ${value}`\n }\n\n // Handle equals syntax: name = value (optional, already valid JS)\n // Just preserve it as-is\n return part\n })\n\n return processed.join(', ')\n}\n\n/**\n * Process an object literal value (nested inside destructuring)\n *\n * In object literals, TJS allows `=` for optional values:\n * { street: '9 High St', zip = '0000' }\n *\n * This must become valid JS object literal syntax:\n * { street: '9 High St', zip: '0000' }\n *\n * (The `=` is TJS shorthand indicating the value is optional/has default,\n * but in an object literal context it must use `:`)\n */\nfunction processObjectLiteralValue(literal: string): string {\n // Remove outer braces, process content, restore braces\n const inner = literal.slice(1, -1).trim()\n const parts = splitParameters(inner)\n\n const processed = parts.map((part) => {\n const trimmed = part.trim()\n if (!trimmed) return part\n\n // Handle nested objects: key: { ... } or key = { ... }\n const nestedObjColonMatch = trimmed.match(/^(\\w+)\\s*:\\s*(\\{[\\s\\S]*\\})$/)\n if (nestedObjColonMatch) {\n const [, key, nested] = nestedObjColonMatch\n return `${key}: ${processObjectLiteralValue(nested)}`\n }\n const nestedObjEqualsMatch = trimmed.match(/^(\\w+)\\s*=\\s*(\\{[\\s\\S]*\\})$/)\n if (nestedObjEqualsMatch) {\n const [, key, nested] = nestedObjEqualsMatch\n return `${key}: ${processObjectLiteralValue(nested)}`\n }\n\n // Handle nested arrays: key: [ ... ] or key = [ ... ]\n const nestedArrColonMatch = trimmed.match(/^(\\w+)\\s*:\\s*(\\[[\\s\\S]*\\])$/)\n if (nestedArrColonMatch) {\n const [, key, nested] = nestedArrColonMatch\n return `${key}: ${processArrayLiteralValue(nested)}`\n }\n const nestedArrEqualsMatch = trimmed.match(/^(\\w+)\\s*=\\s*(\\[[\\s\\S]*\\])$/)\n if (nestedArrEqualsMatch) {\n const [, key, nested] = nestedArrEqualsMatch\n return `${key}: ${processArrayLiteralValue(nested)}`\n }\n\n // Transform equals to colon for simple values: key = value -> key: value\n const equalsMatch = trimmed.match(/^(\\w+)\\s*=\\s*([\\s\\S]+)$/)\n if (equalsMatch) {\n const [, key, value] = equalsMatch\n return `${key}: ${value}`\n }\n\n // Colon syntax is already valid: key: value\n return part\n })\n\n return `{ ${processed.join(', ')} }`\n}\n\n/**\n * Process an array literal value (nested inside destructuring)\n * Similar to processObjectLiteralValue but for arrays\n */\nfunction processArrayLiteralValue(literal: string): string {\n // Remove outer brackets, process content, restore brackets\n const inner = literal.slice(1, -1).trim()\n const parts = splitParameters(inner)\n\n const processed = parts.map((part) => {\n const trimmed = part.trim()\n if (!trimmed) return part\n\n // Handle nested objects\n if (trimmed.startsWith('{') && trimmed.endsWith('}')) {\n return processObjectLiteralValue(trimmed)\n }\n\n // Handle nested arrays\n if (trimmed.startsWith('[') && trimmed.endsWith(']')) {\n return processArrayLiteralValue(trimmed)\n }\n\n // Array elements are just values, no transformation needed\n return part\n })\n\n return `[ ${processed.join(', ')} ]`\n}\n\n/**\n * Check if param has a top-level colon but no top-level equals\n * This distinguishes x: type from x = type and handles nested structures\n */\nfunction hasColonNotEquals(param: string): boolean {\n let depth = 0\n let hasColon = false\n let hasEquals = false\n let inString = false\n let stringChar = ''\n\n for (let i = 0; i < param.length; i++) {\n const char = param[i]\n\n if (!inString && (char === \"'\" || char === '\"' || char === '`')) {\n inString = true\n stringChar = char\n continue\n }\n if (inString) {\n if (char === stringChar && param[i - 1] !== '\\\\') inString = false\n continue\n }\n\n if (char === '(' || char === '{' || char === '[') {\n depth++\n } else if (char === ')' || char === '}' || char === ']') {\n depth--\n } else if (depth === 0) {\n if (char === ':') hasColon = true\n if (char === '=' && param[i + 1] !== '>') hasEquals = true // Ignore =>\n }\n }\n\n return hasColon && !hasEquals\n}\n\n/**\n * Find the position of the first top-level colon in a param\n */\nfunction findTopLevelColon(param: string): number {\n let depth = 0\n let inString = false\n let stringChar = ''\n\n for (let i = 0; i < param.length; i++) {\n const char = param[i]\n\n if (!inString && (char === \"'\" || char === '\"' || char === '`')) {\n inString = true\n stringChar = char\n continue\n }\n if (inString) {\n if (char === stringChar && param[i - 1] !== '\\\\') inString = false\n continue\n }\n\n if (char === '(' || char === '{' || char === '[') {\n depth++\n } else if (char === ')' || char === '}' || char === ']') {\n depth--\n } else if (depth === 0 && char === ':') {\n return i\n }\n }\n\n return -1\n}\n\n/**\n * Preprocess source to handle custom syntax extensions\n *\n * Transforms:\n * function foo(x: 'example') { }\n * Into:\n * function foo(x = 'example') { }\n * And tracks that 'x' is a required parameter.\n *\n * Also handles return type annotation:\n * function foo(x: 'example') -> { result: 'string' } { }\n */\n/** TJS mode flags for opt-in language improvements */\nexport interface TjsModes {\n /** TjsEquals: == and != use structural equality */\n tjsEquals: boolean\n /** TjsClass: classes callable without new, explicit new is banned */\n tjsClass: boolean\n /** TjsDate: Date is banned, use Timestamp/LegalDate */\n tjsDate: boolean\n /** TjsNoeval: eval() and new Function() are banned */\n tjsNoeval: boolean\n /** TjsStandard: newlines as statement terminators (prevents ASI footguns) */\n tjsStandard: boolean\n}\n\nexport function preprocess(\n source: string,\n options: PreprocessOptions = {}\n): {\n source: string\n returnType?: string\n returnSafety?: 'safe' | 'unsafe'\n moduleSafety?: 'none' | 'inputs' | 'all'\n tjsModes: TjsModes\n originalSource: string\n requiredParams: Set<string>\n unsafeFunctions: Set<string>\n safeFunctions: Set<string>\n wasmBlocks: WasmBlock[]\n tests: TestBlock[]\n testErrors: string[]\n} {\n const originalSource = source\n let moduleSafety: 'none' | 'inputs' | 'all' | undefined\n const requiredParams = new Set<string>()\n const unsafeFunctions = new Set<string>()\n const safeFunctions = new Set<string>()\n\n // TJS modes - all default to false (JS-compatible by default)\n const tjsModes: TjsModes = {\n tjsEquals: false,\n tjsClass: false,\n tjsDate: false,\n tjsNoeval: false,\n tjsStandard: false,\n }\n\n // Handle module-level safety directive: safety none | safety inputs | safety all\n // Must be at the start of the file (possibly after comments/whitespace)\n const safetyMatch = source.match(\n /^(\\s*(?:\\/\\/[^\\n]*\\n|\\/\\*[\\s\\S]*?\\*\\/\\s*)*)\\s*safety\\s+(none|inputs|all)\\b/\n )\n if (safetyMatch) {\n moduleSafety = safetyMatch[2] as 'none' | 'inputs' | 'all'\n // Remove the directive from source\n source = source.replace(\n /^(\\s*(?:\\/\\/[^\\n]*\\n|\\/\\*[\\s\\S]*?\\*\\/\\s*)*)\\s*safety\\s+(none|inputs|all)\\s*/,\n '$1'\n )\n }\n\n // Handle TJS mode directives (can appear in any order after safety)\n // TjsStrict enables all TJS modes\n // Individual modes: TjsEquals, TjsClass, TjsDate, TjsNoeval, TjsStandard\n const directivePattern =\n /^(\\s*(?:\\/\\/[^\\n]*\\n|\\/\\*[\\s\\S]*?\\*\\/\\s*)*)\\s*(TjsStrict|TjsEquals|TjsClass|TjsDate|TjsNoeval|TjsStandard|LegacyEquals)\\b/\n\n let match\n while ((match = source.match(directivePattern))) {\n const directive = match[2]\n\n if (directive === 'TjsStrict') {\n // Enable all TJS modes\n tjsModes.tjsEquals = true\n tjsModes.tjsClass = true\n tjsModes.tjsDate = true\n tjsModes.tjsNoeval = true\n tjsModes.tjsStandard = true\n } else if (directive === 'TjsEquals') {\n tjsModes.tjsEquals = true\n } else if (directive === 'TjsClass') {\n tjsModes.tjsClass = true\n } else if (directive === 'TjsDate') {\n tjsModes.tjsDate = true\n } else if (directive === 'TjsNoeval') {\n tjsModes.tjsNoeval = true\n } else if (directive === 'TjsStandard') {\n tjsModes.tjsStandard = true\n } else if (directive === 'LegacyEquals') {\n // DEPRECATED: LegacyEquals is now the default behavior\n // Kept for backwards compatibility - just ignore it\n console.warn(\n 'LegacyEquals is deprecated: JS equality is now the default. Use TjsEquals to enable structural equality.'\n )\n }\n\n // Remove the directive from source\n source = source.replace(\n new RegExp(\n `^(\\\\s*(?:\\\\/\\\\/[^\\\\n]*\\\\n|\\\\/\\\\*[\\\\s\\\\S]*?\\\\*\\\\/\\\\s*)*)\\\\s*${directive}\\\\s*`\n ),\n '$1'\n )\n }\n\n // TjsStandard mode: insert semicolons to prevent ASI footguns\n // Must happen early before other transformations modify line structure\n if (tjsModes.tjsStandard) {\n source = insertAsiProtection(source)\n }\n\n // Transform Is/IsNot infix operators to function calls\n // a Is b -> Is(a, b)\n // a IsNot b -> IsNot(a, b)\n // These are always available for explicit structural equality\n source = transformIsOperators(source)\n\n // Transform == and != to structural equality (Is/IsNot)\n // Only when TjsEquals mode is enabled and not for VM targets\n // VM targets already handle == correctly at runtime\n if (tjsModes.tjsEquals && !options.vmTarget) {\n source = transformEqualityToStructural(source)\n }\n\n // Transform Type, Generic, Union, and Enum declarations\n // Type Foo { ... } -> const Foo = Type(...)\n // Generic Bar<T, U> { ... } -> const Bar = Generic(...)\n // Union Dir 'up' | 'down' -> const Dir = Union(...)\n // Enum Status { Pending, Active, Done } -> const Status = Enum(...)\n source = transformTypeDeclarations(source)\n source = transformGenericDeclarations(source)\n source = transformUnionDeclarations(source)\n source = transformEnumDeclarations(source)\n\n // Transform bare assignments to const declarations\n // Foo = ... -> const Foo = ...\n source = transformBareAssignments(source)\n\n // Unified paren expression transformer\n // Handles: function params, arrow params, return types, safe/unsafe markers\n // Model: open paren can be ( or (? or (!, close can be ) or )-> or )-? or )-!\n const {\n source: transformedSource,\n returnType,\n returnSafety,\n } = transformParenExpressions(source, {\n originalSource,\n requiredParams,\n unsafeFunctions,\n safeFunctions,\n })\n source = transformedSource\n\n // NOTE: unsafe {} blocks removed - they provided no performance benefit because\n // the wrapper decision is made at transpile time. Use (!) on functions instead.\n // See ideas parking lot for potential future approaches.\n\n // Handle try-without-catch: try { ... } (no catch/finally) -> monadic error handling\n // This is the idiomatic TJS way to convert exceptions to AgentError\n source = transformTryWithoutCatch(source)\n\n // Extract WASM blocks: wasm(args) { ... } fallback { ... }\n const wasmBlocks = extractWasmBlocks(source)\n source = wasmBlocks.source\n\n // Extract and run test blocks: test 'desc'? { body }\n // Tests run at transpile time and are stripped from output\n const testResult = extractAndRunTests(source, options.dangerouslySkipTests)\n source = testResult.source\n\n // Wrap class declarations to make them callable without `new`\n // Only when TjsClass mode is enabled\n // class Foo { } -> let Foo = class Foo { }; Foo = globalThis.__tjs?.wrapClass?.(Foo) ?? Foo;\n if (tjsModes.tjsClass) {\n source = wrapClassDeclarations(source)\n }\n\n // Validate TjsDate mode - check for Date usage\n if (tjsModes.tjsDate) {\n source = validateNoDate(source)\n }\n\n // Validate TjsNoeval mode - check for eval/Function usage\n if (tjsModes.tjsNoeval) {\n source = validateNoEval(source)\n }\n\n return {\n source,\n returnType,\n returnSafety,\n moduleSafety,\n tjsModes,\n originalSource,\n requiredParams,\n unsafeFunctions,\n safeFunctions,\n wasmBlocks: wasmBlocks.blocks,\n tests: testResult.tests,\n testErrors: testResult.errors,\n }\n}\n\n/**\n * Transform try blocks without catch/finally into monadic error handling\n * try { ... } (alone) -> try { ... } catch (__err) { return AgentError }\n *\n * Note: try-without-catch only makes sense inside functions (for monadic return).\n * Using it at top level will result in \"'return' outside of function\" error,\n * which is the correct behavior - monadic error flow requires a function context.\n */\nfunction transformTryWithoutCatch(source: string): string {\n let result = ''\n let i = 0\n\n while (i < source.length) {\n // Look for 'try' keyword followed by '{'\n const tryMatch = source.slice(i).match(/^\\btry\\s*\\{/)\n if (tryMatch) {\n // Found 'try {', now find the matching closing brace\n const startBrace = i + tryMatch[0].length - 1\n const bodyStart = startBrace + 1\n let depth = 1\n let j = bodyStart\n\n while (j < source.length && depth > 0) {\n const char = source[j]\n if (char === '{') depth++\n else if (char === '}') depth--\n j++\n }\n\n if (depth !== 0) {\n // Unbalanced braces, let the parser handle the error\n result += source[i]\n i++\n continue\n }\n\n // Check what comes after the closing brace\n const afterTry = source.slice(j).match(/^\\s*(catch|finally)\\b/)\n\n if (afterTry) {\n // Has catch or finally - leave it alone, copy the try block as-is\n result += source.slice(i, j)\n i = j\n } else {\n // No catch or finally - add monadic error handler with call stack\n // In debug mode, __tjs.getStack() returns the call stack for diagnostics\n const body = source.slice(bodyStart, j - 1)\n result += `try {${body}} catch (__try_err) { return { $error: true, message: __try_err?.message || String(__try_err), op: 'try', cause: __try_err, stack: globalThis.__tjs?.getStack?.() } }`\n i = j\n }\n } else {\n result += source[i]\n i++\n }\n }\n\n return result\n}\n\n/**\n * Extract WASM blocks from source and replace with runtime dispatch code\n *\n * Simple form (body used as both WASM source and JS fallback):\n * wasm {\n * for (let i = 0; i < arr.length; i++) { arr[i] *= 2 }\n * }\n *\n * With explicit fallback (when you need different JS code):\n * wasm {\n * // WASM-optimized version\n * } fallback {\n * // Different JS implementation\n * }\n *\n * Output:\n * (globalThis.__tjs_wasm_0\n * ? globalThis.__tjs_wasm_0(captures...)\n * : (() => { body })())\n *\n * Variables are auto-captured from the body.\n */\nfunction extractWasmBlocks(source: string): {\n source: string\n blocks: WasmBlock[]\n} {\n const blocks: WasmBlock[] = []\n let result = ''\n let i = 0\n let blockId = 0\n\n while (i < source.length) {\n // Look for 'wasm {' or 'wasm{' - simple block without params\n const wasmMatch = source.slice(i).match(/^\\bwasm\\s*\\{/)\n if (wasmMatch) {\n const matchStart = i\n\n // Find the body\n const bodyStart = i + wasmMatch[0].length\n let braceDepth = 1\n let j = bodyStart\n\n while (j < source.length && braceDepth > 0) {\n const char = source[j]\n if (char === '{') braceDepth++\n else if (char === '}') braceDepth--\n j++\n }\n\n if (braceDepth !== 0) {\n result += source[i]\n i++\n continue\n }\n\n const body = source.slice(bodyStart, j - 1)\n let fallbackBody: string | undefined\n let matchEnd = j\n\n // Check for optional 'fallback {' block\n const fallbackMatch = source.slice(j).match(/^\\s*fallback\\s*\\{/)\n if (fallbackMatch) {\n const fallbackStart = j + fallbackMatch[0].length\n braceDepth = 1\n let k = fallbackStart\n\n while (k < source.length && braceDepth > 0) {\n const char = source[k]\n if (char === '{') braceDepth++\n else if (char === '}') braceDepth--\n k++\n }\n\n if (braceDepth === 0) {\n fallbackBody = source.slice(fallbackStart, k - 1)\n matchEnd = k\n }\n }\n\n // Auto-detect captured variables from the body\n const captures = detectCaptures(body)\n\n // Create the block record\n const block: WasmBlock = {\n id: `__tjs_wasm_${blockId}`,\n body,\n fallback: fallbackBody,\n captures,\n start: matchStart,\n end: matchEnd,\n }\n blocks.push(block)\n\n // Generate runtime dispatch code:\n // The fallback is the body itself (or explicit fallback if provided)\n const fallbackCode = fallbackBody ?? body\n const captureArgs = captures.length > 0 ? captures.join(', ') : ''\n\n // For WASM: pass captures as arguments\n // For fallback: just run inline (captures are in scope)\n const wasmCall =\n captures.length > 0\n ? `globalThis.${block.id}(${captureArgs})`\n : `globalThis.${block.id}()`\n\n const dispatch = `(globalThis.${block.id} ? ${wasmCall} : (() => {${fallbackCode}})())`\n\n result += dispatch\n i = matchEnd\n blockId++\n } else {\n result += source[i]\n i++\n }\n }\n\n return { source: result, blocks }\n}\n\n/**\n * Detect variables captured from enclosing scope\n *\n * Finds identifiers that are:\n * - Used in the body\n * - Not declared within the body (let, const, var, function params)\n *\n * This is a simple heuristic - a full implementation would use proper AST analysis\n */\nfunction detectCaptures(body: string): string[] {\n // Find all identifiers used in the body\n const identifierPattern = /\\b([a-zA-Z_$][a-zA-Z0-9_$]*)\\b/g\n const allIdentifiers = new Set<string>()\n let match\n while ((match = identifierPattern.exec(body)) !== null) {\n allIdentifiers.add(match[1])\n }\n\n // Find identifiers declared in the body\n const declared = new Set<string>()\n\n // let/const/var declarations\n const declPattern = /\\b(?:let|const|var)\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g\n while ((match = declPattern.exec(body)) !== null) {\n declared.add(match[1])\n }\n\n // for loop variables: for (let i = ...)\n const forPattern =\n /\\bfor\\s*\\(\\s*(?:let|const|var)\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g\n while ((match = forPattern.exec(body)) !== null) {\n declared.add(match[1])\n }\n\n // function declarations and parameters would go here for full impl\n\n // JS keywords and builtins to exclude\n const reserved = new Set([\n 'if',\n 'else',\n 'for',\n 'while',\n 'do',\n 'switch',\n 'case',\n 'break',\n 'continue',\n 'return',\n 'function',\n 'let',\n 'const',\n 'var',\n 'new',\n 'this',\n 'true',\n 'false',\n 'null',\n 'undefined',\n 'typeof',\n 'instanceof',\n 'in',\n 'of',\n 'try',\n 'catch',\n 'finally',\n 'throw',\n 'async',\n 'await',\n 'class',\n 'extends',\n 'super',\n 'import',\n 'export',\n 'default',\n 'from',\n 'as',\n 'static',\n 'get',\n 'set',\n 'yield',\n // Common globals\n 'console',\n 'Math',\n 'Array',\n 'Object',\n 'String',\n 'Number',\n 'Boolean',\n 'Date',\n 'JSON',\n 'Promise',\n 'Map',\n 'Set',\n 'WeakMap',\n 'WeakSet',\n 'Float32Array',\n 'Float64Array',\n 'Int8Array',\n 'Int16Array',\n 'Int32Array',\n 'Uint8Array',\n 'Uint16Array',\n 'Uint32Array',\n 'BigInt64Array',\n 'BigUint64Array',\n 'ArrayBuffer',\n 'DataView',\n 'Error',\n 'TypeError',\n 'RangeError',\n 'length',\n 'push',\n 'pop',\n 'shift',\n 'unshift',\n 'slice',\n 'splice',\n 'map',\n 'filter',\n 'reduce',\n 'forEach',\n 'find',\n 'findIndex',\n 'indexOf',\n 'includes',\n 'globalThis',\n 'window',\n 'document',\n 'Infinity',\n 'NaN',\n 'isNaN',\n 'isFinite',\n 'parseInt',\n 'parseFloat',\n 'encodeURI',\n 'decodeURI',\n 'eval',\n ])\n\n // Return identifiers that are used but not declared or reserved\n const captures: string[] = []\n for (const id of allIdentifiers) {\n if (!declared.has(id) && !reserved.has(id)) {\n captures.push(id)\n }\n }\n\n return captures.sort()\n}\n\n/**\n * Split parameter string respecting nested braces/brackets\n */\nfunction splitParameters(params: string): string[] {\n const result: string[] = []\n let current = ''\n let depth = 0\n let inLineComment = false\n let inBlockComment = false\n let i = 0\n\n while (i < params.length) {\n const char = params[i]\n const nextChar = params[i + 1]\n\n // Handle line comments - preserve them in output\n if (!inBlockComment && char === '/' && nextChar === '/') {\n inLineComment = true\n current += '//'\n i += 2\n continue\n }\n\n // Handle block comments - preserve them in output\n if (!inLineComment && char === '/' && nextChar === '*') {\n inBlockComment = true\n current += '/*'\n i += 2\n continue\n }\n\n // End of line comment\n if (inLineComment && char === '\\n') {\n inLineComment = false\n current += char\n i++\n continue\n }\n\n // End of block comment - preserve closing\n if (inBlockComment && char === '*' && nextChar === '/') {\n inBlockComment = false\n current += '*/'\n i += 2\n continue\n }\n\n // Inside comments - preserve the content\n if (inLineComment || inBlockComment) {\n current += char\n i++\n continue\n }\n\n if (char === '(' || char === '{' || char === '[') {\n depth++\n current += char\n } else if (char === ')' || char === '}' || char === ']') {\n depth--\n current += char\n } else if (char === ',' && depth === 0) {\n result.push(current)\n current = ''\n } else {\n current += char\n }\n i++\n }\n\n if (current.trim()) {\n result.push(current)\n }\n\n return result\n}\n\n/**\n * Transform Is/IsNot infix operators to function calls\n *\n * Syntax:\n * a Is b -> Is(a, b)\n * a IsNot b -> IsNot(a, b)\n *\n * This enables structural equality with a clean syntax.\n * In LegacyEquals mode, these are the explicit operators for structural equality.\n */\nfunction transformIsOperators(source: string): string {\n // Match: (simpleExpr) IsNot (simpleExpr) - must check IsNot first (longer match)\n // simpleExpr = identifier chain with optional [], () OR literals\n const exprPat =\n '([\\\\w][\\\\w.\\\\[\\\\]()]*|null|undefined|true|false|\\\\d+(?:\\\\.\\\\d+)?|\\'[^\\']*\\'|\"[^\"]*\")'\n\n // Transform IsNot first (longer keyword)\n const isNotRegex = new RegExp(exprPat + '\\\\s+IsNot\\\\s+' + exprPat, 'g')\n source = source.replace(isNotRegex, 'IsNot($1, $2)')\n\n // Transform Is\n const isRegex = new RegExp(exprPat + '\\\\s+Is\\\\s+' + exprPat, 'g')\n source = source.replace(isRegex, 'Is($1, $2)')\n\n return source\n}\n\n/**\n * Insert semicolons to prevent ASI footguns (TjsStandard mode)\n *\n * JavaScript's ASI (Automatic Semicolon Insertion) has notorious footguns:\n *\n * foo // Intended: call foo, then IIFE\n * (() => {})() // Actual: foo(...)(...) - calls foo with IIFE as argument!\n *\n * TjsStandard prevents this by treating newlines as statement terminators\n * (like Go, Swift, Kotlin). When a line starts with a problematic character\n * that could continue the previous line, we insert a semicolon.\n *\n * Problematic line starts: ( [ / + - `\n *\n * We only insert when the previous line doesn't already end with:\n * - A semicolon\n * - An opening brace/bracket/paren (multi-line expression)\n * - A comma (array/object literal or params)\n * - An operator that clearly continues (+, -, *, /, =, etc.)\n * - A keyword that expects continuation (return, throw, etc. followed by value)\n */\nfunction insertAsiProtection(source: string): string {\n // Characters that can continue a previous expression (ASI footguns)\n const continuationStarts = /^[\\s]*[([/+\\-`]/\n\n // Characters/patterns that indicate the previous line expects continuation\n // (don't insert semicolon after these)\n const expectsContinuation = /[{([,;:+\\-*/%=&|?<>!~^]\\s*$|^\\s*$/\n\n // Keywords that expect an expression to follow on same or next line\n const continueKeywords =\n /\\b(return|throw|yield|await|case|default|extends|new|typeof|void|delete|in|of|instanceof)\\s*$/\n\n const lines = source.split('\\n')\n const result: string[] = []\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]\n const prevLine = i > 0 ? lines[i - 1] : ''\n\n // Check if this line starts with a problematic character\n if (i > 0 && continuationStarts.test(line)) {\n // Get the previous line without trailing comment\n const prevNoComment = prevLine\n .replace(/\\/\\/.*$/, '')\n .replace(/\\/\\*.*\\*\\/\\s*$/, '')\n\n // Don't insert if prev line clearly expects continuation\n if (\n !expectsContinuation.test(prevNoComment) &&\n !continueKeywords.test(prevNoComment)\n ) {\n // Insert semicolon at start of this line (preserving whitespace)\n const match = line.match(/^(\\s*)/)\n const indent = match ? match[1] : ''\n const rest = line.slice(indent.length)\n result.push(indent + ';' + rest)\n continue\n }\n }\n\n result.push(line)\n }\n\n return result.join('\\n')\n}\n\n/**\n * Transform == and != to Is() and IsNot() calls\n *\n * In TJS normal mode:\n * a == b -> Is(a, b) (structural equality)\n * a != b -> IsNot(a, b) (structural inequality)\n * a === b -> a === b (identity, unchanged)\n *\n * Uses a two-pass algorithm:\n * 1. Find all == and != positions (outside strings/comments/regex)\n * 2. Transform from end to start (so positions remain valid)\n */\nfunction transformEqualityToStructural(source: string): string {\n // First pass: find all == and != positions (outside strings/comments/regex)\n const equalityOps: Array<{ pos: number; op: '==' | '!=' }> = []\n let i = 0\n let state: TokenizerState = 'normal'\n const templateStack: number[] = []\n\n while (i < source.length) {\n const char = source[i]\n const nextChar = source[i + 1]\n\n // Handle state transitions\n switch (state) {\n case 'single-string':\n if (char === '\\\\' && i + 1 < source.length) {\n i += 2\n continue\n }\n if (char === \"'\") state = 'normal'\n i++\n continue\n\n case 'double-string':\n if (char === '\\\\' && i + 1 < source.length) {\n i += 2\n continue\n }\n if (char === '\"') state = 'normal'\n i++\n continue\n\n case 'template-string':\n if (char === '\\\\' && i + 1 < source.length) {\n i += 2\n continue\n }\n if (char === '$' && nextChar === '{') {\n i += 2\n templateStack.push(1)\n state = 'normal'\n continue\n }\n if (char === '`') state = 'normal'\n i++\n continue\n\n case 'line-comment':\n if (char === '\\n') state = 'normal'\n i++\n continue\n\n case 'block-comment':\n if (char === '*' && nextChar === '/') {\n i += 2\n state = 'normal'\n continue\n }\n i++\n continue\n\n case 'regex':\n if (char === '\\\\' && i + 1 < source.length) {\n i += 2\n continue\n }\n if (char === '[') {\n i++\n while (i < source.length && source[i] !== ']') {\n if (source[i] === '\\\\' && i + 1 < source.length) {\n i += 2\n } else {\n i++\n }\n }\n if (i < source.length) i++\n continue\n }\n if (char === '/') {\n i++\n while (i < source.length && /[gimsuy]/.test(source[i])) i++\n state = 'normal'\n continue\n }\n i++\n continue\n\n case 'normal':\n // Handle template stack\n if (templateStack.length > 0) {\n if (char === '{') {\n templateStack[templateStack.length - 1]++\n } else if (char === '}') {\n templateStack[templateStack.length - 1]--\n if (templateStack[templateStack.length - 1] === 0) {\n templateStack.pop()\n i++\n state = 'template-string'\n continue\n }\n }\n }\n\n // Check for string/comment/regex start\n if (char === \"'\") {\n i++\n state = 'single-string'\n continue\n }\n if (char === '\"') {\n i++\n state = 'double-string'\n continue\n }\n if (char === '`') {\n i++\n state = 'template-string'\n continue\n }\n if (char === '/' && nextChar === '/') {\n i += 2\n state = 'line-comment'\n continue\n }\n if (char === '/' && nextChar === '*') {\n i += 2\n state = 'block-comment'\n continue\n }\n\n // Check for regex literal (simplified detection)\n if (char === '/') {\n let j = i - 1\n while (j >= 0 && /\\s/.test(source[j])) j--\n const beforeChar = j >= 0 ? source[j] : ''\n const isRegexContext =\n !beforeChar ||\n /[=(!,;:{[&|?+\\-*%<>~^]/.test(beforeChar) ||\n (j >= 5 &&\n /\\b(return|case|throw|in|of|typeof|instanceof|new|delete|void)$/.test(\n source.slice(Math.max(0, j - 10), j + 1)\n ))\n if (isRegexContext) {\n i++\n state = 'regex'\n continue\n }\n }\n\n // Look for == or != (but not === or !==)\n // For ==: check it's not part of !== (char before is !)\n // For !=: check it's not !== (third char is =)\n if (\n char === '=' &&\n nextChar === '=' &&\n source[i + 2] !== '=' &&\n source[i - 1] !== '!'\n ) {\n equalityOps.push({ pos: i, op: '==' })\n i += 2\n continue\n }\n if (char === '!' && nextChar === '=' && source[i + 2] !== '=') {\n equalityOps.push({ pos: i, op: '!=' })\n i += 2\n continue\n }\n break\n }\n\n i++\n }\n\n // If no equality operators found, return source unchanged\n if (equalityOps.length === 0) {\n return source\n }\n\n // Second pass: transform from end to start (so positions remain valid)\n let result = source\n for (let k = equalityOps.length - 1; k >= 0; k--) {\n const { pos, op } = equalityOps[k]\n const funcName = op === '==' ? 'Is' : 'IsNot'\n\n // Find left operand boundary\n const leftBoundary = findLeftOperandBoundary(result, pos)\n // Find right operand boundary\n const rightBoundary = findRightOperandBoundary(result, pos + 2)\n\n const leftExpr = result.slice(leftBoundary, pos).trim()\n const rightExpr = result.slice(pos + 2, rightBoundary).trim()\n\n if (leftExpr && rightExpr) {\n // Build the replacement\n const before = result.slice(0, leftBoundary)\n const after = result.slice(rightBoundary)\n // Add space after keyword if needed (e.g., return, throw, typeof)\n const needsSpace = /[a-zA-Z0-9_$]$/.test(before)\n const spacer = needsSpace ? ' ' : ''\n result = `${before}${spacer}${funcName}(${leftExpr}, ${rightExpr})${after}`\n }\n }\n\n return result\n}\n\n/**\n * Find the start position of the left operand\n *\n * Scans backwards from the operator position to find where the left expression starts.\n * Respects operator precedence: == has lower precedence than arithmetic operators,\n * so `x % 2 == 0` has left operand `x % 2`.\n */\nfunction findLeftOperandBoundary(source: string, opPos: number): number {\n let i = opPos - 1\n\n // Skip whitespace before operator\n while (i >= 0 && /\\s/.test(source[i])) i--\n if (i < 0) return 0\n\n let depth = 0\n let inString = false\n let stringChar = ''\n\n while (i >= 0) {\n const char = source[i]\n const prevChar = i > 0 ? source[i - 1] : ''\n\n // Handle string literals (scan backwards through them)\n if (inString) {\n if (char === stringChar && prevChar !== '\\\\') {\n inString = false\n }\n i--\n continue\n }\n\n // Check for string end (we're scanning backwards, so end is opening quote)\n if ((char === '\"' || char === \"'\" || char === '`') && prevChar !== '\\\\') {\n inString = true\n stringChar = char\n i--\n continue\n }\n\n // Track depth of parens/brackets (reversed since we're going backwards)\n if (char === ')' || char === ']') {\n depth++\n i--\n continue\n }\n if (char === '(' || char === '[') {\n if (depth > 0) {\n depth--\n i--\n continue\n }\n // Opening paren/bracket at depth 0 - this is a grouping/call paren\n // The expression starts AFTER it, not including it\n return i + 1\n }\n\n // Inside nested expression - keep scanning\n if (depth > 0) {\n i--\n continue\n }\n\n // At depth 0 - check for expression boundaries\n // Statement delimiters\n if (char === ';' || char === '{' || char === '}') {\n return i + 1\n }\n\n // Check for keywords that precede expressions (return, throw, etc.)\n // We need to look backwards for a word boundary and check if it's a keyword\n if (/[a-z]/.test(char)) {\n // Might be end of a keyword - scan backwards to get full word\n const wordEnd = i + 1\n let wordStart = i\n while (wordStart > 0 && /[a-z]/i.test(source[wordStart - 1])) {\n wordStart--\n }\n const word = source.slice(wordStart, wordEnd)\n // Check if preceded by word char (not a keyword then)\n const beforeWord = wordStart > 0 ? source[wordStart - 1] : ''\n if (!/[a-zA-Z0-9_$]/.test(beforeWord)) {\n // These keywords start an expression - stop after them\n if (\n [\n 'return',\n 'throw',\n 'case',\n 'typeof',\n 'void',\n 'delete',\n 'await',\n 'yield',\n 'new',\n ].includes(word)\n ) {\n return wordEnd\n }\n }\n }\n\n // Arrow function - stop before =>\n if (char === '>' && prevChar === '=') {\n return i + 1\n }\n\n // Assignment operator (but not ==, !=, <=, >=)\n if (\n char === '=' &&\n prevChar !== '=' &&\n prevChar !== '!' &&\n prevChar !== '<' &&\n prevChar !== '>'\n ) {\n return i + 1\n }\n\n // Logical operators (lower precedence than ==)\n if (char === '&' && prevChar === '&') {\n return i + 1\n }\n if (char === '|' && prevChar === '|') {\n return i + 1\n }\n\n // Ternary operators\n if (char === '?' || char === ':') {\n return i + 1\n }\n\n // Comma\n if (char === ',') {\n return i + 1\n }\n\n i--\n }\n\n return 0\n}\n\n/**\n * Find the end position of the right operand\n *\n * Scans forward from after the operator to find where the right expression ends.\n */\nfunction findRightOperandBoundary(\n source: string,\n startAfterOp: number\n): number {\n let i = startAfterOp\n\n // Skip whitespace after operator\n while (i < source.length && /\\s/.test(source[i])) i++\n if (i >= source.length) return source.length\n\n let depth = 0\n let inString = false\n let stringChar = ''\n\n while (i < source.length) {\n const char = source[i]\n const nextChar = i + 1 < source.length ? source[i + 1] : ''\n\n // Handle string literals\n if (inString) {\n if (char === stringChar && source[i - 1] !== '\\\\') {\n inString = false\n }\n i++\n continue\n }\n\n if (\n (char === '\"' || char === \"'\" || char === '`') &&\n source[i - 1] !== '\\\\'\n ) {\n inString = true\n stringChar = char\n i++\n continue\n }\n\n // Track depth\n if (char === '(' || char === '[' || char === '{') {\n depth++\n i++\n continue\n }\n if (char === ')' || char === ']' || char === '}') {\n if (depth > 0) {\n depth--\n i++\n continue\n }\n // Closing paren at depth 0 - boundary\n return i\n }\n\n // Inside nested - keep scanning\n if (depth > 0) {\n i++\n continue\n }\n\n // At depth 0 - check for expression boundaries\n if (char === ';') {\n return i\n }\n\n // Logical operators - lower precedence than ==\n if (char === '&' && nextChar === '&') {\n return i\n }\n if (char === '|' && nextChar === '|') {\n return i\n }\n\n // Ternary\n if (char === '?') {\n return i\n }\n if (char === ':') {\n return i\n }\n\n // Comma\n if (char === ',') {\n return i\n }\n\n // Another == or != (chained equality - stop before it)\n if (\n (char === '=' || char === '!') &&\n nextChar === '=' &&\n source[i + 2] !== '='\n ) {\n return i\n }\n\n i++\n }\n\n return source.length\n}\n\n/**\n * Transform Type block declarations\n *\n * Syntax forms:\n * Type Foo 'example' -> const Foo = Type('Foo', 'example')\n * Type Foo { example: 'value' } -> const Foo = Type('Foo', 'value')\n * Type Foo 'description' { example: 'value' }\n * -> const Foo = Type('description', 'value')\n * Type Foo 'description' { example: 0, predicate(x) { return x > 0 } }\n * -> const Foo = Type('description', (x) => { ... }, 0)\n *\n * When predicate + example: auto-generate type guard from example\n */\nfunction transformTypeDeclarations(source: string): string {\n let result = ''\n let i = 0\n\n while (i < source.length) {\n // Look for 'Type' keyword followed by identifier\n const typeMatch = source.slice(i).match(/^\\bType\\s+([A-Z][a-zA-Z0-9_]*)\\s*/)\n if (typeMatch) {\n const typeName = typeMatch[1]\n let j = i + typeMatch[0].length\n\n // Check for optional description string\n // Only treat as description if followed by = or {\n let description = typeName\n let descriptionWasExplicit = false\n const descStringMatch = source.slice(j).match(/^(['\"`])([^]*?)\\1\\s*/)\n if (descStringMatch) {\n const afterString = j + descStringMatch[0].length\n const nextChar = source[afterString]\n // Check if this looks like end of statement (not followed by = or {)\n // Note: the \\s* in the regex consumes trailing whitespace including newlines\n const isEndOfStatement =\n nextChar === undefined ||\n afterString >= source.length ||\n (nextChar !== '=' && nextChar !== '{')\n\n if (nextChar === '=' || nextChar === '{') {\n // It's a description followed by = or { block\n description = descStringMatch[2]\n descriptionWasExplicit = true\n j = afterString\n } else if (isEndOfStatement) {\n // Old simple form: Type Name 'value' - value is both example and default\n const value = descStringMatch[0].trim()\n // Preserve trailing whitespace (newlines) that was consumed by the regex\n const trailingWs = descStringMatch[0].slice(value.length)\n result += `const ${typeName} = Type('${typeName}', ${value})${trailingWs}`\n i = afterString\n continue\n }\n }\n\n // Check for = default value\n let defaultValue: string | undefined\n let posAfterDefault = j // Track position right after the default value\n const equalsMatch = source.slice(j).match(/^=\\s*/)\n if (equalsMatch) {\n j += equalsMatch[0].length\n // Parse the default value (handles +number, strings, objects, arrays, etc.)\n const valueMatch = source\n .slice(j)\n .match(\n /^(\\+?\\d+(?:\\.\\d+)?|['\"`][^'\"`]*['\"`]|\\{[^}]*\\}|\\[[^\\]]*\\]|true|false|null)/\n )\n if (valueMatch) {\n defaultValue = valueMatch[0]\n j += valueMatch[0].length\n posAfterDefault = j // Save position before consuming whitespace\n // Skip whitespace after default (only to check for block)\n const wsMatch = source.slice(j).match(/^\\s*/)\n if (wsMatch) j += wsMatch[0].length\n }\n }\n\n // Check for block { ... }\n if (source[j] === '{') {\n // Block form: Type Foo 'desc'? = default? { ... }\n const bodyStart = j + 1\n let depth = 1\n let k = bodyStart\n\n // Find matching closing brace\n while (k < source.length && depth > 0) {\n const char = source[k]\n if (char === '{') depth++\n else if (char === '}') depth--\n k++\n }\n\n if (depth !== 0) {\n // Unbalanced - just copy and continue\n result += source[i]\n i++\n continue\n }\n\n const blockBody = source.slice(bodyStart, k - 1).trim()\n const blockEnd = k\n\n // Parse block body for description (old syntax fallback), example, predicate\n const descInsideMatch = blockBody.match(\n /description\\s*:\\s*(['\"`])([^]*?)\\1/\n )\n if (descInsideMatch && !descriptionWasExplicit) {\n description = descInsideMatch[2]\n }\n\n // Extract example value using state machine for nested structures\n let example: string | undefined\n const exampleKeyword = blockBody.match(/example\\s*:\\s*/)\n if (exampleKeyword) {\n const valueStart = exampleKeyword.index! + exampleKeyword[0].length\n const extracted = extractJSValue(blockBody, valueStart)\n if (extracted) {\n example = extracted.value.trim()\n }\n }\n\n const predicateMatch = blockBody.match(\n /predicate\\s*\\(([^)]*)\\)\\s*\\{([^]*)\\}/\n )\n\n // Build Type() call with appropriate arguments\n // Type(description, predicateOrExample, example?, default?)\n if (predicateMatch && example) {\n // Predicate + example\n const params = predicateMatch[1].trim()\n const body = predicateMatch[2].trim()\n const defaultArg = defaultValue ? `, ${defaultValue}` : ''\n result += `const ${typeName} = Type('${description}', (${params}) => { if (!globalThis.__tjs?.validate(${params}, globalThis.__tjs?.infer(${example}))) return false; ${body} }, ${example}${defaultArg})`\n } else if (predicateMatch) {\n // Predicate only\n const params = predicateMatch[1].trim()\n const body = predicateMatch[2].trim()\n const defaultArg = defaultValue ? `, undefined, ${defaultValue}` : ''\n result += `const ${typeName} = Type('${description}', (${params}) => { ${body} }${defaultArg})`\n } else if (example) {\n // Example only (becomes validation schema)\n const defaultArg = defaultValue ? `, ${defaultValue}` : ''\n result += `const ${typeName} = Type('${description}', undefined, ${example}${defaultArg})`\n } else if (defaultValue) {\n // Default only (infer schema from default)\n result += `const ${typeName} = Type('${description}', ${defaultValue})`\n } else {\n // Empty block - error or description-only type\n result += `const ${typeName} = Type('${description}')`\n }\n\n i = blockEnd\n continue\n } else if (defaultValue) {\n // Simple form with default: Type Foo = 'value' or Type Foo 'desc' = 'value'\n result += `const ${typeName} = Type('${description}', ${defaultValue})`\n i = posAfterDefault // Use position before whitespace was consumed\n continue\n } else if (!descStringMatch) {\n // No description, no default, no block - look for old simple form: Type Foo 'value'\n const valueMatch = source\n .slice(j)\n .match(\n /^(['\"`][^]*?['\"`]|\\+?\\d+(?:\\.\\d+)?|true|false|null|\\{[^]*?\\}|\\[[^]*?\\])/\n )\n if (valueMatch) {\n const example = valueMatch[0]\n result += `const ${typeName} = Type('${typeName}', ${example})`\n i = j + valueMatch[0].length\n continue\n }\n }\n }\n\n result += source[i]\n i++\n }\n\n return result\n}\n\n/**\n * Transform Generic block declarations\n *\n * Syntax:\n * Generic Pair<T, U> { description: '...', predicate(obj, T, U) { ... } }\n * Generic Container<T, U = ''> { ... } // U has default\n *\n * Transforms to:\n * const Pair = Generic(['T', 'U'], (obj, checkT, checkU) => { ... }, '...')\n * const Container = Generic(['T', ['U', '']], (obj, checkT, checkU) => { ... }, '...')\n */\nfunction transformGenericDeclarations(source: string): string {\n let result = ''\n let i = 0\n\n while (i < source.length) {\n // Look for 'Generic' keyword followed by identifier and type params\n const genericMatch = source\n .slice(i)\n .match(/^\\bGeneric\\s+([A-Z][a-zA-Z0-9_]*)\\s*<([^>]+)>\\s*\\{/)\n if (genericMatch) {\n const genericName = genericMatch[1]\n const typeParamsStr = genericMatch[2]\n const blockStart = i + genericMatch[0].length - 1\n const bodyStart = blockStart + 1\n let depth = 1\n let k = bodyStart\n\n // Find matching closing brace\n while (k < source.length && depth > 0) {\n const char = source[k]\n if (char === '{') depth++\n else if (char === '}') depth--\n k++\n }\n\n if (depth !== 0) {\n // Unbalanced - just copy and continue\n result += source[i]\n i++\n continue\n }\n\n const blockBody = source.slice(bodyStart, k - 1).trim()\n const blockEnd = k\n\n // Parse type params: T, U = Default\n const typeParams = typeParamsStr.split(',').map((p) => {\n const parts = p\n .trim()\n .split('=')\n .map((s) => s.trim())\n if (parts.length === 2) {\n return `['${parts[0]}', ${parts[1]}]`\n }\n return `'${parts[0]}'`\n })\n\n // Parse the block body\n const descMatch = blockBody.match(/description\\s*:\\s*(['\"`])([^]*?)\\1/)\n const predicateMatch = blockBody.match(\n /predicate\\s*\\(([^)]*)\\)\\s*\\{([^]*)\\}/\n )\n\n const description = descMatch ? descMatch[2] : genericName\n\n if (predicateMatch) {\n const params = predicateMatch[1]\n .trim()\n .split(',')\n .map((s) => s.trim())\n let body = predicateMatch[2].trim()\n\n // First param is the value, rest are type params\n const valueParam = params[0] || 'x'\n const typeParamNames = params.slice(1)\n const typeCheckParams = typeParamNames.map((p) => `check${p}`)\n\n // Replace type param names with check functions in body\n // e.g., T(x[0]) becomes checkT(x[0])\n typeParamNames.forEach((name, idx) => {\n body = body.replace(\n new RegExp(`\\\\b${name}\\\\s*\\\\(`, 'g'),\n `${typeCheckParams[idx]}(`\n )\n })\n\n result += `const ${genericName} = Generic([${typeParams.join(\n ', '\n )}], (${valueParam}, ${typeCheckParams.join(\n ', '\n )}) => { ${body} }, '${description}')`\n } else {\n // No predicate - create a generic that always passes\n result += `const ${genericName} = Generic([${typeParams.join(\n ', '\n )}], () => true, '${description}')`\n }\n\n i = blockEnd\n continue\n }\n\n result += source[i]\n i++\n }\n\n return result\n}\n\n/**\n * Transform Union declarations\n *\n * Syntax:\n * Union Direction 'cardinal direction' {\n * 'up' | 'down' | 'left' | 'right'\n * }\n *\n * Transforms to:\n * const Direction = Union('cardinal direction', ['up', 'down', 'left', 'right'])\n *\n * Also supports inline form:\n * Union Direction 'cardinal direction' 'up' | 'down' | 'left' | 'right'\n */\nfunction transformUnionDeclarations(source: string): string {\n let result = ''\n let i = 0\n\n while (i < source.length) {\n // Look for 'Union' keyword followed by identifier and description\n const unionMatch = source\n .slice(i)\n .match(/^\\bUnion\\s+([A-Z][a-zA-Z0-9_]*)\\s+(['\"`])([^]*?)\\2\\s*/)\n if (unionMatch) {\n const unionName = unionMatch[1]\n const description = unionMatch[3]\n const j = i + unionMatch[0].length\n\n // Check what follows: block or inline values\n if (source[j] === '{') {\n // Block form: Union Foo 'desc' { ... }\n const bodyStart = j + 1\n let depth = 1\n let k = bodyStart\n\n // Find matching closing brace\n while (k < source.length && depth > 0) {\n const char = source[k]\n if (char === '{') depth++\n else if (char === '}') depth--\n k++\n }\n\n if (depth !== 0) {\n result += source[i]\n i++\n continue\n }\n\n const blockBody = source.slice(bodyStart, k - 1).trim()\n const blockEnd = k\n\n // Parse values: 'a' | 'b' | 'c' or \"a\" | \"b\" or mixed\n const values = parseUnionValues(blockBody)\n result += `const ${unionName} = Union('${description}', [${values.join(\n ', '\n )}])`\n i = blockEnd\n continue\n } else {\n // Inline form: Union Foo 'desc' 'a' | 'b' | 'c'\n // Find the end of the line or statement\n let lineEnd = source.indexOf('\\n', j)\n if (lineEnd === -1) lineEnd = source.length\n const inlineValues = source.slice(j, lineEnd).trim()\n\n if (inlineValues) {\n const values = parseUnionValues(inlineValues)\n result += `const ${unionName} = Union('${description}', [${values.join(\n ', '\n )}])`\n i = lineEnd\n continue\n }\n }\n }\n\n result += source[i]\n i++\n }\n\n return result\n}\n\n/**\n * Parse union values from a string like: 'a' | 'b' | 123 | true\n * Returns array of value literals as strings\n */\nfunction parseUnionValues(input: string): string[] {\n const values: string[] = []\n // Split on | and trim, preserving quoted strings and literals\n const parts = input.split('|').map((p) => p.trim())\n\n for (const part of parts) {\n if (!part) continue\n // Keep the value as-is (already a valid JS literal)\n values.push(part)\n }\n\n return values\n}\n\n/**\n * Transform Enum declarations\n *\n * Syntax:\n * Enum Status 'task status' {\n * Pending\n * Active\n * Done\n * }\n *\n * Enum Color 'CSS color' {\n * Red = 'red'\n * Green = 'green'\n * Blue = 'blue'\n * }\n *\n * Transforms to:\n * const Status = Enum('task status', { Pending: 0, Active: 1, Done: 2 })\n * const Color = Enum('CSS color', { Red: 'red', Green: 'green', Blue: 'blue' })\n */\nfunction transformEnumDeclarations(source: string): string {\n let result = ''\n let i = 0\n\n while (i < source.length) {\n // Look for 'Enum' keyword followed by identifier and description\n const enumMatch = source\n .slice(i)\n .match(/^\\bEnum\\s+([A-Z][a-zA-Z0-9_]*)\\s+(['\"`])([^]*?)\\2\\s*\\{/)\n if (enumMatch) {\n const enumName = enumMatch[1]\n const description = enumMatch[3]\n const blockStart = i + enumMatch[0].length - 1\n const bodyStart = blockStart + 1\n let depth = 1\n let k = bodyStart\n\n // Find matching closing brace\n while (k < source.length && depth > 0) {\n const char = source[k]\n if (char === '{') depth++\n else if (char === '}') depth--\n k++\n }\n\n if (depth !== 0) {\n result += source[i]\n i++\n continue\n }\n\n const blockBody = source.slice(bodyStart, k - 1).trim()\n const blockEnd = k\n\n // Parse enum members\n const members = parseEnumMembers(blockBody)\n const membersStr = members\n .map(([key, value]) => `${key}: ${value}`)\n .join(', ')\n\n result += `const ${enumName} = Enum('${description}', { ${membersStr} })`\n i = blockEnd\n continue\n }\n\n result += source[i]\n i++\n }\n\n return result\n}\n\n/**\n * Parse enum members from block body\n * Handles: Pending, Active = 5, Done, Name = 'value'\n * Returns array of [key, value] pairs\n */\nfunction parseEnumMembers(input: string): [string, string][] {\n const members: [string, string][] = []\n let currentNumericValue = 0\n\n // Split on newlines and commas, filter empty\n const lines = input\n .split(/[\\n,]/)\n .map((l) => l.trim())\n .filter((l) => l && !l.startsWith('//'))\n\n for (const line of lines) {\n // Match: Name or Name = value\n const match = line.match(/^([A-Za-z_][A-Za-z0-9_]*)\\s*(?:=\\s*(.+))?$/)\n if (match) {\n const key = match[1]\n const explicitValue = match[2]?.trim()\n\n if (explicitValue !== undefined) {\n members.push([key, explicitValue])\n // If it's a number, update the counter\n const numVal = Number(explicitValue)\n if (!isNaN(numVal)) {\n currentNumericValue = numVal + 1\n }\n } else {\n // Auto-increment numeric value\n members.push([key, String(currentNumericValue)])\n currentNumericValue++\n }\n }\n }\n\n return members\n}\n\n/**\n * Transform bare assignments to const declarations\n *\n * Foo = ... -> const Foo = ...\n *\n * Only transforms assignments at statement level (start of line or after semicolon/brace)\n * where the identifier starts with uppercase (to avoid breaking normal assignments)\n */\nfunction transformBareAssignments(source: string): string {\n // Match: start of line/statement, uppercase identifier, =, not ==\n // Negative lookbehind for const/let/var to avoid double-declaring\n return source.replace(\n /(?<=^|[;\\n{])\\s*([A-Z][a-zA-Z0-9_]*)\\s*=(?!=)/gm,\n (match, name) => {\n // Check if already has const/let/var before it\n return match.replace(name, `const ${name}`)\n }\n )\n}\n\n/**\n * Parse source code into an Acorn AST\n */\nexport function parse(\n source: string,\n options: ParseOptions = {}\n): {\n ast: Program\n returnType?: string\n returnSafety?: 'safe' | 'unsafe'\n moduleSafety?: 'none' | 'inputs' | 'all'\n originalSource: string\n requiredParams: Set<string>\n unsafeFunctions: Set<string>\n safeFunctions: Set<string>\n wasmBlocks: WasmBlock[]\n tests: TestBlock[]\n testErrors: string[]\n} {\n const {\n filename = '<source>',\n colonShorthand = true,\n vmTarget = false,\n } = options\n\n // Preprocess for custom syntax\n const {\n source: processedSource,\n returnType,\n returnSafety,\n moduleSafety,\n originalSource,\n requiredParams,\n unsafeFunctions,\n safeFunctions,\n wasmBlocks,\n tests,\n testErrors,\n } = colonShorthand\n ? preprocess(source, { vmTarget })\n : {\n source,\n returnType: undefined,\n returnSafety: undefined,\n moduleSafety: undefined,\n originalSource: source,\n requiredParams: new Set<string>(),\n unsafeFunctions: new Set<string>(),\n safeFunctions: new Set<string>(),\n wasmBlocks: [] as WasmBlock[],\n tests: [] as TestBlock[],\n testErrors: [] as string[],\n }\n\n try {\n const ast = acorn.parse(processedSource, {\n ecmaVersion: 2022,\n sourceType: 'module',\n locations: true,\n allowReturnOutsideFunction: false,\n })\n\n return {\n ast,\n returnType,\n returnSafety,\n moduleSafety,\n originalSource,\n requiredParams,\n unsafeFunctions,\n safeFunctions,\n wasmBlocks,\n tests,\n testErrors,\n }\n } catch (e: any) {\n // Convert Acorn error to our error type\n const loc = e.loc || { line: 1, column: 0 }\n throw new SyntaxError(\n e.message.replace(/\\s*\\(\\d+:\\d+\\)$/, ''), // Remove acorn's location suffix\n loc,\n originalSource,\n filename\n )\n }\n}\n\n/**\n * Validate that the source contains exactly one function declaration\n */\nexport function validateSingleFunction(\n ast: Program,\n filename?: string\n): FunctionDeclaration {\n // Check for unsupported top-level constructs FIRST\n // This gives better error messages for things like classes\n for (const node of ast.body) {\n if (node.type === 'ImportDeclaration') {\n throw new SyntaxError(\n 'Imports are not supported. All atoms must be registered with the VM.',\n node.loc?.start || { line: 1, column: 0 },\n undefined,\n filename\n )\n }\n\n if (\n node.type === 'ExportNamedDeclaration' ||\n node.type === 'ExportDefaultDeclaration'\n ) {\n throw new SyntaxError(\n 'Exports are not supported. The function is automatically exported.',\n node.loc?.start || { line: 1, column: 0 },\n undefined,\n filename\n )\n }\n\n if (node.type === 'ClassDeclaration') {\n throw new SyntaxError(\n 'Classes are not supported. Agent99 uses functional composition.',\n node.loc?.start || { line: 1, column: 0 },\n undefined,\n filename\n )\n }\n }\n\n const functions = ast.body.filter(\n (node): node is FunctionDeclaration => node.type === 'FunctionDeclaration'\n )\n\n if (functions.length === 0) {\n throw new SyntaxError(\n 'Source must contain a function declaration',\n { line: 1, column: 0 },\n undefined,\n filename\n )\n }\n\n if (functions.length > 1) {\n const second = functions[1]\n throw new SyntaxError(\n 'Only a single function per agent is allowed',\n second.loc?.start || { line: 1, column: 0 },\n undefined,\n filename\n )\n }\n\n return functions[0]\n}\n\n/**\n * Extract TDoc comment from before a function\n *\n * TJS doc comments use /*# ... * / syntax and preserve full markdown content.\n * Legacy JSDoc (/** ... * /) is supported as a fallback.\n */\nexport function extractTDoc(\n source: string,\n func: FunctionDeclaration\n): {\n description?: string\n params: Record<string, string>\n} {\n const result: { description?: string; params: Record<string, string> } = {\n params: {},\n }\n\n if (!func.loc) return result\n\n const beforeFunc = source.substring(0, func.start)\n\n // First, check for TJS doc comment: /*# ... */\n // This preserves full markdown content\n // Find the LAST /*# ... */ block and verify it immediately precedes the function\n // (only whitespace and line comments allowed between)\n const allDocBlocks = [...beforeFunc.matchAll(/\\/\\*#([\\s\\S]*?)\\*\\//g)]\n if (allDocBlocks.length > 0) {\n const lastBlock = allDocBlocks[allDocBlocks.length - 1]\n const afterBlock = beforeFunc.substring(\n lastBlock.index! + lastBlock[0].length\n )\n\n // Only attach if nothing but whitespace and line comments between doc and function\n if (/^(?:\\s|\\/\\/[^\\n]*)*$/.test(afterBlock)) {\n // Extract content, trim leading/trailing whitespace, preserve internal formatting\n let content = lastBlock[1]\n\n // Remove common leading whitespace (like dedent)\n const lines = content.split('\\n')\n // Find minimum indentation (ignoring empty lines)\n const minIndent = lines\n .filter((line) => line.trim().length > 0)\n .reduce((min, line) => {\n const indent = line.match(/^(\\s*)/)?.[1].length || 0\n return Math.min(min, indent)\n }, Infinity)\n\n // Remove that indentation from all lines\n if (minIndent > 0 && minIndent < Infinity) {\n content = lines.map((line) => line.slice(minIndent)).join('\\n')\n }\n\n result.description = content.trim()\n return result\n }\n }\n\n // Fall back to JSDoc: /** ... */\n const jsdocMatch = beforeFunc.match(/\\/\\*\\*[\\s\\S]*?\\*\\/\\s*$/)\n if (!jsdocMatch) return result\n\n const jsdoc = jsdocMatch[0]\n\n // Extract description (first non-tag content)\n const descMatch = jsdoc.match(/\\/\\*\\*\\s*\\n?\\s*\\*?\\s*([^@\\n][^\\n]*)/m)\n if (descMatch) {\n result.description = descMatch[1].trim()\n }\n\n // Extract @param tags\n const paramRegex = /@param\\s+(?:\\{[^}]+\\}\\s+)?(\\w+)\\s*-?\\s*(.*)/g\n let match\n while ((match = paramRegex.exec(jsdoc)) !== null) {\n result.params[match[1]] = match[2].trim()\n }\n\n return result\n}\n\n/**\n * Extract and run test blocks from source\n *\n * Syntax:\n * test { body }\n * test 'description' { body }\n *\n * Tests are executed at transpile time and stripped from output.\n * If any test fails, the error is collected (transpilation continues).\n */\nfunction extractAndRunTests(\n source: string,\n skipTests = false\n): {\n source: string\n tests: TestBlock[]\n errors: string[]\n} {\n const tests: TestBlock[] = []\n const errors: string[] = []\n let result = ''\n let i = 0\n\n while (i < source.length) {\n // Look for 'test' keyword followed by optional string then {\n const testMatch = source.slice(i).match(/^\\btest\\s+/)\n if (testMatch) {\n const start = i\n let j = i + testMatch[0].length\n\n // Check for optional description string\n let description: string | undefined\n const descMatch = source.slice(j).match(/^(['\"`])([^]*?)\\1\\s*/)\n if (descMatch) {\n description = descMatch[2]\n j += descMatch[0].length\n }\n\n // Must have opening brace\n if (source[j] === '{') {\n const bodyStart = j + 1\n let depth = 1\n let k = bodyStart\n\n // Find matching closing brace\n while (k < source.length && depth > 0) {\n const char = source[k]\n if (char === '{') depth++\n else if (char === '}') depth--\n k++\n }\n\n if (depth === 0) {\n const body = source.slice(bodyStart, k - 1).trim()\n const end = k\n\n tests.push({ description, body, start, end })\n\n // Run the test unless skipped\n if (!skipTests) {\n try {\n // Execute test in isolated context\n // The test has access to the Types defined before it\n const testFn = new Function(body)\n testFn()\n } catch (err: any) {\n const desc = description || `test at position ${start}`\n errors.push(`Test failed: ${desc}\\n ${err.message || err}`)\n }\n }\n\n // Strip the test block from output (replace with whitespace to preserve line numbers)\n const removed = source.slice(start, end)\n const newlines = (removed.match(/\\n/g) || []).length\n result += '\\n'.repeat(newlines)\n i = end\n continue\n }\n }\n }\n\n result += source[i]\n i++\n }\n\n return { source: result, tests, errors }\n}\n\n/**\n * Wrap class declarations to make them callable without `new`\n *\n * Transforms:\n * class Foo { ... }\n * To:\n * let Foo = class Foo { ... };\n * Foo = new Proxy(Foo, { apply(t, _, a) { return Reflect.construct(t, a) } });\n *\n * This emits standalone JS with no runtime dependencies.\n */\nfunction wrapClassDeclarations(source: string): string {\n // Match class declarations: class Name { or class Name extends Base {\n // Capture the class name and find the full class body\n const classRegex = /\\bclass\\s+(\\w+)(\\s+extends\\s+\\w+)?\\s*\\{/g\n let result = ''\n let lastIndex = 0\n let match\n\n while ((match = classRegex.exec(source)) !== null) {\n const className = match[1]\n const extendsClause = match[2] || ''\n const classStart = match.index\n const bodyStart = classStart + match[0].length - 1 // position of {\n\n // Find matching closing brace\n let depth = 1\n let i = bodyStart + 1\n while (i < source.length && depth > 0) {\n const char = source[i]\n if (char === '{') depth++\n else if (char === '}') depth--\n i++\n }\n\n if (depth === 0) {\n const classEnd = i\n const classBody = source.slice(bodyStart, classEnd)\n\n // Emit standalone JS - no runtime dependency\n result += source.slice(lastIndex, classStart)\n result += `let ${className} = class ${className}${extendsClause} ${classBody}; `\n result += `${className} = new Proxy(${className}, { apply(t, _, a) { return Reflect.construct(t, a) } });`\n lastIndex = classEnd\n }\n }\n\n result += source.slice(lastIndex)\n return result\n}\n\n/**\n * Validate that Date is not used (TjsDate mode)\n * Throws an error if Date constructor or static methods are found\n */\nfunction validateNoDate(source: string): string {\n // Match Date usage: new Date, Date.now, Date.parse, Date.UTC\n const datePatterns = [\n {\n pattern: /\\bnew\\s+Date\\b/,\n message:\n 'new Date() is not allowed in TjsDate mode. Use Timestamp.now() or Timestamp.from()',\n },\n {\n pattern: /\\bDate\\.now\\b/,\n message: 'Date.now() is not allowed in TjsDate mode. Use Timestamp.now()',\n },\n {\n pattern: /\\bDate\\.parse\\b/,\n message:\n 'Date.parse() is not allowed in TjsDate mode. Use Timestamp.parse()',\n },\n {\n pattern: /\\bDate\\.UTC\\b/,\n message:\n 'Date.UTC() is not allowed in TjsDate mode. Use Timestamp.from()',\n },\n ]\n\n for (const { pattern, message } of datePatterns) {\n if (pattern.test(source)) {\n throw new Error(message)\n }\n }\n\n return source\n}\n\n/**\n * Validate that eval and Function constructor are not used (TjsNoeval mode)\n * Note: Eval and SafeFunction from TJS runtime are allowed\n */\nfunction validateNoEval(source: string): string {\n // Match eval() calls - but not Eval() (capital E)\n // Use negative lookbehind to avoid matching inside words\n const evalPattern = /(?<![A-Za-z_$])\\beval\\s*\\(/\n if (evalPattern.test(source)) {\n throw new Error(\n 'eval() is not allowed in TjsNoeval mode. Use Eval() from TJS runtime for safe evaluation.'\n )\n }\n\n // Match new Function() - but not SafeFunction or other *Function names\n const functionPattern = /\\bnew\\s+Function\\s*\\(/\n if (functionPattern.test(source)) {\n throw new Error(\n 'new Function() is not allowed in TjsNoeval mode. Use SafeFunction() from TJS runtime.'\n )\n }\n\n return source\n}\n",
|
|
6
|
+
"/**\n * Type definitions for the Agent99 JavaScript transpiler\n */\n\nimport type { Node } from 'acorn'\nimport type { SeqNode } from '../builder'\n\n// ============================================================================\n// Type System Types\n// ============================================================================\n\n/** Represents a type extracted from value patterns */\nexport interface TypeDescriptor {\n kind:\n | 'string'\n | 'number'\n | 'boolean'\n | 'null'\n | 'undefined'\n | 'array'\n | 'object'\n | 'union'\n | 'any'\n nullable?: boolean\n /** For arrays: the element type */\n items?: TypeDescriptor\n /** For objects: the shape */\n shape?: Record<string, TypeDescriptor>\n /** For unions: the member types */\n members?: TypeDescriptor[]\n /** For destructured parameters: full parameter descriptors */\n destructuredParams?: Record<string, ParameterDescriptor>\n}\n\n/** Describes a function parameter */\nexport interface ParameterDescriptor {\n name: string\n type: TypeDescriptor\n required: boolean\n default?: any\n /** The example value used to infer the type (for autocomplete) */\n example?: any\n description?: string\n /** Source location for error reporting */\n loc?: { start: number; end: number }\n}\n\n/** Describes a function's complete signature */\nexport interface FunctionSignature {\n name: string\n description?: string\n parameters: Record<string, ParameterDescriptor>\n returns?: TypeDescriptor\n}\n\n// ============================================================================\n// Transpiler Options and Results\n// ============================================================================\n\n/** Options for the transpile function */\nexport interface TranspileOptions {\n /** Include source locations in output AST */\n sourceMaps?: boolean\n /** Atom registry for validation (optional) */\n atoms?: Record<string, { op: string }>\n /** Filename for error messages */\n filename?: string\n /** Whether to use strict type checking */\n strict?: boolean\n}\n\n/** Result of transpilation */\nexport interface TranspileResult {\n /** The Agent99 AST */\n ast: SeqNode\n /** The function signature with types */\n signature: FunctionSignature\n /** Source map (if enabled) */\n sourceMap?: SourceMap\n /** Warnings (non-fatal issues) */\n warnings: TranspileWarning[]\n}\n\n/** A non-fatal warning during transpilation */\nexport interface TranspileWarning {\n message: string\n line: number\n column: number\n source?: string\n}\n\n/** Source map for debugging */\nexport interface SourceMap {\n version: 3\n file: string\n sources: string[]\n mappings: string\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/** Base class for transpiler errors with source location */\nexport class TranspileError extends Error {\n line: number\n column: number\n source?: string\n filename?: string\n\n constructor(\n message: string,\n location: { line: number; column: number },\n source?: string,\n filename?: string\n ) {\n const loc = `${filename || '<source>'}:${location.line}:${location.column}`\n super(`${message} at ${loc}`)\n this.name = 'TranspileError'\n this.line = location.line\n this.column = location.column\n this.source = source\n this.filename = filename\n }\n}\n\n/** Syntax error during parsing */\nexport class SyntaxError extends TranspileError {\n constructor(\n message: string,\n location: { line: number; column: number },\n source?: string,\n filename?: string\n ) {\n super(message, location, source, filename)\n this.name = 'SyntaxError'\n }\n\n /**\n * Format the error with source context for better debugging\n * Shows the problematic line with a caret pointing to the error location\n */\n formatWithContext(contextLines = 2): string {\n if (!this.source) return this.message\n\n const lines = this.source.split('\\n')\n const errorLine = this.line - 1 // 0-indexed\n const startLine = Math.max(0, errorLine - contextLines)\n const endLine = Math.min(lines.length - 1, errorLine + contextLines)\n\n const output: string[] = []\n const lineNumWidth = String(endLine + 1).length\n\n // Add context before\n for (let i = startLine; i <= endLine; i++) {\n const lineNum = String(i + 1).padStart(lineNumWidth)\n const marker = i === errorLine ? '>' : ' '\n output.push(`${marker} ${lineNum} | ${lines[i]}`)\n\n // Add caret pointing to error column\n if (i === errorLine) {\n const caretPadding = ' '.repeat(lineNumWidth + 4 + this.column)\n output.push(`${caretPadding}^ ${this.message.split(' at ')[0]}`)\n }\n }\n\n return output.join('\\n')\n }\n}\n\n/** Type error during transpilation or runtime */\nexport class TypeError extends TranspileError {\n expected?: string\n received?: string\n suggestion?: string\n\n constructor(\n message: string,\n location: { line: number; column: number },\n options?: {\n expected?: string\n received?: string\n suggestion?: string\n source?: string\n filename?: string\n }\n ) {\n super(message, location, options?.source, options?.filename)\n this.name = 'TypeError'\n this.expected = options?.expected\n this.received = options?.received\n this.suggestion = options?.suggestion\n }\n}\n\n// ============================================================================\n// Transform Context\n// ============================================================================\n\n/** Context passed through the transformer */\nexport interface TransformContext {\n /** Current scope depth */\n depth: number\n /** Variables declared in current scope with their types */\n locals: Map<string, TypeDescriptor>\n /** Parent scope's context (for scope chain) */\n parent?: TransformContext\n /** Function parameters */\n parameters: Map<string, ParameterDescriptor>\n /** Registered atom names */\n atoms: Set<string>\n /** Accumulated warnings */\n warnings: TranspileWarning[]\n /** Source code for error messages */\n source: string\n /** Filename */\n filename: string\n /** Options */\n options: TranspileOptions\n}\n\n/** Create a child context for nested scopes */\nexport function createChildContext(parent: TransformContext): TransformContext {\n return {\n depth: parent.depth + 1,\n locals: new Map(),\n parent,\n parameters: parent.parameters,\n atoms: parent.atoms,\n warnings: parent.warnings,\n source: parent.source,\n filename: parent.filename,\n options: parent.options,\n }\n}\n\n/** Look up a variable in the scope chain */\nexport function lookupVariable(\n name: string,\n ctx: TransformContext\n): TypeDescriptor | undefined {\n // Check locals first\n if (ctx.locals.has(name)) {\n return ctx.locals.get(name)\n }\n // Check parameters\n if (ctx.parameters.has(name)) {\n return ctx.parameters.get(name)?.type\n }\n // Check parent scope\n if (ctx.parent) {\n return lookupVariable(name, ctx.parent)\n }\n return undefined\n}\n\n// ============================================================================\n// AST Node Helpers\n// ============================================================================\n\n/** Extract location from an Acorn node */\nexport function getLocation(node: Node): { line: number; column: number } {\n if (node.loc) {\n return { line: node.loc.start.line, column: node.loc.start.column }\n }\n return { line: 1, column: 0 }\n}\n",
|
|
7
|
+
"/**\n * Type inference from value patterns\n *\n * Extracts types from example values:\n * 'string' -> { kind: 'string' }\n * 10 -> { kind: 'number' }\n * ['string'] -> { kind: 'array', items: { kind: 'string' } }\n * { name: 'string' } -> { kind: 'object', shape: { name: { kind: 'string' } } }\n * 'string' || null -> { kind: 'string', nullable: true }\n * 'string' || 0 -> { kind: 'union', members: [{ kind: 'string' }, { kind: 'number' }] }\n */\n\nimport { parseExpressionAt } from 'acorn'\nimport type { Expression, Pattern } from 'acorn'\nimport type { TypeDescriptor, ParameterDescriptor } from './types'\nimport { getLocation, TranspileError } from './types'\n\n/**\n * Infer type from a value expression (example value)\n */\nexport function inferTypeFromValue(node: Expression): TypeDescriptor {\n switch (node.type) {\n case 'Literal': {\n const value = (node as any).value\n if (value === null) {\n return { kind: 'null' }\n }\n if (typeof value === 'string') {\n return { kind: 'string' }\n }\n if (typeof value === 'number') {\n return { kind: 'number' }\n }\n if (typeof value === 'boolean') {\n return { kind: 'boolean' }\n }\n return { kind: 'any' }\n }\n\n case 'ArrayExpression': {\n const elements = (node as any).elements as Expression[]\n if (elements.length === 0) {\n return { kind: 'array', items: { kind: 'any' } }\n }\n // Use first element as the item type\n const itemType = inferTypeFromValue(elements[0])\n return { kind: 'array', items: itemType }\n }\n\n case 'ObjectExpression': {\n const properties = (node as any).properties as any[]\n const shape: Record<string, TypeDescriptor> = {}\n\n for (const prop of properties) {\n if (prop.type === 'Property' && prop.key.type === 'Identifier') {\n const key = prop.key.name\n shape[key] = inferTypeFromValue(prop.value)\n }\n }\n\n return { kind: 'object', shape }\n }\n\n case 'LogicalExpression': {\n const { operator, left, right } = node as any\n\n if (operator === '||') {\n const leftType = inferTypeFromValue(left)\n const rightType = inferTypeFromValue(right)\n\n // type || null means nullable type\n if (rightType.kind === 'null') {\n return { ...leftType, nullable: true }\n }\n\n // null || type means nullable type (reverse)\n if (leftType.kind === 'null') {\n return { ...rightType, nullable: true }\n }\n\n // type1 || type2 means union\n return {\n kind: 'union',\n members: [leftType, rightType],\n }\n }\n\n if (operator === '&&') {\n // null && type means required type (null is just a marker)\n const rightType = inferTypeFromValue(right)\n return rightType\n }\n\n if (operator === '??') {\n // Nullish coalescing: left ?? right - type is the right side (fallback)\n const rightType = inferTypeFromValue(right)\n return rightType\n }\n\n return { kind: 'any' }\n }\n\n case 'Identifier': {\n // Handle undefined as a type\n if ((node as any).name === 'undefined') {\n return { kind: 'undefined' }\n }\n // Other identifiers in type position aren't valid example types\n return { kind: 'any' }\n }\n\n case 'UnaryExpression': {\n // Handle negative numbers: -1\n if (\n (node as any).operator === '-' &&\n (node as any).argument.type === 'Literal'\n ) {\n const value = (node as any).argument.value\n if (typeof value === 'number') {\n return { kind: 'number' }\n }\n }\n return { kind: 'any' }\n }\n\n default:\n return { kind: 'any' }\n }\n}\n\n/**\n * Parse a parameter and extract its type and default value\n *\n * @param param - The AST node for the parameter\n * @param requiredParams - Optional set of parameter names that are required (from colon syntax)\n */\nexport function parseParameter(\n param: Pattern,\n requiredParams?: Set<string>\n): ParameterDescriptor {\n // Simple identifier: function foo(x) - required, any type\n if (param.type === 'Identifier') {\n return {\n name: (param as any).name,\n type: { kind: 'any' },\n required: true,\n }\n }\n\n // Assignment pattern: function foo(x = value)\n if (param.type === 'AssignmentPattern') {\n const { left, right } = param as any\n\n if (left.type !== 'Identifier') {\n throw new TranspileError(\n 'Only simple parameter names are supported',\n getLocation(param)\n )\n }\n\n const name = left.name\n\n // Check if this parameter was marked as required via colon syntax\n const isRequired = requiredParams?.has(name) ?? false\n\n // Infer type from the example value\n const type = inferTypeFromValue(right)\n const exampleValue = extractLiteralValue(right)\n\n return {\n name,\n type,\n required: isRequired,\n default: isRequired ? null : exampleValue,\n example: exampleValue,\n loc: { start: param.start, end: param.end },\n }\n }\n\n // Destructuring pattern: function foo({ a, b })\n if (param.type === 'ObjectPattern') {\n // For destructuring, we create a synthetic \"args\" parameter\n // The individual properties become fields with their own defaults\n const properties = (param as any).properties as any[]\n const shape: Record<string, TypeDescriptor> = {}\n // Store full parameter descriptors for destructured properties\n const destructuredParams: Record<string, ParameterDescriptor> = {}\n\n for (const prop of properties) {\n if (prop.type === 'Property') {\n const key =\n prop.key.type === 'Identifier'\n ? prop.key.name\n : String(prop.key.value)\n\n if (prop.value.type === 'Identifier') {\n // { name } - required, any type\n shape[key] = { kind: 'any' }\n destructuredParams[key] = {\n name: key,\n type: { kind: 'any' },\n required: true,\n }\n } else if (prop.value.type === 'AssignmentPattern') {\n // { name = default } - check requiredParams to see if this was originally colon syntax\n const innerParam = parseParameter(prop.value, requiredParams)\n const isRequired = requiredParams?.has(key) ?? false\n shape[key] = innerParam.type\n destructuredParams[key] = {\n name: key,\n type: innerParam.type,\n required: isRequired,\n default: isRequired ? null : innerParam.example,\n example: innerParam.example,\n }\n }\n }\n }\n\n return {\n name: '__destructured__',\n type: { kind: 'object', shape, destructuredParams },\n required: true,\n }\n }\n\n throw new TranspileError(\n `Unsupported parameter pattern: ${param.type}`,\n getLocation(param)\n )\n}\n\n/**\n * Extract a literal value from an expression for default values\n */\nexport function extractLiteralValue(node: Expression): any {\n switch (node.type) {\n case 'Literal':\n return (node as any).value\n\n case 'ArrayExpression':\n return (node as any).elements.map((el: Expression) =>\n el ? extractLiteralValue(el) : null\n )\n\n case 'ObjectExpression': {\n const result: Record<string, any> = {}\n for (const prop of (node as any).properties) {\n if (prop.type === 'Property' && prop.key.type === 'Identifier') {\n result[prop.key.name] = extractLiteralValue(prop.value)\n }\n }\n return result\n }\n\n case 'UnaryExpression':\n if ((node as any).operator === '-') {\n const arg = extractLiteralValue((node as any).argument)\n return typeof arg === 'number' ? -arg : undefined\n }\n return undefined\n\n case 'LogicalExpression': {\n const { operator, left, right } = node as any\n if (operator === '&&') {\n // null && type evaluates to null (falsy short-circuit)\n if (left.type === 'Literal' && left.value === null) {\n return null\n }\n }\n if (operator === '||') {\n // value || fallback - return left if truthy\n const leftVal = extractLiteralValue(left)\n return leftVal ?? extractLiteralValue(right)\n }\n if (operator === '??') {\n // value ?? fallback - return left if not null/undefined\n const leftVal = extractLiteralValue(left)\n return leftVal ?? extractLiteralValue(right)\n }\n return undefined\n }\n\n default:\n return undefined\n }\n}\n\n/**\n * Parse return type from a type annotation expression\n */\nexport function parseReturnType(typeExpr: string): TypeDescriptor {\n // Simple approach: parse as expression and infer type\n try {\n const ast = parseExpressionAt(typeExpr, 0, {\n ecmaVersion: 2022,\n })\n return inferTypeFromValue(ast)\n } catch {\n return { kind: 'any' }\n }\n}\n\n/**\n * Convert TypeDescriptor to a human-readable string\n */\nexport function typeToString(type: TypeDescriptor): string {\n switch (type.kind) {\n case 'string':\n return type.nullable ? 'string | null' : 'string'\n case 'number':\n return type.nullable ? 'number | null' : 'number'\n case 'boolean':\n return type.nullable ? 'boolean | null' : 'boolean'\n case 'null':\n return 'null'\n case 'any':\n return 'any'\n case 'array': {\n const items = type.items ? typeToString(type.items) : 'any'\n return type.nullable ? `${items}[] | null` : `${items}[]`\n }\n case 'object': {\n if (!type.shape || Object.keys(type.shape).length === 0) {\n return type.nullable ? 'object | null' : 'object'\n }\n const props = Object.entries(type.shape)\n .map(([k, v]) => `${k}: ${typeToString(v)}`)\n .join(', ')\n return type.nullable ? `{ ${props} } | null` : `{ ${props} }`\n }\n case 'union':\n return type.members?.map(typeToString).join(' | ') || 'any'\n default:\n return 'any'\n }\n}\n\n/**\n * Check if a value matches a type descriptor\n */\nexport function checkType(value: any, type: TypeDescriptor): boolean {\n // Handle null\n if (value === null || value === undefined) {\n return type.nullable || type.kind === 'null' || type.kind === 'any'\n }\n\n switch (type.kind) {\n case 'any':\n return true\n case 'null':\n return value === null\n case 'string':\n return typeof value === 'string'\n case 'number':\n return typeof value === 'number'\n case 'boolean':\n return typeof value === 'boolean'\n case 'array':\n if (!Array.isArray(value)) return false\n if (!type.items) return true\n return value.every((item) => checkType(item, type.items!))\n case 'object':\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false\n }\n if (!type.shape) return true\n // Check that all required shape properties exist and match\n for (const [key, propType] of Object.entries(type.shape)) {\n if (!checkType(value[key], propType)) {\n return false\n }\n }\n return true\n case 'union':\n if (!type.members) return true\n return type.members.some((member) => checkType(value, member))\n default:\n return true\n }\n}\n",
|
|
8
|
+
"/**\n * ESTree to Agent99 AST Transformer\n *\n * Converts parsed JavaScript into Agent99's JSON AST format.\n */\n\nimport type {\n Statement,\n Expression,\n FunctionDeclaration,\n BlockStatement,\n VariableDeclaration,\n ExpressionStatement,\n IfStatement,\n WhileStatement,\n ForOfStatement,\n TryStatement,\n ReturnStatement,\n CallExpression,\n AssignmentExpression,\n BinaryExpression,\n LogicalExpression,\n MemberExpression,\n Identifier,\n Literal,\n TemplateLiteral,\n ArrayExpression,\n ObjectExpression,\n} from 'acorn'\nimport type { BaseNode } from '../../builder'\nimport type { ExprNode } from '../../runtime'\nimport type {\n TransformContext,\n TranspileOptions,\n FunctionSignature,\n ParameterDescriptor,\n TypeDescriptor,\n TranspileWarning,\n} from '../types'\nimport { TranspileError, getLocation, createChildContext } from '../types'\nimport {\n parseParameter,\n inferTypeFromValue,\n parseReturnType,\n} from '../inference'\nimport { extractTDoc } from '../parser'\n\n/**\n * Convert TypeDescriptor to JSON Schema\n */\nfunction typeToJsonSchema(type: TypeDescriptor): any {\n switch (type.kind) {\n case 'string':\n return { type: 'string' }\n case 'number':\n return { type: 'number' }\n case 'boolean':\n return { type: 'boolean' }\n case 'null':\n // null as a default value means \"any type, defaults to null\"\n // In JSON Schema, empty object means any type is allowed\n return {}\n case 'undefined':\n return {} // JSON Schema doesn't have undefined, treat as any\n case 'any':\n return {} // No constraints\n case 'array':\n return {\n type: 'array',\n items: type.items ? typeToJsonSchema(type.items) : {},\n }\n case 'object':\n if (type.shape) {\n const properties: Record<string, any> = {}\n for (const [key, propType] of Object.entries(type.shape)) {\n properties[key] = typeToJsonSchema(propType)\n }\n return {\n type: 'object',\n properties,\n additionalProperties: false,\n }\n }\n return { type: 'object' }\n case 'union':\n if (type.members) {\n return { oneOf: type.members.map(typeToJsonSchema) }\n }\n return {}\n default:\n return {}\n }\n}\n\n/**\n * Convert function parameters to JSON Schema for input validation\n */\nfunction parametersToJsonSchema(\n parameters: Record<string, ParameterDescriptor>\n): any {\n const properties: Record<string, any> = {}\n const required: string[] = []\n\n for (const [name, param] of Object.entries(parameters)) {\n properties[name] = typeToJsonSchema(param.type)\n if (param.required) {\n required.push(name)\n }\n }\n\n return {\n type: 'object',\n properties,\n required: required.length > 0 ? required : undefined,\n additionalProperties: false,\n }\n}\n\n/**\n * Transform a function declaration into Agent99 AST\n */\nexport function transformFunction(\n func: FunctionDeclaration,\n source: string,\n returnTypeAnnotation: string | undefined,\n options: TranspileOptions = {},\n requiredParamsFromPreprocess?: Set<string>\n): {\n ast: BaseNode\n signature: FunctionSignature\n warnings: TranspileWarning[]\n} {\n // Extract TDoc (/*# ... */) comments\n const tdoc = extractTDoc(source, func)\n\n // Parse parameters\n const parameters = new Map<string, ParameterDescriptor>()\n\n for (const param of func.params) {\n const parsed = parseParameter(param, requiredParamsFromPreprocess)\n\n // Handle destructured parameters - expand into individual params\n if (\n parsed.name === '__destructured__' &&\n parsed.type.kind === 'object' &&\n parsed.type.destructuredParams\n ) {\n for (const [key, paramDesc] of Object.entries(\n parsed.type.destructuredParams\n )) {\n parameters.set(key, {\n ...(paramDesc as any),\n description: tdoc.params[key],\n })\n }\n } else {\n parsed.description = tdoc.params[parsed.name]\n parameters.set(parsed.name, parsed)\n }\n }\n\n // Parse return type\n let returnType: TypeDescriptor | undefined\n if (returnTypeAnnotation) {\n returnType = parseReturnType(returnTypeAnnotation)\n }\n\n // Create transform context\n const ctx: TransformContext = {\n depth: 0,\n locals: new Map(),\n parameters,\n atoms: new Set(Object.keys(options.atoms || {})),\n warnings: [],\n source,\n filename: options.filename || '<source>',\n options,\n }\n\n // Transform function body\n const bodySteps = transformBlock(func.body, ctx)\n\n // Handle parameters: varsImport for required, varSet with defaults for optional\n const steps: BaseNode[] = []\n const requiredParams: string[] = []\n const optionalParams: Array<{ name: string; defaultValue: any }> = []\n\n for (const [name, param] of parameters.entries()) {\n if (param.required) {\n requiredParams.push(name)\n } else if (param.default !== undefined) {\n optionalParams.push({ name, defaultValue: param.default })\n } else {\n // Optional without explicit default - still import from args\n requiredParams.push(name)\n }\n }\n\n // Import required params directly from args\n if (requiredParams.length > 0) {\n steps.push({\n op: 'varsImport',\n keys: requiredParams,\n })\n }\n\n // For optional params with defaults: import from args, then check and set default if null\n for (const { name, defaultValue } of optionalParams) {\n // Import from args (will be undefined if not provided)\n steps.push({\n op: 'varsImport',\n keys: [name],\n })\n // If null/undefined, set the default\n steps.push({\n op: 'if',\n condition: {\n $expr: 'binary',\n op: '==',\n left: { $expr: 'ident', name },\n right: { $expr: 'literal', value: null },\n },\n then: [\n {\n op: 'varSet',\n key: name,\n value: defaultValue,\n },\n ],\n })\n }\n\n steps.push(...bodySteps)\n\n // Build signature\n const signatureParams = Object.fromEntries(parameters)\n const signature: FunctionSignature = {\n name: func.id?.name || 'anonymous',\n description: tdoc.description,\n parameters: signatureParams,\n returns: returnType,\n }\n\n // Generate input schema for runtime validation\n const inputSchema = parametersToJsonSchema(signatureParams)\n\n return {\n ast: { op: 'seq', steps, inputSchema },\n signature,\n warnings: ctx.warnings,\n }\n}\n\n/**\n * Transform a block statement into a list of steps\n */\nexport function transformBlock(\n block: BlockStatement,\n ctx: TransformContext\n): BaseNode[] {\n const steps: BaseNode[] = []\n\n for (const stmt of block.body) {\n const transformed = transformStatement(stmt, ctx)\n if (transformed) {\n if (Array.isArray(transformed)) {\n steps.push(...transformed)\n } else {\n steps.push(transformed)\n }\n }\n }\n\n return steps\n}\n\n/**\n * Transform a statement\n */\nexport function transformStatement(\n stmt: Statement,\n ctx: TransformContext\n): BaseNode | BaseNode[] | null {\n switch (stmt.type) {\n case 'VariableDeclaration':\n return transformVariableDeclaration(stmt as VariableDeclaration, ctx)\n\n case 'ExpressionStatement':\n return transformExpressionStatement(stmt as ExpressionStatement, ctx)\n\n case 'IfStatement':\n return transformIfStatement(stmt as IfStatement, ctx)\n\n case 'WhileStatement':\n return transformWhileStatement(stmt as WhileStatement, ctx)\n\n case 'ForOfStatement':\n return transformForOfStatement(stmt as ForOfStatement, ctx)\n\n case 'TryStatement':\n return transformTryStatement(stmt as TryStatement, ctx)\n\n case 'ReturnStatement':\n return transformReturnStatement(stmt as ReturnStatement, ctx)\n\n case 'ThrowStatement':\n throw new TranspileError(\n `'throw' is not supported in AsyncJS. Use Error('message') to trigger error flow`,\n getLocation(stmt),\n ctx.source,\n ctx.filename\n )\n\n case 'BlockStatement':\n // Nested block creates a scope\n return {\n op: 'scope',\n steps: transformBlock(stmt as BlockStatement, createChildContext(ctx)),\n }\n\n case 'EmptyStatement':\n return null\n\n default:\n throw new TranspileError(\n `Unsupported statement type: ${stmt.type}`,\n getLocation(stmt),\n ctx.source,\n ctx.filename\n )\n }\n}\n\n/**\n * Transform variable declaration: let x = value or const x = value\n */\nfunction transformVariableDeclaration(\n decl: VariableDeclaration,\n ctx: TransformContext\n): BaseNode[] {\n const steps: BaseNode[] = []\n const isConst = decl.kind === 'const'\n const opName = isConst ? 'constSet' : 'varSet'\n\n for (const declarator of decl.declarations) {\n if (declarator.id.type !== 'Identifier') {\n throw new TranspileError(\n 'Only simple variable names are supported',\n getLocation(declarator),\n ctx.source,\n ctx.filename\n )\n }\n\n const name = (declarator.id as Identifier).name\n\n if (declarator.init) {\n // Transform the initializer\n const { step, resultVar } = transformExpressionToStep(\n declarator.init,\n ctx,\n name,\n isConst\n )\n\n if (step) {\n steps.push(step)\n } else if (resultVar !== name) {\n // Simple value assignment\n steps.push({\n op: opName,\n key: name,\n value: resultVar,\n })\n }\n\n // Track variable type\n const type = inferTypeFromValue(declarator.init as Expression)\n ctx.locals.set(name, type)\n } else {\n // Uninitialized variable (only valid for let, not const)\n if (isConst) {\n throw new TranspileError(\n 'const declarations must be initialized',\n getLocation(declarator),\n ctx.source,\n ctx.filename\n )\n }\n steps.push({\n op: 'varSet',\n key: name,\n value: null,\n })\n ctx.locals.set(name, { kind: 'any', nullable: true })\n }\n }\n\n return steps\n}\n\n/**\n * Transform expression statement (e.g., function call)\n */\nfunction transformExpressionStatement(\n stmt: ExpressionStatement,\n ctx: TransformContext\n): BaseNode | null {\n const expr = stmt.expression\n\n // Assignment expression: x = value\n if (expr.type === 'AssignmentExpression') {\n return transformAssignment(expr as AssignmentExpression, ctx)\n }\n\n // Function call (side effect)\n if (expr.type === 'CallExpression') {\n const { step, resultVar } = transformExpressionToStep(expr, ctx)\n if (step) {\n return step\n }\n // If no step but we got an expression (e.g., method call on builtin),\n // we still need to evaluate it for side effects (like s.add(x))\n if (resultVar) {\n return {\n op: 'varSet',\n key: '_',\n value: resultVar,\n }\n }\n return null\n }\n\n // Other expressions (e.g., just a value) - no-op\n ctx.warnings.push({\n message: 'Expression statement has no effect',\n line: getLocation(stmt).line,\n column: getLocation(stmt).column,\n })\n\n return null\n}\n\n/**\n * Transform assignment: x = value\n */\nfunction transformAssignment(\n expr: AssignmentExpression,\n ctx: TransformContext\n): BaseNode {\n if (expr.left.type !== 'Identifier') {\n throw new TranspileError(\n 'Only simple variable assignment is supported',\n getLocation(expr),\n ctx.source,\n ctx.filename\n )\n }\n\n const name = (expr.left as Identifier).name\n const { step, resultVar } = transformExpressionToStep(expr.right, ctx, name)\n\n if (step) {\n return step\n }\n\n return {\n op: 'varSet',\n key: name,\n value: resultVar,\n }\n}\n\n/**\n * Transform if statement\n */\nfunction transformIfStatement(\n stmt: IfStatement,\n ctx: TransformContext\n): BaseNode {\n // Convert condition to ExprNode\n const condition = expressionToExprNode(stmt.test, ctx)\n\n // Transform then branch\n const thenSteps =\n stmt.consequent.type === 'BlockStatement'\n ? transformBlock(\n stmt.consequent as BlockStatement,\n createChildContext(ctx)\n )\n : ([transformStatement(stmt.consequent, ctx)].filter(\n Boolean\n ) as BaseNode[])\n\n // Transform else branch if present\n let elseSteps: BaseNode[] | undefined\n if (stmt.alternate) {\n elseSteps =\n stmt.alternate.type === 'BlockStatement'\n ? transformBlock(\n stmt.alternate as BlockStatement,\n createChildContext(ctx)\n )\n : ([transformStatement(stmt.alternate, ctx)].filter(\n Boolean\n ) as BaseNode[])\n }\n\n return {\n op: 'if',\n condition,\n then: thenSteps,\n ...(elseSteps && { else: elseSteps }),\n }\n}\n\n/**\n * Transform while statement\n */\nfunction transformWhileStatement(\n stmt: WhileStatement,\n ctx: TransformContext\n): BaseNode {\n const condition = expressionToExprNode(stmt.test, ctx)\n\n const body =\n stmt.body.type === 'BlockStatement'\n ? transformBlock(stmt.body as BlockStatement, createChildContext(ctx))\n : ([transformStatement(stmt.body, ctx)].filter(Boolean) as BaseNode[])\n\n return {\n op: 'while',\n condition,\n body,\n }\n}\n\n/**\n * Transform for...of statement into map atom\n */\nfunction transformForOfStatement(\n stmt: ForOfStatement,\n ctx: TransformContext\n): BaseNode {\n // Get the loop variable name\n let varName: string\n if (stmt.left.type === 'VariableDeclaration') {\n const decl = stmt.left.declarations[0]\n if (decl.id.type !== 'Identifier') {\n throw new TranspileError(\n 'Only simple variable names are supported in for...of',\n getLocation(stmt.left),\n ctx.source,\n ctx.filename\n )\n }\n varName = (decl.id as Identifier).name\n } else if (stmt.left.type === 'Identifier') {\n varName = (stmt.left as Identifier).name\n } else {\n throw new TranspileError(\n 'Unsupported for...of left-hand side',\n getLocation(stmt.left),\n ctx.source,\n ctx.filename\n )\n }\n\n // Get the iterable\n const items = expressionToValue(stmt.right, ctx)\n\n // Create child context with loop variable\n const childCtx = createChildContext(ctx)\n childCtx.locals.set(varName, { kind: 'any' })\n\n // Transform body\n const steps =\n stmt.body.type === 'BlockStatement'\n ? transformBlock(stmt.body as BlockStatement, childCtx)\n : ([transformStatement(stmt.body, childCtx)].filter(\n Boolean\n ) as BaseNode[])\n\n return {\n op: 'map',\n items,\n as: varName,\n steps,\n }\n}\n\n/**\n * Transform try/catch statement\n */\nfunction transformTryStatement(\n stmt: TryStatement,\n ctx: TransformContext\n): BaseNode {\n const trySteps = transformBlock(stmt.block, createChildContext(ctx))\n\n let catchSteps: BaseNode[] | undefined\n let catchParam: string | undefined\n if (stmt.handler) {\n const catchCtx = createChildContext(ctx)\n // Add error variable to scope if named\n if (stmt.handler.param?.type === 'Identifier') {\n catchParam = (stmt.handler.param as Identifier).name\n catchCtx.locals.set(catchParam, {\n kind: 'any',\n })\n }\n catchSteps = transformBlock(stmt.handler.body, catchCtx)\n }\n\n return {\n op: 'try',\n try: trySteps,\n ...(catchSteps && { catch: catchSteps }),\n ...(catchParam && { catchParam }),\n }\n}\n\n/**\n * Transform return statement\n */\nfunction transformReturnStatement(\n stmt: ReturnStatement,\n ctx: TransformContext\n): BaseNode | BaseNode[] {\n if (!stmt.argument) {\n return { op: 'return', value: {} }\n }\n\n // Check if the return expression requires a preceding step (e.g., atom call)\n const { step, resultVar } = transformExpressionToStep(\n stmt.argument,\n ctx,\n '__returnVal__'\n )\n\n // If there's a step (atom call), emit it first, then return the result variable\n if (step) {\n return [step, { op: 'return', value: resultVar }]\n }\n\n // Otherwise, convert expression directly to a value for return\n const value = expressionToValue(stmt.argument, ctx)\n return { op: 'return', value }\n}\n\n// Known builtins that should be evaluated as expressions, not atom calls\nconst BUILTIN_OBJECTS = new Set([\n 'Math',\n 'JSON',\n 'Array',\n 'Object',\n 'String',\n 'Number',\n 'console',\n 'Date', // Date factory with static methods like Date.now()\n 'Schema', // tosijs-schema fluent API for building JSON Schemas\n])\n\nconst BUILTIN_GLOBALS = new Set([\n 'parseInt',\n 'parseFloat',\n 'isNaN',\n 'isFinite',\n 'encodeURI',\n 'decodeURI',\n 'encodeURIComponent',\n 'decodeURIComponent',\n 'Set', // Factory function for set-like objects\n 'Date', // Factory function for date-like objects\n 'filter', // Schema-based object filtering\n])\n\nconst UNSUPPORTED_BUILTINS = new Set([\n 'RegExp',\n 'Promise',\n 'Map',\n 'WeakSet',\n 'WeakMap',\n 'Symbol',\n 'Proxy',\n 'Reflect',\n 'Function',\n 'eval',\n 'setTimeout',\n 'setInterval',\n 'fetch',\n 'require',\n 'import',\n 'process',\n 'window',\n 'document',\n 'global',\n 'globalThis',\n])\n\n// Instance methods that should be evaluated as expressions, not atom calls\n// These are methods on values (strings, arrays, etc.) that have native implementations\nconst INSTANCE_METHODS = new Set([\n // String methods\n 'toUpperCase',\n 'toLowerCase',\n 'trim',\n 'trimStart',\n 'trimEnd',\n 'charAt',\n 'charCodeAt',\n 'codePointAt',\n 'concat',\n 'includes',\n 'indexOf',\n 'lastIndexOf',\n 'startsWith',\n 'endsWith',\n 'slice',\n 'substring',\n 'substr',\n 'replace',\n 'replaceAll',\n 'match',\n 'search',\n 'padStart',\n 'padEnd',\n 'repeat',\n 'normalize',\n 'localeCompare',\n 'toString',\n 'valueOf',\n 'at',\n // Array methods (that don't need special atom handling)\n 'reverse',\n 'sort',\n 'fill',\n 'copyWithin',\n 'flat',\n 'flatMap',\n 'every',\n 'some',\n 'forEach',\n // Note: map, filter, find, reduce are handled specially as atoms for lambda support\n // Set methods (from Set() builtin)\n 'add',\n 'remove',\n 'has',\n 'clear',\n 'toArray',\n 'union',\n 'intersection',\n 'diff',\n // Date methods (from Date() builtin)\n 'format',\n 'isBefore',\n 'isAfter',\n // Note: Date.add and Date.diff are method calls that return new values\n])\n\n/**\n * Check if a CallExpression is a builtin call (Math.floor, JSON.parse, etc.)\n * or an instance method call (str.toUpperCase(), arr.includes(), etc.)\n */\nfunction isBuiltinCall(expr: CallExpression): boolean {\n // Check for global functions like parseInt()\n if (expr.callee.type === 'Identifier') {\n const name = (expr.callee as Identifier).name\n return BUILTIN_GLOBALS.has(name) || UNSUPPORTED_BUILTINS.has(name)\n }\n\n // Check for method calls\n if (expr.callee.type === 'MemberExpression') {\n const member = expr.callee as MemberExpression\n\n // Check for method calls on builtin objects like Math.floor()\n if (member.object.type === 'Identifier') {\n const objName = (member.object as Identifier).name\n if (BUILTIN_OBJECTS.has(objName) || UNSUPPORTED_BUILTINS.has(objName)) {\n return true\n }\n }\n\n // Check for instance method calls like str.toUpperCase()\n if (member.property.type === 'Identifier') {\n const methodName = (member.property as Identifier).name\n if (INSTANCE_METHODS.has(methodName)) {\n return true\n }\n }\n }\n\n return false\n}\n\n/**\n * Check if a MemberExpression is accessing a builtin object (Math.PI, Number.MAX_VALUE, etc.)\n */\nfunction isBuiltinMemberAccess(expr: MemberExpression): boolean {\n if (expr.object.type === 'Identifier') {\n const objName = (expr.object as Identifier).name\n return BUILTIN_OBJECTS.has(objName) || UNSUPPORTED_BUILTINS.has(objName)\n }\n return false\n}\n\n// Error messages for unsupported builtins\nconst UNSUPPORTED_BUILTIN_MESSAGES: Record<string, string> = {\n RegExp: 'RegExp is not available. Use string methods or the regexMatch atom.',\n Promise: 'Promise is not needed. All operations are implicitly async.',\n Map: 'Map is not available. Use plain objects instead.',\n WeakSet: 'WeakSet is not available.',\n WeakMap: 'WeakMap is not available.',\n Symbol: 'Symbol is not available.',\n Proxy: 'Proxy is not available.',\n Reflect: 'Reflect is not available.',\n Function: 'Function constructor is not available. Define functions normally.',\n eval: 'eval is not available. Code is compiled, not evaluated.',\n setTimeout: 'setTimeout is not available. Use the delay atom.',\n setInterval: 'setInterval is not available. Use while loops with delay.',\n fetch: 'fetch is not available. Use the httpFetch atom.',\n require: 'require is not available. Atoms must be registered with the VM.',\n import: 'import is not available. Atoms must be registered with the VM.',\n process: 'process is not available. AsyncJS runs in a sandboxed environment.',\n window: 'window is not available. AsyncJS runs in a sandboxed environment.',\n document:\n 'document is not available. AsyncJS runs in a sandboxed environment.',\n global: 'global is not available. AsyncJS runs in a sandboxed environment.',\n globalThis: 'globalThis is not available. Use builtins directly.',\n}\n\n/**\n * Check if expression uses an unsupported builtin and return error message if so\n */\nfunction getUnsupportedBuiltinError(expr: CallExpression): string | null {\n if (expr.callee.type === 'Identifier') {\n const name = (expr.callee as Identifier).name\n if (UNSUPPORTED_BUILTINS.has(name)) {\n return (\n UNSUPPORTED_BUILTIN_MESSAGES[name] ||\n `${name} is not available in AsyncJS.`\n )\n }\n }\n\n if (expr.callee.type === 'MemberExpression') {\n const member = expr.callee as MemberExpression\n if (member.object.type === 'Identifier') {\n const objName = (member.object as Identifier).name\n if (UNSUPPORTED_BUILTINS.has(objName)) {\n return (\n UNSUPPORTED_BUILTIN_MESSAGES[objName] ||\n `${objName} is not available in AsyncJS.`\n )\n }\n }\n }\n\n return null\n}\n\n/**\n * Get helpful suggestion for 'new' expression alternatives\n */\nfunction getNewExpressionSuggestion(constructorName: string): string {\n const suggestions: Record<string, string> = {\n Date: \" Use Date() or Date('2024-01-15') instead - no 'new' needed.\",\n Set: \" Use Set([items]) instead - no 'new' needed.\",\n Map: ' Use plain objects instead of Map.',\n Array: ' Use array literals like [1, 2, 3] instead.',\n Object: ' Use object literals like { key: value } instead.',\n Error: \" Return an error object like { error: 'message' } instead.\",\n RegExp: ' Use string methods or the regexMatch atom.',\n Promise: ' Not needed - all operations are implicitly async.',\n WeakSet: ' WeakSet is not available.',\n WeakMap: ' WeakMap is not available.',\n }\n return (\n suggestions[constructorName] ||\n ' Use factory functions or object literals instead.'\n )\n}\n\n/**\n * Transform an expression, potentially into a step with a result variable\n */\nfunction transformExpressionToStep(\n expr: Expression,\n ctx: TransformContext,\n resultVar?: string,\n isConst?: boolean\n): { step: BaseNode | null; resultVar: any } {\n const varOp = isConst ? 'constSet' : 'varSet'\n\n // Unwrap ChainExpression (optional chaining wrapper)\n if (expr.type === 'ChainExpression') {\n const chain = expr as any\n // The inner expression has optional: true on the relevant nodes\n // Just recurse with the unwrapped expression\n return transformExpressionToStep(\n chain.expression as Expression,\n ctx,\n resultVar,\n isConst\n )\n }\n\n // Check for 'new' keyword - not supported in AsyncJS\n if (expr.type === 'NewExpression') {\n const newExpr = expr as any\n let constructorName = 'constructor'\n if (newExpr.callee.type === 'Identifier') {\n constructorName = newExpr.callee.name\n }\n const suggestion = getNewExpressionSuggestion(constructorName)\n throw new TranspileError(\n `The 'new' keyword is not supported in AsyncJS.${suggestion}`,\n getLocation(expr),\n ctx.source,\n ctx.filename\n )\n }\n\n // Check for unsupported builtins first and give helpful error\n if (expr.type === 'CallExpression') {\n const unsupportedError = getUnsupportedBuiltinError(expr as CallExpression)\n if (unsupportedError) {\n throw new TranspileError(\n unsupportedError,\n getLocation(expr),\n ctx.source,\n ctx.filename\n )\n }\n }\n\n // Check if this is a builtin call (Math.floor, JSON.parse, parseInt, etc.)\n // Builtins are evaluated as expressions, not atom calls\n if (expr.type === 'CallExpression' && isBuiltinCall(expr as CallExpression)) {\n const exprNode = expressionToExprNode(expr, ctx)\n\n if (resultVar) {\n return {\n step: {\n op: varOp,\n key: resultVar,\n value: exprNode,\n },\n resultVar,\n }\n }\n\n return { step: null, resultVar: exprNode as any }\n }\n\n // Check if this is a builtin member access (Math.PI, Number.MAX_SAFE_INTEGER, etc.)\n if (\n expr.type === 'MemberExpression' &&\n isBuiltinMemberAccess(expr as MemberExpression)\n ) {\n const exprNode = expressionToExprNode(expr, ctx)\n\n if (resultVar) {\n return {\n step: {\n op: varOp,\n key: resultVar,\n value: exprNode,\n },\n resultVar,\n }\n }\n\n return { step: null, resultVar: exprNode as any }\n }\n\n // Function call -> atom invocation\n if (expr.type === 'CallExpression') {\n return transformCallExpression(\n expr as CallExpression,\n ctx,\n resultVar,\n isConst\n )\n }\n\n // Template literal -> template atom\n if (expr.type === 'TemplateLiteral') {\n return transformTemplateLiteral(\n expr as TemplateLiteral,\n ctx,\n resultVar,\n isConst\n )\n }\n\n // Binary/logical/unary expression - convert to ExprNode\n if (\n expr.type === 'BinaryExpression' ||\n expr.type === 'LogicalExpression' ||\n expr.type === 'UnaryExpression'\n ) {\n const exprNode = expressionToExprNode(expr, ctx)\n\n // If we need to store the result, emit a varSet/constSet with the expression node as value\n if (resultVar) {\n return {\n step: {\n op: varOp,\n key: resultVar,\n value: exprNode,\n },\n resultVar,\n }\n }\n\n // No storage needed, just return the expression node as the result\n return { step: null, resultVar: exprNode as any }\n }\n\n // Simple value - no step needed\n const value = expressionToValue(expr, ctx)\n return { step: null, resultVar: value }\n}\n\n/**\n * Transform a function call expression\n */\nfunction transformCallExpression(\n expr: CallExpression,\n ctx: TransformContext,\n resultVar?: string,\n isConst?: boolean\n): { step: BaseNode; resultVar: string | undefined } {\n // Get the function name\n let funcName: string\n let isMethodCall = false\n let receiver: any\n\n if (expr.callee.type === 'Identifier') {\n funcName = (expr.callee as Identifier).name\n } else if (expr.callee.type === 'MemberExpression') {\n const member = expr.callee as MemberExpression\n if (member.property.type === 'Identifier') {\n funcName = (member.property as Identifier).name\n isMethodCall = true\n receiver = expressionToValue(member.object as Expression, ctx)\n } else {\n throw new TranspileError(\n 'Computed method names are not supported',\n getLocation(expr),\n ctx.source,\n ctx.filename\n )\n }\n } else {\n throw new TranspileError(\n 'Only named function calls are supported',\n getLocation(expr),\n ctx.source,\n ctx.filename\n )\n }\n\n // Handle built-in method calls\n if (isMethodCall) {\n return transformMethodCall(\n funcName,\n receiver,\n expr.arguments as Expression[],\n ctx,\n resultVar,\n isConst\n )\n }\n\n // Handle console.log specially\n if (funcName === 'console' && expr.callee.type === 'MemberExpression') {\n // This would be caught above, but just in case\n }\n\n // Check if it's a known atom\n // For now, we assume any function call is an atom call\n // The VM will validate at runtime\n\n // Extract arguments\n const args = extractCallArguments(expr, ctx)\n\n return {\n step: {\n op: funcName,\n ...args,\n ...(resultVar && { result: resultVar }),\n ...(resultVar && isConst && { resultConst: true }),\n },\n resultVar,\n }\n}\n\n/**\n * Handle method calls like arr.map(), str.slice(), etc.\n */\nfunction transformMethodCall(\n method: string,\n receiver: any,\n args: Expression[],\n ctx: TransformContext,\n resultVar?: string,\n isConst?: boolean\n): { step: BaseNode; resultVar: string | undefined } {\n switch (method) {\n case 'map':\n // arr.map(x => ...) -> map atom\n if (\n args.length > 0 &&\n (args[0].type === 'ArrowFunctionExpression' ||\n args[0].type === 'FunctionExpression')\n ) {\n const callback = args[0] as any\n const param = callback.params[0]\n const paramName = param?.type === 'Identifier' ? param.name : 'item'\n\n const childCtx = createChildContext(ctx)\n childCtx.locals.set(paramName, { kind: 'any' })\n\n let steps: BaseNode[]\n if (callback.body.type === 'BlockStatement') {\n steps = transformBlock(callback.body, childCtx)\n } else {\n // Expression body: x => x * 2\n const { step, resultVar: exprResult } = transformExpressionToStep(\n callback.body,\n childCtx,\n 'result'\n )\n steps = step\n ? [step]\n : [{ op: 'varSet', key: 'result', value: exprResult }]\n }\n\n return {\n step: {\n op: 'map',\n items: receiver,\n as: paramName,\n steps,\n ...(resultVar && { result: resultVar }),\n ...(resultVar && isConst && { resultConst: true }),\n },\n resultVar,\n }\n }\n break\n\n case 'filter':\n // arr.filter(x => condition) -> filter atom\n if (\n args.length > 0 &&\n (args[0].type === 'ArrowFunctionExpression' ||\n args[0].type === 'FunctionExpression')\n ) {\n const callback = args[0] as any\n const param = callback.params[0]\n const paramName = param?.type === 'Identifier' ? param.name : 'item'\n\n const childCtx = createChildContext(ctx)\n childCtx.locals.set(paramName, { kind: 'any' })\n\n // For filter, the callback should return a boolean expression\n // Convert the body to an ExprNode\n let condition: any\n if (callback.body.type === 'BlockStatement') {\n // Block body - look for return statement\n throw new TranspileError(\n 'filter callback must be an expression, not a block',\n getLocation(args[0]),\n ctx.source,\n ctx.filename\n )\n } else {\n // Expression body: x => x > 5\n condition = expressionToExprNode(callback.body, childCtx)\n }\n\n return {\n step: {\n op: 'filter',\n items: receiver,\n as: paramName,\n condition,\n ...(resultVar && { result: resultVar }),\n ...(resultVar && isConst && { resultConst: true }),\n },\n resultVar,\n }\n }\n break\n\n case 'find':\n // arr.find(x => condition) -> find atom\n if (\n args.length > 0 &&\n (args[0].type === 'ArrowFunctionExpression' ||\n args[0].type === 'FunctionExpression')\n ) {\n const callback = args[0] as any\n const param = callback.params[0]\n const paramName = param?.type === 'Identifier' ? param.name : 'item'\n\n const childCtx = createChildContext(ctx)\n childCtx.locals.set(paramName, { kind: 'any' })\n\n let condition: any\n if (callback.body.type === 'BlockStatement') {\n throw new TranspileError(\n 'find callback must be an expression, not a block',\n getLocation(args[0]),\n ctx.source,\n ctx.filename\n )\n } else {\n condition = expressionToExprNode(callback.body, childCtx)\n }\n\n return {\n step: {\n op: 'find',\n items: receiver,\n as: paramName,\n condition,\n ...(resultVar && { result: resultVar }),\n ...(resultVar && isConst && { resultConst: true }),\n },\n resultVar,\n }\n }\n break\n\n case 'reduce':\n // arr.reduce((acc, x) => expr, initial) -> reduce atom\n if (\n args.length >= 2 &&\n (args[0].type === 'ArrowFunctionExpression' ||\n args[0].type === 'FunctionExpression')\n ) {\n const callback = args[0] as any\n const accParam = callback.params[0]\n const itemParam = callback.params[1]\n const accName = accParam?.type === 'Identifier' ? accParam.name : 'acc'\n const itemName =\n itemParam?.type === 'Identifier' ? itemParam.name : 'item'\n\n const childCtx = createChildContext(ctx)\n childCtx.locals.set(accName, { kind: 'any' })\n childCtx.locals.set(itemName, { kind: 'any' })\n\n let steps: BaseNode[]\n if (callback.body.type === 'BlockStatement') {\n steps = transformBlock(callback.body, childCtx)\n } else {\n // Expression body: (acc, x) => acc + x\n const { step, resultVar: exprResult } = transformExpressionToStep(\n callback.body,\n childCtx,\n 'result'\n )\n steps = step\n ? [step]\n : [{ op: 'varSet', key: 'result', value: exprResult }]\n }\n\n const initial = expressionToValue(args[1], ctx)\n\n return {\n step: {\n op: 'reduce',\n items: receiver,\n as: itemName,\n accumulator: accName,\n initial,\n steps,\n ...(resultVar && { result: resultVar }),\n ...(resultVar && isConst && { resultConst: true }),\n },\n resultVar,\n }\n }\n break\n\n case 'slice':\n // TODO: Could map to a slice atom\n break\n\n case 'push':\n return {\n step: {\n op: 'push',\n list: receiver,\n item: expressionToValue(args[0], ctx),\n ...(resultVar && { result: resultVar }),\n ...(resultVar && isConst && { resultConst: true }),\n },\n resultVar,\n }\n\n case 'join':\n return {\n step: {\n op: 'join',\n list: receiver,\n sep: args.length > 0 ? expressionToValue(args[0], ctx) : '',\n ...(resultVar && { result: resultVar }),\n ...(resultVar && isConst && { resultConst: true }),\n },\n resultVar,\n }\n\n case 'split':\n return {\n step: {\n op: 'split',\n str: receiver,\n sep: args.length > 0 ? expressionToValue(args[0], ctx) : '',\n ...(resultVar && { result: resultVar }),\n ...(resultVar && isConst && { resultConst: true }),\n },\n resultVar,\n }\n }\n\n // Unknown method - emit warning and try as generic call\n ctx.warnings.push({\n message: `Unknown method '${method}' - treating as atom call`,\n line: 0,\n column: 0,\n })\n\n return {\n step: {\n op: method,\n receiver,\n args: args.map((a) => expressionToValue(a, ctx)),\n ...(resultVar && { result: resultVar }),\n ...(resultVar && isConst && { resultConst: true }),\n },\n resultVar,\n }\n}\n\n/**\n * Transform template literal\n */\nfunction transformTemplateLiteral(\n expr: TemplateLiteral,\n ctx: TransformContext,\n resultVar?: string,\n isConst?: boolean\n): { step: BaseNode; resultVar: string | undefined } {\n // Build template string with {{var}} placeholders\n let tmpl = ''\n const vars: Record<string, any> = {}\n\n for (let i = 0; i < expr.quasis.length; i++) {\n tmpl += expr.quasis[i].value.cooked || expr.quasis[i].value.raw\n\n if (i < expr.expressions.length) {\n const exprNode = expr.expressions[i]\n const varName = `_${i}`\n vars[varName] = expressionToValue(exprNode as Expression, ctx)\n tmpl += `{{${varName}}}`\n }\n }\n\n return {\n step: {\n op: 'template',\n tmpl,\n vars,\n ...(resultVar && { result: resultVar }),\n ...(resultVar && isConst && { resultConst: true }),\n },\n resultVar,\n }\n}\n\n/**\n * Convert an Acorn expression to an ExprNode for direct VM evaluation.\n * This replaces the string-based condition system.\n */\nfunction expressionToExprNode(\n expr: Expression,\n ctx: TransformContext\n): ExprNode {\n switch (expr.type) {\n case 'Literal': {\n const lit = expr as Literal\n return { $expr: 'literal', value: lit.value }\n }\n\n case 'Identifier': {\n const id = expr as Identifier\n return { $expr: 'ident', name: id.name }\n }\n\n case 'MemberExpression': {\n const mem = expr as MemberExpression\n const obj = expressionToExprNode(mem.object as Expression, ctx)\n const isOptional = (mem as any).optional === true\n\n if (mem.computed) {\n // arr[0] or obj[key] - computed access\n // For now, only support literal indices\n const prop = mem.property as Expression\n if (prop.type === 'Literal') {\n return {\n $expr: 'member',\n object: obj,\n property: String((prop as Literal).value),\n computed: true,\n ...(isOptional && { optional: true }),\n }\n }\n // For computed with variable, we'd need more complex handling\n throw new TranspileError(\n 'Computed member access with variables not yet supported',\n getLocation(expr),\n ctx.source,\n ctx.filename\n )\n }\n\n const propName = (mem.property as Identifier).name\n return {\n $expr: 'member',\n object: obj,\n property: propName,\n ...(isOptional && { optional: true }),\n }\n }\n\n case 'ChainExpression': {\n // ChainExpression wraps optional chaining (?.)\n // Just unwrap to the inner expression which will have optional: true\n const chain = expr as any\n return expressionToExprNode(chain.expression as Expression, ctx)\n }\n\n case 'BinaryExpression': {\n const bin = expr as BinaryExpression\n return {\n $expr: 'binary',\n op: bin.operator,\n left: expressionToExprNode(bin.left as Expression, ctx),\n right: expressionToExprNode(bin.right as Expression, ctx),\n }\n }\n\n case 'LogicalExpression': {\n const log = expr as LogicalExpression\n return {\n $expr: 'logical',\n op: log.operator as '&&' | '||' | '??',\n left: expressionToExprNode(log.left as Expression, ctx),\n right: expressionToExprNode(log.right as Expression, ctx),\n }\n }\n\n case 'UnaryExpression': {\n const un = expr as any\n return {\n $expr: 'unary',\n op: un.operator,\n argument: expressionToExprNode(un.argument as Expression, ctx),\n }\n }\n\n case 'ConditionalExpression': {\n const cond = expr as any\n return {\n $expr: 'conditional',\n test: expressionToExprNode(cond.test as Expression, ctx),\n consequent: expressionToExprNode(cond.consequent as Expression, ctx),\n alternate: expressionToExprNode(cond.alternate as Expression, ctx),\n }\n }\n\n case 'ArrayExpression': {\n const arr = expr as ArrayExpression\n return {\n $expr: 'array',\n elements: arr.elements\n .filter((el): el is Expression => el !== null)\n .map((el) => expressionToExprNode(el, ctx)),\n }\n }\n\n case 'ObjectExpression': {\n const obj = expr as ObjectExpression\n const properties: { key: string; value: ExprNode }[] = []\n\n for (const prop of obj.properties) {\n if (prop.type === 'Property') {\n const key =\n prop.key.type === 'Identifier'\n ? (prop.key as Identifier).name\n : String((prop.key as Literal).value)\n properties.push({\n key,\n value: expressionToExprNode(prop.value as Expression, ctx),\n })\n }\n }\n\n return { $expr: 'object', properties }\n }\n\n case 'CallExpression': {\n const call = expr as CallExpression\n\n // Handle method calls (e.g., Math.floor(x), str.toUpperCase(), arr.push(x))\n if (call.callee.type === 'MemberExpression') {\n const member = call.callee as MemberExpression\n const method =\n member.property.type === 'Identifier'\n ? (member.property as Identifier).name\n : String((member.property as Literal).value)\n\n // Check for optional chaining: obj?.method() or obj.method?.()\n const isOptional =\n (member as any).optional === true || (call as any).optional === true\n\n return {\n $expr: 'methodCall',\n object: expressionToExprNode(member.object as Expression, ctx),\n method,\n arguments: call.arguments.map((arg) =>\n expressionToExprNode(arg as Expression, ctx)\n ),\n ...(isOptional && { optional: true }),\n }\n }\n\n // Handle global function calls (e.g., parseInt(x), parseFloat(x))\n if (call.callee.type === 'Identifier') {\n const funcName = (call.callee as Identifier).name\n return {\n $expr: 'call',\n callee: funcName,\n arguments: call.arguments.map((arg) =>\n expressionToExprNode(arg as Expression, ctx)\n ),\n }\n }\n\n // Other call types not supported in expressions\n throw new TranspileError(\n 'Complex function calls in expressions should be lifted to statements',\n getLocation(expr),\n ctx.source,\n ctx.filename\n )\n }\n\n case 'NewExpression': {\n const newExpr = expr as any\n let constructorName = 'constructor'\n if (newExpr.callee.type === 'Identifier') {\n constructorName = newExpr.callee.name\n }\n const suggestion = getNewExpressionSuggestion(constructorName)\n throw new TranspileError(\n `The 'new' keyword is not supported in AsyncJS.${suggestion}`,\n getLocation(expr),\n ctx.source,\n ctx.filename\n )\n }\n\n case 'TemplateLiteral':\n throw new TranspileError(\n 'Template literals inside expressions are not supported. ' +\n 'Assign to a variable first: const msg = `hello ${name}`; then use msg',\n getLocation(expr),\n ctx.source,\n ctx.filename\n )\n\n default:\n throw new TranspileError(\n `Unsupported expression type in condition: ${expr.type}`,\n getLocation(expr),\n ctx.source,\n ctx.filename\n )\n }\n}\n\n// Note: extractCondition, expressionToConditionString, and extractVariablesFromExpression\n// have been removed. Use expressionToExprNode instead - it converts Acorn AST directly\n// to ExprNode format, eliminating the need for JSEP string parsing at runtime.\n\n/**\n * Convert an expression to a runtime value (for varSet, etc.)\n */\nfunction expressionToValue(expr: Expression, ctx: TransformContext): any {\n switch (expr.type) {\n case 'Literal':\n return (expr as Literal).value\n\n case 'Identifier': {\n const name = (expr as Identifier).name\n // Parameters are imported into state via varsImport at function start,\n // so we reference them as state variables (just the name string)\n // No need for $kind: 'arg' since args are copied to state\n return name\n }\n\n case 'MemberExpression': {\n const mem = expr as MemberExpression\n const isOptional = (mem as any).optional === true\n\n // If optional chaining, we need an ExprNode for proper runtime handling\n if (isOptional) {\n return expressionToExprNode(expr, ctx)\n }\n\n const objValue = expressionToValue(mem.object as Expression, ctx)\n\n // If the object resolved to an ExprNode (e.g., from nested optional chaining),\n // we need to build an ExprNode for this access too\n if (objValue && typeof objValue === 'object' && objValue.$expr) {\n const prop = mem.computed\n ? String((mem.property as Literal).value)\n : (mem.property as Identifier).name\n return {\n $expr: 'member',\n object: objValue,\n property: prop,\n ...(mem.computed && { computed: true }),\n }\n }\n\n if (mem.computed) {\n // arr[0] - would need runtime evaluation\n return `${objValue}[${expressionToValue(\n mem.property as Expression,\n ctx\n )}]`\n }\n\n const prop = (mem.property as Identifier).name\n\n // If objValue is a string path, extend it\n if (typeof objValue === 'string') {\n return `${objValue}.${prop}`\n }\n\n // If objValue is an arg ref, extend the path\n if (objValue && objValue.$kind === 'arg') {\n return { $kind: 'arg', path: `${objValue.path}.${prop}` }\n }\n\n return `${objValue}.${prop}`\n }\n\n case 'ChainExpression': {\n // Unwrap ChainExpression and process the inner expression\n const chain = expr as any\n return expressionToValue(chain.expression as Expression, ctx)\n }\n\n case 'ArrayExpression':\n return (expr as ArrayExpression).elements.map((el) =>\n el ? expressionToValue(el as Expression, ctx) : null\n )\n\n case 'ObjectExpression': {\n const result: Record<string, any> = {}\n for (const prop of (expr as ObjectExpression).properties) {\n if (prop.type === 'Property') {\n const key =\n prop.key.type === 'Identifier'\n ? (prop.key as Identifier).name\n : String((prop.key as Literal).value)\n result[key] = expressionToValue(prop.value as Expression, ctx)\n }\n }\n return result\n }\n\n case 'TemplateLiteral':\n // Template literals need runtime evaluation - convert to ExprNode\n // This will throw a helpful error explaining the limitation\n return expressionToExprNode(expr, ctx)\n\n case 'CallExpression':\n // Method calls like s.toArray() used as values need to be ExprNodes\n return expressionToExprNode(expr, ctx)\n\n case 'BinaryExpression':\n case 'LogicalExpression':\n case 'UnaryExpression':\n case 'ConditionalExpression':\n // Complex expressions need to be ExprNodes for runtime evaluation\n return expressionToExprNode(expr, ctx)\n\n default:\n return null\n }\n}\n\n/**\n * Extract call arguments from a call expression\n */\nfunction extractCallArguments(\n expr: CallExpression,\n ctx: TransformContext\n): Record<string, any> {\n // If single object argument, spread it\n if (\n expr.arguments.length === 1 &&\n expr.arguments[0].type === 'ObjectExpression'\n ) {\n const obj = expr.arguments[0] as ObjectExpression\n const result: Record<string, any> = {}\n\n for (const prop of obj.properties) {\n if (prop.type === 'Property') {\n const key =\n prop.key.type === 'Identifier'\n ? (prop.key as Identifier).name\n : String((prop.key as Literal).value)\n result[key] = expressionToValue(prop.value as Expression, ctx)\n }\n }\n\n return result\n }\n\n // Otherwise, use positional args\n return {\n args: expr.arguments.map((arg) =>\n expressionToValue(arg as Expression, ctx)\n ),\n }\n}\n",
|
|
9
|
+
"/**\n * TJS Core - Essential transpiler functions without TypeScript dependency\n *\n * This module provides the core AJS transpilation functions.\n * Import from here (not ./index) to avoid pulling in the TS compiler.\n */\n\nimport type { SeqNode } from '../builder'\nimport type {\n TranspileOptions,\n TranspileResult,\n FunctionSignature,\n} from './types'\nimport { parse, validateSingleFunction } from './parser'\nimport { transformFunction } from './emitters/ast'\n\nexport * from './types'\nexport {\n parse,\n preprocess,\n extractTDoc,\n validateSingleFunction,\n} from './parser'\nexport { transformFunction } from './emitters/ast'\n\n/**\n * Transpile JavaScript source code to Agent99 AST\n */\nexport function transpile(\n source: string,\n options: TranspileOptions = {}\n): TranspileResult {\n const {\n ast: program,\n returnType,\n originalSource,\n requiredParams,\n } = parse(source, {\n filename: options.filename,\n colonShorthand: true,\n vmTarget: true,\n })\n\n const func = validateSingleFunction(program, options.filename)\n\n const { ast, signature, warnings } = transformFunction(\n func,\n originalSource,\n returnType,\n options,\n requiredParams\n )\n\n return {\n ast: ast as SeqNode,\n signature,\n warnings,\n }\n}\n\n/**\n * Transpile AsyncJS source and return just the AST\n */\nexport function ajs(strings: TemplateStringsArray, ...values: any[]): SeqNode\nexport function ajs(source: string): SeqNode\nexport function ajs(\n sourceOrStrings: string | TemplateStringsArray,\n ...values: any[]\n): SeqNode {\n if (typeof sourceOrStrings === 'string') {\n return transpile(sourceOrStrings).ast\n }\n const source = sourceOrStrings.reduce(\n (acc, str, i) =>\n acc + str + (values[i] !== undefined ? String(values[i]) : ''),\n ''\n )\n return transpile(source).ast\n}\n\n/**\n * Create a function with attached signature for introspection\n */\nexport function createAgent(\n source: string,\n vm: { run: (ast: any, args: any, options?: any) => Promise<any> },\n runOptions?: { fuel?: number; capabilities?: any }\n): ((args: Record<string, any>) => Promise<any>) & {\n signature: FunctionSignature\n ast: SeqNode\n} {\n const { ast, signature } = transpile(source)\n\n const agent = async (args: Record<string, any>) => {\n const result = await vm.run(ast, args, runOptions)\n return result.result\n }\n\n ;(agent as any).signature = signature\n ;(agent as any).ast = ast\n\n return agent as any\n}\n\n/**\n * Get tool definitions from a set of agent functions\n */\nexport function getToolDefinitions(\n agents: Record<string, { signature: FunctionSignature }>\n): Array<{\n type: 'function'\n function: {\n name: string\n description?: string\n parameters: {\n type: 'object'\n properties: Record<string, any>\n required: string[]\n }\n }\n}> {\n return Object.entries(agents).map(([name, agent]) => {\n const sig = agent.signature\n\n const properties: Record<string, any> = {}\n const required: string[] = []\n\n for (const [paramName, param] of Object.entries(sig.parameters)) {\n properties[paramName] = param.schema || { type: 'any' }\n if (param.description) {\n properties[paramName].description = param.description\n }\n if (param.required) {\n required.push(paramName)\n }\n }\n\n return {\n type: 'function' as const,\n function: {\n name,\n description: sig.description,\n parameters: {\n type: 'object' as const,\n properties,\n required,\n },\n },\n }\n })\n}\n",
|
|
10
|
+
"/**\n * TJS to JavaScript Emitter\n *\n * Transforms TJS source into standard JavaScript with runtime type metadata.\n * Unlike the AST emitter (for AgentJS), this outputs executable JS code.\n *\n * Input:\n * function greet(name: 'world') -> '' {\n * return `Hello, ${name}!`\n * }\n *\n * Output:\n * function greet(name = 'world') {\n * return `Hello, ${name}!`\n * }\n * greet.__tjs = {\n * params: { name: { type: 'string', required: true, example: 'world' } },\n * returns: { type: 'string' }\n * }\n */\n\nimport type { FunctionDeclaration, Program } from 'acorn'\nimport { parseExpressionAt } from 'acorn'\nimport { parse, extractTDoc, preprocess } from '../parser'\nimport type { TypeDescriptor, ParameterDescriptor } from '../types'\nimport { inferTypeFromValue, parseParameter } from '../inference'\nimport { extractTests } from '../tests'\n\nexport interface TJSTranspileOptions {\n /** Filename for error messages */\n filename?: string\n /** Include source map comment */\n sourceMap?: boolean\n /** Mode: 'dev' | 'strict' | 'production' */\n mode?: 'dev' | 'strict' | 'production'\n /**\n * Test execution mode:\n * - true (default): run tests at transpile time, throw on failure\n * - false: skip tests entirely (production build)\n * - 'only': only run tests, don't emit code (CI/test runner)\n * - 'report': run tests, report results in testResults, don't throw\n * (caller decides whether to use the code based on results)\n */\n runTests?: boolean | 'only' | 'report'\n /**\n * Debug mode: include source locations in __tjs metadata\n * Enables better error messages with file:line:column info\n */\n debug?: boolean\n /**\n * Pre-resolved import code for test execution.\n * Map of import specifier to compiled JavaScript code.\n * Used when tests depend on imported modules.\n */\n resolvedImports?: Record<string, string>\n}\n\n/** Result of running tests at transpile time */\nexport interface TestResult {\n /** Test description */\n description: string\n /** Whether the test passed */\n passed: boolean\n /** Error message if failed */\n error?: string\n /** Whether this was an implicit signature test */\n isSignatureTest?: boolean\n /** Source line number (1-indexed) where the test or error occurred */\n line?: number\n /** Source column number (1-indexed) */\n column?: number\n}\n\nexport interface TJSTranspileResult {\n /** The transpiled JavaScript code */\n code: string\n /** Type information for the function(s) - Record of function name to type info */\n types: Record<string, TJSTypeInfo>\n /** Function metadata (alias for types, used by runtime) */\n metadata: Record<string, TJSTypeInfo>\n /** Any warnings during transpilation */\n warnings?: string[]\n /** Generated test runner code (if tests were present) - DEPRECATED, tests now run at transpile time */\n testRunner?: string\n /** Number of tests extracted */\n testCount?: number\n /** Test results (when runTests is true or 'only') */\n testResults?: TestResult[]\n}\n\nexport interface TJSTypeInfo {\n /** Function name */\n name: string\n /** Parameter types */\n params: Record<string, ParameterDescriptor>\n /** Return type */\n returns?: TypeDescriptor\n /** TDoc description */\n description?: string\n /** True if function uses destructured object param (the fast path) */\n isDestructuredParam?: boolean\n /** The shape of the destructured param (for inline validation) */\n destructuredShape?: Record<string, TypeDescriptor>\n /** Which fields in destructuredShape are required */\n destructuredRequired?: Set<string>\n}\n\n/**\n * Extract type info for a single function declaration\n */\nfunction extractFunctionTypeInfo(\n func: FunctionDeclaration,\n originalSource: string,\n requiredParams: Set<string>,\n returnTypeStr: string | null\n): { types: TJSTypeInfo; warnings: string[] } {\n const warnings: string[] = []\n\n // Extract TDoc (/*# ... */) comments\n const tdoc = extractTDoc(originalSource, func)\n\n // Build parameter type info\n const params: Record<string, ParameterDescriptor> = {}\n let isDestructuredParam = false\n let destructuredShape: Record<string, TypeDescriptor> | undefined\n let destructuredRequired: Set<string> | undefined\n\n // Check if this is a single destructured object param (the fast path)\n if (\n func.params.length === 1 &&\n (func.params[0].type === 'ObjectPattern' ||\n (func.params[0].type === 'AssignmentPattern' &&\n func.params[0].left.type === 'ObjectPattern'))\n ) {\n isDestructuredParam = true\n const param = func.params[0]\n const objectPattern =\n param.type === 'ObjectPattern' ? param : (param as any).left\n\n const paramInfo = parseParameter(objectPattern, requiredParams)\n if (paramInfo.type.kind === 'object' && paramInfo.type.destructuredParams) {\n destructuredShape = {}\n destructuredRequired = new Set()\n\n // Build shape and track required fields\n for (const [key, descriptor] of Object.entries(\n paramInfo.type.destructuredParams\n )) {\n params[key] = {\n ...descriptor,\n description: tdoc.params[key],\n }\n destructuredShape[key] = descriptor.type\n if (descriptor.required) {\n destructuredRequired.add(key)\n }\n }\n }\n } else {\n // Traditional param handling (multiple params or non-destructured)\n for (const param of func.params) {\n if (param.type === 'Identifier') {\n const paramInfo = parseParameter(param, requiredParams)\n params[param.name] = {\n ...paramInfo,\n required: requiredParams.has(param.name),\n description: tdoc.params[param.name],\n }\n } else if (\n param.type === 'AssignmentPattern' &&\n param.left.type === 'Identifier'\n ) {\n const paramInfo = parseParameter(param, requiredParams)\n params[param.left.name] = {\n ...paramInfo,\n required: requiredParams.has(param.left.name),\n description: tdoc.params[param.left.name],\n }\n } else if (param.type === 'ObjectPattern') {\n // Handle destructured object parameters (non-single case)\n const paramInfo = parseParameter(param, requiredParams)\n if (\n paramInfo.type.kind === 'object' &&\n paramInfo.type.destructuredParams\n ) {\n for (const [key, descriptor] of Object.entries(\n paramInfo.type.destructuredParams\n )) {\n params[key] = {\n ...descriptor,\n description: tdoc.params[key],\n }\n }\n }\n }\n }\n }\n\n // Parse return type if present\n let returns: TypeDescriptor | undefined\n if (returnTypeStr) {\n try {\n const returnExpr = parseExpressionAt(returnTypeStr, 0, {\n ecmaVersion: 2022,\n })\n returns = inferTypeFromValue(returnExpr as any)\n } catch {\n // If we can't parse the return type, just store it as-is\n returns = { kind: 'any' }\n warnings.push(`Could not parse return type: ${returnTypeStr}`)\n }\n }\n\n // Build type info object\n const types: TJSTypeInfo = {\n name: func.id?.name || 'anonymous',\n params,\n returns,\n description: tdoc.description,\n isDestructuredParam,\n destructuredShape,\n destructuredRequired,\n }\n\n return { types, warnings }\n}\n\n/**\n * Generate inline validation code to be inserted at the start of a function body\n *\n * Implements proper monadic error handling:\n * 1. Check if any param is an Error - if so, pass it through (no work)\n * 2. Check types with fast inline typeof checks\n * 3. On type mismatch, call __tjs.typeError() (only on error path)\n *\n * @param funcName - Function name for error paths\n * @param types - Type information for the function\n * @param source - Source location (e.g., \"src/utils.ts:42\") for error reporting\n */\nfunction generateInlineValidationCode(\n funcName: string,\n types: TJSTypeInfo,\n source?: string\n): string | null {\n const lines: string[] = []\n // Include source in path if available: \"src/file.ts:42:funcName.param\"\n const pathPrefix = source ? `${source}:` : ''\n const stackEntry = source ? `${source}:${funcName}` : funcName\n\n // Push onto call stack for debug mode (only runs if debug enabled)\n lines.push(`__tjs.pushStack('${stackEntry}');`)\n\n // Destructured params: validate each field of the input object\n if (types.isDestructuredParam && types.destructuredShape) {\n const shape = types.destructuredShape\n const requiredFields = types.destructuredRequired || new Set()\n const fieldNames = Object.keys(shape)\n\n if (fieldNames.length === 0) return null\n\n // 1. Error pass-through: check if any field is an Error\n for (const fieldName of fieldNames) {\n lines.push(`if (${fieldName} instanceof Error) return ${fieldName};`)\n }\n\n // 2. Type checks with proper error emission\n for (const [fieldName, fieldType] of Object.entries(shape)) {\n const isRequired = requiredFields.has(fieldName)\n const path = `${pathPrefix}${funcName}.${fieldName}`\n const typeCheck = generateTypeCheckExpr(fieldName, fieldType)\n\n if (typeCheck) {\n const expectedType = fieldType.kind\n if (isRequired) {\n lines.push(\n `if (${typeCheck}) return __tjs.typeError('${path}', '${expectedType}', ${fieldName});`\n )\n } else {\n lines.push(\n `if (${fieldName} !== undefined && ${typeCheck}) return __tjs.typeError('${path}', '${expectedType}', ${fieldName});`\n )\n }\n }\n }\n\n return lines.length > 0 ? lines.join('\\n ') : null\n }\n\n // Positional params: validate each param\n const params = Object.entries(types.params)\n if (params.length === 0) return null\n\n // 1. Error pass-through: check if any param is an Error\n for (const [paramName] of params) {\n lines.push(`if (${paramName} instanceof Error) return ${paramName};`)\n }\n\n // 2. Type checks with proper error emission\n for (const [paramName, param] of params) {\n const path = `${pathPrefix}${funcName}.${paramName}`\n const typeCheck = generateTypeCheckExpr(paramName, param.type)\n\n if (typeCheck) {\n const expectedType = param.type.kind\n if (param.required) {\n lines.push(\n `if (${typeCheck}) return __tjs.typeError('${path}', '${expectedType}', ${paramName});`\n )\n } else {\n lines.push(\n `if (${paramName} !== undefined && ${typeCheck}) return __tjs.typeError('${path}', '${expectedType}', ${paramName});`\n )\n }\n }\n }\n\n return lines.length > 0 ? lines.join('\\n ') : null\n}\n\n/**\n * Extract the return type string for a specific function from source\n * Returns null if no return type found\n */\nfunction extractFunctionReturnType(\n source: string,\n funcName: string\n): string | null {\n // Match: function funcName(params) -> returnExample {\n // or: function funcName(params) -? returnExample {\n // or: function funcName(params) -! returnExample {\n const regex = new RegExp(\n `function\\\\s+${funcName}\\\\s*\\\\([^)]*\\\\)\\\\s*(-[>?!])\\\\s*`,\n 'g'\n )\n const match = regex.exec(source)\n if (!match) return null\n\n const afterMarker = source.slice(match.index + match[0].length)\n return extractReturnExampleFromSource(afterMarker)\n}\n\n/**\n * Extract return safety marker for a specific function from source\n * Returns 'safe' for -?, 'unsafe' for -!, undefined for -> or no marker\n */\nfunction extractFunctionReturnSafety(\n source: string,\n funcName: string\n): 'safe' | 'unsafe' | undefined {\n // Match: function funcName(params) -X where X is >, ?, or !\n const regex = new RegExp(\n `function\\\\s+${funcName}\\\\s*\\\\([^)]*\\\\)\\\\s*-([>?!])`,\n 'g'\n )\n const match = regex.exec(source)\n if (!match) return undefined\n\n const marker = match[1]\n if (marker === '?') return 'safe'\n if (marker === '!') return 'unsafe'\n return undefined // -> is the default, no special safety flag\n}\n\n/**\n * Extract source file annotation from TJS source\n * Looks for: /★ tjs <- path/to/file.ts ★/ at the start (★ = *)\n */\nfunction extractSourceFileAnnotation(source: string): string | undefined {\n const match = source.match(/^\\/\\*\\s*tjs\\s*<-\\s*([^*]+?)\\s*\\*\\//)\n return match ? match[1].trim() : undefined\n}\n\n/**\n * Extract line number annotation for a specific function\n * Looks for: /★ line N ★/ immediately before the function declaration\n */\nfunction extractLineAnnotation(\n source: string,\n funcName: string\n): number | undefined {\n // Match: /* line N */ followed by function declaration\n // Allow for async, whitespace variations\n const regex = new RegExp(\n `\\\\/\\\\*\\\\s*line\\\\s+(\\\\d+)\\\\s*\\\\*\\\\/\\\\s*(?:async\\\\s+)?function\\\\s+${funcName}\\\\s*\\\\(`,\n 'm'\n )\n const match = source.match(regex)\n return match ? parseInt(match[1], 10) : undefined\n}\n\n/**\n * Transpile TJS source to JavaScript\n *\n * This function handles:\n * - Files with no functions (just statements/tests)\n * - Files with multiple functions\n * - Inline validation (no wrappers)\n * - __tjs metadata inserted immediately after each function\n */\nexport function transpileToJS(\n source: string,\n options: TJSTranspileOptions = {}\n): TJSTranspileResult {\n const {\n filename = '<source>',\n runTests = true,\n debug = false,\n resolvedImports = {},\n } = options\n const warnings: string[] = []\n\n // Extract source file annotation if present (from TS transpilation)\n const sourceFileAnnotation = extractSourceFileAnnotation(source)\n const effectiveFilename = sourceFileAnnotation || filename\n\n // Extract test/mock blocks before parsing (they're not valid JS)\n const { code: cleanSource, tests, mocks, testRunner } = extractTests(source)\n\n // Parse the cleaned source (handles TJS syntax like x: 'type' and -> ReturnType)\n const {\n ast: program,\n originalSource,\n requiredParams,\n unsafeFunctions,\n } = parse(cleanSource, {\n filename,\n colonShorthand: true,\n })\n\n // Find ALL functions in the program\n const functions = findAllFunctions(program)\n\n // Preprocess source (handles TJS syntax transformations)\n const preprocessed = preprocess(cleanSource)\n\n // Build types map for all functions\n const allTypes: Record<string, TJSTypeInfo> = {}\n\n // Collect insertions: { position, text } to be applied in reverse order\n const insertions: { position: number; text: string }[] = []\n\n // Process each function\n for (const func of functions) {\n const funcName = func.id?.name || 'anonymous'\n\n // Extract return type for this specific function from original source\n const returnTypeStr = extractFunctionReturnType(cleanSource, funcName)\n\n // Extract type info for this function\n const { types, warnings: funcWarnings } = extractFunctionTypeInfo(\n func,\n originalSource,\n requiredParams,\n returnTypeStr\n )\n warnings.push(...funcWarnings)\n allTypes[funcName] = types\n\n // Determine safety options\n // Module-level \"safety none\" makes ALL functions unsafe (no validation)\n const isUnsafe =\n preprocessed.moduleSafety === 'none' || unsafeFunctions.has(funcName)\n const isSafe = preprocessed.safeFunctions.has(funcName)\n // Extract return safety per-function from original source\n const returnSafety = extractFunctionReturnSafety(cleanSource, funcName)\n\n // Get source location - prefer line annotation from TS transpilation\n const annotatedLine = extractLineAnnotation(source, funcName)\n const funcLoc = {\n file: effectiveFilename,\n line: annotatedLine ?? func.loc?.start.line ?? 0,\n column: func.loc?.start.column ?? 0,\n }\n\n const safetyOptions = {\n unsafe: isUnsafe,\n safe: isSafe,\n returnSafety,\n }\n\n // Generate __tjs metadata (to insert after function)\n const typeMetadata = generateTypeMetadata(funcName, types, safetyOptions, {\n debug,\n source: funcLoc,\n })\n\n // Queue insertion of __tjs after function closing brace\n insertions.push({\n position: func.end,\n text: `\\n${typeMetadata}`,\n })\n\n // Generate inline validation (to insert at start of function body)\n // Skip for unsafe functions\n if (!isUnsafe) {\n const sourceStr = `${funcLoc.file}:${funcLoc.line}`\n const validationCode = generateInlineValidationCode(\n funcName,\n types,\n sourceStr\n )\n if (validationCode && func.body && func.body.start !== undefined) {\n // Insert right after the opening brace\n insertions.push({\n position: func.body.start + 1,\n text: `\\n ${validationCode}\\n`,\n })\n }\n }\n }\n\n // Apply insertions in reverse position order (to maintain correct offsets)\n insertions.sort((a, b) => b.position - a.position)\n\n let code = preprocessed.source\n for (const { position, text } of insertions) {\n code = code.slice(0, position) + text + code.slice(position)\n }\n\n // Add __tjs reference for monadic error handling and structural equality\n // Use createRuntime() for isolated state per-module\n const needsTypeError = code.includes('__tjs.typeError(')\n const needsIs = code.includes('Is(')\n const needsIsNot = code.includes('IsNot(')\n\n if (needsTypeError || needsIs || needsIsNot) {\n // Create isolated runtime instance for this module\n // Falls back to shared global if createRuntime not available\n let preamble =\n 'const __tjs = globalThis.__tjs?.createRuntime?.() ?? globalThis.__tjs;\\n'\n\n // Add destructured imports for Is/IsNot if used\n if (needsIs || needsIsNot) {\n const imports = [needsIs && 'Is', needsIsNot && 'IsNot']\n .filter(Boolean)\n .join(', ')\n preamble += `const { ${imports} } = __tjs ?? {};\\n`\n }\n\n code = preamble + code\n }\n\n // Run tests at transpile time if enabled\n let testResults: TestResult[] | undefined\n\n if (runTests) {\n testResults = []\n\n // Run explicit test blocks\n if (tests.length > 0) {\n const blockResults = runTestBlocks(tests, mocks, code, resolvedImports)\n testResults.push(...blockResults)\n }\n\n // Run signature tests for ALL functions with -> return types\n // Extract from original source since parser only tracks the first one\n const sigTests = runAllSignatureTests(source, code, resolvedImports)\n testResults.push(...sigTests)\n\n // Check for failures and throw only if runTests === true (strict mode)\n // 'only' and 'report' modes return results without throwing\n const failures = testResults.filter((r) => !r.passed)\n if (failures.length > 0 && runTests === true) {\n const errorLines = failures.map((f) => {\n if (f.isSignatureTest) {\n return ` Function signature example is inconsistent:\\n ${f.error}`\n }\n return ` Test '${f.description}' failed:\\n ${f.error}`\n })\n throw new Error(`Transpile-time test failures:\\n${errorLines.join('\\n')}`)\n }\n }\n\n // If runTests === 'only', return minimal result\n if (runTests === 'only') {\n return {\n code: '',\n types: allTypes,\n metadata: allTypes,\n testResults,\n testCount: testResults?.length,\n }\n }\n\n return {\n code,\n types: allTypes,\n metadata: allTypes, // alias for runtime compatibility\n warnings: warnings.length > 0 ? warnings : undefined,\n testRunner: tests.length > 0 ? testRunner : undefined,\n testCount: tests.length > 0 ? tests.length : undefined,\n testResults,\n }\n}\n\n/**\n * Find ALL function declarations in the AST\n * Includes functions inside export declarations\n */\nfunction findAllFunctions(program: Program): FunctionDeclaration[] {\n const functions: FunctionDeclaration[] = []\n\n for (const node of program.body) {\n if (node.type === 'FunctionDeclaration') {\n functions.push(node)\n } else if (\n node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'FunctionDeclaration'\n ) {\n functions.push(node.declaration as FunctionDeclaration)\n } else if (\n node.type === 'ExportDefaultDeclaration' &&\n node.declaration?.type === 'FunctionDeclaration'\n ) {\n functions.push(node.declaration as FunctionDeclaration)\n }\n }\n\n return functions\n}\n\n/**\n * Serialize a TypeDescriptor to JSON-compatible object\n * Preserves full type structure (shape, items, members)\n */\nfunction serializeType(t: TypeDescriptor): any {\n const result: any = { kind: t.kind }\n if (t.nullable) result.nullable = true\n if (t.items) result.items = serializeType(t.items)\n if (t.shape) {\n result.shape = Object.fromEntries(\n Object.entries(t.shape).map(([k, v]) => [k, serializeType(v)])\n )\n }\n if (t.members) result.members = t.members.map(serializeType)\n return result\n}\n\n/**\n * Safety options for metadata generation\n */\ninterface SafetyOptions {\n /** Function marked with (!) - never validate inputs */\n unsafe?: boolean\n /** Function marked with (?) - always validate inputs */\n safe?: boolean\n /** Return type safety: 'safe' (-?) or 'unsafe' (-!) */\n returnSafety?: 'safe' | 'unsafe'\n}\n\n/**\n * Debug options for metadata generation\n */\ninterface DebugOptions {\n /** Include source locations in metadata */\n debug?: boolean\n /** Source location of the function */\n source?: {\n file: string\n line: number\n column: number\n }\n}\n\n/**\n * Generate type metadata code\n *\n * @param funcName - Function name\n * @param types - Type information\n * @param safety - Safety flags for the function\n * @param debugOpts - Debug options (source locations)\n */\nfunction generateTypeMetadata(\n funcName: string,\n types: TJSTypeInfo,\n safety: SafetyOptions = {},\n debugOpts: DebugOptions = {}\n): string {\n const paramsObj: Record<string, any> = {}\n\n for (const [name, param] of Object.entries(types.params)) {\n paramsObj[name] = {\n type: serializeType(param.type),\n required: param.required,\n }\n if (param.default !== undefined) {\n paramsObj[name].default = param.default\n }\n if (param.description) {\n paramsObj[name].description = param.description\n }\n }\n\n const metadata: any = {\n params: paramsObj,\n }\n\n if (types.returns) {\n metadata.returns = {\n type: serializeType(types.returns),\n }\n // Add return safety flags\n if (safety.returnSafety === 'safe') {\n metadata.safeReturn = true // -? forces output validation\n } else if (safety.returnSafety === 'unsafe') {\n metadata.unsafeReturn = true // -! skips output validation\n }\n }\n\n if (types.description) {\n metadata.description = types.description\n }\n\n // Mark unsafe functions - they skip runtime input validation\n if (safety.unsafe) {\n metadata.unsafe = true\n }\n\n // Mark safe functions - they force runtime input validation\n if (safety.safe) {\n metadata.safe = true\n }\n\n // Always include source location for error reporting\n if (debugOpts.source) {\n const { file, line } = debugOpts.source\n metadata.source = `${file}:${line}`\n }\n\n return `${funcName}.__tjs = ${JSON.stringify(metadata, null, 2)}`\n}\n\n/**\n * Check if this function can use inline validation (the fast path)\n *\n * Two patterns qualify:\n * 1. Single destructured object param: function foo({ x: 0, y: '' }) { ... }\n * 2. Single named object param: function foo(input: { x: 0, y: '' }) { ... }\n *\n * These can be validated with fast inline checks instead of schema interpretation.\n */\nfunction canUseInlineValidation(types: TJSTypeInfo): boolean {\n // Destructured params always qualify\n if (types.isDestructuredParam && types.destructuredShape) {\n return true\n }\n\n // Any function with params can use inline validation\n // (we generate typeof checks for primitives too)\n return Object.keys(types.params).length > 0\n}\n\n/**\n * Generate inline validation code for single-arg object types\n *\n * This is ~20x faster than schema-based validation because:\n * 1. No schema interpretation at runtime\n * 2. No object iteration\n * 3. JIT can inline the checks\n *\n * Generated code looks like:\n * if (typeof input !== 'object' || input === null ||\n * typeof input.x !== 'number' ||\n * typeof input.y !== 'number') {\n * return { $error: true, message: '...', path: 'funcName.input' }\n * }\n */\nexport function generateInlineValidation(\n funcName: string,\n paramName: string,\n shape: Record<string, TypeDescriptor>,\n requiredFields: Set<string>\n): string {\n const checks: string[] = []\n const path = `${funcName}.${paramName}`\n\n // Check it's an object\n checks.push(`typeof ${paramName} !== 'object'`)\n checks.push(`${paramName} === null`)\n\n // Check each field\n for (const [fieldName, fieldType] of Object.entries(shape)) {\n const fieldPath = `${paramName}.${fieldName}`\n const isRequired = requiredFields.has(fieldName)\n\n const typeCheck = generateTypeCheck(fieldPath, fieldType)\n if (typeCheck) {\n if (isRequired) {\n // Required: must exist and have correct type\n checks.push(typeCheck)\n } else {\n // Optional: only check type if defined\n checks.push(`(${fieldPath} !== undefined && ${typeCheck})`)\n }\n }\n }\n\n if (checks.length === 0) return ''\n\n return `if (${checks.join(' || ')}) {\n return { $error: true, message: 'Invalid ${paramName}', path: '${path}' }\n}`\n}\n\n/**\n * Generate a type check expression for a single field\n * Returns null if no check needed (e.g., 'any' type)\n */\n/**\n * Generate a type check expression for a single field\n * Returns an expression that evaluates to true when type is INVALID\n * Returns null if no check needed (e.g., 'any' type)\n */\nfunction generateTypeCheckExpr(\n fieldPath: string,\n type: TypeDescriptor\n): string | null {\n switch (type.kind) {\n case 'string':\n return `typeof ${fieldPath} !== 'string'`\n case 'number':\n return `typeof ${fieldPath} !== 'number'`\n case 'boolean':\n return `typeof ${fieldPath} !== 'boolean'`\n case 'null':\n return `${fieldPath} !== null`\n case 'undefined':\n return `${fieldPath} !== undefined`\n case 'array':\n return `!Array.isArray(${fieldPath})`\n case 'object':\n // For nested objects, just check it's an object (deep validation is separate)\n return `(typeof ${fieldPath} !== 'object' || ${fieldPath} === null || Array.isArray(${fieldPath}))`\n case 'any':\n return null // No check needed\n default:\n return null\n }\n}\n\n// Alias for backward compatibility with other functions that use this\nconst generateTypeCheck = generateTypeCheckExpr\n\n/**\n * Generate the complete function wrapper with inline validation\n *\n * For destructured object params, this generates:\n *\n * const _original_funcName = funcName\n * funcName = function(__input) {\n * if (typeof __input !== 'object' || __input === null || ...) {\n * return { $error: true, message: '...', path: '...' }\n * }\n * return _original_funcName.call(this, __input)\n * }\n *\n * For single named object params, same pattern with the actual param name.\n */\nexport function generateInlineWrapper(\n funcName: string,\n types: TJSTypeInfo,\n safety: SafetyOptions = {}\n): string | null {\n // Check if we can use inline validation\n if (!canUseInlineValidation(types)) return null\n\n // Unsafe functions don't need wrappers\n if (safety.unsafe) return null\n\n // Destructured params: use __input as the wrapper param name\n if (types.isDestructuredParam && types.destructuredShape) {\n const paramName = '__input'\n const shape = types.destructuredShape\n const requiredFields = types.destructuredRequired || new Set()\n\n const validation = generateInlineValidation(\n funcName,\n paramName,\n shape,\n requiredFields\n )\n if (!validation) return null\n\n return `\nconst _original_${funcName} = ${funcName}\n${funcName} = function(${paramName}) {\n ${validation}\n return _original_${funcName}.call(this, ${paramName})\n}\n`.trim()\n }\n\n // Positional params path (primitives or single object param)\n const params = Object.entries(types.params)\n\n // Check if it's a single object param with shape\n if (params.length === 1) {\n const [paramName, param] = params[0]\n if (param.type.kind === 'object' && param.type.shape) {\n // Single named object param\n const shape = param.type.shape\n const requiredFields = new Set<string>()\n for (const [fieldName] of Object.entries(shape)) {\n requiredFields.add(fieldName)\n }\n\n const validation = generateInlineValidation(\n funcName,\n paramName,\n shape,\n requiredFields\n )\n if (!validation) return null\n\n return `\nconst _original_${funcName} = ${funcName}\n${funcName} = function(${paramName}) {\n ${validation}\n return _original_${funcName}.call(this, ${paramName})\n}\n`.trim()\n }\n }\n\n // Generate validation for positional primitive params\n const validation = generatePositionalValidation(funcName, params)\n if (!validation) return null\n\n const paramNames = params.map(([name]) => name).join(', ')\n return `\nconst _original_${funcName} = ${funcName}\n${funcName} = function(${paramNames}) {\n ${validation}\n return _original_${funcName}.call(this, ${paramNames})\n}\n`.trim()\n}\n\n/**\n * Generate validation for positional (primitive) params\n */\nfunction generatePositionalValidation(\n funcName: string,\n params: [string, ParameterDescriptor][]\n): string | null {\n const checks: string[] = []\n\n for (const [paramName, param] of params) {\n const typeCheck = generateTypeCheck(paramName, param.type)\n if (typeCheck) {\n if (param.required) {\n // Required: must have correct type\n checks.push(typeCheck)\n } else {\n // Optional: only check if defined\n checks.push(`(${paramName} !== undefined && ${typeCheck})`)\n }\n }\n }\n\n if (checks.length === 0) return null\n\n return `if (${checks.join(' || ')}) {\n return { $error: true, message: 'Invalid arguments', path: '${funcName}' }\n }`\n}\n\n// =============================================================================\n// Transpile-time Test Execution\n// =============================================================================\n\n/**\n * Fuzzy comparison for floating point numbers\n */\nfunction fuzzyEqual(a: unknown, b: unknown, epsilon = 1e-9): boolean {\n if (a === b) return true\n if (typeof a === 'number' && typeof b === 'number') {\n // Check if either is non-integer (float)\n if (!Number.isInteger(a) || !Number.isInteger(b)) {\n const diff = Math.abs(a - b)\n const maxAbs = Math.max(Math.abs(a), Math.abs(b), 1)\n return diff / maxAbs < epsilon\n }\n }\n return false\n}\n\n/**\n * Deep equality check with fuzzy float comparison\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (fuzzyEqual(a, b)) return true\n if (a === null || b === null) return a === b\n if (a === undefined || b === undefined) return a === b\n if (typeof a !== typeof b) return false\n if (typeof a !== 'object') return false\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n return a.every((v, i) => deepEqual(v, b[i]))\n }\n\n if (Array.isArray(a) !== Array.isArray(b)) return false\n\n const keysA = Object.keys(a as object)\n const keysB = Object.keys(b as object)\n if (keysA.length !== keysB.length) return false\n return keysA.every((k) => deepEqual((a as any)[k], (b as any)[k]))\n}\n\n/**\n * Check if a value matches an expected type pattern (from example value)\n * Unlike deepEqual, this checks TYPE compatibility, not value equality.\n *\n * Example patterns:\n * 0 matches any number\n * \"\" matches any string\n * true matches any boolean\n * null matches null\n * [] matches any array\n * [0] matches array of numbers\n * {name: \"\", age: 0} matches object with string name and number age\n */\nfunction typeMatches(\n actual: unknown,\n pattern: unknown,\n path = ''\n): { matches: boolean; error?: string } {\n // null pattern matches null\n if (pattern === null) {\n if (actual === null) return { matches: true }\n return {\n matches: false,\n error: `Expected null at '${path}', got ${typeOf(actual)}`,\n }\n }\n\n // undefined pattern matches undefined\n if (pattern === undefined) {\n if (actual === undefined) return { matches: true }\n return {\n matches: false,\n error: `Expected undefined at '${path}', got ${typeOf(actual)}`,\n }\n }\n\n // Primitive types - check type, not value\n if (typeof pattern === 'number') {\n if (typeof actual === 'number') return { matches: true }\n return {\n matches: false,\n error: `Expected number at '${path}', got ${typeOf(actual)}`,\n }\n }\n\n if (typeof pattern === 'string') {\n if (typeof actual === 'string') return { matches: true }\n return {\n matches: false,\n error: `Expected string at '${path}', got ${typeOf(actual)}`,\n }\n }\n\n if (typeof pattern === 'boolean') {\n if (typeof actual === 'boolean') return { matches: true }\n return {\n matches: false,\n error: `Expected boolean at '${path}', got ${typeOf(actual)}`,\n }\n }\n\n // Arrays\n if (Array.isArray(pattern)) {\n if (!Array.isArray(actual)) {\n return {\n matches: false,\n error: `Expected array at '${path}', got ${typeOf(actual)}`,\n }\n }\n // Empty array pattern matches any array\n if (pattern.length === 0) return { matches: true }\n // Non-empty array pattern: check each element against first pattern element\n const elementPattern = pattern[0]\n for (let i = 0; i < actual.length; i++) {\n const result = typeMatches(actual[i], elementPattern, `${path}[${i}]`)\n if (!result.matches) return result\n }\n return { matches: true }\n }\n\n // Objects\n if (typeof pattern === 'object' && pattern !== null) {\n if (\n typeof actual !== 'object' ||\n actual === null ||\n Array.isArray(actual)\n ) {\n return {\n matches: false,\n error: `Expected object at '${path}', got ${typeOf(actual)}`,\n }\n }\n // Check all pattern keys exist and match types\n for (const key of Object.keys(pattern)) {\n const keyPath = path ? `${path}.${key}` : key\n if (!(key in actual)) {\n return { matches: false, error: `Missing property '${keyPath}'` }\n }\n const result = typeMatches(\n (actual as any)[key],\n (pattern as any)[key],\n keyPath\n )\n if (!result.matches) return result\n }\n return { matches: true }\n }\n\n // Fallback: exact equality\n if (actual === pattern) return { matches: true }\n return { matches: false, error: `Type mismatch at '${path}'` }\n}\n\n/**\n * Get a human-readable type description\n */\nfunction typeOf(v: unknown): string {\n if (v === null) return 'null'\n if (v === undefined) return 'undefined'\n if (Array.isArray(v)) return 'array'\n return typeof v\n}\n\n/**\n * Format a value for error messages - uses cleaner object notation\n * Multi-line for objects with 3+ properties\n */\nfunction formatValue(v: unknown, indent = 0): string {\n if (v === null) return 'null'\n if (v === undefined) return 'undefined'\n if (typeof v === 'string') return JSON.stringify(v)\n if (typeof v === 'number') return String(v)\n if (typeof v === 'boolean') return String(v)\n if (Array.isArray(v)) {\n if (v.length === 0) return '[]'\n if (v.length <= 3)\n return `[${v.map((x) => formatValue(x, indent)).join(', ')}]`\n return `[${v\n .slice(0, 3)\n .map((x) => formatValue(x, indent))\n .join(', ')}, ...]`\n }\n if (typeof v === 'object') {\n const entries = Object.entries(v)\n if (entries.length === 0) return '{}'\n\n const formatKey = (k: string) =>\n /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? k : JSON.stringify(k)\n\n // Single line for 1-2 properties\n if (entries.length <= 2) {\n const formatted = entries\n .map(([k, val]) => `${formatKey(k)}: ${formatValue(val, indent)}`)\n .join(', ')\n return `{${formatted}}`\n }\n\n // Multi-line for 3+ properties\n const pad = ' '.repeat(indent + 1)\n const closePad = ' '.repeat(indent)\n const formatted = entries\n .slice(0, 8)\n .map(\n ([k, val]) => `${pad}${formatKey(k)}: ${formatValue(val, indent + 1)}`\n )\n .join(',\\n')\n const suffix = entries.length > 8 ? `,\\n${pad}...` : ''\n return `{\\n${formatted}${suffix}\\n${closePad}}`\n }\n return String(v)\n}\n\nimport type { ExtractedTest, ExtractedMock } from '../tests'\n\n/**\n * Strip comments from source code\n * Used to avoid matching code patterns inside comments\n */\nfunction stripComments(code: string): string {\n // Replace block comments with equivalent whitespace (preserve line numbers)\n let result = code.replace(/\\/\\*[\\s\\S]*?\\*\\//g, (match) => {\n // Replace with same number of newlines to preserve line numbers\n const newlines = match.split('\\n').length - 1\n return '\\n'.repeat(newlines)\n })\n\n // Replace line comments\n result = result.replace(/\\/\\/[^\\n]*/g, '')\n\n return result\n}\n\n/**\n * Strip import/export syntax for test execution context\n * Tests run in new Function() which doesn't support ES modules\n *\n * Useful for:\n * - Running tests in new Function() context\n * - CLI test runners\n * - Bundler plugins that need to extract module code\n */\nexport function stripModuleSyntax(code: string): string {\n // Remove import statements (entire line)\n let result = code.replace(/^import\\s+.*?from\\s+['\"][^'\"]+['\"];?\\s*$/gm, '')\n result = result.replace(/^import\\s+['\"][^'\"]+['\"];?\\s*$/gm, '')\n\n // Remove 'export ' keyword but keep the declaration\n result = result.replace(/^export\\s+default\\s+/gm, '')\n result = result.replace(/^export\\s+/gm, '')\n\n return result\n}\n\n/**\n * Strip the __tjs runtime preamble from transpiled code\n * This is needed when injecting resolved imports into a test context\n * that already has its own __tjs stub\n *\n * Useful for:\n * - Combining multiple TJS modules into a single execution context\n * - Test runners that provide their own __tjs runtime\n * - Bundlers that need to deduplicate runtime setup\n */\nexport function stripTjsPreamble(code: string): string {\n // Remove the __tjs runtime setup lines:\n // const __tjs = globalThis.__tjs?.createRuntime?.() ?? globalThis.__tjs;\n // const { Is, IsNot } = __tjs ?? {};\n let result = code.replace(\n /^const __tjs = globalThis\\.__tjs\\?\\.createRuntime\\?\\.\\(\\) \\?\\? globalThis\\.__tjs;\\n?/m,\n ''\n )\n result = result.replace(\n /^const \\{ (?:Is|IsNot|Is, IsNot) \\} = __tjs \\?\\? \\{\\};\\n?/m,\n ''\n )\n return result\n}\n\n/**\n * Build code to inject resolved imports into test execution context\n *\n * Takes a map of module specifier -> compiled code and returns code that\n * makes those exports available in the test scope.\n *\n * For example, if resolvedImports contains:\n * { 'mymath': 'function add(a, b) { return a + b }\\nadd.__tjs = {...}' }\n *\n * This will return code that evaluates that module and makes `add` available.\n */\nfunction buildResolvedImportsCode(\n resolvedImports: Record<string, string>\n): string {\n if (Object.keys(resolvedImports).length === 0) {\n return ''\n }\n\n const lines: string[] = []\n\n for (const [specifier, moduleCode] of Object.entries(resolvedImports)) {\n // Strip module syntax from the imported code too (it may have exports)\n let cleanCode = stripModuleSyntax(moduleCode)\n // Strip __tjs preamble to avoid duplicate declarations\n // (test execution context provides its own __tjs stub)\n cleanCode = stripTjsPreamble(cleanCode)\n\n lines.push(`// Resolved import: ${specifier}`)\n lines.push(cleanCode)\n }\n\n return lines.join('\\n')\n}\n\n/**\n * Run extracted test blocks at transpile time\n */\nfunction runTestBlocks(\n tests: ExtractedTest[],\n mocks: ExtractedMock[],\n transpiledCode: string,\n resolvedImports: Record<string, string> = {}\n): TestResult[] {\n const results: TestResult[] = []\n\n // Strip import/export for test execution (can't use modules in new Function)\n let executableCode = stripModuleSyntax(transpiledCode)\n // Strip __tjs preamble - test context provides its own stub\n executableCode = stripTjsPreamble(executableCode)\n\n // Build resolved imports code - inject imported module code into execution context\n const importedCode = buildResolvedImportsCode(resolvedImports)\n\n // Build execution context with the transpiled function\n const mockSetup = mocks.map((m) => m.body).join('\\n')\n\n for (const test of tests) {\n try {\n // Create a function that runs the test\n // Always provide a clean __tjs stub for isolated test execution\n // Save and restore globalThis.__tjs to prevent pollution\n const tjsStub = `\n const __saved_tjs = globalThis.__tjs;\n const __stub_tjs = { version: '0.0.0', pushStack: () => {}, typeError: (path, expected, value) => new Error(\\`Type error at \\${path}: expected \\${expected}\\`), createRuntime: function() { return this; } };\n globalThis.__tjs = __stub_tjs;\n `\n const tjsRestore = `globalThis.__tjs = __saved_tjs;`\n const testCode = `\n ${tjsStub}\n try {\n // Inject resolved imports first (they may be dependencies)\n ${importedCode}\n ${executableCode}\n ${mockSetup}\n\n // Test assertions\n function assert(condition, message) {\n if (!condition) throw new Error(message || 'Assertion failed')\n }\n\n function expect(actual) {\n return {\n toBe(expected) {\n if (!__deepEqual(actual, expected)) {\n throw new Error('Expected ' + __format(expected) + ' but got ' + __format(actual))\n }\n },\n toEqual(expected) {\n if (!__deepEqual(actual, expected)) {\n throw new Error('Expected ' + __format(expected) + ' but got ' + __format(actual))\n }\n }\n }\n }\n\n // Run the test body\n ${test.body}\n } finally {\n ${tjsRestore}\n }\n `\n\n // Execute the test\n const fn = new Function('__deepEqual', '__format', testCode)\n fn(deepEqual, formatValue)\n\n results.push({\n description: test.description,\n passed: true,\n line: test.line,\n })\n } catch (e: any) {\n results.push({\n description: test.description,\n passed: false,\n error: e.message || String(e),\n line: test.line,\n })\n }\n }\n\n return results\n}\n\n/**\n * Evaluate an ObjectExpression AST node to a plain object\n */\nfunction evalObjectExpression(node: any): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const prop of node.properties) {\n if (prop.type === 'Property' && prop.key) {\n const key =\n prop.key.type === 'Identifier' ? prop.key.name : prop.key.value\n if (prop.value.type === 'Literal') {\n result[key] = prop.value.value\n } else if (prop.value.type === 'ObjectExpression') {\n result[key] = evalObjectExpression(prop.value)\n } else if (prop.value.type === 'ArrayExpression') {\n result[key] = evalArrayExpression(prop.value)\n } else {\n throw new Error('Unsupported value type')\n }\n }\n }\n return result\n}\n\n/**\n * Evaluate an ArrayExpression AST node to an array\n */\nfunction evalArrayExpression(node: any): unknown[] {\n const result: unknown[] = []\n for (const elem of node.elements) {\n if (elem.type === 'Literal') {\n result.push(elem.value)\n } else if (elem.type === 'ObjectExpression') {\n result.push(evalObjectExpression(elem))\n } else if (elem.type === 'ArrayExpression') {\n result.push(evalArrayExpression(elem))\n } else {\n throw new Error('Unsupported element type')\n }\n }\n return result\n}\n\n/**\n * Extract and run signature tests for ALL functions with -> return types\n * Parses the original source to find function signatures\n *\n * Current limitations (future work):\n * - Only tests top-level `function` declarations (not arrow functions yet)\n * - Nested functions (inside other functions/blocks) are not excluded yet\n * and will fail if tested since they're not in global scope\n * - Arrow functions like `Foo = (x: 5) -> 10 => {}` not yet supported\n */\nfunction runAllSignatureTests(\n originalSource: string,\n transpiledCode: string,\n resolvedImports: Record<string, string> = {}\n): TestResult[] {\n const results: TestResult[] = []\n\n // Strip comments to avoid matching functions inside doc comments/code examples\n const sourceWithoutComments = stripComments(originalSource)\n\n // Match function declarations with return type marker (-> or -?)\n // Skip -! which means \"don't test\"\n // Pattern: function name(params) -> returnExample {\n const funcRegex = /function\\s+(\\w+)\\s*\\(([^)]*)\\)\\s*(-[>?])\\s*/g\n\n let match\n while ((match = funcRegex.exec(sourceWithoutComments)) !== null) {\n const funcName = match[1]\n const paramsStr = match[2]\n const returnMarker = match[3]\n\n // Calculate line number from match position in stripped source\n const lineNumber = sourceWithoutComments\n .slice(0, match.index)\n .split('\\n').length\n\n // -! means skip test\n if (returnMarker === '-!') continue\n\n // Extract return example - handle nested braces/brackets\n // Use stripped source since match.index is from that\n const afterMarker = sourceWithoutComments.slice(\n match.index + match[0].length\n )\n const returnExample = extractReturnExampleFromSource(afterMarker)\n if (!returnExample) continue\n\n // Extract parameter examples\n const paramExamples = extractParamExamples(paramsStr)\n if (paramsStr.trim() && paramExamples.length === 0) continue\n\n // Run the signature test\n try {\n const expectedStr = returnExample\n\n // Parse expected value\n const expected = new Function(`return ${expectedStr}`)()\n\n // Parse args\n const args = paramExamples.map((p) => new Function(`return ${p}`)())\n\n const result = runSignatureTest(\n funcName,\n transpiledCode,\n args,\n expected,\n resolvedImports\n )\n result.line = lineNumber\n results.push(result)\n } catch (e: any) {\n results.push({\n description: `${funcName} signature example`,\n passed: false,\n error: `Failed to parse signature: ${e.message}`,\n isSignatureTest: true,\n line: lineNumber,\n })\n }\n }\n\n return results\n}\n\n/**\n * Extract return type example from source, handling nested braces\n */\nfunction extractReturnExampleFromSource(source: string): string | null {\n let result = ''\n let depth = 0\n let hasContent = false\n\n for (let i = 0; i < source.length; i++) {\n const char = source[i]\n\n if (char === '{' || char === '[' || char === '(') {\n if (char === '{' && depth === 0 && hasContent) {\n // Found the function body opening brace\n break\n }\n depth++\n result += char\n hasContent = true\n } else if (char === '}' || char === ']' || char === ')') {\n depth--\n result += char\n } else if (!/\\s/.test(char)) {\n result += char\n hasContent = true\n } else {\n result += char\n }\n }\n\n const trimmed = result.trim()\n return trimmed || null\n}\n\n/**\n * Extract parameter example values from params string\n */\nfunction extractParamExamples(paramsStr: string): string[] {\n if (!paramsStr.trim()) return []\n\n const examples: string[] = []\n const params = splitParams(paramsStr)\n\n for (const param of params) {\n // Match: name: example or name = example (with optional safety markers)\n // Handle: (? name: example) or (! name: example)\n const match = param.match(/(?:\\(\\s*[?!]\\s*)?(\\w+)\\s*[:=]\\s*(.+?)(?:\\))?$/)\n if (match) {\n examples.push(match[2].trim())\n } else {\n // No example value - can't run signature test\n return []\n }\n }\n\n return examples\n}\n\n/**\n * Split parameter string on commas, respecting nested structures\n */\nfunction splitParams(paramsStr: string): string[] {\n const params: string[] = []\n let current = ''\n let depth = 0\n\n for (const char of paramsStr) {\n if (char === '(' || char === '[' || char === '{') depth++\n else if (char === ')' || char === ']' || char === '}') depth--\n else if (char === ',' && depth === 0) {\n params.push(current.trim())\n current = ''\n continue\n }\n current += char\n }\n\n if (current.trim()) params.push(current.trim())\n return params\n}\n\n/**\n * Run signature example test\n */\nfunction runSignatureTest(\n funcName: string,\n transpiledCode: string,\n args: unknown[],\n expected: unknown,\n resolvedImports: Record<string, string> = {}\n): TestResult {\n const description = `${funcName} signature example`\n\n // Strip import/export for test execution (can't use modules in new Function)\n let executableCode = stripModuleSyntax(transpiledCode)\n // Strip __tjs preamble - test context provides its own stub\n executableCode = stripTjsPreamble(executableCode)\n\n // Build resolved imports code - inject imported module code into execution context\n const importedCode = buildResolvedImportsCode(resolvedImports)\n\n try {\n // Execute the function with example args\n // Provide a minimal __tjs stub for pushStack/typeError (used by inline validation)\n // Only define if not already in the transpiled code\n // Always provide a clean __tjs stub for isolated test execution\n // Save and restore globalThis.__tjs to prevent pollution\n const tjsStub = `\n const __saved_tjs = globalThis.__tjs;\n const __stub_tjs = { version: '0.0.0', pushStack: () => {}, typeError: (path, expected, value) => new Error(\\`Type error at \\${path}: expected \\${expected}\\`), createRuntime: function() { return this; } };\n globalThis.__tjs = __stub_tjs;\n `\n const tjsRestore = `globalThis.__tjs = __saved_tjs;`\n const testCode = `\n ${tjsStub}\n try {\n // Inject resolved imports first (they may be dependencies)\n ${importedCode}\n ${executableCode}\n return ${funcName}(${args.map((a) => JSON.stringify(a)).join(', ')})\n } finally {\n ${tjsRestore}\n }\n `\n const fn = new Function(testCode)\n const actual = fn()\n\n // Use type matching, not value equality\n // The expected value is a TYPE PATTERN (example), not the exact expected result\n const result = typeMatches(actual, expected, funcName)\n if (!result.matches) {\n return {\n description,\n passed: false,\n error: result.error || `Type mismatch: got ${formatValue(actual)}`,\n isSignatureTest: true,\n }\n }\n\n return { description, passed: true, isSignatureTest: true }\n } catch (e: any) {\n return {\n description,\n passed: false,\n error: e.message || String(e),\n isSignatureTest: true,\n }\n }\n}\n",
|
|
11
|
+
"/**\n * TJS Inline Tests\n *\n * Extracts test blocks from TJS source and generates test runners.\n *\n * Syntax (TJS):\n * test 'description' {\n * assert(condition)\n * expect(a).toBe(b)\n * }\n *\n * test {\n * // Anonymous test\n * }\n *\n * mock {\n * // Setup code that runs before each test\n * }\n *\n * Syntax (TypeScript - embedded in comments):\n * /*test 'description' {\n * expect(add(2, 3)).toBe(5)\n * }* /\n *\n * This syntax survives TypeScript compilation, enabling literate\n * programming for TypeScript: tests live alongside the code they\n * verify, extracted and executed at runtime by TJS.\n *\n * For TS developers who don't care about TJS: you still get inline\n * tests that live with your code, literate development, and faster\n * debug loops. Set `safety none` and keep living in your world.\n *\n * Output:\n * - code: Clean source with tests stripped\n * - tests: Array of extracted test definitions\n * - testRunner: Generated code to execute tests\n */\n\n// Note: parser could be used for more robust test extraction in future\n\nexport interface ExtractedTest {\n description: string\n body: string\n line?: number\n}\n\nexport interface ExtractedMock {\n body: string\n line?: number\n}\n\nexport interface TestExtractionResult {\n /** Source code with tests and mocks removed */\n code: string\n /** Extracted test definitions */\n tests: ExtractedTest[]\n /** Extracted mock/setup blocks */\n mocks: ExtractedMock[]\n /** Generated test runner code */\n testRunner: string\n}\n\n/**\n * Check if a position in source is inside a comment\n */\nfunction isInsideComment(source: string, pos: number): boolean {\n // Check for line comment - scan backwards to start of line\n let lineStart = pos\n while (lineStart > 0 && source[lineStart - 1] !== '\\n') {\n lineStart--\n }\n const lineBeforePos = source.slice(lineStart, pos)\n if (lineBeforePos.includes('//')) {\n return true\n }\n\n // Check for block comment - find last /* and */ before pos\n let i = 0\n let inBlockComment = false\n while (i < pos) {\n if (!inBlockComment && source.slice(i, i + 2) === '/*') {\n inBlockComment = true\n i += 2\n } else if (inBlockComment && source.slice(i, i + 2) === '*/') {\n inBlockComment = false\n i += 2\n } else {\n i++\n }\n }\n return inBlockComment\n}\n\n/**\n * Extract embedded tests from block comments\n *\n * Syntax:\n * /*test 'description' {\n * assert(condition)\n * }* /\n *\n * This allows tests to be embedded in TypeScript files that would\n * otherwise strip out `test {}` blocks during TS compilation.\n */\nfunction extractEmbeddedTests(source: string): ExtractedTest[] {\n const tests: ExtractedTest[] = []\n\n // Match: /*test 'description' { ... }*/ or /*test { ... }*/\n const embeddedRegex =\n /\\/\\*test\\s+(['\"`])([^'\"`]*)\\1\\s*\\{([\\s\\S]*?)\\}\\s*\\*\\/|\\/\\*test\\s*\\{([\\s\\S]*?)\\}\\s*\\*\\//g\n\n let match\n while ((match = embeddedRegex.exec(source)) !== null) {\n // Group 2 = description for quoted, group 3 = body for quoted\n // Group 4 = body for anonymous\n const desc = match[2] || `embedded test ${tests.length + 1}`\n const body = (match[3] || match[4] || '').trim()\n\n tests.push({\n description: desc,\n body,\n line: getLineNumber(source, match.index),\n })\n }\n\n return tests\n}\n\n/**\n * Extract inline tests from TJS source\n *\n * Note: Signature tests (from -> return types) are handled separately by the\n * transpiler in js.ts. This function only extracts explicit test blocks.\n */\nexport function extractTests(source: string): TestExtractionResult {\n const tests: ExtractedTest[] = []\n const mocks: ExtractedMock[] = []\n\n // First, extract embedded tests from block comments (for TS compatibility)\n // These use syntax: /*test 'description' { ... }*/\n const embeddedTests = extractEmbeddedTests(source)\n tests.push(...embeddedTests)\n\n // Regex to match test blocks - three syntaxes supported:\n // test { ... } (anonymous test)\n // test 'description' { ... } (canonical TJS)\n // test('description') { ... } (also valid - parenthesized string is still a string)\n const testRegex =\n /test\\s+(['\"`])([^'\"`]*)\\1\\s*\\{|test\\s*\\(\\s*(['\"`])([^'\"`]*)\\3\\s*\\)\\s*\\{|test\\s*\\{/g\n const mockRegex = /mock\\s*\\{/g\n\n let cleanCode = source\n let match\n\n // Extract test blocks\n // We need to find matching braces for each test\n const testMatches: Array<{ start: number; end: number; desc: string }> = []\n\n while ((match = testRegex.exec(source)) !== null) {\n const start = match.index\n\n // Skip matches inside comments (but embedded tests were already extracted above)\n if (isInsideComment(source, start)) {\n continue\n }\n\n // Description is in group 2 for `test 'desc'`, group 4 for `test('desc')`, or undefined for `test {`\n const desc = match[2] || match[4] || `test ${tests.length + 1}`\n const bodyStart = match.index + match[0].length\n\n // Find matching closing brace\n const end = findMatchingBrace(source, bodyStart - 1)\n if (end === -1) continue\n\n const body = source.slice(bodyStart, end).trim()\n\n tests.push({\n description: desc,\n body,\n line: getLineNumber(source, start),\n })\n\n testMatches.push({ start, end: end + 1, desc })\n }\n\n // Extract mock blocks\n const mockMatches: Array<{ start: number; end: number }> = []\n\n while ((match = mockRegex.exec(source)) !== null) {\n const start = match.index\n const bodyStart = match.index + match[0].length\n\n const end = findMatchingBrace(source, bodyStart - 1)\n if (end === -1) continue\n\n const body = source.slice(bodyStart, end).trim()\n\n mocks.push({\n body,\n line: getLineNumber(source, start),\n })\n\n mockMatches.push({ start, end: end + 1 })\n }\n\n // Remove test and mock blocks from source (in reverse order to preserve indices)\n const allMatches = [...testMatches, ...mockMatches].sort(\n (a, b) => b.start - a.start\n )\n\n for (const m of allMatches) {\n cleanCode = cleanCode.slice(0, m.start) + cleanCode.slice(m.end)\n }\n\n // Clean up extra whitespace\n cleanCode = cleanCode.replace(/\\n\\s*\\n\\s*\\n/g, '\\n\\n').trim()\n\n // Generate test runner\n const testRunner = generateTestRunner(tests, mocks)\n\n return {\n code: cleanCode,\n tests,\n mocks,\n testRunner,\n }\n}\n\n/**\n * Find the matching closing brace\n */\nfunction findMatchingBrace(source: string, start: number): number {\n let depth = 0\n let inString: string | null = null\n let escaped = false\n\n for (let i = start; i < source.length; i++) {\n const char = source[i]\n\n if (escaped) {\n escaped = false\n continue\n }\n\n if (char === '\\\\') {\n escaped = true\n continue\n }\n\n // Track string state\n if (!inString && (char === '\"' || char === \"'\" || char === '`')) {\n inString = char\n continue\n }\n if (inString === char) {\n inString = null\n continue\n }\n if (inString) continue\n\n // Track braces\n if (char === '{') depth++\n if (char === '}') {\n depth--\n if (depth === 0) return i\n }\n }\n\n return -1\n}\n\n/**\n * Get line number for a position in source\n */\nfunction getLineNumber(source: string, pos: number): number {\n return source.slice(0, pos).split('\\n').length\n}\n\n/**\n * Generate test runner code\n */\nfunction generateTestRunner(\n tests: ExtractedTest[],\n mocks: ExtractedMock[]\n): string {\n if (tests.length === 0) {\n return '// No tests defined'\n }\n\n const mockSetup = mocks.map((m) => m.body).join('\\n')\n\n const testCases = tests\n .map(\n (t, i) => `\n // Test ${i + 1}: ${t.description}\n try {\n ${mockSetup}\n await (async () => {\n ${t.body}\n })()\n __results.push({ description: ${JSON.stringify(\n t.description\n )}, passed: true })\n } catch (__e) {\n __results.push({ description: ${JSON.stringify(\n t.description\n )}, passed: false, error: __e.message })\n }`\n )\n .join('\\n')\n\n // Note: No comment before IIFE - ASI would break `return (async...)` if comment is between\n return `(async () => {\nconst __results = []\n\n${testCases}\n\n// Report results\nconst __passed = __results.filter(r => r.passed).length\nconst __failed = __results.filter(r => !r.passed).length\nconsole.log(\\`Tests: \\${__passed} passed, \\${__failed} failed\\`)\n__results.filter(r => !r.passed).forEach(r => {\n console.log(\\` ✗ \\${r.description}: \\${r.error}\\`)\n})\n\n// Return summary\nreturn { passed: __passed, failed: __failed, results: __results }\n})()`.trim()\n}\n\n/**\n * Test utilities - assert and expect\n * Include this in the runtime or inject it\n */\nexport const assertFunction = `\nfunction assert(condition, message) {\n if (!condition) {\n throw new Error(message || 'Assertion failed')\n }\n}\n`\n\n/**\n * Expect API for richer test assertions\n * Uses deep equality, handles null/undefined correctly\n */\nexport const expectFunction = `\nfunction expect(actual) {\n const deepEqual = (a, b) => {\n if (a === b) return true\n if (a === null || b === null) return a === b\n if (a === undefined || b === undefined) return a === undefined && b === undefined\n if (typeof a !== typeof b) return false\n if (typeof a !== 'object') return a === b\n if (Array.isArray(a) !== Array.isArray(b)) return false\n if (Array.isArray(a)) {\n if (a.length !== b.length) return false\n return a.every((v, i) => deepEqual(v, b[i]))\n }\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n if (keysA.length !== keysB.length) return false\n return keysA.every(k => deepEqual(a[k], b[k]))\n }\n\n const format = (v) => {\n if (v === null) return 'null'\n if (v === undefined) return 'undefined'\n if (typeof v === 'string') return JSON.stringify(v)\n if (typeof v === 'object') return JSON.stringify(v)\n return String(v)\n }\n\n return {\n toBe(expected) {\n if (!deepEqual(actual, expected)) {\n throw new Error(\\`Expected \\${format(expected)} but got \\${format(actual)}\\`)\n }\n },\n toEqual(expected) {\n if (!deepEqual(actual, expected)) {\n throw new Error(\\`Expected \\${format(expected)} but got \\${format(actual)}\\`)\n }\n },\n toContain(item) {\n if (!Array.isArray(actual) || !actual.some(v => deepEqual(v, item))) {\n throw new Error(\\`Expected \\${format(actual)} to contain \\${format(item)}\\`)\n }\n },\n toThrow(message) {\n let threw = false\n let thrownMessage = ''\n try {\n if (typeof actual === 'function') actual()\n } catch (e) {\n threw = true\n thrownMessage = e.message || String(e)\n }\n if (!threw) {\n throw new Error('Expected function to throw but it did not')\n }\n if (message && !thrownMessage.includes(message)) {\n throw new Error(\\`Expected error containing \"\\${message}\" but got \"\\${thrownMessage}\"\\`)\n }\n },\n toBeTruthy() {\n if (!actual) {\n throw new Error(\\`Expected \\${format(actual)} to be truthy\\`)\n }\n },\n toBeFalsy() {\n if (actual) {\n throw new Error(\\`Expected \\${format(actual)} to be falsy\\`)\n }\n },\n toBeNull() {\n if (actual !== null) {\n throw new Error(\\`Expected null but got \\${format(actual)}\\`)\n }\n },\n toBeUndefined() {\n if (actual !== undefined) {\n throw new Error(\\`Expected undefined but got \\${format(actual)}\\`)\n }\n },\n toBeGreaterThan(n) {\n if (!(actual > n)) {\n throw new Error(\\`Expected \\${format(actual)} to be greater than \\${n}\\`)\n }\n },\n toBeLessThan(n) {\n if (!(actual < n)) {\n throw new Error(\\`Expected \\${format(actual)} to be less than \\${n}\\`)\n }\n }\n }\n}\n`\n\n/**\n * Combined test utilities (assert + expect)\n */\nexport const testUtils = assertFunction + '\\n' + expectFunction\n\n/**\n * Questions/Notes:\n *\n * Q1: Should mocks be scoped per-test or shared?\n * Current: Each test runs all mocks before executing\n *\n * Q2: Should we support test.only / test.skip?\n * Easy to add with syntax: test.only('...') { } or test.skip('...') { }\n *\n * Q3: Integration with playground?\n * Playground could run extractTests() and show test results in a panel\n *\n * Q4: DOM tests - test.browser('desc') { }?\n * SHELVED: Plan is to run tests in actual browser (playground)\n * Happy-DOM is ~1MB packed, too heavy to bundle\n * If needed later: lazy-load happy-dom only for Node/Bun DOM tests\n */\n",
|
|
12
|
+
"/**\n * TJS Schema - Runtime type system for Typed JavaScript\n *\n * Builds on tosijs-schema to provide:\n * - Schema(x) callable for inference by example\n * - Schema.type(x) for \"fixed typeof\" (null returns 'null', not 'object')\n * - All tosijs-schema methods (string, number, object, array, etc.)\n *\n * Usage:\n * Schema('hello') // Schema matching string\n * Schema(42) // Schema matching number (integer)\n * Schema(null) // Schema matching null\n * Schema(undefined) // Schema matching undefined\n * Schema([1, 2, 3]) // Schema matching array of integers\n * Schema({name: 'Anne'}) // Schema matching object with name: string\n *\n * Schema.type(null) // 'null' (not 'object' like typeof)\n * Schema.type(undefined) // 'undefined'\n * Schema.type([]) // 'array' (not 'object' like typeof)\n *\n * Schema.null.validate(x) // true if x is null\n * Schema.undefined.validate(x) // true if x is undefined\n */\n\nimport { s, type Base } from 'tosijs-schema'\n\n/**\n * Get the \"fixed\" type of a value - unlike typeof, correctly handles null and arrays\n */\nfunction getType(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n if (Array.isArray(value)) return 'array'\n return typeof value\n}\n\n/**\n * Infer a schema from an example value\n * This wraps tosijs-schema's s.infer() for consistency\n */\nfunction infer(value: unknown): Base<unknown> {\n return s.infer(value)\n}\n\n// The base callable function\nfunction schemaCallable(value: unknown): Base<unknown> {\n return infer(value)\n}\n\n// Add our custom methods\nschemaCallable.type = getType\nschemaCallable.infer = infer\n\n// Create the Schema callable that proxies to s for all other properties\ntype SchemaCallable = {\n (value: unknown): Base<unknown>\n type: (value: unknown) => string\n infer: (value: unknown) => Base<unknown>\n} & typeof s\n\n/**\n * Schema - callable for inference, with all tosijs-schema methods attached\n * Uses a Proxy to delegate property access to tosijs-schema's s object\n */\nexport const Schema: SchemaCallable = new Proxy(schemaCallable as any, {\n get(target, prop) {\n // Our custom methods take precedence\n if (prop === 'type') return getType\n if (prop === 'infer') return infer\n // Delegate everything else to tosijs-schema's s\n return (s as any)[prop]\n },\n apply(target, thisArg, args) {\n // Make it callable - Schema(value) infers schema\n return infer(args[0])\n },\n})\n\n// Re-export useful types from tosijs-schema\nexport type { Base, Infer } from 'tosijs-schema'\n",
|
|
13
|
+
"// AST walker module for ESTree compatible trees\n\n// A simple walk is one where you simply specify callbacks to be\n// called on specific nodes. The last two arguments are optional. A\n// simple use would be\n//\n// walk.simple(myTree, {\n// Expression: function(node) { ... }\n// });\n//\n// to do something with all expressions. All ESTree node types\n// can be used to identify node types, as well as Expression and\n// Statement, which denote categories of nodes.\n//\n// The base argument can be used to pass a custom (recursive)\n// walker, and state can be used to give this walked an initial\n// state.\n\nfunction simple(node, visitors, baseVisitor, state, override) {\n if (!baseVisitor) { baseVisitor = base\n ; }(function c(node, st, override) {\n var type = override || node.type;\n baseVisitor[type](node, st, c);\n if (visitors[type]) { visitors[type](node, st); }\n })(node, state, override);\n}\n\n// An ancestor walk keeps an array of ancestor nodes (including the\n// current node) and passes them to the callback as third parameter\n// (and also as state parameter when no other state is present).\nfunction ancestor(node, visitors, baseVisitor, state, override) {\n var ancestors = [];\n if (!baseVisitor) { baseVisitor = base\n ; }(function c(node, st, override) {\n var type = override || node.type;\n var isNew = node !== ancestors[ancestors.length - 1];\n if (isNew) { ancestors.push(node); }\n baseVisitor[type](node, st, c);\n if (visitors[type]) { visitors[type](node, st || ancestors, ancestors); }\n if (isNew) { ancestors.pop(); }\n })(node, state, override);\n}\n\n// A recursive walk is one where your functions override the default\n// walkers. They can modify and replace the state parameter that's\n// threaded through the walk, and can opt how and whether to walk\n// their child nodes (by calling their third argument on these\n// nodes).\nfunction recursive(node, state, funcs, baseVisitor, override) {\n var visitor = funcs ? make(funcs, baseVisitor || undefined) : baseVisitor\n ;(function c(node, st, override) {\n visitor[override || node.type](node, st, c);\n })(node, state, override);\n}\n\nfunction makeTest(test) {\n if (typeof test === \"string\")\n { return function (type) { return type === test; } }\n else if (!test)\n { return function () { return true; } }\n else\n { return test }\n}\n\nvar Found = function Found(node, state) { this.node = node; this.state = state; };\n\n// A full walk triggers the callback on each node\nfunction full(node, callback, baseVisitor, state, override) {\n if (!baseVisitor) { baseVisitor = base; }\n var last\n ;(function c(node, st, override) {\n var type = override || node.type;\n baseVisitor[type](node, st, c);\n if (last !== node) {\n callback(node, st, type);\n last = node;\n }\n })(node, state, override);\n}\n\n// An fullAncestor walk is like an ancestor walk, but triggers\n// the callback on each node\nfunction fullAncestor(node, callback, baseVisitor, state) {\n if (!baseVisitor) { baseVisitor = base; }\n var ancestors = [], last\n ;(function c(node, st, override) {\n var type = override || node.type;\n var isNew = node !== ancestors[ancestors.length - 1];\n if (isNew) { ancestors.push(node); }\n baseVisitor[type](node, st, c);\n if (last !== node) {\n callback(node, st || ancestors, ancestors, type);\n last = node;\n }\n if (isNew) { ancestors.pop(); }\n })(node, state);\n}\n\n// Find a node with a given start, end, and type (all are optional,\n// null can be used as wildcard). Returns a {node, state} object, or\n// undefined when it doesn't find a matching node.\nfunction findNodeAt(node, start, end, test, baseVisitor, state) {\n if (!baseVisitor) { baseVisitor = base; }\n test = makeTest(test);\n try {\n (function c(node, st, override) {\n var type = override || node.type;\n if ((start == null || node.start <= start) &&\n (end == null || node.end >= end))\n { baseVisitor[type](node, st, c); }\n if ((start == null || node.start === start) &&\n (end == null || node.end === end) &&\n test(type, node))\n { throw new Found(node, st) }\n })(node, state);\n } catch (e) {\n if (e instanceof Found) { return e }\n throw e\n }\n}\n\n// Find the innermost node of a given type that contains the given\n// position. Interface similar to findNodeAt.\nfunction findNodeAround(node, pos, test, baseVisitor, state) {\n test = makeTest(test);\n if (!baseVisitor) { baseVisitor = base; }\n try {\n (function c(node, st, override) {\n var type = override || node.type;\n if (node.start > pos || node.end < pos) { return }\n baseVisitor[type](node, st, c);\n if (test(type, node)) { throw new Found(node, st) }\n })(node, state);\n } catch (e) {\n if (e instanceof Found) { return e }\n throw e\n }\n}\n\n// Find the outermost matching node after a given position.\nfunction findNodeAfter(node, pos, test, baseVisitor, state) {\n test = makeTest(test);\n if (!baseVisitor) { baseVisitor = base; }\n try {\n (function c(node, st, override) {\n if (node.end < pos) { return }\n var type = override || node.type;\n if (node.start >= pos && test(type, node)) { throw new Found(node, st) }\n baseVisitor[type](node, st, c);\n })(node, state);\n } catch (e) {\n if (e instanceof Found) { return e }\n throw e\n }\n}\n\n// Find the outermost matching node before a given position.\nfunction findNodeBefore(node, pos, test, baseVisitor, state) {\n test = makeTest(test);\n if (!baseVisitor) { baseVisitor = base; }\n var max\n ;(function c(node, st, override) {\n if (node.start > pos) { return }\n var type = override || node.type;\n if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node))\n { max = new Found(node, st); }\n baseVisitor[type](node, st, c);\n })(node, state);\n return max\n}\n\n// Used to create a custom walker. Will fill in all missing node\n// type properties with the defaults.\nfunction make(funcs, baseVisitor) {\n var visitor = Object.create(baseVisitor || base);\n for (var type in funcs) { visitor[type] = funcs[type]; }\n return visitor\n}\n\nfunction skipThrough(node, st, c) { c(node, st); }\nfunction ignore(_node, _st, _c) {}\n\n// Node walkers.\n\nvar base = {};\n\nbase.Program = base.BlockStatement = base.StaticBlock = function (node, st, c) {\n for (var i = 0, list = node.body; i < list.length; i += 1)\n {\n var stmt = list[i];\n\n c(stmt, st, \"Statement\");\n }\n};\nbase.Statement = skipThrough;\nbase.EmptyStatement = ignore;\nbase.ExpressionStatement = base.ParenthesizedExpression = base.ChainExpression =\n function (node, st, c) { return c(node.expression, st, \"Expression\"); };\nbase.IfStatement = function (node, st, c) {\n c(node.test, st, \"Expression\");\n c(node.consequent, st, \"Statement\");\n if (node.alternate) { c(node.alternate, st, \"Statement\"); }\n};\nbase.LabeledStatement = function (node, st, c) { return c(node.body, st, \"Statement\"); };\nbase.BreakStatement = base.ContinueStatement = ignore;\nbase.WithStatement = function (node, st, c) {\n c(node.object, st, \"Expression\");\n c(node.body, st, \"Statement\");\n};\nbase.SwitchStatement = function (node, st, c) {\n c(node.discriminant, st, \"Expression\");\n for (var i = 0, list = node.cases; i < list.length; i += 1) {\n var cs = list[i];\n\n c(cs, st);\n }\n};\nbase.SwitchCase = function (node, st, c) {\n if (node.test) { c(node.test, st, \"Expression\"); }\n for (var i = 0, list = node.consequent; i < list.length; i += 1)\n {\n var cons = list[i];\n\n c(cons, st, \"Statement\");\n }\n};\nbase.ReturnStatement = base.YieldExpression = base.AwaitExpression = function (node, st, c) {\n if (node.argument) { c(node.argument, st, \"Expression\"); }\n};\nbase.ThrowStatement = base.SpreadElement =\n function (node, st, c) { return c(node.argument, st, \"Expression\"); };\nbase.TryStatement = function (node, st, c) {\n c(node.block, st, \"Statement\");\n if (node.handler) { c(node.handler, st); }\n if (node.finalizer) { c(node.finalizer, st, \"Statement\"); }\n};\nbase.CatchClause = function (node, st, c) {\n if (node.param) { c(node.param, st, \"Pattern\"); }\n c(node.body, st, \"Statement\");\n};\nbase.WhileStatement = base.DoWhileStatement = function (node, st, c) {\n c(node.test, st, \"Expression\");\n c(node.body, st, \"Statement\");\n};\nbase.ForStatement = function (node, st, c) {\n if (node.init) { c(node.init, st, \"ForInit\"); }\n if (node.test) { c(node.test, st, \"Expression\"); }\n if (node.update) { c(node.update, st, \"Expression\"); }\n c(node.body, st, \"Statement\");\n};\nbase.ForInStatement = base.ForOfStatement = function (node, st, c) {\n c(node.left, st, \"ForInit\");\n c(node.right, st, \"Expression\");\n c(node.body, st, \"Statement\");\n};\nbase.ForInit = function (node, st, c) {\n if (node.type === \"VariableDeclaration\") { c(node, st); }\n else { c(node, st, \"Expression\"); }\n};\nbase.DebuggerStatement = ignore;\n\nbase.FunctionDeclaration = function (node, st, c) { return c(node, st, \"Function\"); };\nbase.VariableDeclaration = function (node, st, c) {\n for (var i = 0, list = node.declarations; i < list.length; i += 1)\n {\n var decl = list[i];\n\n c(decl, st);\n }\n};\nbase.VariableDeclarator = function (node, st, c) {\n c(node.id, st, \"Pattern\");\n if (node.init) { c(node.init, st, \"Expression\"); }\n};\n\nbase.Function = function (node, st, c) {\n if (node.id) { c(node.id, st, \"Pattern\"); }\n for (var i = 0, list = node.params; i < list.length; i += 1)\n {\n var param = list[i];\n\n c(param, st, \"Pattern\");\n }\n c(node.body, st, node.expression ? \"Expression\" : \"Statement\");\n};\n\nbase.Pattern = function (node, st, c) {\n if (node.type === \"Identifier\")\n { c(node, st, \"VariablePattern\"); }\n else if (node.type === \"MemberExpression\")\n { c(node, st, \"MemberPattern\"); }\n else\n { c(node, st); }\n};\nbase.VariablePattern = ignore;\nbase.MemberPattern = skipThrough;\nbase.RestElement = function (node, st, c) { return c(node.argument, st, \"Pattern\"); };\nbase.ArrayPattern = function (node, st, c) {\n for (var i = 0, list = node.elements; i < list.length; i += 1) {\n var elt = list[i];\n\n if (elt) { c(elt, st, \"Pattern\"); }\n }\n};\nbase.ObjectPattern = function (node, st, c) {\n for (var i = 0, list = node.properties; i < list.length; i += 1) {\n var prop = list[i];\n\n if (prop.type === \"Property\") {\n if (prop.computed) { c(prop.key, st, \"Expression\"); }\n c(prop.value, st, \"Pattern\");\n } else if (prop.type === \"RestElement\") {\n c(prop.argument, st, \"Pattern\");\n }\n }\n};\n\nbase.Expression = skipThrough;\nbase.ThisExpression = base.Super = base.MetaProperty = ignore;\nbase.ArrayExpression = function (node, st, c) {\n for (var i = 0, list = node.elements; i < list.length; i += 1) {\n var elt = list[i];\n\n if (elt) { c(elt, st, \"Expression\"); }\n }\n};\nbase.ObjectExpression = function (node, st, c) {\n for (var i = 0, list = node.properties; i < list.length; i += 1)\n {\n var prop = list[i];\n\n c(prop, st);\n }\n};\nbase.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration;\nbase.SequenceExpression = function (node, st, c) {\n for (var i = 0, list = node.expressions; i < list.length; i += 1)\n {\n var expr = list[i];\n\n c(expr, st, \"Expression\");\n }\n};\nbase.TemplateLiteral = function (node, st, c) {\n for (var i = 0, list = node.quasis; i < list.length; i += 1)\n {\n var quasi = list[i];\n\n c(quasi, st);\n }\n\n for (var i$1 = 0, list$1 = node.expressions; i$1 < list$1.length; i$1 += 1)\n {\n var expr = list$1[i$1];\n\n c(expr, st, \"Expression\");\n }\n};\nbase.TemplateElement = ignore;\nbase.UnaryExpression = base.UpdateExpression = function (node, st, c) {\n c(node.argument, st, \"Expression\");\n};\nbase.BinaryExpression = base.LogicalExpression = function (node, st, c) {\n c(node.left, st, \"Expression\");\n c(node.right, st, \"Expression\");\n};\nbase.AssignmentExpression = base.AssignmentPattern = function (node, st, c) {\n c(node.left, st, \"Pattern\");\n c(node.right, st, \"Expression\");\n};\nbase.ConditionalExpression = function (node, st, c) {\n c(node.test, st, \"Expression\");\n c(node.consequent, st, \"Expression\");\n c(node.alternate, st, \"Expression\");\n};\nbase.NewExpression = base.CallExpression = function (node, st, c) {\n c(node.callee, st, \"Expression\");\n if (node.arguments)\n { for (var i = 0, list = node.arguments; i < list.length; i += 1)\n {\n var arg = list[i];\n\n c(arg, st, \"Expression\");\n } }\n};\nbase.MemberExpression = function (node, st, c) {\n c(node.object, st, \"Expression\");\n if (node.computed) { c(node.property, st, \"Expression\"); }\n};\nbase.ExportNamedDeclaration = base.ExportDefaultDeclaration = function (node, st, c) {\n if (node.declaration)\n { c(node.declaration, st, node.type === \"ExportNamedDeclaration\" || node.declaration.id ? \"Statement\" : \"Expression\"); }\n if (node.source) { c(node.source, st, \"Expression\"); }\n};\nbase.ExportAllDeclaration = function (node, st, c) {\n if (node.exported)\n { c(node.exported, st); }\n c(node.source, st, \"Expression\");\n};\nbase.ImportDeclaration = function (node, st, c) {\n for (var i = 0, list = node.specifiers; i < list.length; i += 1)\n {\n var spec = list[i];\n\n c(spec, st);\n }\n c(node.source, st, \"Expression\");\n};\nbase.ImportExpression = function (node, st, c) {\n c(node.source, st, \"Expression\");\n};\nbase.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.PrivateIdentifier = base.Literal = ignore;\n\nbase.TaggedTemplateExpression = function (node, st, c) {\n c(node.tag, st, \"Expression\");\n c(node.quasi, st, \"Expression\");\n};\nbase.ClassDeclaration = base.ClassExpression = function (node, st, c) { return c(node, st, \"Class\"); };\nbase.Class = function (node, st, c) {\n if (node.id) { c(node.id, st, \"Pattern\"); }\n if (node.superClass) { c(node.superClass, st, \"Expression\"); }\n c(node.body, st);\n};\nbase.ClassBody = function (node, st, c) {\n for (var i = 0, list = node.body; i < list.length; i += 1)\n {\n var elt = list[i];\n\n c(elt, st);\n }\n};\nbase.MethodDefinition = base.PropertyDefinition = base.Property = function (node, st, c) {\n if (node.computed) { c(node.key, st, \"Expression\"); }\n if (node.value) { c(node.value, st, \"Expression\"); }\n};\n\nexport { ancestor, base, findNodeAfter, findNodeAround, findNodeAt, findNodeBefore, full, fullAncestor, make, recursive, simple };\n",
|
|
14
|
+
"/**\n * TJS Linter\n *\n * Static analysis for TJS code:\n * - Unused variables\n * - Undefined variables\n * - Type mismatches (when __tjs metadata available)\n * - Unreachable code\n *\n * POC: Focus on variable usage first, then type checking.\n */\n\nimport type { Program, Node, Identifier, VariableDeclaration } from 'acorn'\nimport { parse } from './parser'\nimport * as walk from 'acorn-walk'\n\nexport interface LintDiagnostic {\n severity: 'error' | 'warning' | 'info'\n message: string\n line?: number\n column?: number\n rule: string\n}\n\nexport interface LintResult {\n diagnostics: LintDiagnostic[]\n valid: boolean\n}\n\nexport interface LintOptions {\n /** Check for unused variables */\n unusedVariables?: boolean\n /** Check for undefined variables */\n undefinedVariables?: boolean\n /** Check for unreachable code */\n unreachableCode?: boolean\n /** Warn about explicit `new` keyword usage (TJS makes classes callable without new) */\n noExplicitNew?: boolean\n /** Filename for error messages */\n filename?: string\n}\n\nconst DEFAULT_OPTIONS: LintOptions = {\n unusedVariables: true,\n undefinedVariables: true,\n unreachableCode: true,\n noExplicitNew: true,\n}\n\n/**\n * Lint TJS source code\n */\nexport function lint(source: string, options: LintOptions = {}): LintResult {\n const opts = { ...DEFAULT_OPTIONS, ...options }\n const diagnostics: LintDiagnostic[] = []\n\n // Parse the source\n let program: Program\n try {\n const result = parse(source, {\n filename: opts.filename,\n colonShorthand: true,\n })\n program = result.ast\n } catch (error: any) {\n return {\n diagnostics: [\n {\n severity: 'error',\n message: error.message,\n line: error.loc?.line,\n column: error.loc?.column,\n rule: 'parse-error',\n },\n ],\n valid: false,\n }\n }\n\n // Track variable declarations and usages per scope\n const scopes: Scope[] = [createScope()] // Global scope\n\n // First pass: collect all declarations\n walk.ancestor(program, {\n FunctionDeclaration(node: any, _state: any, _ancestors: any) {\n // Function creates new scope\n const scope = createScope()\n scopes.push(scope)\n\n // Add parameters to scope\n for (const param of node.params) {\n addDeclaration(scope, param, 'parameter')\n }\n\n // Function name is in parent scope\n if (node.id) {\n const parentScope = scopes[scopes.length - 2] || scopes[0]\n parentScope.declarations.set(node.id.name, {\n node: node.id,\n kind: 'function',\n used: false,\n })\n }\n },\n\n VariableDeclaration(node: VariableDeclaration) {\n const scope = scopes[scopes.length - 1]\n for (const decl of node.declarations) {\n if (decl.id.type === 'Identifier') {\n scope.declarations.set(decl.id.name, {\n node: decl.id,\n kind: node.kind as 'let' | 'const' | 'var',\n used: false,\n })\n }\n // TODO: handle destructuring patterns\n }\n },\n })\n\n // Second pass: check usages\n walk.simple(program, {\n Identifier(node: Identifier) {\n // Skip declaration sites (handled above)\n // This is a simplified check - just mark as used\n for (let i = scopes.length - 1; i >= 0; i--) {\n const decl = scopes[i].declarations.get(node.name)\n if (decl) {\n decl.used = true\n break\n }\n }\n },\n })\n\n // Report unused variables\n if (opts.unusedVariables) {\n for (const scope of scopes) {\n for (const [name, decl] of scope.declarations) {\n // Skip parameters starting with _ (intentionally unused)\n if (name.startsWith('_')) continue\n\n if (!decl.used && decl.kind !== 'function') {\n diagnostics.push({\n severity: 'warning',\n message: `'${name}' is declared but never used`,\n line: (decl.node as any).loc?.start?.line,\n column: (decl.node as any).loc?.start?.column,\n rule: 'no-unused-vars',\n })\n }\n }\n }\n }\n\n // Check for unreachable code\n if (opts.unreachableCode) {\n walk.simple(program, {\n BlockStatement(node: any) {\n let foundReturn = false\n for (const stmt of node.body) {\n if (foundReturn) {\n diagnostics.push({\n severity: 'warning',\n message: 'Unreachable code after return statement',\n line: stmt.loc?.start?.line,\n column: stmt.loc?.start?.column,\n rule: 'no-unreachable',\n })\n break // Only report once per block\n }\n if (stmt.type === 'ReturnStatement') {\n foundReturn = true\n }\n }\n },\n })\n }\n\n // Check for explicit `new` keyword usage\n // In TJS, classes are callable without `new`, so using `new` is unnecessary\n if (opts.noExplicitNew) {\n walk.simple(program, {\n NewExpression(node: any) {\n // Get the callee name\n let calleeName = 'class'\n if (node.callee.type === 'Identifier') {\n calleeName = node.callee.name\n } else if (node.callee.type === 'MemberExpression') {\n // e.g., new foo.Bar()\n if (node.callee.property.type === 'Identifier') {\n calleeName = node.callee.property.name\n }\n }\n\n diagnostics.push({\n severity: 'warning',\n message: `Unnecessary 'new' keyword. In TJS, classes are callable without 'new': ${calleeName}(...) instead of new ${calleeName}(...)`,\n line: node.loc?.start?.line,\n column: node.loc?.start?.column,\n rule: 'no-explicit-new',\n })\n },\n })\n }\n\n return {\n diagnostics,\n valid: diagnostics.filter((d) => d.severity === 'error').length === 0,\n }\n}\n\n// --- Internal types and helpers ---\n\ninterface Scope {\n declarations: Map<string, Declaration>\n}\n\ninterface Declaration {\n node: Node\n kind: 'let' | 'const' | 'var' | 'parameter' | 'function'\n used: boolean\n}\n\nfunction createScope(): Scope {\n return { declarations: new Map() }\n}\n\nfunction addDeclaration(scope: Scope, node: Node, kind: Declaration['kind']) {\n if (node.type === 'Identifier') {\n scope.declarations.set((node as Identifier).name, {\n node,\n kind,\n used: false,\n })\n } else if (\n node.type === 'AssignmentPattern' &&\n (node as any).left.type === 'Identifier'\n ) {\n scope.declarations.set((node as any).left.name, {\n node: (node as any).left,\n kind,\n used: false,\n })\n }\n // TODO: handle destructuring\n}\n\n/**\n * Questions/Notes for future:\n *\n * Q1: Should we integrate with __tjs metadata for cross-file type checking?\n * - Would need to load metadata from imported modules\n * - Could check function call arguments against declared parameter types\n *\n * Q2: How strict should undefined variable checking be?\n * - Currently relies on JS globals being available\n * - Could have a whitelist of known globals (console, Math, etc.)\n *\n * Q3: Should linting be incremental / cacheable?\n * - For large projects, re-linting everything is slow\n * - Could hash files and skip unchanged ones\n */\n",
|
|
15
|
+
"/**\n * TJS Runtime\n *\n * Monadic type checking at runtime:\n * - Functions validate inputs against __tjs metadata\n * - If any input is an error, pass it through (no work)\n * - Type mismatches return error objects\n * - Errors propagate through call chains\n *\n * This runtime is attached to globalThis.__tjs and shared across modules.\n */\n\nimport { validate, s } from 'tosijs-schema'\nimport {\n Type,\n isRuntimeType,\n Union,\n Generic,\n Enum,\n Nullable,\n Optional,\n TArray,\n // Built-in types\n TString,\n TNumber,\n TBoolean,\n TInteger,\n TPositiveInt,\n TNonEmptyString,\n TEmail,\n TUrl,\n TUuid,\n Timestamp,\n LegalDate,\n // Built-in generics\n TPair,\n TRecord,\n // Portable predicate helpers (future AJS builtins)\n isValidUrl,\n isValidTimestamp,\n isValidLegalDate,\n} from '../types/Type'\n\n// Re-export Type utilities for consumers\nexport {\n Type,\n isRuntimeType,\n Union,\n Generic,\n Enum,\n Nullable,\n Optional,\n TArray,\n TString,\n TNumber,\n TBoolean,\n TInteger,\n TPositiveInt,\n TNonEmptyString,\n TEmail,\n TUrl,\n TUuid,\n Timestamp,\n LegalDate,\n TPair,\n TRecord,\n isValidUrl,\n isValidTimestamp,\n isValidLegalDate,\n}\n\n// Version from package.json - injected at build time or imported\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst pkg = require('../../package.json') as { version: string }\n\nexport const TJS_VERSION: string = pkg.version\n\n/**\n * Parse semver version string into components\n */\nfunction parseVersion(version: string): {\n major: number\n minor: number\n patch: number\n} {\n const [major = 0, minor = 0, patch = 0] = version.split('.').map(Number)\n return { major, minor, patch }\n}\n\n/**\n * Compare two version strings\n * Returns: -1 if a < b, 0 if equal, 1 if a > b\n */\nexport function compareVersions(a: string, b: string): -1 | 0 | 1 {\n const va = parseVersion(a)\n const vb = parseVersion(b)\n\n if (va.major !== vb.major) return va.major < vb.major ? -1 : 1\n if (va.minor !== vb.minor) return va.minor < vb.minor ? -1 : 1\n if (va.patch !== vb.patch) return va.patch < vb.patch ? -1 : 1\n return 0\n}\n\n/**\n * Check if two versions are compatible (same major version)\n */\nexport function versionsCompatible(a: string, b: string): boolean {\n const va = parseVersion(a)\n const vb = parseVersion(b)\n return va.major === vb.major\n}\n\n/**\n * MonadicError - Internal error type for monadic error propagation\n *\n * This extends Error so:\n * 1. It's a real Error with proper stack traces\n * 2. User code can't accidentally process it as data (unlike { $error: true })\n * 3. It flows through function calls via instanceof checks\n *\n * NOT exported to user code - they just see Error instances.\n */\nexport class MonadicError extends Error {\n /** Path where the error occurred, e.g., \"src/file.ts:42:greet.name\" */\n readonly path: string\n /** Expected type */\n readonly expected?: string\n /** Actual type received */\n readonly actual?: string\n /** TJS call stack (only in debug mode) - shows source locations */\n readonly callStack?: string[]\n\n constructor(\n message: string,\n path: string,\n expected?: string,\n actual?: string,\n callStack?: string[]\n ) {\n super(message)\n this.name = 'MonadicError'\n this.path = path\n this.expected = expected\n this.actual = actual\n this.callStack = callStack\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, MonadicError)\n }\n }\n}\n\n/**\n * Create a type error for inline validation\n *\n * Called ONLY when a type check fails - no overhead on happy path.\n * Returns a MonadicError that propagates through the call chain.\n * In debug mode, captures the TJS call stack with source locations.\n *\n * @param path - Location of the error, e.g., \"src/file.ts:42:greet.name\"\n * @param expected - Expected type, e.g., \"string\"\n * @param value - The actual value that failed the check\n */\nexport function typeError(\n path: string,\n expected: string,\n value: unknown\n): MonadicError {\n const actual = value === null ? 'null' : typeof value\n // Capture call stack in debug mode (getStack returns [] if not in debug mode)\n const stack = config.debug ? getStack() : undefined\n return new MonadicError(\n `Expected ${expected} for '${path}', got ${actual}`,\n path,\n expected,\n actual,\n stack\n )\n}\n\n/**\n * Check if a value is a MonadicError (for internal use)\n */\nexport function isMonadicError(value: unknown): value is MonadicError {\n return value instanceof MonadicError\n}\n\n/**\n * Error marker - identifies TJS error objects\n * @deprecated Use MonadicError instead. This interface is kept for backward compatibility.\n */\nexport interface TJSError {\n $error: true\n message: string\n /** Failure location - e.g., \"greet.name\" */\n path?: string\n /** Call stack in debug mode - e.g., [\"main\", \"processUser\", \"greet.name\"] */\n stack?: string[]\n expected?: string\n actual?: string\n cause?: Error | TJSError\n /** Source location for error reporting */\n loc?: { start: number; end: number }\n /** Multiple errors (when composing parameter errors) */\n errors?: TJSError[]\n}\n\n/**\n * Safety levels for runtime validation\n * - 'none': No validation unless explicitly forced with (?) or -?\n * - 'inputs': Validate inputs only (default) - outputs only with explicit -> or -?\n * - 'all': Validate both inputs and outputs unless explicitly skipped with (!) or -!\n */\nexport type SafetyLevel = 'none' | 'inputs' | 'all'\n\n/**\n * Runtime configuration\n */\nexport interface TJSConfig {\n /** Enable debug mode - captures call stacks in errors */\n debug?: boolean\n /** Safety level for validation (default: 'inputs') */\n safety?: SafetyLevel\n /** Require explicit return types (error if -> not specified) */\n requireReturnTypes?: boolean\n /** Maximum call stack size to prevent memory issues (default: 100) */\n maxStackSize?: number\n}\n\n/** Default configuration values */\nconst DEFAULT_CONFIG: TJSConfig = {\n debug: false,\n safety: 'inputs',\n requireReturnTypes: false,\n maxStackSize: 100,\n}\n\n/** Current runtime configuration */\nlet config: TJSConfig = { ...DEFAULT_CONFIG }\n\n/** Current call stack (only tracked in debug mode) */\nconst callStack: string[] = []\n\n/** Unsafe mode depth - when > 0, skip validation in wrap() */\nlet unsafeDepth = 0\n\n/**\n * Enter unsafe mode - disables validation for all wrapped function calls\n * Can be nested (uses depth counter)\n */\nexport function enterUnsafe(): void {\n unsafeDepth++\n}\n\n/**\n * Exit unsafe mode - re-enables validation when depth returns to 0\n */\nexport function exitUnsafe(): void {\n if (unsafeDepth > 0) unsafeDepth--\n}\n\n/**\n * Check if currently in unsafe mode\n */\nexport function isUnsafeMode(): boolean {\n return unsafeDepth > 0\n}\n\n/**\n * Configure TJS runtime\n */\nexport function configure(options: TJSConfig): void {\n config = { ...config, ...options }\n}\n\n/**\n * Get current configuration\n */\nexport function getConfig(): TJSConfig {\n return { ...config }\n}\n\n/**\n * Push a function onto the call stack (debug mode only)\n * Respects maxStackSize to prevent unbounded memory growth\n */\nexport function pushStack(name: string): void {\n if (config.debug && name) {\n callStack.push(name)\n // Enforce max stack size by removing oldest entries\n const maxSize = config.maxStackSize ?? 100\n while (callStack.length > maxSize) {\n callStack.shift()\n }\n }\n}\n\n/**\n * Pop a function from the call stack (debug mode only)\n */\nexport function popStack(): void {\n if (config.debug) {\n callStack.pop()\n }\n}\n\n/**\n * Get current call stack snapshot\n */\nexport function getStack(): string[] {\n return [...callStack]\n}\n\n/**\n * Reset runtime state to defaults\n *\n * Resets: config, callStack, unsafeDepth\n * Use this in test teardown to prevent state leaking between tests.\n */\nexport function resetRuntime(): void {\n config = { ...DEFAULT_CONFIG }\n callStack.length = 0\n unsafeDepth = 0\n}\n\n/**\n * Structural equality - the == that works\n *\n * Rules:\n * 1. If left has .Equals, call left.Equals(right)\n * 2. If right has .Equals, call right.Equals(left)\n * 3. Arrays/objects: recursive structural comparison\n * 4. Primitives: strict equality (no coercion)\n *\n * Usage: `a Is b` transforms to `Is(a, b)`\n */\nexport function Is(a: unknown, b: unknown): boolean {\n // Check for .Equals method\n if (\n a !== null &&\n typeof a === 'object' &&\n typeof (a as any).Equals === 'function'\n ) {\n return (a as any).Equals(b)\n }\n if (\n b !== null &&\n typeof b === 'object' &&\n typeof (b as any).Equals === 'function'\n ) {\n return (b as any).Equals(a)\n }\n\n // Identical references or primitives\n if (a === b) return true\n\n // null and undefined are equal to each other (nullish equality)\n // This preserves the useful JS pattern: x == null checks for both\n if ((a === null || a === undefined) && (b === null || b === undefined)) {\n return true\n }\n\n // If only one is nullish, not equal\n if (a === null || a === undefined || b === null || b === undefined) {\n return false\n }\n\n // Different types - not equal (no coercion)\n if (typeof a !== typeof b) return false\n\n // Primitives that aren't === are not equal\n if (typeof a !== 'object') return false\n\n // Arrays\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n return a.every((v, i) => Is(v, b[i]))\n }\n if (Array.isArray(a) !== Array.isArray(b)) return false\n\n // Objects - structural comparison\n const keysA = Object.keys(a as object)\n const keysB = Object.keys(b as object)\n if (keysA.length !== keysB.length) return false\n return keysA.every((k) => Is((a as any)[k], (b as any)[k]))\n}\n\n/**\n * Structural inequality - the != that works\n *\n * Usage: `a IsNot b` transforms to `IsNot(a, b)`\n */\nexport function IsNot(a: unknown, b: unknown): boolean {\n return !Is(a, b)\n}\n\n/**\n * Check if a value is a TJS error\n */\nexport function isError(value: unknown): value is TJSError {\n return (\n value !== null &&\n typeof value === 'object' &&\n (value as any).$error === true\n )\n}\n\n/**\n * Create a TJS error\n * In debug mode, captures the current call stack\n */\nexport function error(\n message: string,\n details?: Partial<Omit<TJSError, '$error' | 'message'>>\n): TJSError {\n const err: TJSError = {\n $error: true,\n message,\n ...details,\n }\n\n // In debug mode, capture the call stack\n if (config.debug && callStack.length > 0) {\n // Add the path to the stack if it exists\n const fullStack = details?.path\n ? [...callStack, details.path]\n : [...callStack]\n err.stack = fullStack\n }\n\n return err\n}\n\n/**\n * Compose multiple errors into a single error\n * Used when multiple parameters have errors\n */\nexport function composeErrors(errors: TJSError[], funcName?: string): TJSError {\n if (errors.length === 0) {\n return error('Unknown error')\n }\n if (errors.length === 1) {\n return errors[0]\n }\n\n // Build a message listing all failed parameters\n const paramNames = errors\n .map((e) => {\n // Extract param name from path (e.g., \"func.paramName\" -> \"paramName\")\n if (e.path) {\n const parts = e.path.split('.')\n return parts[parts.length - 1]\n }\n return 'unknown'\n })\n .join(', ')\n\n const message = `Multiple parameter errors in ${\n funcName || 'function'\n }: ${paramNames}`\n\n return error(message, {\n path: funcName,\n errors,\n })\n}\n\n/**\n * Get the type of a value\n *\n * Enhanced typeof that handles:\n * - null (returns 'null' not 'object')\n * - undefined (returns 'undefined')\n * - arrays (returns 'array' not 'object')\n * - native/platform types (returns constructor name for objects)\n *\n * For objects, returns the constructor name which enables pragmatic\n * native type checking (e.g., 'HTMLElement', 'Buffer', 'Event')\n */\nexport function typeOf(value: unknown): string {\n if (value === null) return 'null'\n if (value === undefined) return 'undefined'\n if (Array.isArray(value)) return 'array'\n\n const t = typeof value\n if (t !== 'object') return t\n\n // For objects, return constructor name for pragmatic native type checking\n // This enables checking for HTMLElement, Buffer, Event, etc.\n const constructorName = (value as object).constructor?.name\n if (constructorName && constructorName !== 'Object') {\n return constructorName\n }\n\n return 'object'\n}\n\n/**\n * Check if a value is an instance of a native/platform type by constructor name\n *\n * This enables pragmatic native type checking without shipping type definitions:\n * - isNativeType(el, 'HTMLElement') - DOM element check\n * - isNativeType(buf, 'Buffer') - Node.js Buffer check\n * - isNativeType(evt, 'Event') - DOM Event check\n * - isNativeType(map, 'Map') - Map instance check\n *\n * @param value - The value to check\n * @param typeName - The constructor name to match (e.g., 'HTMLElement', 'Buffer')\n * @returns true if value's constructor.name matches or is in prototype chain\n */\nexport function isNativeType(value: unknown, typeName: string): boolean {\n if (value === null || value === undefined) return false\n if (typeof value !== 'object' && typeof value !== 'function') return false\n\n // Check constructor name\n let proto = value\n while (proto !== null) {\n const constructorName = (proto as object).constructor?.name\n if (constructorName === typeName) return true\n proto = Object.getPrototypeOf(proto)\n }\n\n return false\n}\n\n/**\n * Check if a value matches an expected type\n *\n * @param value - The value to check\n * @param expected - Either a string type name ('string', 'number', etc.)\n * or a RuntimeType instance with .check() method\n * @param path - Optional path for error messages\n */\nexport function checkType(\n value: unknown,\n expected: string | { check: (v: unknown) => boolean; description: string },\n path?: string\n): TJSError | null {\n // If value is already an error, propagate it\n if (isError(value)) return value\n\n // Handle RuntimeType instances (Type() results)\n if (\n typeof expected === 'object' &&\n expected !== null &&\n 'check' in expected\n ) {\n if (expected.check(value)) return null\n return error(`Expected ${expected.description} but got ${typeOf(value)}`, {\n path,\n expected: expected.description,\n actual: typeOf(value),\n })\n }\n\n const actual = typeOf(value)\n\n // Handle special cases\n if (expected === 'any') return null\n if (expected === actual) return null\n\n // Number accepts both number types\n if (expected === 'number' && actual === 'number') return null\n if (expected === 'integer' && actual === 'number' && Number.isInteger(value))\n return null\n\n // Object matching (basic)\n if (expected === 'object' && actual === 'object') return null\n\n return error(`Expected ${expected} but got ${actual}`, {\n path,\n expected,\n actual,\n })\n}\n\n/** Type specifier - either a string name or a RuntimeType */\ntype TypeSpec = string | { check: (v: unknown) => boolean; description: string }\n\n/** Parameter metadata with optional location */\ninterface ParamMeta {\n type: TypeSpec\n required: boolean\n default?: unknown\n loc?: { start: number; end: number }\n}\n\n/**\n * Validate function arguments against __tjs metadata\n * Returns first error found, or null if all valid\n */\nexport function validateArgs(\n args: Record<string, unknown>,\n meta: {\n params: Record<string, ParamMeta>\n },\n funcName?: string\n): TJSError | null {\n for (const [name, param] of Object.entries(meta.params)) {\n const value = args[name]\n\n // Check if any arg is already an error - propagate first one\n if (isError(value)) return value\n\n // Check required\n if (param.required && value === undefined) {\n const expectedDesc =\n typeof param.type === 'string' ? param.type : param.type.description\n return error(`Missing required parameter '${name}'`, {\n path: funcName ? `${funcName}.${name}` : name,\n expected: expectedDesc,\n actual: 'undefined',\n loc: param.loc,\n })\n }\n\n // Skip type check for undefined optional params\n if (value === undefined) continue\n\n // Type check\n const typeError = checkType(\n value,\n param.type,\n funcName ? `${funcName}.${name}` : name\n )\n if (typeError) {\n // Add location info if available\n if (param.loc) {\n typeError.loc = param.loc\n }\n return typeError\n }\n }\n\n return null\n}\n\n/**\n * Function metadata with safety flags\n */\nexport interface FunctionMeta {\n params: Record<string, any>\n returns?: { type: any; safe?: boolean }\n /** Function marked with (!) - never validate inputs */\n unsafe?: boolean\n /** Function marked with (?) - always validate inputs */\n safe?: boolean\n /** Return type marked with -! - never validate output */\n unsafeReturn?: boolean\n /** Return type marked with -? - always validate output */\n safeReturn?: boolean\n /** Explicit function name for stack tracking (used when fn.name is empty) */\n name?: string\n}\n\n/**\n * Determine if we should validate inputs for this call\n * Reserved for future use with runtime validation modes\n */\nfunction _shouldValidateInputs(meta: FunctionMeta): boolean {\n // Per-function flags take precedence\n if (meta.unsafe) return false\n if (meta.safe) return true\n\n // Block-level override\n if (unsafeDepth > 0) return false\n\n // Global safety level\n return config.safety !== 'none'\n}\n\n/**\n * Determine if we should validate outputs for this call\n * Reserved for future use with runtime validation modes\n */\nfunction _shouldValidateOutputs(meta: FunctionMeta): boolean {\n // No return type declared = no validation\n if (!meta.returns) return false\n\n // Per-function return flags take precedence\n if (meta.unsafeReturn) return false\n if (meta.safeReturn) return true\n\n // Block-level override\n if (unsafeDepth > 0) return false\n\n // Global safety level: 'all' validates outputs, others don't by default\n return config.safety === 'all'\n}\n\n/**\n * Wrap a function with monadic type checking\n *\n * @param fn - The original function\n * @param meta - The __tjs metadata\n * @returns Wrapped function that validates inputs and propagates errors\n */\nexport function wrap<T extends (...args: any[]) => any>(\n fn: T,\n meta: FunctionMeta\n): T {\n // Always attach metadata for introspection/autocomplete\n (fn as any).__tjs = meta\n\n // Determine if we need a wrapper at all\n const needsWrapper =\n // Has forced safety that requires validation\n meta.safe ||\n meta.safeReturn ||\n // Global safety requires validation (and not explicitly unsafe)\n (config.safety !== 'none' && !meta.unsafe) ||\n // Has return type that might need validation\n (meta.returns && config.safety === 'all' && !meta.unsafeReturn)\n\n if (!needsWrapper) {\n return fn\n }\n\n // Pre-compute flags at wrap time\n const hasReturns = !!meta.returns\n const metaUnsafe = !!meta.unsafe\n const metaSafe = !!meta.safe\n const metaUnsafeReturn = !!meta.unsafeReturn\n const metaSafeReturn = !!meta.safeReturn\n const paramEntries = Object.entries(meta.params)\n const paramCount = paramEntries.length\n // Use meta.name as fallback when fn.name is empty (anonymous functions)\n const funcName = fn.name || meta.name || 'anonymous'\n\n const wrapped = function (this: any, ...args: Parameters<T>): ReturnType<T> {\n // Fast path: inside unsafe block, skip all validation\n if (unsafeDepth > 0) {\n return fn.apply(this, args)\n }\n\n // Compute validation flags\n const validateInputs = metaSafe || (!metaUnsafe && config.safety !== 'none')\n const validateOutputs =\n hasReturns &&\n (metaSafeReturn || (!metaUnsafeReturn && config.safety === 'all'))\n\n // Fast path: no validation needed\n if (!validateInputs && !validateOutputs) {\n return fn.apply(this, args)\n }\n\n // Fast path: check for error as first arg\n if (args.length > 0 && isError(args[0])) {\n return args[0] as ReturnType<T>\n }\n\n // Input validation\n if (validateInputs) {\n // Detect if single object arg (named params) vs positional\n const isNamedCall =\n args.length === 1 &&\n typeof args[0] === 'object' &&\n args[0] !== null &&\n !Array.isArray(args[0])\n\n // Collect all errors to compose them\n const collectedErrors: TJSError[] = []\n\n // Fast positional validation (avoids object allocation)\n if (!isNamedCall) {\n for (let i = 0; i < paramCount; i++) {\n const [name, param] = paramEntries[i]\n const value = args[i]\n\n // Check for error propagation (passed-in errors)\n if (isError(value)) {\n collectedErrors.push(value)\n continue\n }\n\n // Check required\n if (param.required && value === undefined) {\n collectedErrors.push(\n error(`Missing required parameter '${name}'`, {\n path: `${funcName}.${name}`,\n expected:\n typeof param.type === 'string'\n ? param.type\n : param.type?.description || 'value',\n actual: 'undefined',\n loc: param.loc,\n })\n )\n continue\n }\n\n // Type check (skip undefined optional)\n if (value !== undefined) {\n const typeErr = checkType(value, param.type, `${funcName}.${name}`)\n if (typeErr) {\n if (param.loc) typeErr.loc = param.loc\n collectedErrors.push(typeErr)\n }\n }\n }\n } else {\n // Named args path (slower, but supports object destructuring)\n const namedArgs = args[0] as Record<string, unknown>\n for (let i = 0; i < paramCount; i++) {\n const [name, param] = paramEntries[i]\n const value = namedArgs[name]\n\n if (isError(value)) {\n collectedErrors.push(value)\n continue\n }\n\n if (param.required && value === undefined) {\n collectedErrors.push(\n error(`Missing required parameter '${name}'`, {\n path: `${funcName}.${name}`,\n expected:\n typeof param.type === 'string'\n ? param.type\n : param.type?.description || 'value',\n actual: 'undefined',\n loc: param.loc,\n })\n )\n continue\n }\n\n if (value !== undefined) {\n const typeErr = checkType(value, param.type, `${funcName}.${name}`)\n if (typeErr) {\n if (param.loc) typeErr.loc = param.loc\n collectedErrors.push(typeErr)\n }\n }\n }\n }\n\n // If we collected any errors, compose and return them\n if (collectedErrors.length > 0) {\n return composeErrors(collectedErrors, funcName) as ReturnType<T>\n }\n }\n\n // Push onto call stack in debug mode\n pushStack(funcName)\n\n try {\n // Execute function\n const result = fn.apply(this, args)\n\n // Output validation\n if (validateOutputs && meta.returns && !isError(result)) {\n const returnError = checkType(\n result,\n meta.returns.type,\n `${funcName}()`\n )\n if (returnError) {\n popStack()\n return returnError as ReturnType<T>\n }\n }\n\n popStack()\n return result\n } catch (e) {\n popStack()\n // Convert thrown errors to TJS errors\n return error((e as Error).message || String(e), {\n path: funcName,\n cause: e as Error,\n }) as ReturnType<T>\n }\n }\n\n // Preserve function name and metadata\n Object.defineProperty(wrapped, 'name', { value: fn.name })\n ;(wrapped as any).__tjs = meta\n\n return wrapped as T\n}\n\n/**\n * Wrap a class to make it callable without `new`\n *\n * In TJS, classes can be instantiated without the `new` keyword:\n * const obj = MyClass(args) // equivalent to new MyClass(args)\n *\n * This eliminates a common source of errors where developers forget `new`.\n * Using explicit `new` still works but should be flagged by the linter.\n */\nexport function wrapClass<T extends new (...args: any[]) => any>(\n cls: T\n): T & ((...args: ConstructorParameters<T>) => InstanceType<T>) {\n // Use a Proxy to intercept both `new Wrapper()` and `Wrapper()` calls\n const wrapped = new Proxy(cls, {\n // Called when using `new Wrapper(...)`\n construct(target, args, newTarget) {\n return Reflect.construct(target, args, newTarget)\n },\n // Called when using `Wrapper(...)` without new\n apply(target, _thisArg, args) {\n return Reflect.construct(target, args)\n },\n })\n\n // Preserve class name\n Object.defineProperty(wrapped, 'name', { value: cls.name })\n\n // Copy static properties and methods\n for (const key of Object.getOwnPropertyNames(cls)) {\n if (key !== 'length' && key !== 'name' && key !== 'prototype') {\n Object.defineProperty(\n wrapped,\n key,\n Object.getOwnPropertyDescriptor(cls, key)!\n )\n }\n }\n\n return wrapped as T & ((...args: ConstructorParameters<T>) => InstanceType<T>)\n}\n\n// ============================================================================\n// SafeFunction and Eval - moved to ./eval.ts\n// ============================================================================\n//\n// Eval and SafeFunction are in a separate module to keep the runtime lite.\n// Import from 'tjs-lang/eval' when you need dynamic code execution.\n//\n// Runtime (this file): ~5KB gzipped - type checking, Is/IsNot, wrap, etc.\n// Eval module: ~27KB gzipped - adds transpiler + VM for dynamic code\n// ============================================================================\n\n/**\n * Create an isolated TJS runtime instance\n *\n * Each call returns a fresh runtime with its own:\n * - config (debug, safety, etc.)\n * - callStack\n * - unsafeDepth\n *\n * The new instance inherits the current global config at creation time,\n * but subsequent changes are isolated.\n *\n * Use this to prevent state leaking between transpiled modules.\n */\nexport function createRuntime() {\n // Per-instance state - inherit current global config\n let instanceConfig: TJSConfig = { ...config }\n const instanceCallStack: string[] = []\n let instanceUnsafeDepth = 0\n\n // Per-instance stateful functions\n function instanceConfigure(options: TJSConfig): void {\n instanceConfig = { ...instanceConfig, ...options }\n }\n\n function instanceGetConfig(): TJSConfig {\n return { ...instanceConfig }\n }\n\n function instancePushStack(name: string): void {\n if (instanceConfig.debug && name) {\n instanceCallStack.push(name)\n const maxSize = instanceConfig.maxStackSize ?? 100\n while (instanceCallStack.length > maxSize) {\n instanceCallStack.shift()\n }\n }\n }\n\n function instancePopStack(): void {\n if (instanceConfig.debug) {\n instanceCallStack.pop()\n }\n }\n\n function instanceGetStack(): string[] {\n return [...instanceCallStack]\n }\n\n function instanceResetRuntime(): void {\n instanceConfig = { ...DEFAULT_CONFIG }\n instanceCallStack.length = 0\n instanceUnsafeDepth = 0\n }\n\n function instanceEnterUnsafe(): void {\n instanceUnsafeDepth++\n }\n\n function instanceExitUnsafe(): void {\n if (instanceUnsafeDepth > 0) instanceUnsafeDepth--\n }\n\n function instanceIsUnsafeMode(): boolean {\n return instanceUnsafeDepth > 0\n }\n\n function instanceTypeError(\n path: string,\n expected: string,\n value: unknown\n ): MonadicError {\n const actual = value === null ? 'null' : typeof value\n const stack = instanceConfig.debug ? instanceGetStack() : undefined\n return new MonadicError(\n `Expected ${expected} for '${path}', got ${actual}`,\n path,\n expected,\n actual,\n stack\n )\n }\n\n function instanceError(\n message: string,\n details?: Partial<Omit<TJSError, '$error' | 'message'>>\n ): TJSError {\n const err: TJSError = {\n $error: true,\n message,\n ...details,\n }\n if (instanceConfig.debug && instanceCallStack.length > 0) {\n const fullStack = details?.path\n ? [...instanceCallStack, details.path]\n : [...instanceCallStack]\n err.stack = fullStack\n }\n return err\n }\n\n return {\n version: TJS_VERSION,\n // Monadic error handling\n MonadicError,\n typeError: instanceTypeError,\n isMonadicError,\n // Legacy error handling\n isError,\n error: instanceError,\n composeErrors,\n typeOf,\n isNativeType,\n checkType,\n validateArgs,\n wrap,\n wrapClass,\n compareVersions,\n versionsCompatible,\n // Debug mode (instance-specific)\n configure: instanceConfigure,\n getConfig: instanceGetConfig,\n pushStack: instancePushStack,\n popStack: instancePopStack,\n getStack: instanceGetStack,\n resetRuntime: instanceResetRuntime,\n // Unsafe mode (instance-specific)\n enterUnsafe: instanceEnterUnsafe,\n exitUnsafe: instanceExitUnsafe,\n isUnsafeMode: instanceIsUnsafeMode,\n // Type system\n validate,\n infer: s.infer.bind(s),\n Type,\n isRuntimeType,\n Union,\n Generic,\n Enum,\n Nullable,\n Optional,\n TArray,\n TString,\n TNumber,\n TBoolean,\n TInteger,\n TPositiveInt,\n TNonEmptyString,\n TEmail,\n TUrl,\n TUuid,\n TPair,\n TRecord,\n // Structural equality\n Is,\n IsNot,\n }\n}\n\n/** Type for runtime instances */\nexport type TJSRuntime = ReturnType<typeof createRuntime>\n\n/**\n * TJS Runtime object - attached to globalThis.__tjs\n *\n * NOTE: This is a shared global instance. For isolated execution,\n * use createRuntime() instead.\n */\nexport const runtime = {\n version: TJS_VERSION,\n // Monadic error handling (new)\n MonadicError,\n typeError,\n isMonadicError,\n // Legacy error handling (deprecated)\n isError,\n error,\n composeErrors,\n typeOf,\n isNativeType,\n checkType,\n validateArgs,\n wrap,\n wrapClass,\n compareVersions,\n versionsCompatible,\n // Debug mode\n configure,\n getConfig,\n pushStack,\n popStack,\n getStack,\n resetRuntime,\n // Unsafe mode\n enterUnsafe,\n exitUnsafe,\n isUnsafeMode,\n // Factory for isolated instances\n createRuntime,\n // Type system (used by transpiled Type declarations)\n validate,\n infer: s.infer.bind(s),\n Type,\n isRuntimeType,\n Union,\n Generic,\n Enum,\n Nullable,\n Optional,\n TArray,\n // Built-in types\n TString,\n TNumber,\n TBoolean,\n TInteger,\n TPositiveInt,\n TNonEmptyString,\n TEmail,\n TUrl,\n TUuid,\n Timestamp,\n LegalDate,\n TPair,\n TRecord,\n // Structural equality (used by == and != in TJS)\n Is,\n IsNot,\n}\n\n/**\n * Install runtime globally (idempotent, version-checked)\n *\n * Version handling:\n * - Same version: reuse existing (no warning)\n * - Compatible (same major): reuse existing, log info\n * - Incompatible (different major): warn, use newer version\n */\nexport function installRuntime(): typeof runtime {\n const g = globalThis as any\n\n if (g.__tjs) {\n const existingVersion = g.__tjs.version\n\n // Guard against polluted __tjs without proper version\n if (typeof existingVersion !== 'string') {\n g.__tjs = runtime\n return runtime\n }\n\n const comparison = compareVersions(TJS_VERSION, existingVersion)\n\n if (comparison === 0) {\n // Exact same version - just reuse\n return g.__tjs\n }\n\n if (versionsCompatible(TJS_VERSION, existingVersion)) {\n // Same major version - compatible, use newer\n if (comparison > 0) {\n console.info(\n `TJS runtime: upgrading ${existingVersion} → ${TJS_VERSION}`\n )\n g.__tjs = runtime\n } else {\n console.info(\n `TJS runtime: keeping ${existingVersion} (newer than ${TJS_VERSION})`\n )\n }\n } else {\n // Different major version - breaking change potential\n console.warn(\n `TJS runtime version conflict: ${existingVersion} vs ${TJS_VERSION} (major version mismatch)`\n )\n // Use the newer one but warn about potential issues\n if (comparison > 0) {\n console.warn(`Upgrading to ${TJS_VERSION} - check for breaking changes`)\n g.__tjs = runtime\n }\n }\n\n return g.__tjs\n }\n\n g.__tjs = runtime\n return runtime\n}\n\n/**\n * Generate runtime wrapper code for emitted JS\n * Skips wrapping for unsafe functions (marked with !)\n */\nexport function emitRuntimeWrapper(funcName: string): string {\n return `\n// TJS runtime wrapper (skips unsafe functions)\nif (typeof ${funcName}.__tjs === 'object' && !${funcName}.__tjs.unsafe && typeof globalThis.__tjs?.wrap === 'function') {\n ${funcName} = globalThis.__tjs.wrap(${funcName}, ${funcName}.__tjs)\n}\n`.trim()\n}\n\n/**\n * Generate class wrapper code for emitted JS\n * Makes classes callable without `new` keyword\n * Emits standalone JS - no runtime dependency\n */\nexport function emitClassWrapper(className: string): string {\n return `\n// TJS: callable without new\n${className} = new Proxy(${className}, { apply(t, _, a) { return Reflect.construct(t, a) } });\n`.trim()\n}\n\n/**\n * Questions/Notes:\n *\n * Q1: Should wrap() be automatic or opt-in?\n * Current: Must be explicitly wrapped\n * Could: Auto-wrap all functions with __tjs metadata\n *\n * Q2: Performance overhead of validation?\n * Need benchmarks comparing wrapped vs unwrapped\n * Could have 'production' mode that skips validation\n *\n * Q3: Async function handling?\n * wrap() should detect async and handle Promise returns\n *\n * Q4: Deep object validation?\n * Currently only checks top-level type\n * Could recursively validate object shapes\n */\n",
|
|
16
|
+
"/**\n * Type() - Runtime type definitions with descriptions and validation\n *\n * Forms:\n * Type(description, predicate) - full form with custom validation\n * Type(description, schema) - schema-based validation\n * Type(schema) - schema only, self-documenting\n *\n * Usage:\n * const ZipCode = Type('5-digit US zip code', (s) => /^\\d{5}$/.test(s))\n * const Email = Type('valid email', s.string.email)\n * const Age = Type(s.number.min(0).max(150))\n *\n * ZipCode.check('12345') // true\n * ZipCode.check('abc') // false\n * ZipCode.description // '5-digit US zip code'\n */\n\nimport { validate, s, type Base, type JSONSchema } from 'tosijs-schema'\n\n/** Schema can be a tosijs-schema builder or a raw JSON Schema object */\ntype Schema = Base<any> | JSONSchema\n\n/** A runtime type with description and validation */\nexport interface RuntimeType<T = unknown> {\n /** Human-readable description of the type */\n readonly description: string\n /** Check if a value matches this type */\n check(value: unknown): value is T\n /** The underlying schema (if schema-based) */\n readonly schema?: Schema\n /** The predicate function (if predicate-based) */\n readonly predicate?: (value: unknown) => boolean\n /** Example value (for documentation and implicit testing) */\n readonly example?: T\n /** Default value (for instantiation) */\n readonly default?: T\n /** Brand for type identification */\n readonly __runtimeType: true\n}\n\n/** Check if a value is a RuntimeType */\nexport function isRuntimeType(value: unknown): value is RuntimeType {\n return (\n value !== null &&\n typeof value === 'object' &&\n '__runtimeType' in value &&\n (value as any).__runtimeType === true\n )\n}\n\n/**\n * Create a runtime type with description and validation\n *\n * @overload Type(description, predicate) - custom validation function\n * @overload Type(description, schema) - schema-based validation\n * @overload Type(schema) - schema only\n */\n/**\n * Check if a value is a tosijs-schema builder (has .schema property)\n */\nfunction isSchemaBuilder(value: unknown): value is Base<any> {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'schema' in value &&\n typeof (value as any).schema === 'object'\n )\n}\n\n/**\n * Check if a value looks like a raw JSON Schema object\n */\nfunction isJSONSchema(value: unknown): value is JSONSchema {\n return (\n value !== null &&\n typeof value === 'object' &&\n 'type' in value &&\n typeof (value as any).type === 'string'\n )\n}\n\nexport function Type<T = unknown>(\n descriptionOrSchema: string | Schema,\n predicateOrSchemaOrExample?:\n | ((value: unknown) => boolean)\n | Schema\n | T\n | undefined,\n exampleArg?: T,\n defaultArg?: T\n): RuntimeType<T> {\n // Parse arguments\n let description: string\n let predicate: ((value: unknown) => boolean) | undefined\n let schema: Schema | undefined\n let example: T | undefined = exampleArg\n let defaultValue: T | undefined = defaultArg\n\n if (typeof descriptionOrSchema === 'string') {\n // Form: Type(description, predicate/schema/example, example?, default?)\n description = descriptionOrSchema\n\n if (typeof predicateOrSchemaOrExample === 'function') {\n // Type(description, predicate, example?, default?)\n predicate = predicateOrSchemaOrExample\n // If we have example, infer schema from it for the type guard in predicate\n if (example !== undefined) {\n schema = s.infer(example)\n }\n } else if (\n predicateOrSchemaOrExample === undefined &&\n example !== undefined\n ) {\n // Type(description, undefined, example, default?) - example provides schema\n schema = s.infer(example)\n } else if (isSchemaBuilder(predicateOrSchemaOrExample)) {\n // Type(description, schemaBuilder)\n schema = predicateOrSchemaOrExample\n } else if (isJSONSchema(predicateOrSchemaOrExample)) {\n // Type(description, jsonSchema)\n schema = predicateOrSchemaOrExample\n } else if (predicateOrSchemaOrExample !== undefined) {\n // Type(description, example) - second arg is the example/default, infer schema\n // This is the simple form: Type('Name', 'Alice')\n example = predicateOrSchemaOrExample as T\n defaultValue = example // In simple form, example IS the default\n schema = s.infer(example)\n } else {\n throw new Error(\n 'Type(description) requires a predicate, schema, or example'\n )\n }\n } else {\n // Form: Type(schema) or Type(schemaBuilder)\n if (isSchemaBuilder(descriptionOrSchema)) {\n schema = descriptionOrSchema\n } else {\n schema = descriptionOrSchema as Schema\n }\n description = schemaToDescription(schema)\n }\n\n // Build the check function\n const check = (value: unknown): value is T => {\n if (predicate) {\n return predicate(value)\n }\n if (schema) {\n return validate(value, schema)\n }\n return false\n }\n\n return {\n description,\n check,\n schema,\n predicate,\n example,\n default: defaultValue,\n __runtimeType: true as const,\n }\n}\n\n/**\n * Generate a description from a schema\n */\nfunction schemaToDescription(schema: Schema): string {\n // tosijs-schema wraps JSON schema in .schema property\n const jsonSchema = (schema as any)?.schema ?? schema\n\n // Handle schema objects with type property\n if (jsonSchema && typeof jsonSchema === 'object' && 'type' in jsonSchema) {\n const s = jsonSchema as any\n switch (s.type) {\n case 'string':\n if (s.format) return `string (${s.format})`\n if (s.pattern) return `string matching ${s.pattern}`\n if (s.minLength !== undefined && s.maxLength !== undefined)\n return `string (${s.minLength}-${s.maxLength} chars)`\n return 'string'\n case 'number':\n case 'integer':\n if (s.minimum !== undefined && s.maximum !== undefined)\n return `${s.type} (${s.minimum}-${s.maximum})`\n if (s.minimum !== undefined) return `${s.type} >= ${s.minimum}`\n if (s.maximum !== undefined) return `${s.type} <= ${s.maximum}`\n return s.type\n case 'boolean':\n return 'boolean'\n case 'array':\n return 'array'\n case 'object':\n return 'object'\n case 'null':\n return 'null'\n }\n }\n\n // Fallback\n return 'value'\n}\n\n// ============================================================================\n// Built-in Types\n// ============================================================================\n\n/** String type */\nexport const TString = Type<string>('string', (v) => typeof v === 'string')\n\n/** Number type */\nexport const TNumber = Type<number>('number', (v) => typeof v === 'number')\n\n/** Boolean type */\nexport const TBoolean = Type<boolean>('boolean', (v) => typeof v === 'boolean')\n\n/** Integer type */\nexport const TInteger = Type<number>(\n 'integer',\n (v) => typeof v === 'number' && Number.isInteger(v)\n)\n\n/** Positive integer type */\nexport const TPositiveInt = Type<number>(\n 'positive integer',\n (v) => typeof v === 'number' && Number.isInteger(v) && v > 0\n)\n\n/** Non-empty string type */\nexport const TNonEmptyString = Type<string>(\n 'non-empty string',\n (v) => typeof v === 'string' && v.length > 0\n)\n\n/** Email type (basic validation) */\nexport const TEmail = Type<string>(\n 'email address',\n (v) => typeof v === 'string' && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(v)\n)\n\n/**\n * Check if a string is a valid URL (portable helper for predicates)\n * This will become an AJS builtin\n */\nexport const isValidUrl = (v: string): boolean => {\n try {\n new URL(v)\n return true\n } catch {\n return false\n }\n}\n\n/** URL type */\nexport const TUrl = Type<string>(\n 'URL',\n (v) => typeof v === 'string' && isValidUrl(v)\n)\n\n/** UUID type */\nexport const TUuid = Type<string>(\n 'UUID',\n (v) =>\n typeof v === 'string' &&\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v)\n)\n\n/**\n * Check if a string is a valid ISO 8601 timestamp (portable helper for predicates)\n * This will become an AJS builtin\n */\nexport const isValidTimestamp = (v: string): boolean => {\n const d = new Date(v)\n return !isNaN(d.getTime()) && v.includes('T')\n}\n\n/**\n * Check if a string is a valid YYYY-MM-DD date (portable helper for predicates)\n * This will become an AJS builtin\n */\nexport const isValidLegalDate = (v: string): boolean => {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(v)) return false\n const d = new Date(v + 'T00:00:00Z')\n return !isNaN(d.getTime())\n}\n\n/** ISO 8601 timestamp string (e.g., \"2024-01-15T10:30:00Z\") */\nexport const Timestamp = Type<string>(\n 'ISO 8601 timestamp',\n (v) => typeof v === 'string' && isValidTimestamp(v)\n)\n\n/** Legal date string in YYYY-MM-DD format */\nexport const LegalDate = Type<string>(\n 'date (YYYY-MM-DD)',\n (v) => typeof v === 'string' && isValidLegalDate(v)\n)\n\n// ============================================================================\n// Type Combinators\n// ============================================================================\n\n/** Create a nullable version of a type */\nexport function Nullable<T>(type: RuntimeType<T>): RuntimeType<T | null> {\n return Type<T | null>(\n `${type.description} or null`,\n (v) => v === null || type.check(v)\n )\n}\n\n/** Create an optional version of a type (nullable + undefined) */\nexport function Optional<T>(\n type: RuntimeType<T>\n): RuntimeType<T | null | undefined> {\n return Type<T | null | undefined>(\n `${type.description} (optional)`,\n (v) => v === null || v === undefined || type.check(v)\n )\n}\n\n/**\n * Create a union type\n *\n * Two forms:\n * Union(...types: RuntimeType[]) - combine existing types\n * Union(description, values) - create literal union from values\n *\n * @example\n * // From RuntimeTypes\n * const StringOrNumber = Union(TString, TNumber)\n *\n * // From literal values (used by TJS syntax)\n * const Direction = Union('cardinal direction', ['up', 'down', 'left', 'right'])\n */\nexport function Union<T extends unknown[]>(\n descriptionOrType: string | RuntimeType,\n valuesOrType?: T | RuntimeType,\n ...restTypes: RuntimeType[]\n): RuntimeType {\n // New form: Union(description, values[])\n if (typeof descriptionOrType === 'string' && Array.isArray(valuesOrType)) {\n const description = descriptionOrType\n const values = valuesOrType as unknown[]\n const valueSet = new Set(values)\n\n const result: RuntimeType & { values: unknown[] } = {\n description,\n check: (v: unknown): v is T[number] => valueSet.has(v),\n __runtimeType: true as const,\n values, // Expose values for introspection\n }\n return result\n }\n\n // Old form: Union(...types: RuntimeType[])\n const types: RuntimeType[] = []\n if (isRuntimeType(descriptionOrType)) {\n types.push(descriptionOrType)\n }\n if (isRuntimeType(valuesOrType)) {\n types.push(valuesOrType as RuntimeType)\n }\n types.push(...restTypes)\n\n const description = types.map((t) => t.description).join(' | ')\n return Type(description, (v) => types.some((t) => t.check(v)))\n}\n\n/** Create an array type */\nexport function TArray<T>(itemType: RuntimeType<T>): RuntimeType<T[]> {\n return Type<T[]>(\n `array of ${itemType.description}`,\n (v) => Array.isArray(v) && v.every((item) => itemType.check(item))\n )\n}\n\n// ============================================================================\n// Generic Types\n// ============================================================================\n\n/** Type parameter - can be a RuntimeType, schema, or example value */\nexport type TypeParam = RuntimeType | Base<any> | JSONSchema | unknown\n\n/** Generic type factory */\nexport interface GenericType<TParams extends string[] = string[]> {\n /** Instantiate the generic with concrete type arguments */\n (...typeArgs: TypeParam[]): RuntimeType\n /** The type parameter names */\n readonly params: TParams\n /** Description template */\n readonly description: string\n}\n\n/**\n * Convert a type param to a check function\n */\nfunction typeParamToCheck(param: TypeParam): (value: unknown) => boolean {\n if (isRuntimeType(param)) {\n return (v) => param.check(v)\n }\n // Check if it's a schema builder (has .schema property)\n if (param && typeof param === 'object' && 'schema' in param) {\n return (v) => validate(v, param as Base<any>)\n }\n // It's an example value - infer schema using s.infer\n const schema = s.infer(param)\n return (v) => validate(v, schema)\n}\n\n/**\n * Create a generic (parameterized) type factory\n *\n * @param params Array of type parameter names, with optional defaults: ['T', ['U', defaultSchema]]\n * @param predicate Function receiving (value, ...typeChecks) where typeChecks are validation functions\n * @param description Human-readable description template (type params will be substituted)\n *\n * @example\n * // Pair<T, U>\n * const Pair = Generic(\n * ['T', 'U'],\n * (x, checkT, checkU) =>\n * Array.isArray(x) && x.length === 2 && checkT(x[0]) && checkU(x[1]),\n * 'Pair<T, U>'\n * )\n *\n * // Usage: Pair(TString, TNumber) creates a type for [string, number]\n * // Or with examples: Pair('', 0)\n */\nexport function Generic<TParams extends string[]>(\n params: (string | [string, TypeParam])[],\n predicate: (\n value: unknown,\n ...typeChecks: Array<(v: unknown) => boolean>\n ) => boolean,\n description: string\n): GenericType<TParams> {\n // Extract param names and defaults\n const paramNames: string[] = []\n const defaults: (TypeParam | undefined)[] = []\n\n for (const p of params) {\n if (typeof p === 'string') {\n paramNames.push(p)\n defaults.push(undefined)\n } else {\n paramNames.push(p[0])\n defaults.push(p[1])\n }\n }\n\n // The factory function\n const factory = (...typeArgs: TypeParam[]): RuntimeType => {\n // Resolve type arguments, using defaults where not provided\n const checks = paramNames.map((_, i) => {\n const arg = i < typeArgs.length ? typeArgs[i] : defaults[i]\n if (arg === undefined) {\n // No arg and no default - accept anything\n return () => true\n }\n return typeParamToCheck(arg)\n })\n\n // Build description with substituted types\n let desc = description\n paramNames.forEach((name, i) => {\n const arg = i < typeArgs.length ? typeArgs[i] : defaults[i]\n let typeStr = 'any'\n if (isRuntimeType(arg)) {\n typeStr = arg.description\n } else if (arg !== undefined) {\n typeStr = typeof arg === 'string' ? 'string' : JSON.stringify(arg)\n }\n desc = desc.replace(new RegExp(`\\\\b${name}\\\\b`, 'g'), typeStr)\n })\n\n return Type(desc, (value) => predicate(value, ...checks))\n }\n\n ;(factory as any).params = paramNames as TParams\n ;(factory as any).description = description\n\n return factory as GenericType<TParams>\n}\n\n// ============================================================================\n// Built-in Generic Types\n// ============================================================================\n\n/** Pair<T, U> - 2-element tuple */\nexport const TPair = Generic(\n ['T', 'U'],\n (x, checkT, checkU) =>\n Array.isArray(x) && x.length === 2 && checkT(x[0]) && checkU(x[1]),\n 'Pair<T, U>'\n)\n\n/** Record<V> - object with string keys and values of type V */\nexport const TRecord = Generic(\n ['V'],\n (x, checkV) =>\n typeof x === 'object' &&\n x !== null &&\n !Array.isArray(x) &&\n Object.values(x).every(checkV),\n 'Record<string, V>'\n)\n\n// ============================================================================\n// Enum Types\n// ============================================================================\n\n/** Enum type with bidirectional lookup */\nexport interface EnumType<\n T extends Record<string, string | number> = Record<string, string | number>\n> extends RuntimeType<T[keyof T]> {\n /** The enum members as { Name: value } */\n readonly members: T\n /** Reverse lookup: value -> name */\n readonly names: Record<string | number, string>\n /** Get all valid values */\n readonly values: Array<T[keyof T]>\n /** Get all member names */\n readonly keys: Array<keyof T>\n}\n\n/**\n * Create an enum type with bidirectional lookup\n *\n * @param description Human-readable description\n * @param members Object mapping names to values { Pending: 0, Active: 1 }\n *\n * @example\n * const Status = Enum('task status', { Pending: 0, Active: 1, Done: 2 })\n * Status.check(0) // true\n * Status.check('done') // false\n * Status.members.Pending // 0\n * Status.names[0] // 'Pending'\n * Status.values // [0, 1, 2]\n * Status.keys // ['Pending', 'Active', 'Done']\n *\n * const Color = Enum('CSS color', { Red: 'red', Green: 'green', Blue: 'blue' })\n * Color.check('red') // true\n * Color.members.Red // 'red'\n */\nexport function Enum<T extends Record<string, string | number>>(\n description: string,\n members: T\n): EnumType<T> {\n const values = Object.values(members) as Array<T[keyof T]>\n const valueSet = new Set(values)\n const keys = Object.keys(members) as Array<keyof T>\n\n // Build reverse lookup\n const names: Record<string | number, string> = {}\n for (const [key, value] of Object.entries(members)) {\n names[value] = key\n }\n\n const enumType: EnumType<T> = {\n description,\n check: (v: unknown): v is T[keyof T] => valueSet.has(v as T[keyof T]),\n __runtimeType: true as const,\n members,\n names,\n values,\n keys,\n }\n\n return enumType\n}\n"
|
|
17
|
+
],
|
|
18
|
+
"mappings": "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",
|
|
19
|
+
"debugId": "FC3AC8E18381E48464756E2164756E21",
|
|
20
|
+
"names": []
|
|
21
|
+
}
|