# Baba Yaga JavaScript Implementation Architecture ## Overview Baba Yaga is a functional scripting language implemented in JavaScript with a combinator-based architecture. The language emphasizes functional programming patterns, immutable data structures, and a consistent execution model where all operations are translated to function calls. ## Core Architecture Principles ### 1. Combinator Foundation All language operations are translated to function calls to standard library combinators. This eliminates parsing ambiguity while preserving intuitive syntax. **Key Design Decision**: Operators like `+`, `-`, `*`, `/` are translated to `add(x, y)`, `subtract(x, y)`, `multiply(x, y)`, `divide(x, y)` respectively. ### 2. Functional Programming Paradigm - First-class functions with support for partial application and currying - Immutable data structures (tables are never modified in-place) - Pattern matching through `when` expressions - Function composition via `via` operator ### 3. Cross-Platform Compatibility The implementation supports Node.js, Bun, and browser environments through environment detection and platform-specific adapters. ## Language Components ### 1. Lexer (`lexer.js`) **Purpose**: Converts source code into tokens for parsing. **Key Features**: - Character-by-character scanning with lookahead - Comprehensive token type enumeration (NUMBER, PLUS, MINUS, IDENTIFIER, etc.) - Support for comments (single-line `//` and multi-line `/* */`) - IO operations (`..in`, `..out`, `..assert`, `..listen`, `..emit`) - Function references (`@functionName`) and arguments (`@(expression)`) - String literals with escape sequences (`\n`, `\t`, `\r`, `\\`, `\"`) - Detailed position tracking (line/column) for error reporting - Minus operator disambiguation based on spacing context **Token Types**: ```javascript export const TokenType = { NUMBER: 'NUMBER', PLUS: 'PLUS', MINUS: 'MINUS', UNARY_MINUS: 'UNARY_MINUS', BINARY_MINUS: 'BINARY_MINUS', MULTIPLY: 'MULTIPLY', DIVIDE: 'DIVIDE', IDENTIFIER: 'IDENTIFIER', ASSIGNMENT: 'ASSIGNMENT', // ':' ARROW: 'ARROW', // '->' CASE: 'CASE', OF: 'OF', WHEN: 'WHEN', IS: 'IS', THEN: 'THEN', WILDCARD: 'WILDCARD', // '_' FUNCTION: 'FUNCTION', LEFT_PAREN: 'LEFT_PAREN', // '(' RIGHT_PAREN: 'RIGHT_PAREN', // ')' LEFT_BRACE: 'LEFT_BRACE', // '{' RIGHT_BRACE: 'RIGHT_BRACE', // '}' LEFT_BRACKET: 'LEFT_BRACKET', // '[' RIGHT_BRACKET: 'RIGHT_BRACKET', // ']' SEMICOLON: 'SEMICOLON', // ';' COMMA: 'COMMA', // ',' DOT: 'DOT', // '.' STRING: 'STRING', TRUE: 'TRUE', FALSE: 'FALSE', AND: 'AND', OR: 'OR', XOR: 'XOR', NOT: 'NOT', EQUALS: 'EQUALS', // '==' LESS_THAN: 'LESS_THAN', // '<' GREATER_THAN: 'GREATER_THAN', // '>' LESS_EQUAL: 'LESS_EQUAL', // '<=' GREATER_EQUAL: 'GREATER_EQUAL', // '>=' NOT_EQUAL: 'NOT_EQUAL', // '!=' MODULO: 'MODULO', // '%' POWER: 'POWER', // '^' IO_IN: 'IO_IN', // '..in' IO_OUT: 'IO_OUT', // '..out' IO_ASSERT: 'IO_ASSERT', // '..assert' IO_LISTEN: 'IO_LISTEN', // '..listen' IO_EMIT: 'IO_EMIT', // '..emit' FUNCTION_REF: 'FUNCTION_REF', // '@functionName' FUNCTION_ARG: 'FUNCTION_ARG', // '@(expression)' COMPOSE: 'COMPOSE' // 'via' }; ``` **Critical Implementation Details**: - Minus operator disambiguation: Uses spacing context to distinguish unary vs binary minus - Function composition: `via` keyword for function composition - IO operations: `..` prefix for all IO operations - Function references: `@` prefix for function references **Token Structure**: ```javascript /** * @typedef {Object} Token * @property {string} type - The token type from TokenType enum * @property {*} [value] - The token's value (for literals and identifiers) * @property {string} [name] - Function name (for FUNCTION_REF tokens) * @property {number} line - Line number where token appears (1-indexed) * @property {number} column - Column number where token appears (1-indexed) */ ``` **Minus Operator Disambiguation Logic**: ```javascript // Check spacing to determine token type const isUnary = !hasLeadingWhitespace(); const isBinary = hasLeadingAndTrailingSpaces(); const isFollowedByNumber = current + 1 < input.length && /[0-9]/.test(input[current + 1]); if (isUnary && isFollowedByNumber) { // Unary minus at start of expression: -5 tokens.push({ type: TokenType.UNARY_MINUS, line, column }); } else if (isBinary) { // Binary minus with spaces: 5 - 3 tokens.push({ type: TokenType.BINARY_MINUS, line, column }); } else if (isFollowedByNumber) { // Minus followed by number but not at start: 5-3 (legacy) tokens.push({ type: TokenType.MINUS, line, column }); } else { // Fallback to legacy MINUS token for edge cases tokens.push({ type: TokenType.MINUS, line, column }); } ``` ### 2. Parser (`parser.js`) **Purpose**: Converts tokens into an Abstract Syntax Tree (AST) using recursive descent parsing. **Architecture**: Combinator-based parsing where all operators become `FunctionCall` nodes. **Key Parsing Functions**: #### Operator Precedence (highest to lowest): 1. **Primary**: Literals, identifiers, parenthesized expressions, table access 2. **Factor**: Power expressions (`^`), unary operators (`not`, `-`) 3. **Term**: Multiplication, division, modulo (`*`, `/`, `%`) 4. **Expression**: Addition, subtraction, comparisons (`+`, `-`, `=`, `<`, `>`, etc.) 5. **Application**: Function application (juxtaposition) - left-associative 6. **Composition**: Function composition (`via`) - right-associative 7. **Logical**: Logical operators (`and`, `or`, `xor`) #### Function Application - **Juxtaposition**: `f x` becomes `apply(f, x)` - left-associative - **Composition**: `f via g` becomes `compose(f, g)` - right-associative - **Parenthesized**: `f(x)` becomes `apply(f, x)` #### When Expressions (Pattern Matching) ```javascript // Syntax: when value is pattern then result pattern then result; { type: 'WhenExpression', value: [value1, value2, ...], // Can be single value or array cases: [ { pattern: [pattern1, pattern2, ...], // Can be single pattern or array result: [result1, result2, ...] // Can be single result or array } ] } ``` **Example When Expression Parsing**: ```javascript // Input: when x is 42 then "correct" _ then "wrong"; { type: 'WhenExpression', value: { type: 'Identifier', value: 'x' }, cases: [ { pattern: [{ type: 'NumberLiteral', value: 42 }], result: [{ type: 'StringLiteral', value: 'correct' }] }, { pattern: [{ type: 'WildcardPattern' }], result: [{ type: 'StringLiteral', value: 'wrong' }] } ] } ``` **Multi-Value Pattern Matching**: ```javascript // Input: when x y is 0 0 then "both zero" _ _ then "not both"; { type: 'WhenExpression', value: [ { type: 'Identifier', value: 'x' }, { type: 'Identifier', value: 'y' } ], cases: [ { pattern: [ { type: 'NumberLiteral', value: 0 }, { type: 'NumberLiteral', value: 0 } ], result: [{ type: 'StringLiteral', value: 'both zero' }] }, { pattern: [ { type: 'WildcardPattern' }, { type: 'WildcardPattern' } ], result: [{ type: 'StringLiteral', value: 'not both' }] } ] } ``` **Pattern Types**: - Literals (numbers, strings, booleans) - Wildcards (`_`) - Function references (`@functionName`) - Comparison expressions (`x < 0`) - Table patterns - Parenthesized expressions #### Table Literals Supports both key-value pairs and array-like entries: ```javascript // Key-value: {name: "Alice", age: 30} // Array-like: {1, 2, 3} // Auto-assigned keys 1, 2, 3 // Mixed: {1, name: "Alice", 2} ``` **Table Literal AST Structure**: ```javascript { type: 'TableLiteral', entries: [ { key: { type: 'Identifier', value: 'name' }, value: { type: 'StringLiteral', value: 'Alice' } }, { key: null, // Array-like entry value: { type: 'NumberLiteral', value: 1 } }, { key: { type: 'NumberLiteral', value: 2 }, value: { type: 'StringLiteral', value: 'value' } } ] } ``` **Table Access AST Structure**: ```javascript // table.property { type: 'TableAccess', table: { type: 'Identifier', value: 'table' }, key: { type: 'Identifier', value: 'property' } } // table[key] { type: 'TableAccess', table: { type: 'Identifier', value: 'table' }, key: { type: 'Identifier', value: 'key' } } // Chained access: table.property[key].nested { type: 'TableAccess', table: { type: 'TableAccess', table: { type: 'TableAccess', table: { type: 'Identifier', value: 'table' }, key: { type: 'Identifier', value: 'property' } }, key: { type: 'Identifier', value: 'key' } }, key: { type: 'Identifier', value: 'nested' } } ``` ### 3. Interpreter (`lang.js`) **Purpose**: Evaluates AST nodes using the combinator foundation. **Core Architecture**: #### Standard Library Initialization The interpreter initializes a comprehensive standard library with combinator functions: **Higher-Order Functions**: - `map(f, x)`: Apply function to value or collection - `compose(f, g)`: Function composition (right-associative) - `apply(f, x)`: Function application - `pipe(f, g)`: Left-to-right function composition - `filter(p, x)`: Filter based on predicate - `reduce(f, init, x)`: Reduce with binary function - `curry(f, x, y)`: Currying support **Standard Library Implementation Example**: ```javascript function initializeStandardLibrary(scope) { // Map: Apply a function to a value or collection scope.map = function(f, x) { if (typeof f !== 'function') { throw new Error('map: first argument must be a function'); } if (x === undefined) { // Partial application: return a function that waits for the second argument return function(x) { return scope.map(f, x); }; } // Handle tables (APL-style element-wise operations) if (typeof x === 'object' && x !== null && !Array.isArray(x)) { const result = {}; for (const [key, value] of Object.entries(x)) { result[key] = f(value); } return result; } // Default: apply to single value return f(x); }; // Compose: Combine two functions into a new function scope.compose = function(f, g) { if (typeof f !== 'function') { throw new Error(`compose: first argument must be a function, got ${typeof f}`); } if (g === undefined) { // Partial application: return a function that waits for the second argument return function(g) { if (typeof g !== 'function') { throw new Error(`compose: second argument must be a function, got ${typeof g}`); } return function(x) { return f(g(x)); }; }; } if (typeof g !== 'function') { throw new Error(`compose: second argument must be a function, got ${typeof g}`); } return function(x) { return f(g(x)); }; }; // Apply: Apply a function to an argument scope.apply = function(f, x) { if (typeof f !== 'function') { throw new Error('apply: first argument must be a function'); } if (x === undefined) { // Partial application: return a function that waits for the second argument return function(x) { return f(x); }; } // Full application: apply the function to the argument return f(x); }; } ``` **Arithmetic Combinators**: - `add(x, y)`, `subtract(x, y)`, `multiply(x, y)`, `divide(x, y)` - `modulo(x, y)`, `power(x, y)`, `negate(x)` **Arithmetic Combinator Implementation**: ```javascript // Add: Add two numbers scope.add = function(x, y) { if (y === undefined) { // Partial application: return a function that waits for the second argument return function(y) { return x + y; }; } return x + y; }; // Subtract: Subtract second number from first scope.subtract = function(x, y) { if (y === undefined) { // Partial application: return a function that waits for the second argument return function(y) { return x - y; }; } return x - y; }; // Multiply: Multiply two numbers scope.multiply = function(x, y) { if (y === undefined) { // Partial application: return a function that waits for the second argument return function(y) { return x * y; }; } return x * y; }; // Divide: Divide first number by second scope.divide = function(x, y) { if (y === undefined) { // Partial application: return a function that waits for the second argument return function(y) { if (y === 0) { throw new Error('Division by zero'); } return x / y; }; } if (y === 0) { throw new Error('Division by zero'); } return x / y; }; // Negate: Negate a number scope.negate = function(x) { return -x; }; ``` **Comparison Combinators**: - `equals(x, y)`, `notEquals(x, y)` - `lessThan(x, y)`, `greaterThan(x, y)` - `lessEqual(x, y)`, `greaterEqual(x, y)` **Logical Combinators**: - `logicalAnd(x, y)`, `logicalOr(x, y)`, `logicalXor(x, y)`, `logicalNot(x)` **Enhanced Combinators**: - `identity(x)`: Returns input unchanged - `constant(x)`: Creates constant function - `flip(f, x, y)`: Flips argument order - `each(f, x)`: Multi-argument element-wise operations #### Table Operations Namespace (`t.`) Immutable table operations: - `t.map(f, table)`: Apply function to table values - `t.filter(p, table)`: Filter table values - `t.reduce(f, init, table)`: Reduce table values - `t.set(table, key, value)`: Immutable set - `t.delete(table, key)`: Immutable delete - `t.merge(table1, table2)`: Immutable merge - `t.pairs(table)`, `t.keys(table)`, `t.values(table)` - `t.length(table)`, `t.has(table, key)`, `t.get(table, key, default)` #### Scope Management - **Global Scope**: Prototypal inheritance for variable lookup - **Local Scope**: Function parameters create new scope inheriting from global - **Forward Declaration**: Recursive functions supported through placeholder creation **Scope Management Pattern**: ```javascript // Global scope: Object with standard library functions const globalScope = { ...initialState }; initializeStandardLibrary(globalScope); // Local scope: Prototypal inheritance from global scope const localScope = Object.create(globalScope); // Local variables shadow global variables // Forward declaration for recursive functions: // 1. Create placeholder function in global scope // 2. Evaluate function definition (can reference placeholder) // 3. Replace placeholder with actual function ``` #### Evaluation Functions 1. **`evalNode(node)`**: Global scope evaluation 2. **`localEvalNodeWithScope(node, scope)`**: Local scope evaluation 3. **`localEvalNode(node)`**: Internal recursion #### IO Operations - **`..in`**: Read from standard input - **`..out expression`**: Write expression result to standard output - **`..assert expression`**: Assert condition is true - **`..listen`**: Get current state from external system - **`..emit expression`**: Send value to external system **IO Operations Implementation**: ```javascript // IO Input: Read from standard input case 'IOInExpression': const rl = createReadline(); return new Promise((resolve) => { rl.question('', (input) => { rl.close(); const num = parseInt(input); resolve(isNaN(num) ? input : num); }); }); // IO Output: Write to standard output case 'IOOutExpression': const outputValue = evalNode(node.value); safeConsoleLog(outputValue); ioOperationsPerformed = true; return outputValue; // IO Assert: Assert condition is true case 'IOAssertExpression': const assertionValue = evalNode(node.value); if (!assertionValue) { throw new Error('Assertion failed'); } return assertionValue; // IO Listen: Get current state from external system case 'IOListenExpression': if (environment && typeof environment.getCurrentState === 'function') { return environment.getCurrentState(); } else { return { status: 'placeholder', message: 'State not available in standalone mode' }; } // IO Emit: Send value to external system case 'IOEmitExpression': const emitValue = evalNode(node.value); if (environment && typeof environment.emitValue === 'function') { environment.emitValue(emitValue); } else { safeConsoleLog('[EMIT]', emitValue); } ioOperationsPerformed = true; return emitValue; ``` ## Data Types ### 1. Primitives - **Numbers**: JavaScript numbers (integers and floats) - **Strings**: JavaScript strings with escape sequences - **Booleans**: `true` and `false` - **Functions**: First-class functions with partial application ### 2. Tables - **Structure**: JavaScript objects with string/number keys - **Immutability**: All operations return new tables - **APL-style Operations**: Element-wise operations on table values - **Access**: Dot notation (`table.property`) and bracket notation (`table[key]`) ### 3. Special Types - **Wildcard Pattern**: `_` (matches any value) - **Function References**: `@functionName` - **Function Arguments**: `@(expression)` ## Function System ### 1. Function Definitions ```javascript // Arrow functions f : x y -> x + y; // Traditional functions function(x, y) : x + y; // Table functions {add: x y -> x + y, multiply: x y -> x * y} ``` ### 2. Function Application - **Juxtaposition**: `f x` (left-associative) - **Parenthesized**: `f(x)` - **Composition**: `f via g` (right-associative) ### 3. Partial Application All functions support partial application: ```javascript add 5 // Returns function that adds 5 map @add 5 // Returns function that adds 5 to each element ``` **Partial Application Implementation Pattern**: ```javascript // All standard library functions follow this pattern: function exampleFunction(x, y) { if (y === undefined) { // Partial application: return a function that waits for the second argument return function(y) { return exampleFunction(x, y); }; } // Full application: perform the operation return x + y; // or whatever the operation is } // This enables currying patterns: const addFive = add 5; // Returns function that adds 5 const result = addFive 3; // Returns 8 const double = multiply 2; // Returns function that multiplies by 2 const doubled = map @double; // Returns function that doubles each element ``` ## Error Handling ### 1. Lexer Errors - Unexpected characters with line/column information - Malformed tokens (invalid numbers, strings, etc.) ### 2. Parser Errors - Unexpected tokens with context - Missing delimiters (parentheses, braces, etc.) - Malformed expressions ### 3. Interpreter Errors - Undefined variables/functions - Type mismatches - Division by zero - Table access errors - Pattern matching failures ### 4. Call Stack Tracking Comprehensive call stack tracking for debugging: ```javascript const callStackTracker = { stack: [], push: (functionName, context) => { /* ... */ }, pop: () => { /* ... */ }, reset: () => { /* ... */ }, getTrace: () => { /* ... */ } }; ``` **Call Stack Tracking**: ```javascript const callStackTracker = { stack: [], push: (functionName, context) => { /* ... */ }, pop: () => { /* ... */ }, reset: () => { /* ... */ }, getTrace: () => { /* ... */ } }; ``` ## Cross-Platform Support ### 1. Environment Detection ```javascript const isNode = typeof process !== 'undefined' && process.versions && process.versions.node; const isBun = typeof process !== 'undefined' && process.versions && process.versions.bun; const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined'; ``` ### 2. Platform-Specific Adapters - **Readline**: Node.js/Bun use `readline`, browser uses `prompt()` - **File System**: Node.js/Bun use `fs`, browser uses mock - **Console**: Safe console logging across platforms - **Process Exit**: Node.js/Bun use `process.exit()`, browser throws error ## Debug Support ### 1. Debug Mode ```javascript const DEBUG = (isNode && process.env.DEBUG) || (isBrowser && window.DEBUG) || false; ``` ### 2. Debug Functions - `debugLog(message, data)`: Safe logging across platforms - `debugError(message, error)`: Error logging with stack traces - Comprehensive debug output in parser and interpreter ## External System Integration ### 1. Environment Interface ```javascript /** * @typedef {Object} Environment * @property {Function} getCurrentState - Returns current state from external system * @property {Function} emitValue - Sends value to external system */ ``` ### 2. IO Operations - **Listen**: `environment.getCurrentState()` - **Emit**: `environment.emitValue(value)` ## Performance Considerations ### 1. Lazy Evaluation - Functions are only evaluated when called - Partial application enables deferred execution ### 2. Immutable Data - Tables are never modified in-place - New structures created for transformations ### 3. Scope Optimization - Prototypal inheritance for efficient variable lookup - Local scopes inherit from global scope ## Compatibility Requirements for C Implementation ### 1. Token Types Must implement all token types from `TokenType` enumeration with identical names and semantics. ### 2. AST Node Types Must support all AST node types with identical structure: - `Program`, `NumberLiteral`, `StringLiteral`, `BooleanLiteral` - `Identifier`, `FunctionCall`, `FunctionDeclaration`, `FunctionDefinition` - `Assignment`, `WhenExpression`, `WildcardPattern` - `TableLiteral`, `TableAccess`, `FunctionReference` - IO expression types (`IOInExpression`, `IOOutExpression`, etc.) ### 3. Standard Library Functions Must implement all standard library functions with identical signatures and behavior: - Higher-order functions (`map`, `compose`, `apply`, etc.) - Arithmetic combinators (`add`, `subtract`, `multiply`, etc.) - Comparison combinators (`equals`, `lessThan`, etc.) - Logical combinators (`logicalAnd`, `logicalOr`, etc.) - Table operations namespace (`t.map`, `t.filter`, etc.) ### 4. Operator Precedence Must implement identical operator precedence and associativity rules. ### 5. Function Application Must support juxtaposition (left-associative) and composition (right-associative) with identical semantics. ### 6. Pattern Matching Must implement `when` expressions with identical pattern matching semantics. ### 7. Error Handling Must provide similar error messages and context information. ### 8. IO Operations Must support all IO operations (`..in`, `..out`, `..assert`, `..listen`, `..emit`) with identical behavior. ## Testing Strategy The JavaScript implementation includes comprehensive test suites that should be used to validate C implementation compatibility: 1. **Lexer Tests**: Token recognition and error handling 2. **Parser Tests**: AST generation and operator precedence 3. **Interpreter Tests**: Expression evaluation and function behavior 4. **Integration Tests**: End-to-end language features 5. **Error Tests**: Error handling and reporting **Test File Structure**: ``` tests/ ├── 01_lexer_basic.txt ├── 02_arithmetic_operations.txt ├── 03_comparison_operators.txt ├── 04_logical_operators.txt ├── 05_io_operations.txt ├── 06_function_definitions.txt ├── 07_case_expressions.txt ├── 08_first_class_functions.txt ├── 09_tables.txt ├── 10_standard_library.txt ├── 11_edge_cases.txt ├── 12_advanced_tables.txt ├── 13_standard_library_complete.txt ├── 14_error_handling.txt ├── 15_performance_stress.txt ├── 16_function_composition.txt ├── 17_table_enhancements.txt ├── 18_each_combinator.txt ├── 19_embedded_functions.txt ├── 20_via_operator.txt ├── 21_enhanced_case_statements.txt ├── 22_parser_limitations.txt ├── 23_minus_operator_spacing.txt └── integration_*.txt ``` **Example Test Format**: ```javascript // Test file: 02_arithmetic_operations.txt // Test basic arithmetic operations // Test addition x : 5 + 3; ..out x; // Expected: 8 // Test subtraction y : 10 - 4; ..out y; // Expected: 6 // Test multiplication z : 6 * 7; ..out z; // Expected: 42 // Test division w : 20 / 4; ..out w; // Expected: 5 // Test unary minus neg : -5; ..out neg; // Expected: -5 // Test operator precedence result : 2 + 3 * 4; ..out result; // Expected: 14 (not 20) ``` **Critical Test Cases for C Implementation**: 1. **Operator Precedence**: Ensure `2 + 3 * 4` evaluates to 14, not 20 2. **Function Application**: Test juxtaposition `f x` vs parenthesized `f(x)` 3. **Partial Application**: Verify `add 5` returns a function 4. **Pattern Matching**: Test `when` expressions with various patterns 5. **Table Operations**: Verify immutable table operations 6. **Error Handling**: Test division by zero, undefined variables, etc. 7. **IO Operations**: Test all IO operations (`..in`, `..out`, `..assert`, etc.) 8. **Function Composition**: Test `via` operator and `compose` function 9. **Scope Management**: Test variable shadowing and recursive functions 10. **Edge Cases**: Test empty programs, malformed syntax, etc. ## Conclusion The JavaScript implementation provides a robust, well-documented foundation for the baba yaga scripting language. The C implementation should maintain strict compatibility with this architecture to ensure consistent behavior across platforms and enable seamless migration between implementations. Key architectural decisions that must be preserved: 1. Combinator foundation for all operations 2. Functional programming paradigm with immutable data 3. Comprehensive standard library with partial application support 4. Pattern matching through when expressions 5. Cross-platform IO operations 6. Detailed error reporting and debugging support ## Implementation Checklist for C Team ### Phase 1: Core Infrastructure - [ ] Implement all token types from `TokenType` enumeration - [ ] Implement lexer with character-by-character scanning - [ ] Implement parser with recursive descent parsing - [ ] Implement basic AST node types - [ ] Implement operator precedence and associativity rules ### Phase 2: Standard Library - [ ] Implement all arithmetic combinators (`add`, `subtract`, `multiply`, `divide`, etc.) - [ ] Implement all comparison combinators (`equals`, `lessThan`, etc.) - [ ] Implement all logical combinators (`logicalAnd`, `logicalOr`, etc.) - [ ] Implement higher-order functions (`map`, `compose`, `apply`, etc.) - [ ] Implement table operations namespace (`t.map`, `t.filter`, etc.) ### Phase 3: Language Features - [ ] Implement function definitions and application - [ ] Implement partial application and currying - [ ] Implement `when` expressions with pattern matching - [ ] Implement table literals and access - [ ] Implement function composition with `via` operator ### Phase 4: IO and Integration - [ ] Implement all IO operations (`..in`, `..out`, `..assert`, `..listen`, `..emit`) - [ ] Implement environment interface for external system integration - [ ] Implement cross-platform compatibility layer - [ ] Implement error handling and debugging support ### Phase 5: Testing and Validation - [ ] Run all JavaScript test suites against C implementation - [ ] Verify identical behavior for all language constructs - [ ] Test edge cases and error conditions - [ ] Performance testing and optimization ## References - **Source Files**: `lexer.js`, `parser.js`, `lang.js` - **Test Suite**: `tests/` directory with comprehensive test cases - **Documentation**: `tutorials/` directory with language tutorials - **Web Interface**: `web/` directory with AST viewer and interactive examples The C implementation should strive for 100% compatibility with the JavaScript version to ensure a seamless developer experience across both platforms.