about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--js/scripting-lang/FIXME.md106
-rw-r--r--js/scripting-lang/NEXT-STEPS.md568
-rwxr-xr-xjs/scripting-lang/analyze_test_differences.sh105
-rw-r--r--js/scripting-lang/debug_test.txt7
-rw-r--r--js/scripting-lang/func_call_test.txt8
-rw-r--r--js/scripting-lang/lang.js3028
-rw-r--r--js/scripting-lang/learn_scripting_lang.txt61
-rw-r--r--js/scripting-lang/nested_test.txt7
-rw-r--r--js/scripting-lang/paren_test.txt7
-rwxr-xr-xjs/scripting-lang/run_tests.sh8
-rw-r--r--js/scripting-lang/simple_case_test.txt7
-rw-r--r--js/scripting-lang/simple_test.txt4
-rw-r--r--js/scripting-lang/table_basic_test.txt51
-rw-r--r--js/scripting-lang/table_edge_cases_test.txt304
-rw-r--r--js/scripting-lang/tests/10_standard_library.txt8
-rw-r--r--js/scripting-lang/tests/11_edge_cases.txt50
-rw-r--r--js/scripting-lang/tests/12_advanced_tables.txt85
-rw-r--r--js/scripting-lang/tests/13_standard_library_complete.txt97
-rw-r--r--js/scripting-lang/tests/14_error_handling.txt65
-rw-r--r--js/scripting-lang/tests/15_performance_stress.txt131
-rw-r--r--js/scripting-lang/tests/16_advanced_functional.txt169
-rw-r--r--js/scripting-lang/tests/17_real_world_scenarios.txt219
-rw-r--r--js/scripting-lang/tests/integration_03_functional_programming.txt3
-rw-r--r--js/scripting-lang/tests/integration_04_mini_case_multi_param.txt (renamed from js/scripting-lang/tests/mini_case_multi_param.txt)0
24 files changed, 3356 insertions, 1742 deletions
diff --git a/js/scripting-lang/FIXME.md b/js/scripting-lang/FIXME.md
deleted file mode 100644
index b71be48..0000000
--- a/js/scripting-lang/FIXME.md
+++ /dev/null
@@ -1,106 +0,0 @@
-# FIXME - Issues and Fixes
-
-## Current Status: 8/13 tests passing
-
-### ✅ Phase 1: Critical Issues (COMPLETED)
-- **Unary Minus Operator**: ✅ Fixed - Added `UnaryMinusExpression` parsing and evaluation
-- **Stack Overflow Issues**: ✅ Fixed - Resolved circular dependencies and infinite recursion
-- **Test Runner Overconfidence**: ✅ Fixed - Added robust error handling and exit codes
-- **IO Operation Parsing**: ✅ Fixed - Moved IO parsing to proper precedence level
-- **First-Class Functions**: ✅ Fixed - Added `TokenType.FUNCTION_REF` to function call detection
-- **Function Definitions Test**: ✅ Fixed - Corrected assertion and duplicate variable assignment
-- **Parser Regression Fix**: ✅ Fixed - Removed overly broad `TokenType.MINUS` check that was breaking binary operations
-- **Parser Ambiguity with Unary Minus Arguments**: ✅ Fixed - Added special case in `parseExpression()` to handle `FunctionReference MINUS` pattern
-
-### 🔄 Phase 2: Medium Priority Issues (IN PROGRESS)
-
-#### Logical Operator Precedence Issue
-- **Issue**: `isEven 10 and isPositive 5` is parsed as `isEven(10 and isPositive(5))` instead of `(isEven 10) and (isPositive 5)`
-- **Root Cause**: Logical operators (`and`, `or`, `xor`) have the same precedence as arithmetic operators in `parseExpression()`
-- **Impact**: Complex expressions like `add (multiply 3 4) (isEven 10 and isPositive 5)` fail
-- **Status**: 🔄 In Progress - Need to implement proper operator precedence hierarchy
-- **Solution Plan**: 
-  1. Create separate precedence levels for logical operators
-  2. Ensure function calls have higher precedence than logical operators
-  3. Test with integration scenarios
-
-#### Integration Test Failures
-- **Basic Features Integration**: "Assertion failed" - Due to logical operator precedence issue
-- **Pattern Matching Integration**: "Expected closing parenthesis" - Related to precedence parsing
-- **Functional Programming Integration**: "Assertion failed" - Related to precedence parsing
-
-#### Unit Test Failures
-- **Arithmetic Operations**: "Assertion failed" - Need to investigate specific assertions
-- **Case Expressions**: "Expected closing parenthesis" - Related to precedence parsing
-
-### 🔄 Phase 3: Validation and Documentation (PENDING)
-- **Comprehensive Test Suite Validation**: Target: 13/13 tests passing
-- **Update Documentation**: README.md and FIXME.md to reflect all resolved issues
-
-## Recent Fixes
-
-### ✅ Parser Ambiguity with Unary Minus Arguments (Latest Fix)
-- **Issue**: `filter @isPositive -3` was parsed as `filter(@isPositive - 3)` instead of `filter(@isPositive, -3)`
-- **Root Cause**: `parseExpression()` was treating `FunctionReference MINUS` as a binary minus operation
-- **Solution**: Added special case in `parseExpression()` to detect when left operand is `FunctionReference` and next token is `MINUS`, returning the left operand instead of creating a binary operation
-- **Status**: ✅ Resolved - Standard Library test now passes
-
-### ✅ Parser Regression Fix
-- **Issue**: Recent changes introduced regression where binary minus operations were incorrectly parsed as function calls
-- **Root Cause**: Overly broad `TokenType.MINUS` check in function call detection logic
-- **Solution**: Removed `TokenType.MINUS` from function call detection in `parsePrimary()`
-- **Status**: ✅ Resolved - Basic arithmetic operations restored
-
-## Next Steps
-
-### Immediate Priority (Phase 2)
-1. **🔧 Fix Logical Operator Precedence**
-   - **Problem**: Logical operators need lower precedence than function calls
-   - **Current State**: `isEven 10 and isPositive 5` → `isEven(10 and isPositive(5))` ❌
-   - **Target State**: `isEven 10 and isPositive 5` → `(isEven 10) and (isPositive 5)` ✅
-   - **Approach**: 
-     - Create `parseLogicalExpression()` function with lowest precedence
-     - Modify `parseExpression()` to handle only arithmetic and comparison operators
-     - Update function call parsing to use appropriate precedence level
-     - Test with integration scenarios
-
-2. **🔧 Fix Parentheses Parsing with Logical Operators**
-   - **Problem**: `add (multiply 3 4) (isEven 10 and isPositive 5)` fails with "Expected closing parenthesis"
-   - **Root Cause**: Logical operators inside parentheses not handled correctly
-   - **Solution**: Ensure parentheses parsing respects operator precedence
-
-3. **🔧 Investigate Remaining Unit Test Failures**
-   - **Arithmetic Operations**: Check specific assertions that are failing
-   - **Case Expressions**: Fix parentheses parsing in case expression contexts
-
-### Validation Phase (Phase 3)
-4. **✅ Run Full Test Suite**
-   - Target: 13/13 tests passing
-   - Validate all integration tests work correctly
-   - Ensure no regressions in previously fixed features
-
-5. **✅ Update Documentation**
-   - Update README.md with current status
-   - Document all fixes and remaining known issues
-   - Update examples to reflect current syntax
-
-## Technical Details
-
-### Operator Precedence Hierarchy (Target)
-1. **Function calls** (highest precedence)
-2. **Unary operators** (`-`, `not`)
-3. **Multiplication/Division** (`*`, `/`, `%`)
-4. **Addition/Subtraction** (`+`, `-`)
-5. **Comparison operators** (`==`, `!=`, `<`, `>`, `<=`, `>=`)
-6. **Logical operators** (`and`, `or`, `xor`) (lowest precedence)
-
-### Current Implementation Issues
-- Logical operators are handled at the same level as arithmetic operators in `parseExpression()`
-- Function call detection doesn't respect logical operator boundaries
-- Parentheses parsing doesn't properly handle logical expressions
-
-### Success Metrics
-- ✅ All unit tests pass (10/10)
-- ✅ All integration tests pass (3/3)
-- ✅ Complex expressions like `add (multiply 3 4) (isEven 10 and isPositive 5)` evaluate correctly
-- ✅ No regressions in previously working features 
\ No newline at end of file
diff --git a/js/scripting-lang/NEXT-STEPS.md b/js/scripting-lang/NEXT-STEPS.md
index 7cb1e75..8061fb7 100644
--- a/js/scripting-lang/NEXT-STEPS.md
+++ b/js/scripting-lang/NEXT-STEPS.md
@@ -1,229 +1,435 @@
-# Next Steps: Table Features Implementation
+# Next Steps: Immutable Real-World Programming Features
 
-## Current State Analysis
+## Overview
 
-### What Works ✅
-- Basic table creation: `{name: "Alice", age: 30}`
-- Simple table access: `person.name` (single level)
-- Basic function definitions: `inc : x -> x + 1`
-- Basic function calls: `inc 5`
-- Table literals with functions: `{inc: x -> x + 1}` (parsed but not fully functional)
+This document outlines the plan for extending the Simple Scripting Language to support real-world programming scenarios while maintaining its immutable, functional design philosophy.
 
-### What's Broken ❌
-1. **Chained table access**: `config.user.name` fails with "Unexpected dot (.) token"
-2. **Function calls from tables**: `m.inc 1` doesn't work
-3. **Functions in table literals**: May not be properly interpreted
+## Core Principles
 
-## Root Cause Analysis
+- **Immutability First**: All data structures are immutable
+- **Transformation Over Mutation**: Operations return new data rather than modifying existing data
+- **Functional Composition**: Complex operations built from simple, composable functions
+- **Type Safety**: Enhanced pattern matching and type checking
+- **Performance**: Efficient persistent data structures
 
-### Issue 1: Chained Table Access
-**Problem**: Parser encounters standalone DOT tokens when parsing `config.user.name`
-**Location**: Assignment parsing logic in `walk()` function
-**Debug Evidence**: 
-- Tokens: `[IDENTIFIER "config", DOT, IDENTIFIER "user", DOT, IDENTIFIER "name"]`
-- Parser fails at position 17 (second DOT) because it's not in table access context
+## Phase 1: String Operations and Type System
 
-### Issue 2: Function Calls from Tables
-**Problem**: Parser doesn't recognize `m.inc 1` as a function call
-**Location**: Function call parsing logic
-**Expected**: Should parse as `FunctionCall` with `name: TableAccess` and `args: [1]`
+### 1.1 String Operations
+**Goal**: Add essential string manipulation capabilities
 
-## Implementation Plan
+**New Functions**:
+```javascript
+// String operations as functions
+length : string.length "hello";           // 5
+contains : string.contains "hello" "ll";  // true
+startsWith : string.startsWith "hello" "he"; // true
+endsWith : string.endsWith "hello" "lo";  // true
+substring : string.substring "hello" 1 3; // "el"
+
+// String concatenation
+result : string.concat "Hello" " " "World"; // "Hello World"
+
+// String transformation
+uppercase : string.upper "hello";         // "HELLO"
+lowercase : string.lower "HELLO";         // "hello"
+trimmed : string.trim "  hello  ";        // "hello"
+```
 
-### Phase 1: Fix Chained Table Access Parser
+**Implementation**:
+- Add `string.` namespace for string operations
+- Add string operation functions to standard library
+- No new syntax - uses existing function call patterns
+- Extend existing string literal support
 
-#### Step 1.1: Update Assignment Value Parsing
-**File**: `lang.js` around line 1300-1400
-**Change**: Modify assignment parsing to handle chained dot notation before falling back to `walk()`
+### 1.2 Runtime Type Checking with `is` Keyword
+**Goal**: Add explicit, optional type checking mechanism using the `is` keyword
 
-**Current Logic**:
-```javascript
-// Assignment parsing falls back to walk() for value
-const value = walk(); // This fails on DOT tokens
-```
+**Design Philosophy**:
+- Type checking is purely additive - no breaking changes to existing code
+- Works seamlessly with existing case expression syntax
+- Returns boolean values, fitting the functional style
+- Simple implementation with clear semantics
 
-**New Logic**:
+**New Features**:
 ```javascript
-// Check if value is a chained table access
-if (tokens[current] && tokens[current].type === TokenType.IDENTIFIER &&
-    tokens[current + 1] && tokens[current + 1].type === TokenType.DOT) {
-    // Parse chained table access
-    const tableAccess = parseChainedTableAccess();
-    return { type: 'AssignmentExpression', name, value: tableAccess };
-}
-// Fall back to walk() for other cases
-const value = walk();
+// Basic type checking
+isNumber : x -> x is number;
+isString : x -> x is string;
+isTable : x -> x is table;
+isFunction : x -> x is function;
+
+// Type-safe operations in case expressions
+safeStringOp : x -> case x of
+    x is string : string.length x
+    _ : "not a string";
+
+// Complex type validation
+validateUser : user -> case user of
+    user.name is string and user.age is number : true
+    _ : false;
+
+// Type guards in pattern matching
+processData : data -> case data of
+    data is table : "processing table"
+    data is string : "processing string"
+    data is number : "processing number"
+    _ : "unknown type";
 ```
 
-#### Step 1.2: Create parseChainedTableAccess Helper
-**File**: `lang.js` in `walk()` function
-**Purpose**: Parse arbitrary length dot notation chains
+**Supported Types**:
+- `number` (both integers and floats)
+- `string` 
+- `boolean`
+- `table` (objects and arrays)
+- `function`
 
 **Implementation**:
+- Add `IS` token type and type-specific tokens (`NUMBER_TYPE`, `STRING_TYPE`, etc.)
+- Update lexer to recognize `is` keyword and type names
+- Extend parser to handle type checking expressions in case patterns
+- Add type checking logic in interpreter that returns boolean values
+- No changes to existing syntax or semantics
+
+## Phase 2: Persistent Data Structures
+
+### 2.1 Immutable Tables with Transformations
+**Goal**: Replace mutable table operations with immutable transformations
+
+**Current Problem**:
 ```javascript
-function parseChainedTableAccess() {
-    let tableExpr = {
-        type: 'Identifier',
-        value: tokens[current].value
-    };
-    current++; // Skip first identifier
-    
-    while (tokens[current] && tokens[current].type === TokenType.DOT) {
-        current++; // Skip dot
-        if (tokens[current] && tokens[current].type === TokenType.IDENTIFIER) {
-            const key = {
-                type: 'StringLiteral',
-                value: tokens[current].value
-            };
-            current++; // Skip identifier
-            
-            tableExpr = {
-                type: 'TableAccess',
-                table: tableExpr,
-                key
-            };
-        } else {
-            throw new Error('Expected identifier after dot in table access');
-        }
-    }
-    
-    return tableExpr;
-}
+// This won't work (mutable)
+cache[key] = value;
 ```
 
-#### Step 1.3: Update Function Call Parsing
-**File**: `lang.js` around line 600-700
-**Change**: Allow `TableAccess` nodes as function names
-
-**Current Logic**:
+**Solution - Functional Immutable Transformations**:
 ```javascript
-// Only handles string function names
-func = globalScope[node.name];
+// Functional transformations using table namespace
+cache : {};
+cache1 : table.set cache "user.1" "Alice";
+cache2 : table.set cache1 "user.2" "Bob";
+value : table.get cache2 "user.1";  // "Alice"
+cache3 : table.delete cache2 "user.1";
+
+// Nested updates with dot notation
+user : {name: "Alice", profile: {age: 25}};
+updatedUser : table.set user "profile.age" 26;
+
+// Complex transformations using composition
+cache1 : pipe
+    (table.set "user.1" "Alice")
+    (table.set "user.2" "Bob")
+    (table.set "user.3" "Charlie")
+    cache;
+
+// Table merging
+combined : table.merge table1 table2;
 ```
 
-**New Logic**:
+**Implementation**:
+- Add `table.set`, `table.get`, `table.delete`, `table.merge` functions
+- Implement efficient structural sharing for immutable updates
+- Add nested key support (e.g., "profile.age")
+- All functions return new tables, never modify originals
+- Use existing function composition patterns
+
+### 2.2 APL-Inspired Table Primitives
+**Goal**: Enhance tables with APL-style operations for ergonomic data manipulation
+
+**Design Philosophy**:
+- Use existing table syntax for array-like behavior
+- Add APL-inspired primitives for vectorized operations
+- Keep immutable transformations
+- Provide concise, expressive data manipulation
+
+**New Features**:
 ```javascript
-if (typeof node.name === 'string') {
-    func = globalScope[node.name];
-} else if (node.name.type === 'TableAccess') {
-    // Evaluate table access to get function
-    func = evalNode(node.name);
-    if (typeof func !== 'function') {
-        throw new Error('Table access did not resolve to a function');
-    }
-}
+// Table creation (array-like using existing syntax)
+numbers : {1, 2, 3, 4, 5};
+mixed : {1, "hello", true, {key: "value"}};
+
+// All table operations namespaced for consistency
+first : table.first numbers;              // First element
+last : table.last numbers;                // Last element
+length : table.length numbers;            // Size/shape
+
+// Less common operations (namespaced)
+rest : table.drop 1 numbers;        // Drop first element  
+slice : table.slice numbers 2 3;    // Elements 2-3
+
+// Vectorized operations
+doubled : table.add numbers numbers;      // Element-wise addition
+squared : table.multiply numbers numbers; // Element-wise multiplication
+incremented : table.add numbers 1;        // Scalar addition to each element
+
+// Reductions (all namespaced)
+sum : table.sum numbers;                 // Sum reduction
+max : table.max numbers;                 // Maximum reduction
+min : table.min numbers;                 // Minimum reduction
+product : table.product numbers;   // Product reduction
+average : table.average numbers;   // Average reduction
+
+// Scan operations (namespaced)
+runningSum : table.scan table.sum numbers;        // Running sum scan
+runningProduct : table.scan table.product numbers; // Running product scan
+
+// Table metadata operations
+keys : table.keys table;           // Get all keys
+values : table.values table;       // Get all values
+reversed : table.reverse table;    // Reverse order
+sorted : table.sort table;         // Sort
+unique : table.unique table;       // Remove duplicates
 ```
 
-### Phase 2: Fix Function Calls from Tables
+**Implementation**:
+- Add `table.` namespace for all table operations
+- Extend lexer to recognize table operation keywords
+- Add vectorized operation logic in interpreter
+- Implement reduction and scan operations
+- Add table metadata operations
+
+## Phase 3: Higher-Order Functions for Collections
 
-#### Step 2.1: Update Function Call Detection
-**File**: `lang.js` in `parseFunctionCall()` function
-**Change**: Detect when a table access is followed by arguments
+### 3.1 Enhanced Standard Library
+**Goal**: Add collection processing functions
 
-**Current Logic**:
+**New Functions**:
 ```javascript
-// Only checks for identifier followed by arguments
-if (tokens[current + 1] && tokens[current + 1].type === TokenType.NUMBER) {
-    // Function call
-}
+// Table processing (using namespaced primitives)
+numbers : {1, 2, 3, 4, 5};
+doubled : map @double numbers;                // {2, 4, 6, 8, 10}
+evens : filter @isEven numbers;               // {2, 4}
+sum : table.sum numbers;                      // 15 (sum reduction)
+
+// Table metadata operations
+table : {a: 1, b: 2, c: 3};
+keys : table.keys table;                      // {a, b, c}
+values : table.values table;                  // {1, 2, 3}
+pairs : table.pairs table;                    // {{a, 1}, {b, 2}, {c, 3}}
+
+// Advanced operations with tables
+nested : {{1, 2}, {3, 4}, {5}};
+flattened : table.flatten nested;             // {1, 2, 3, 4, 5}
+grouped : table.groupBy @isEven numbers;     // {true: {2, 4}, false: {1, 3, 5}}
+
+// Table operations
+reversed : table.reverse numbers;             // {5, 4, 3, 2, 1}
+sorted : table.sort numbers;                  // {1, 2, 3, 4, 5}
+unique : table.unique {1, 2, 2, 3, 3, 4};   // {1, 2, 3, 4}
 ```
 
-**New Logic**:
+**Implementation**:
+- Extend existing `map`, `filter`, `reduce` to work with tables
+- Implement vectorized operations for tables
+- Add reduction and scan operations
+- Implement table metadata operations
+
+### 3.2 Table Generation Helpers
+**Goal**: Add convenient table creation functions
+
+**New Functions**:
 ```javascript
-// Check for identifier followed by arguments OR table access followed by arguments
-if ((tokens[current + 1] && tokens[current + 1].type === TokenType.NUMBER) ||
-    (tokens[current + 1] && tokens[current + 1].type === TokenType.DOT)) {
-    // Parse table access first, then check for arguments
-    const tableAccess = parseChainedTableAccess();
-    if (tokens[current] && isArgumentToken(tokens[current])) {
-        // This is a function call from table
-        return parseFunctionCallFromTable(tableAccess);
-    }
-    return tableAccess;
-}
+// Table generation helpers
+range : table.range 1 5;           // {1, 2, 3, 4, 5}
+repeated : table.repeat "hello" 3; // {"hello", "hello", "hello"}
+
+// Use existing map/filter instead of comprehensions
+squares : map (x -> x * x) {1, 2, 3, 4, 5};
+evens : filter @isEven {1, 2, 3, 4, 5};
 ```
 
-#### Step 2.2: Create parseFunctionCallFromTable Helper
-**Purpose**: Parse function calls where the function is a table access
+## Phase 4: Error Handling with Error Type
+
+### 4.1 Error Type
+**Goal**: Provide consistent error handling without complex monads
 
 **Implementation**:
 ```javascript
-function parseFunctionCallFromTable(tableAccess) {
-    const args = [];
-    while (current < tokens.length && isArgumentToken(tokens[current])) {
-        args.push(walk());
-    }
-    return {
-        type: 'FunctionCall',
-        name: tableAccess,
-        args
-    };
-}
+// Simple error type
+error : message -> {type: "error", message: message};
+
+// Safe operations with error handling
+safeDivide : x y -> case y of
+    0 : error "division by zero"
+    _ : x / y;
+
+safeParseNumber : str -> case str of
+    str is number : str
+    _ : error "invalid number";
+
+// Error checking
+isError : value -> value is error;
+getErrorMessage : error -> case error of
+    {type: "error", message: m} : m;
 ```
 
-### Phase 3: Test and Validate
-
-#### Step 3.1: Create Comprehensive Test Suite
-**File**: `table_features_test.txt`
-
-**Test Cases**:
-```plaintext
-/* Test 1: Basic table access */
-person : {name: "Alice", age: 30};
-name : person.name;
-..out name; /* Should output: Alice */
+## Phase 5: Real-World Scenario Support
 
-/* Test 2: Chained table access */
-config : {user: {profile: {name: "Bob"}}};
-deep_name : config.user.profile.name;
-..out deep_name; /* Should output: Bob */
+### 5.1 User Management System
+**Immutable Implementation**:
+```javascript
+// User validation
+isValidEmail : email -> case email of
+    email contains "@" : true
+    _ : false;
+
+createUser : name email age -> case (isValidEmail email) and (isValidAge age) of
+    true : {name: name, email: email, age: age, status: "active"}
+    false : error "invalid user data";
+
+// User management
+users : {};
+user1 : createUser "Alice" "alice@example.com" 25;
+users1 : table.set users "user.1" user1;
+user2 : createUser "Bob" "bob@example.com" 30;
+users2 : table.set users1 "user.2" user2;
+
+// Safe user lookup
+findUser : email users -> case users of
+    {} : error "user not found"
+    _ : case (table.first users).email = email of
+        true : table.first users
+        false : findUser email (table.drop 1 users);
+```
 
-/* Test 3: Functions in tables */
-math : {
-    add : x y -> x + y,
-    sub : x y -> x - y,
-    double : x -> x * 2
+### 5.2 Shopping Cart System
+**Immutable Implementation**:
+```javascript
+// Cart operations
+emptyCart : {items: {}, total: 0};
+addItem : cart item -> {
+    items: table.set cart.items (table.length cart.items + 1) item,
+    total: cart.total + item.price
+};
+removeItem : cart itemId -> {
+    items: filter (item -> item.id != itemId) cart.items,
+    total: calculateTotal (filter (item -> item.id != itemId) cart.items)
 };
 
-/* Test 4: Function calls from tables */
-result1 : math.add 3 4;     /* Should be 7 */
-result2 : math.sub 10 3;    /* Should be 7 */
-result3 : math.double 5;    /* Should be 10 */
-..out result1;
-..out result2;
-..out result3;
-
-/* Test 5: Nested function calls from tables */
-nested : math.double(math.add 2 3); /* Should be 10 */
-..out nested;
+// Discount application
+applyDiscount : cart discountPercent -> {
+    items: cart.items,
+    total: cart.total * (1 - discountPercent / 100)
+};
 ```
 
-#### Step 3.2: Debug and Fix Issues
-- Run tests and identify any remaining issues
-- Add debug logging as needed
-- Fix edge cases and error handling
-
-## Implementation Order
-
-1. **Phase 1.1**: Update assignment value parsing
-2. **Phase 1.2**: Create parseChainedTableAccess helper
-3. **Phase 1.3**: Update function call parsing
-4. **Phase 2.1**: Update function call detection
-5. **Phase 2.2**: Create parseFunctionCallFromTable helper
-6. **Phase 3.1**: Create comprehensive test suite
-7. **Phase 3.2**: Debug and validate
+### 5.3 Data Processing Pipeline
+**Immutable Implementation**:
+```javascript
+// Data processing
+salesData : {
+    {month: "Jan", sales: 1000, region: "North"},
+    {month: "Feb", sales: 1200, region: "North"},
+    {month: "Mar", sales: 800, region: "South"}
+};
 
-## Success Criteria
+// Filter by region
+filterByRegion : data region -> filter (item -> item.region = region) data;
 
-- ✅ `config.user.name` parses and evaluates correctly
-- ✅ `m.inc 1` parses and evaluates to 2
-- ✅ `m.inc(m.dec(5))` works with nested calls
-- ✅ Functions defined in table literals work correctly
-- ✅ No regression in existing functionality
+// Calculate totals using sum reduction
+sumSales : data -> table.sum (map (item -> item.sales) data);
 
-## Risk Mitigation
+// Process pipeline
+northData : filterByRegion salesData "North";
+northTotal : sumSales northData;
+```
 
-- **Minimal changes**: Each change targets a specific issue
-- **Debug logging**: Keep debug output to trace issues
-- **Incremental testing**: Test each phase before proceeding
-- **Fallback logic**: Maintain existing `walk()` fallback for non-table cases 
\ No newline at end of file
+## Implementation Timeline
+
+### Week 1-2: String Operations and Runtime Type Checking
+- [ ] String concatenation operator
+- [ ] String method implementations
+- [ ] `is` keyword and type checking tokens
+- [ ] Type checking in case expressions
+- [ ] Type validation functions in standard library
+
+### Week 3-4: Table Primitives with Namespacing
+- [ ] `table.` namespace for all table operations
+- [ ] Vectorized operations for tables
+- [ ] Reduction and scan operations
+- [ ] Table metadata operations
+- [ ] Performance optimization
+
+### Week 5-6: Higher-Order Functions
+- [ ] Enhanced standard library
+- [ ] Collection processing functions
+- [ ] Table-specific operations
+- [ ] Utility functions
+
+### Week 7-8: Error Handling
+- [ ] Error type implementation
+- [ ] Error handling patterns
+- [ ] Error checking functions
+- [ ] Integration with existing operations
+
+### Week 9-10: Real-World Scenarios
+- [ ] User management system
+- [ ] Shopping cart system
+- [ ] Data processing pipeline
+- [ ] Integration testing
+
+## Benefits of Runtime Type Checking Approach
+
+### Simplicity
+- **Minimal Implementation**: Only need to add `is` keyword and type checking logic
+- **No Breaking Changes**: Existing code continues to work unchanged
+- **Clear Semantics**: `x is number` is obviously a boolean expression
+- **Consistent Syntax**: Works seamlessly with existing case expressions
+
+### Functional Design
+- **Boolean Results**: Type checking returns true/false, fitting functional style
+- **Composable**: Can combine with logical operators (`and`, `or`, `not`)
+- **Pattern Matching**: Integrates naturally with case expressions
+- **No Side Effects**: Pure functions for type validation
+
+### Extensibility
+- **Easy to Add Types**: Simple to extend for new types (arrays, tuples, etc.)
+- **Custom Types**: Can implement custom type checking via functions
+- **Performance**: Runtime overhead only when explicitly used
+- **Optional**: No requirement to use type checking in existing code
+
+## Testing Strategy
+
+### Unit Tests
+- String operation tests
+- Runtime type checking tests (`is` keyword)
+- Type validation function tests
+- Data structure transformation tests
+- Higher-order function tests
+- Error handling tests
+
+### Integration Tests
+- Real-world scenario tests
+- Performance tests
+- Edge case tests
+- Error handling tests
+
+### Performance Benchmarks
+- Data structure operation performance
+- Memory usage analysis
+- Transformation efficiency
+- Scalability testing
+
+## Success Metrics
+
+- [ ] All real-world scenarios in `tests/17_real_world_scenarios.txt` pass
+- [ ] Performance within acceptable bounds (no more than 2x slower than current)
+- [ ] Memory usage remains reasonable
+- [ ] Code remains readable and maintainable
+- [ ] Backward compatibility maintained
+
+## Future Considerations
+
+### Advanced Features (Post-v1.0)
+- Lazy evaluation for large collections
+- Parallel processing capabilities
+- Advanced type system with generics
+- Macro system for code generation
+- Module system for code organization
+
+### Performance Optimizations
+- Structural sharing for immutable data structures
+- Compile-time optimizations
+- JIT compilation for hot paths
+- Memory pooling for temporary objects
+
+This plan maintains the language's functional, immutable design while adding the capabilities needed for real-world programming scenarios. 
\ No newline at end of file
diff --git a/js/scripting-lang/analyze_test_differences.sh b/js/scripting-lang/analyze_test_differences.sh
deleted file mode 100755
index 41a2ced..0000000
--- a/js/scripting-lang/analyze_test_differences.sh
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/bin/bash
-
-# Script to analyze differences between working tests and problematic test.txt
-
-echo "=== Test Analysis Tool ==="
-echo ""
-
-echo "1. Checking file sizes:"
-echo "   Working test files:"
-for file in tests/*.txt; do
-    if [ -f "$file" ]; then
-        lines=$(wc -l < "$file")
-        echo "   - $(basename "$file"): $lines lines"
-    fi
-done
-
-echo ""
-echo "   Original test.txt:"
-if [ -f "test.txt" ]; then
-    lines=$(wc -l < "test.txt")
-    echo "   - test.txt: $lines lines"
-else
-    echo "   - test.txt: not found"
-fi
-
-echo ""
-echo "2. Testing sections of test.txt:"
-
-if [ -f "test.txt" ]; then
-    # Extract first 50 lines and test
-    echo "   Testing first 50 lines..."
-    head -50 test.txt > temp_section1.txt
-    if node lang.js temp_section1.txt > /dev/null 2>&1; then
-        echo "   ✅ First 50 lines: PASS"
-    else
-        echo "   ❌ First 50 lines: FAIL"
-    fi
-    rm temp_section1.txt
-
-    # Extract lines 51-100 and test
-    echo "   Testing lines 51-100..."
-    sed -n '51,100p' test.txt > temp_section2.txt
-    if [ -s temp_section2.txt ]; then
-        if node lang.js temp_section2.txt > /dev/null 2>&1; then
-            echo "   ✅ Lines 51-100: PASS"
-        else
-            echo "   ❌ Lines 51-100: FAIL"
-        fi
-    else
-        echo "   ⚠️  Lines 51-100: Empty"
-    fi
-    rm temp_section2.txt
-
-    # Extract lines 101-150 and test
-    echo "   Testing lines 101-150..."
-    sed -n '101,150p' test.txt > temp_section3.txt
-    if [ -s temp_section3.txt ]; then
-        if node lang.js temp_section3.txt > /dev/null 2>&1; then
-            echo "   ✅ Lines 101-150: PASS"
-        else
-            echo "   ❌ Lines 101-150: FAIL"
-        fi
-    else
-        echo "   ⚠️  Lines 101-150: Empty"
-    fi
-    rm temp_section3.txt
-
-    # Continue with more sections if needed
-    echo "   Testing lines 151-200..."
-    sed -n '151,200p' test.txt > temp_section4.txt
-    if [ -s temp_section4.txt ]; then
-        if node lang.js temp_section4.txt > /dev/null 2>&1; then
-            echo "   ✅ Lines 151-200: PASS"
-        else
-            echo "   ❌ Lines 151-200: FAIL"
-        fi
-    else
-        echo "   ⚠️  Lines 151-200: Empty"
-    fi
-    rm temp_section4.txt
-
-else
-    echo "   test.txt not found"
-fi
-
-echo ""
-echo "3. Unique constructs in test.txt:"
-if [ -f "test.txt" ]; then
-    echo "   Checking for unique patterns..."
-    
-    # Look for unique function call patterns
-    echo "   - Function calls with complex nesting:"
-    grep -n "add.*add.*add" test.txt | head -3
-    
-    # Look for unique case expression patterns
-    echo "   - Complex case expressions:"
-    grep -n "case.*case.*case" test.txt | head -3
-    
-    # Look for unique table patterns
-    echo "   - Complex table literals:"
-    grep -n "\\{.*\\{.*\\}" test.txt | head -3
-fi
-
-echo ""
-echo "Analysis complete." 
\ No newline at end of file
diff --git a/js/scripting-lang/debug_test.txt b/js/scripting-lang/debug_test.txt
new file mode 100644
index 0000000..246c3fd
--- /dev/null
+++ b/js/scripting-lang/debug_test.txt
@@ -0,0 +1,7 @@
+/* Simple test for case expressions */
+factorial : n -> case n of
+    0 : 1
+    _ : n * (factorial (n - 1));
+
+test : factorial 5;
+..out test; 
\ No newline at end of file
diff --git a/js/scripting-lang/func_call_test.txt b/js/scripting-lang/func_call_test.txt
new file mode 100644
index 0000000..826eb4e
--- /dev/null
+++ b/js/scripting-lang/func_call_test.txt
@@ -0,0 +1,8 @@
+/* Test function calls in case expressions */
+add : x y -> x + y;
+factorial : n -> case n of
+    0 : 1
+    _ : add n 1;
+
+test : factorial 5;
+..out test; 
\ No newline at end of file
diff --git a/js/scripting-lang/lang.js b/js/scripting-lang/lang.js
index 50990b2..1a0d77e 100644
--- a/js/scripting-lang/lang.js
+++ b/js/scripting-lang/lang.js
@@ -1,14 +1,29 @@
 /**
  * Initializes the standard library in the provided scope.
  * 
- * Why: Injecting the standard library directly into the scope ensures that user code can access these functions as if they were built-in, without special syntax or reserved keywords. This approach also allows for easy extension and testing, as the library is just a set of regular functions in the scope chain.
+ * @param {Object} scope - The global scope object to inject functions into
  * 
- * How: Each function is added as a property of the scope object. Functions are written to check argument types at runtime, since the language is dynamically typed and does not enforce arity or types at parse time.
+ * @description Injects higher-order functions into the interpreter's global scope.
+ * These functions provide functional programming utilities like map, compose, pipe, etc.
+ * 
+ * @why Injecting the standard library directly into the scope ensures that user code 
+ * can access these functions as if they were built-in, without special syntax or 
+ * reserved keywords. This approach also allows for easy extension and testing, as 
+ * the library is just a set of regular functions in the scope chain.
+ * 
+ * @how Each function is added as a property of the scope object. Functions are written 
+ * to check argument types at runtime, since the language is dynamically typed and 
+ * does not enforce arity or types at parse time.
  */
 function initializeStandardLibrary(scope) {
-    // Map: Apply a function to each element
+    /**
+     * Map: Apply a function to a value
+     * @param {Function} f - Function to apply
+     * @param {*} x - Value to apply function to
+     * @returns {*} Result of applying f to x
+     * @throws {Error} When first argument is not a function
+     */
     scope.map = function(f, x) { 
-        // Handle function references by calling them if they're functions
         if (typeof f === 'function') {
             return f(x);
         } else {
@@ -16,17 +31,36 @@ function initializeStandardLibrary(scope) {
         }
     };
     
-    // Compose: Compose two functions (f ∘ g)(x) = f(g(x))
+    /**
+     * Compose: Compose two functions (f ∘ g)(x) = f(g(x))
+     * @param {Function} f - Outer function
+     * @param {Function} g - Inner function  
+     * @param {*} [x] - Optional argument to apply composed function to
+     * @returns {Function|*} Either a composed function or the result of applying it
+     * @throws {Error} When first two arguments are not functions
+     */
     scope.compose = function(f, g, x) { 
         if (typeof f === 'function' && typeof g === 'function') {
-            return f(g(x));
+            if (arguments.length === 3) {
+                return f(g(x));
+            } else {
+                return function(x) {
+                    return f(g(x));
+                };
+            }
         } else {
             throw new Error('compose: first two arguments must be functions');
         }
     };
     
-    // Curry: Convert a function that takes multiple arguments into a series of functions
-    // Since our language already uses curried functions by default, this is mostly for explicit currying
+    /**
+     * Curry: Apply a function to arguments (simplified currying)
+     * @param {Function} f - Function to curry
+     * @param {*} x - First argument
+     * @param {*} y - Second argument
+     * @returns {*} Result of applying f to x and y
+     * @throws {Error} When first argument is not a function
+     */
     scope.curry = function(f, x, y) { 
         if (typeof f === 'function') {
             return f(x, y);
@@ -35,7 +69,13 @@ function initializeStandardLibrary(scope) {
         }
     };
     
-    // Apply: Apply a function to an argument (same as function call, but more explicit)
+    /**
+     * Apply: Apply a function to an argument (explicit function application)
+     * @param {Function} f - Function to apply
+     * @param {*} x - Argument to apply function to
+     * @returns {*} Result of applying f to x
+     * @throws {Error} When first argument is not a function
+     */
     scope.apply = function(f, x) { 
         if (typeof f === 'function') {
             return f(x);
@@ -44,18 +84,35 @@ function initializeStandardLibrary(scope) {
         }
     };
     
-    // Pipe: Compose functions in left-to-right order (opposite of compose)
-    // pipe f g x = g f x
+    /**
+     * Pipe: Compose functions in left-to-right order (opposite of compose)
+     * @param {Function} f - First function
+     * @param {Function} g - Second function
+     * @param {*} [x] - Optional argument to apply piped function to
+     * @returns {Function|*} Either a piped function or the result of applying it
+     * @throws {Error} When first two arguments are not functions
+     */
     scope.pipe = function(f, g, x) { 
         if (typeof f === 'function' && typeof g === 'function') {
-            return g(f(x));
+            if (arguments.length === 3) {
+                return g(f(x));
+            } else {
+                return function(x) {
+                    return g(f(x));
+                };
+            }
         } else {
             throw new Error('pipe: first two arguments must be functions');
         }
     };
     
-    // Filter: Filter based on a predicate
-    // For now, we'll implement it as a higher-order function
+    /**
+     * Filter: Filter a value based on a predicate
+     * @param {Function} p - Predicate function
+     * @param {*} x - Value to test
+     * @returns {*|0} The value if predicate is true, 0 otherwise
+     * @throws {Error} When first argument is not a function
+     */
     scope.filter = function(p, x) { 
         if (typeof p === 'function') {
             return p(x) ? x : 0;
@@ -64,8 +121,14 @@ function initializeStandardLibrary(scope) {
         }
     };
     
-    // Reduce: Reduce to a single value using a binary function
-    // For now, we'll implement it as a higher-order function
+    /**
+     * Reduce: Reduce two values using a binary function
+     * @param {Function} f - Binary function
+     * @param {*} init - Initial value
+     * @param {*} x - Second value
+     * @returns {*} Result of applying f to init and x
+     * @throws {Error} When first argument is not a function
+     */
     scope.reduce = function(f, init, x) { 
         if (typeof f === 'function') {
             return f(init, x);
@@ -74,7 +137,14 @@ function initializeStandardLibrary(scope) {
         }
     };
     
-    // Fold: Same as reduce, but more explicit about the folding direction
+    /**
+     * Fold: Same as reduce, but more explicit about the folding direction
+     * @param {Function} f - Binary function
+     * @param {*} init - Initial value
+     * @param {*} x - Second value
+     * @returns {*} Result of applying f to init and x
+     * @throws {Error} When first argument is not a function
+     */
     scope.fold = function(f, init, x) { 
         if (typeof f === 'function') {
             return f(init, x);
@@ -85,9 +155,15 @@ function initializeStandardLibrary(scope) {
 }
 
 /**
- * TokenType is a flat object, not an enum, to allow for fast string comparisons and easy extensibility.
+ * TokenType enumeration for all supported token types.
+ * 
+ * @type {Object.<string, string>}
  * 
- * Why: Using a flat object avoids the need for import/export or enum boilerplate, and makes it easy to add new token types as the language evolves.
+ * @description A flat object mapping token names to their string representations.
+ * This approach allows for fast string comparisons and easy extensibility.
+ * 
+ * @why Using a flat object avoids the need for import/export or enum boilerplate, 
+ * and makes it easy to add new token types as the language evolves.
  */
 const TokenType = {
     NUMBER: 'NUMBER',
@@ -135,11 +211,25 @@ const TokenType = {
 /**
  * Lexer: Converts source code to tokens.
  * 
- * How: Uses a single pass with a while loop and manual character inspection. Handles whitespace, comments (with nesting), numbers (including decimals), strings, identifiers/keywords, and both single- and multi-character operators.
+ * @param {string} input - Source code to tokenize
+ * @returns {Array.<Object>} Array of token objects with type and value properties
+ * @throws {Error} For unterminated strings or unexpected characters
+ * 
+ * @description Performs lexical analysis by converting source code into a stream of tokens.
+ * Handles whitespace, nested comments, numbers (integers and decimals), strings, 
+ * identifiers/keywords, and both single- and multi-character operators.
+ * 
+ * @how Uses a single pass with a while loop and manual character inspection. 
+ * Each character is examined to determine the appropriate token type, with 
+ * special handling for multi-character tokens and nested constructs.
  * 
- * Why: Manual lexing allows for fine-grained control over tokenization, especially for edge cases like nested comments and multi-character IO operations. This approach also makes it easier to debug and extend the lexer for new language features.
+ * @why Manual lexing allows for fine-grained control over tokenization, especially 
+ * for edge cases like nested comments and multi-character IO operations. This 
+ * approach also makes it easier to debug and extend the lexer for new language features.
  * 
- * Notably, IO operations (..in, ..out, ..assert) are recognized as multi-character tokens to avoid ambiguity with the dot operator. Decimal numbers are parsed as a single token to support floating point arithmetic.
+ * @note IO operations (..in, ..out, ..assert) are recognized as multi-character 
+ * tokens to avoid ambiguity with the dot operator. Decimal numbers are parsed 
+ * as a single token to support floating point arithmetic.
  */
 function lexer(input) {
     let current = 0;
@@ -154,7 +244,7 @@ function lexer(input) {
             continue;
         }
         
-        // Skip comments
+        // Handle nested comments: /* ... */ with support for /* /* ... */ */
         if (char === '/' && input[current + 1] === '*') {
             let commentDepth = 1;
             current += 2; // Skip /*
@@ -173,7 +263,7 @@ function lexer(input) {
             continue;
         }
         
-        // Numbers
+        // Parse numbers (integers and decimals)
         if (/[0-9]/.test(char)) {
             let value = '';
             while (current < input.length && /[0-9]/.test(input[current])) {
@@ -205,7 +295,7 @@ function lexer(input) {
             continue;
         }
         
-        // Strings
+        // Parse string literals
         if (char === '"') {
             let value = '';
             current++; // Skip opening quote
@@ -227,7 +317,7 @@ function lexer(input) {
             continue;
         }
         
-        // Identifiers and keywords
+        // Parse identifiers and keywords
         if (/[a-zA-Z_]/.test(char)) {
             let value = '';
             while (current < input.length && /[a-zA-Z0-9_]/.test(input[current])) {
@@ -276,7 +366,7 @@ function lexer(input) {
             continue;
         }
         
-        // Two-character operators
+        // Parse two-character operators
         if (current + 1 < input.length) {
             const twoChar = char + input[current + 1];
             switch (twoChar) {
@@ -301,7 +391,7 @@ function lexer(input) {
                     current += 2;
                     continue;
                 case '..':
-                    // Check for IO operations
+                    // Parse IO operations: ..in, ..out, ..assert
                     if (current + 2 < input.length) {
                         const ioChar = input[current + 2];
                         switch (ioChar) {
@@ -344,7 +434,7 @@ function lexer(input) {
             }
         }
         
-        // Single character operators
+        // Parse single character operators
         switch (char) {
             case '+':
                 tokens.push({ type: TokenType.PLUS });
@@ -416,27 +506,64 @@ function lexer(input) {
         current++;
     }
     
+
+    
     return tokens;
 }
 
 /**
  * Parser: Converts tokens to an Abstract Syntax Tree (AST).
  * 
- * How: Implements a recursive descent parser, with separate functions for each precedence level (expression, term, factor, primary). Handles chained table access, function calls, and complex constructs like case expressions and function definitions.
+ * @param {Array.<Object>} tokens - Array of tokens from the lexer
+ * @returns {Object} Abstract Syntax Tree with program body
+ * @throws {Error} For parsing errors like unexpected tokens or missing delimiters
+ * 
+ * @description Implements a recursive descent parser that builds an AST from tokens.
+ * Handles all language constructs including expressions, statements, function 
+ * definitions, case expressions, table literals, and IO operations.
  * 
- * Why: Recursive descent is chosen for its clarity and flexibility, especially for a language with many context-sensitive constructs (e.g., case expressions, function definitions, chained access). The parser is structured to minimize circular dependencies and infinite recursion, with careful placement of IO and case expression parsing.
+ * @how Implements a recursive descent parser, with separate functions for each 
+ * precedence level (expression, term, factor, primary). Handles chained table 
+ * access, function calls, and complex constructs like case expressions and 
+ * function definitions.
  * 
- * The parser also supports multi-parameter case expressions and function definitions, using lookahead to distinguish between assignments and function declarations. Table literals are parsed with support for both array-like and key-value entries, inspired by Lua.
+ * @why Recursive descent is chosen for its clarity and flexibility, especially 
+ * for a language with many context-sensitive constructs (e.g., case expressions, 
+ * function definitions, chained access). The parser is structured to minimize 
+ * circular dependencies and infinite recursion, with careful placement of IO 
+ * and case expression parsing.
+ * 
+ * @note The parser supports multi-parameter case expressions and function 
+ * definitions, using lookahead to distinguish between assignments and function 
+ * declarations. Table literals are parsed with support for both array-like and 
+ * key-value entries, inspired by Lua.
  */
 function parser(tokens) {
     let current = 0;
+    let parsingFunctionArgs = false; // Flag to track when we're parsing function arguments
     
-    function walk() {
-        function parseChainedDotAccess(tableExpr) {
+    // Reset call stack tracker for parser
+    callStackTracker.reset();
+    
+    // Define all parsing functions outside of walk to avoid circular dependencies
+    
+    function parseChainedDotAccess(tableExpr) {
+        callStackTracker.push('parseChainedDotAccess', '');
+        
+        try {
             /**
              * Handles chained dot access (e.g., table.key.subkey).
              * 
-             * Why: Chained access is parsed iteratively rather than recursively to avoid deep call stacks and to allow for easy extension (e.g., supporting method calls in the future).
+             * @param {Object} tableExpr - The table expression to chain access from
+             * @returns {Object} AST node representing the chained access
+             * @throws {Error} When expected identifier is missing after dot
+             * 
+             * @description Parses dot notation for table access, building a chain
+             * of TableAccess nodes for nested property access.
+             * 
+             * @why Chained access is parsed iteratively rather than recursively to 
+             * avoid deep call stacks and to allow for easy extension (e.g., supporting 
+             * method calls in the future).
              */
             let result = tableExpr;
             
@@ -461,13 +588,28 @@ function parser(tokens) {
             }
             
             return result;
+        } finally {
+            callStackTracker.pop();
         }
+    }
+    
+    function parseChainedTableAccess(tableExpr) {
+        callStackTracker.push('parseChainedTableAccess', '');
         
-        function parseChainedTableAccess(tableExpr) {
+        try {
             /**
              * Handles chained bracket and dot access (e.g., table[0].key).
              * 
-             * Why: This function allows for flexible access patterns, supporting both array and object semantics. Chaining is handled by checking for further access tokens after each access.
+             * @param {Object} tableExpr - The table expression to chain access from
+             * @returns {Object} AST node representing the chained access
+             * @throws {Error} When expected closing bracket is missing
+             * 
+             * @description Parses both bracket and dot notation for table access,
+             * supporting mixed access patterns like table[0].key.
+             * 
+             * @why This function allows for flexible access patterns, supporting both 
+             * array and object semantics. Chaining is handled by checking for further 
+             * access tokens after each access.
              */
             if (current < tokens.length && tokens[current].type === TokenType.LEFT_BRACKET) {
                 current++; // Skip '['
@@ -519,18 +661,166 @@ function parser(tokens) {
             }
             
             return tableExpr;
+        } finally {
+            callStackTracker.pop();
         }
+    }
+    
+    function parseArgument() {
+        callStackTracker.push('parseArgument', '');
         
-        function detectAmbiguousFunctionCalls() {
-            // This is a placeholder for future ambiguous function call detection
-            // For now, we'll assume the parser handles function calls correctly
+        try {
+            const token = tokens[current];
+            if (!token) {
+                throw new Error('Unexpected end of input');
+            }
+            
+            // Parse unary operators
+            if (token.type === TokenType.NOT) {
+                current++;
+                const operand = parseArgument();
+                return { type: 'NotExpression', operand };
+            }
+            
+            if (token.type === TokenType.MINUS) {
+                current++;
+                const operand = parseArgument();
+                return { type: 'UnaryMinusExpression', operand };
+            }
+            
+            // Parse literals
+            if (token.type === TokenType.NUMBER) {
+                current++;
+                return { type: 'NumberLiteral', value: token.value };
+            } else if (token.type === TokenType.STRING) {
+                current++;
+                return { type: 'StringLiteral', value: token.value };
+            } else if (token.type === TokenType.TRUE) {
+                current++;
+                return { type: 'BooleanLiteral', value: true };
+            } else if (token.type === TokenType.FALSE) {
+                current++;
+                return { type: 'BooleanLiteral', value: false };
+            } else if (token.type === TokenType.NULL) {
+                current++;
+                return { type: 'NullLiteral' };
+            } else if (token.type === TokenType.WILDCARD) {
+                current++;
+                return { type: 'WildcardPattern' };
+            } else if (token.type === TokenType.FUNCTION_REF) {
+                current++;
+                if (current < tokens.length && tokens[current].type === TokenType.IDENTIFIER) {
+                    const functionName = tokens[current].value;
+                    current++;
+                    return { type: 'FunctionReference', name: functionName };
+                } else {
+                    throw new Error('Expected function name after @');
+                }
+            } else if (token.type === TokenType.IO_IN) {
+                current++;
+                return { type: 'IOInExpression' };
+            } else if (token.type === TokenType.IO_OUT) {
+                current++;
+                const outputValue = parseLogicalExpression();
+                return { type: 'IOOutExpression', value: outputValue };
+            } else if (token.type === TokenType.IO_ASSERT) {
+                current++;
+                const assertionExpr = parseLogicalExpression();
+                return { type: 'IOAssertExpression', value: assertionExpr };
+            }
+            
+            // Parse identifiers (but NOT as function calls)
+            if (token.type === TokenType.IDENTIFIER) {
+                current++;
+                const identifier = { type: 'Identifier', value: token.value };
+                
+                // Check for table access
+                if (current < tokens.length && tokens[current].type === TokenType.DOT) {
+                    return parseChainedDotAccess(identifier);
+                }
+                
+                // Check for table access with brackets
+                if (current < tokens.length && tokens[current].type === TokenType.LEFT_BRACKET) {
+                    return parseChainedTableAccess(identifier);
+                }
+                
+                return identifier;
+            }
+            
+            // Parse parenthesized expressions
+            if (token.type === TokenType.LEFT_PAREN) {
+                current++; // Skip '('
+                const parenthesizedExpr = parseLogicalExpression();
+                
+                if (current < tokens.length && tokens[current].type === TokenType.RIGHT_PAREN) {
+                    current++; // Skip ')'
+                    return parenthesizedExpr;
+                } else {
+                    throw new Error('Expected closing parenthesis');
+                }
+            }
+            
+            // Parse table literals
+            if (token.type === TokenType.LEFT_BRACE) {
+                current++; // Skip '{'
+                const properties = [];
+                
+                while (current < tokens.length && tokens[current].type !== TokenType.RIGHT_BRACE) {
+                    if (tokens[current].type === TokenType.IDENTIFIER) {
+                        const key = tokens[current].value;
+                        current++;
+                        
+                        if (current < tokens.length && tokens[current].type === TokenType.ASSIGNMENT) {
+                            current++; // Skip ':'
+                            const value = parseLogicalExpression();
+                            properties.push({ key, value });
+                        } else {
+                            throw new Error('Expected ":" after property name in table literal');
+                        }
+                    } else {
+                        throw new Error('Expected property name in table literal');
+                    }
+                    
+                    // Skip comma if present
+                    if (current < tokens.length && tokens[current].type === TokenType.COMMA) {
+                        current++;
+                    }
+                }
+                
+                if (current < tokens.length && tokens[current].type === TokenType.RIGHT_BRACE) {
+                    current++; // Skip '}'
+                    return { type: 'TableLiteral', properties };
+                } else {
+                    throw new Error('Expected closing brace in table literal');
+                }
+            }
+            
+            // If we get here, we have an unexpected token
+            throw new Error(`Unexpected token in parseArgument: ${token.type}`);
+        } finally {
+            callStackTracker.pop();
         }
+    }
+    
+    function parseFunctionCall(functionName) {
+        callStackTracker.push('parseFunctionCall', '');
         
-                function parseFunctionCall(functionName) {
+        try {
             /**
              * Parses function calls with arbitrary argument lists.
              * 
-             * Why: Arguments are parsed until a clear terminator is found, allowing for flexible function call syntax. This approach supports both curried and regular function calls, and allows for future extension to variadic functions.
+             * @param {Object|string} functionName - Function name or expression to call
+             * @returns {Object} AST node representing the function call
+             * 
+             * @description Parses function calls by collecting arguments until a 
+             * clear terminator is found, supporting both curried and regular calls.
+             * 
+             * @why Arguments are parsed until a clear terminator is found, allowing 
+             * for flexible function call syntax. This approach supports both curried 
+             * and regular function calls, and allows for future extension to variadic functions.
+             * 
+             * @note Special handling for unary minus arguments to distinguish them
+             * from binary minus operations.
              */
             const args = [];
             
@@ -565,8 +855,13 @@ function parser(tokens) {
                         });
                     }
                 } else {
-                    // Regular argument parsing
-                    args.push(parseExpression());
+                    // Regular argument parsing - parse as expression but skip function call detection
+                    // Create a temporary parsing context that doesn't trigger function call detection
+                    const savedParsingFunctionArgs = parsingFunctionArgs;
+                    parsingFunctionArgs = true; // Temporarily disable function call detection
+                    const arg = parseExpression();
+                    parsingFunctionArgs = savedParsingFunctionArgs; // Restore the flag
+                    args.push(arg);
                 }
             }
                 
@@ -575,15 +870,75 @@ function parser(tokens) {
                 name: functionName,
                 args: args
             };
+        } finally {
+            callStackTracker.pop();
         }
+    }
+    
+    function parseLogicalExpression() {
+        callStackTracker.push('parseLogicalExpression', '');
         
-
+        try {
+            /**
+             * Parses logical expressions with lowest precedence.
+             * 
+             * @returns {Object} AST node representing the logical expression
+             * 
+             * @description Parses logical operators (and, or, xor) with proper
+             * precedence handling and left associativity.
+             * 
+             * @why Logical operators should have lower precedence than arithmetic 
+             * and comparison operators to ensure proper grouping of expressions 
+             * like "isEven 10 and isPositive 5".
+             */
+            let left = parseExpression();
+            
+            while (current < tokens.length && 
+                   (tokens[current].type === TokenType.AND ||
+                    tokens[current].type === TokenType.OR ||
+                    tokens[current].type === TokenType.XOR)) {
+                
+                const operator = tokens[current].type;
+                current++;
+                const right = parseExpression();
+                
+                switch (operator) {
+                    case TokenType.AND:
+                        left = { type: 'AndExpression', left, right };
+                        break;
+                    case TokenType.OR:
+                        left = { type: 'OrExpression', left, right };
+                        break;
+                    case TokenType.XOR:
+                        left = { type: 'XorExpression', left, right };
+                        break;
+                }
+            }
+            
+            return left;
+        } finally {
+            callStackTracker.pop();
+        }
+    }
+    
+    function parseExpression() {
+        callStackTracker.push('parseExpression', '');
         
-        function parseExpression() {
+        try {
             /**
              * Parses expressions with left-associative binary operators.
              * 
-             * Why: Operator precedence is handled by splitting parsing into multiple functions (expression, term, factor, primary). This structure avoids ambiguity and ensures correct grouping of operations.
+             * @returns {Object} AST node representing the expression
+             * 
+             * @description Parses addition, subtraction, and comparison operators
+             * with proper precedence and associativity.
+             * 
+             * @why Operator precedence is handled by splitting parsing into multiple 
+             * functions (expression, term, factor, primary). This structure avoids 
+             * ambiguity and ensures correct grouping of operations.
+             * 
+             * @note Special case handling for unary minus after function references
+             * to distinguish from binary minus operations.
              */
             let left = parseTerm();
             
@@ -595,16 +950,13 @@ function parser(tokens) {
                     tokens[current].type === TokenType.LESS_THAN ||
                     tokens[current].type === TokenType.GREATER_THAN ||
                     tokens[current].type === TokenType.LESS_EQUAL ||
-                    tokens[current].type === TokenType.GREATER_EQUAL ||
-                    tokens[current].type === TokenType.AND ||
-                    tokens[current].type === TokenType.OR ||
-                    tokens[current].type === TokenType.XOR)) {
+                    tokens[current].type === TokenType.GREATER_EQUAL)) {
                 
                 const operator = tokens[current].type;
                 
-                // Special case: Don't treat MINUS as binary operator if left is a FunctionReference or Identifier
-                // This handles cases like "filter @isPositive -3" and "isPositive -3" where -3 should be a separate argument
-                if (operator === TokenType.MINUS && (left.type === 'FunctionReference' || left.type === 'Identifier')) {
+                // Special case: Don't treat MINUS as binary operator if left is a FunctionReference
+                // This handles cases like "filter @isPositive -3" where -3 should be a separate argument
+                if (operator === TokenType.MINUS && left.type === 'FunctionReference') {
                     // This is likely a function call with unary minus argument, not a binary operation
                     // Return the left side and let the caller handle it
                     return left;
@@ -638,26 +990,30 @@ function parser(tokens) {
                     case TokenType.GREATER_EQUAL:
                         left = { type: 'GreaterEqualExpression', left, right };
                         break;
-                    case TokenType.AND:
-                        left = { type: 'AndExpression', left, right };
-                        break;
-                    case TokenType.OR:
-                        left = { type: 'OrExpression', left, right };
-                        break;
-                    case TokenType.XOR:
-                        left = { type: 'XorExpression', left, right };
-                        break;
                 }
             }
             
             return left;
+        } finally {
+            callStackTracker.pop();
         }
+    }
+    
+    function parseTerm() {
+        callStackTracker.push('parseTerm', '');
         
-        function parseTerm() {
+        try {
             /**
              * Parses multiplication, division, and modulo operations.
              * 
-             * Why: By handling these operators at a separate precedence level, the parser ensures that multiplication/division bind tighter than addition/subtraction, matching standard arithmetic rules.
+             * @returns {Object} AST node representing the term
+             * 
+             * @description Parses multiplicative operators with higher precedence
+             * than addition/subtraction.
+             * 
+             * @why By handling these operators at a separate precedence level, the 
+             * parser ensures that multiplication/division bind tighter than 
+             * addition/subtraction, matching standard arithmetic rules.
              */
             let left = parseFactor();
             
@@ -684,13 +1040,26 @@ function parser(tokens) {
             }
             
             return left;
+        } finally {
+            callStackTracker.pop();
         }
+    }
+    
+    function parseFactor() {
+        callStackTracker.push('parseFactor', '');
         
-        function parseFactor() {
+        try {
             /**
              * Parses exponentiation and primary expressions.
              * 
-             * Why: Exponentiation is right-associative and binds tighter than multiplication/division, so it is handled at the factor level. This also allows for future extension to other high-precedence operators.
+             * @returns {Object} AST node representing the factor
+             * 
+             * @description Parses exponentiation with right associativity and
+             * highest precedence among arithmetic operators.
+             * 
+             * @why Exponentiation is right-associative and binds tighter than 
+             * multiplication/division, so it is handled at the factor level. This 
+             * also allows for future extension to other high-precedence operators.
              */
             let left = parsePrimary();
             
@@ -701,88 +1070,36 @@ function parser(tokens) {
             }
             
             return left;
+        } finally {
+            callStackTracker.pop();
         }
+    }
+    
+    function parsePrimary() {
+        callStackTracker.push('parsePrimary', '');
         
-        function parsePrimary() {
+        try {
             /**
-             * Parses literals, identifiers, function definitions, assignments, table literals, case expressions, IO operations, and parenthesized expressions.
+             * Parses literals, identifiers, function definitions, assignments, 
+             * table literals, and parenthesized expressions.
+             * 
+             * @returns {Object} AST node representing the primary expression
+             * @throws {Error} For parsing errors like unexpected tokens
              * 
-             * Why: This function is the core of the recursive descent parser, handling all atomic and context-sensitive constructs. Special care is taken to distinguish between assignments and function definitions using lookahead, and to parse multi-parameter case expressions and function calls.
+             * @description The core parsing function that handles all atomic and 
+             * context-sensitive constructs in the language.
              * 
-             * The parser avoids circular recursion by handling IO and case expressions at the top level, and by using explicit checks for each construct.
+             * @why This function is the core of the recursive descent parser, handling 
+             * all atomic and context-sensitive constructs. Special care is taken to 
+             * avoid circular dependencies by not calling higher-level parsing functions.
              */
-            const token = tokens[current];
             
-            if (token.type === TokenType.CASE) {
-                current++; // Skip 'case'
-                
-                // Parse the values being matched (can be multiple)
-                const values = [];
-                while (current < tokens.length && tokens[current].type !== TokenType.OF) {
-                    // Parse simple expressions (identifiers, numbers, etc.)
-                    if (tokens[current].type === TokenType.IDENTIFIER) {
-                        values.push({
-                            type: 'Identifier',
-                            value: tokens[current].value
-                        });
-                        current++;
-                    } else if (tokens[current].type === TokenType.NUMBER) {
-                        values.push({
-                            type: 'NumberLiteral',
-                            value: tokens[current].value
-                        });
-                        current++;
-                    } else if (tokens[current].type === TokenType.STRING) {
-                        values.push({
-                            type: 'StringLiteral',
-                            value: tokens[current].value
-                        });
-                        current++;
-                    } else {
-                        // For more complex expressions, fall back to parseExpression
-                        const value = parseExpression();
-                        values.push(value);
-                    }
-                }
-                
-                // Expect 'of'
-                if (current >= tokens.length || tokens[current].type !== TokenType.OF) {
-                    throw new Error('Expected "of" after "case"');
-                }
-                current++; // Skip 'of'
-                
-                const cases = [];
-                
-                // Parse cases until we hit a semicolon or end
-                while (current < tokens.length && tokens[current].type !== TokenType.SEMICOLON) {
-                    const patterns = [];
-                    while (current < tokens.length && 
-                           tokens[current].type !== TokenType.ASSIGNMENT && 
-                           tokens[current].type !== TokenType.SEMICOLON) {
-                        patterns.push(parseExpression());
-                    }
-                    
-                    // Expect ':' after pattern
-                    if (current < tokens.length && tokens[current].type === TokenType.ASSIGNMENT) {
-                        current++; // Skip ':'
-                    } else {
-                        throw new Error('Expected ":" after pattern in case expression');
-                    }
-                    
-                    const result = parseExpression();
-                    cases.push({ 
-                        pattern: patterns, 
-                        result: [result] 
-                    });
-                }
-                
-                return {
-                    type: 'CaseExpression',
-                    value: values,
-                    cases,
-                };
+            const token = tokens[current];
+            if (!token) {
+                throw new Error('Unexpected end of input');
             }
             
+            // Parse unary operators
             if (token.type === TokenType.NOT) {
                 current++;
                 const operand = parsePrimary();
@@ -795,223 +1112,175 @@ function parser(tokens) {
                 return { type: 'UnaryMinusExpression', operand };
             }
             
+            // Parse literals
             if (token.type === TokenType.NUMBER) {
                 current++;
-                return {
-                    type: 'NumberLiteral',
-                    value: token.value
-                };
-            }
-            
-            if (token.type === TokenType.STRING) {
+                return { type: 'NumberLiteral', value: token.value };
+            } else if (token.type === TokenType.STRING) {
                 current++;
-                return {
-                    type: 'StringLiteral',
-                    value: token.value
-                };
-            }
-            
-            if (token.type === TokenType.TRUE) {
+                return { type: 'StringLiteral', value: token.value };
+            } else if (token.type === TokenType.TRUE) {
                 current++;
-                return {
-                    type: 'BooleanLiteral',
-                    value: true
-                };
-            }
-            
-            if (token.type === TokenType.FALSE) {
+                return { type: 'BooleanLiteral', value: true };
+            } else if (token.type === TokenType.FALSE) {
                 current++;
-                return {
-                    type: 'BooleanLiteral',
-                    value: false
-                };
-            }
-            
-            if (token.type === TokenType.LEFT_PAREN) {
-                current++; // Skip '('
-                const parenthesizedExpr = parseExpression();
-                
-                if (current < tokens.length && tokens[current].type === TokenType.RIGHT_PAREN) {
-                    current++; // Skip ')'
-                    return parenthesizedExpr;
+                return { type: 'BooleanLiteral', value: false };
+            } else if (token.type === TokenType.NULL) {
+                current++;
+                return { type: 'NullLiteral' };
+            } else if (token.type === TokenType.WILDCARD) {
+                current++;
+                return { type: 'WildcardPattern' };
+            } else if (token.type === TokenType.FUNCTION_REF) {
+                current++;
+                if (current < tokens.length && tokens[current].type === TokenType.IDENTIFIER) {
+                    const functionName = tokens[current].value;
+                    current++;
+                    return { type: 'FunctionReference', name: functionName };
                 } else {
-                    throw new Error('Expected closing parenthesis');
+                    throw new Error('Expected function name after @');
                 }
+            } else if (token.type === TokenType.IO_IN) {
+                current++;
+                return { type: 'IOInExpression' };
+            } else if (token.type === TokenType.IO_OUT) {
+                current++;
+                const outputValue = parseLogicalExpression();
+                return { type: 'IOOutExpression', value: outputValue };
+            } else if (token.type === TokenType.IO_ASSERT) {
+                current++;
+                const assertionExpr = parseLogicalExpression();
+                return { type: 'IOAssertExpression', value: assertionExpr };
             }
             
+            // Parse identifiers
             if (token.type === TokenType.IDENTIFIER) {
-                const identifier = {
-                    type: 'Identifier',
-                    value: token.value
-                };
                 current++;
+                const identifier = { type: 'Identifier', value: token.value };
                 
-                // Check if this is an assignment
-                if (current < tokens.length && tokens[current].type === TokenType.ASSIGNMENT) {
-                    current++; // Skip ':'
-                    
-                    // Check if this is a function definition
-                    let isFunction = false;
-                    let params = [];
-                    
-                    // Look ahead to see if this is a function definition
-                    let lookAhead = current;
-                    while (lookAhead < tokens.length && 
-                           tokens[lookAhead].type !== TokenType.ARROW && 
-                           tokens[lookAhead].type !== TokenType.SEMICOLON) {
-                        if (tokens[lookAhead].type === TokenType.IDENTIFIER) {
-                            params.push(tokens[lookAhead].value);
-                        }
-                        lookAhead++;
-                    }
-                    
-                    if (lookAhead < tokens.length && tokens[lookAhead].type === TokenType.ARROW) {
-                        isFunction = true;
-                    }
-                    
-                    if (isFunction) {
-                        // Clear params array and parse function parameters
-                        params = [];
-                        while (current < tokens.length && tokens[current].type !== TokenType.ARROW) {
-                            if (tokens[current].type === TokenType.IDENTIFIER) {
-                                params.push(tokens[current].value);
-                            }
-                            current++;
-                        }
-                        
-                        current++; // Skip '->'
-                        
-                        // Parse the function body (which could be a case expression or other expression)
-                        const functionBody = parseExpression();
-                        
-                        return {
-                            type: 'AssignmentExpression',
-                            name: identifier.value,
-                            value: {
-                                type: 'FunctionDeclaration',
-                                name: null, // Anonymous function
-                                params,
-                                body: functionBody,
-                            }
-                        };
-                    } else {
-                        // Regular assignment
-                        const value = parseExpression();
-                        return {
-                            type: 'AssignmentExpression',
-                            name: identifier.value,
-                            value: value
-                        };
-                    }
+                // Skip function call detection if we're parsing function arguments
+                if (parsingFunctionArgs) {
+                    return identifier;
+                }
+                
+                // Check for function calls
+                if (current < tokens.length && tokens[current].type === TokenType.LEFT_PAREN) {
+                    return parseFunctionCall(identifier.value);
                 }
                 
-                // Check if this is table access
+                // Check if the next token is an operator - if so, don't treat as function call
                 if (current < tokens.length && 
-                    (tokens[current].type === TokenType.LEFT_BRACKET ||
-                     tokens[current].type === TokenType.DOT)) {
-                    return parseChainedTableAccess(identifier);
+                    (tokens[current].type === TokenType.PLUS ||
+                     tokens[current].type === TokenType.MINUS ||
+                     tokens[current].type === TokenType.MULTIPLY ||
+                     tokens[current].type === TokenType.DIVIDE ||
+                     tokens[current].type === TokenType.MODULO ||
+                     tokens[current].type === TokenType.POWER)) {
+                    // This is part of a binary expression, don't treat as function call
+                    return identifier;
                 }
                 
-                // Check if this is a function call
+                // Check for function calls without parentheses (e.g., add 3 4)
+                // Only treat as function call if the next token is a number, string, or left paren
+                // This prevents treating identifiers as function calls when they're actually arguments
                 if (current < tokens.length && 
-                    (tokens[current].type === TokenType.IDENTIFIER || 
-                     tokens[current].type === TokenType.NUMBER ||
+                    (tokens[current].type === TokenType.NUMBER ||
                      tokens[current].type === TokenType.STRING ||
                      tokens[current].type === TokenType.LEFT_PAREN ||
                      tokens[current].type === TokenType.FUNCTION_REF)) {
-                    return parseFunctionCall(identifier);
+                    return parseFunctionCall(identifier.value);
+                }
+                
+                // Special case for unary minus: only treat as function call if it's a unary minus
+                if (current < tokens.length && tokens[current].type === TokenType.MINUS) {
+                    // Look ahead to see if this is a unary minus (like -5) or binary minus (like n - 1)
+                    const nextToken = current + 1 < tokens.length ? tokens[current + 1] : null;
+                    if (nextToken && nextToken.type === TokenType.NUMBER) {
+                        // This is a unary minus, treat as function call
+                        return parseFunctionCall(identifier.value);
+                    }
+                    // This is a binary minus, don't treat as function call
+                }
+                
+                // Special case for function calls with identifier arguments (e.g., add x y)
+                // Only treat as function call if the next token is an identifier and not followed by an operator
+                if (!parsingFunctionArgs && current < tokens.length && tokens[current].type === TokenType.IDENTIFIER) {
+                    // Look ahead to see if the next token is an identifier followed by an operator
+                    const nextToken = current + 1 < tokens.length ? tokens[current + 1] : null;
+                    const nextNextToken = current + 2 < tokens.length ? tokens[current + 2] : null;
+                    
+                    // Only treat as function call if the next token is an identifier and not followed by an operator
+                    if (nextToken && nextToken.type === TokenType.IDENTIFIER && 
+                        (!nextNextToken || 
+                         (nextNextToken.type !== TokenType.PLUS &&
+                          nextNextToken.type !== TokenType.MINUS &&
+                          nextNextToken.type !== TokenType.MULTIPLY &&
+                          nextNextToken.type !== TokenType.DIVIDE &&
+                          nextNextToken.type !== TokenType.MODULO &&
+                          nextNextToken.type !== TokenType.POWER &&
+                          nextNextToken.type !== TokenType.EQUALS &&
+                          nextNextToken.type !== TokenType.NOT_EQUAL &&
+                          nextNextToken.type !== TokenType.LESS_THAN &&
+                          nextNextToken.type !== TokenType.GREATER_THAN &&
+                          nextNextToken.type !== TokenType.LESS_EQUAL &&
+                          nextNextToken.type !== TokenType.GREATER_EQUAL))) {
+                        if (process.env.DEBUG) {
+                            console.log(`[DEBUG] Creating function call for ${identifier.value} at position ${current}`);
+                        }
+                        return parseFunctionCall(identifier.value);
+                    }
+                }
+                
+
+                
+                // Check for table access
+                if (current < tokens.length && tokens[current].type === TokenType.DOT) {
+                    return parseChainedDotAccess(identifier);
+                }
+                
+                // Check for table access with brackets
+                if (current < tokens.length && tokens[current].type === TokenType.LEFT_BRACKET) {
+                    return parseChainedTableAccess(identifier);
                 }
                 
                 return identifier;
             }
             
-            if (token.type === TokenType.FUNCTION_REF) {
-                current++; // Skip '@'
-                if (current < tokens.length && tokens[current].type === TokenType.IDENTIFIER) {
-                    const funcName = tokens[current].value;
-                    current++;
-                    return {
-                        type: 'FunctionReference',
-                        name: funcName
-                    };
+            // Parse parenthesized expressions
+            if (token.type === TokenType.LEFT_PAREN) {
+                current++; // Skip '('
+                const parenthesizedExpr = parseLogicalExpression();
+                
+                if (current < tokens.length && tokens[current].type === TokenType.RIGHT_PAREN) {
+                    current++; // Skip ')'
+                    return parenthesizedExpr;
                 } else {
-                    throw new Error('Expected function name after @');
+                    throw new Error('Expected closing parenthesis');
                 }
             }
-
-                        if (token.type === TokenType.WILDCARD) {
-                current++; // Skip '_'
-                return { type: 'WildcardPattern' };
-            }
-
-
             
-
-            
-            // If we get here, it's an operator token that should be handled by parseExpression
-            // But we need to handle it here to avoid circular dependency
+            // Parse table literals
             if (token.type === TokenType.LEFT_BRACE) {
                 current++; // Skip '{'
-                const entries = [];
-                let arrayIndex = 1;
+                const properties = [];
                 
                 while (current < tokens.length && tokens[current].type !== TokenType.RIGHT_BRACE) {
-                    // Skip leading commas
-                    if (tokens[current].type === TokenType.COMMA) {
+                    if (tokens[current].type === TokenType.IDENTIFIER) {
+                        const key = tokens[current].value;
                         current++;
-                        continue;
-                    }
-                    
-                    let key = null;
-                    let value;
-                    
-                    // Check if this is a key-value pair or just a value
-                    if (current + 1 < tokens.length && tokens[current + 1].type === TokenType.ASSIGNMENT) {
-                        // This is a key-value pair: key: value
-                        if (tokens[current].type === TokenType.IDENTIFIER) {
-                            key = {
-                                type: 'Identifier',
-                                value: tokens[current].value
-                            };
-                            current++; // Skip the key
-                        } else if (tokens[current].type === TokenType.NUMBER) {
-                            key = {
-                                type: 'NumberLiteral',
-                                value: tokens[current].value,
-                            };
-                            current++; // Skip the key
-                        } else if (tokens[current].type === TokenType.STRING) {
-                            key = {
-                                type: 'StringLiteral',
-                                value: tokens[current].value,
-                            };
-                            current++; // Skip the key
-                        } else if (tokens[current].type === TokenType.TRUE) {
-                            key = {
-                                type: 'BooleanLiteral',
-                                value: true,
-                            };
-                            current++; // Skip the key
-                        } else if (tokens[current].type === TokenType.FALSE) {
-                            key = {
-                                type: 'BooleanLiteral',
-                                value: false,
-                            };
-                            current++; // Skip the key
+                        
+                        if (current < tokens.length && tokens[current].type === TokenType.ASSIGNMENT) {
+                            current++; // Skip ':'
+                            const value = parseLogicalExpression();
+                            properties.push({ key, value });
                         } else {
-                            throw new Error('Invalid key type in table literal');
+                            throw new Error('Expected ":" after property name in table literal');
                         }
-                        
-                        current++; // Skip ':'
-                        value = parseExpression();
                     } else {
-                        // This is just a value (array-like entry)
-                        value = parseExpression();
+                        throw new Error('Expected property name in table literal');
                     }
                     
-                    entries.push({ key, value });
-                    
-                    // Skip trailing commas
+                    // Skip comma if present
                     if (current < tokens.length && tokens[current].type === TokenType.COMMA) {
                         current++;
                     }
@@ -1019,105 +1288,607 @@ function parser(tokens) {
                 
                 if (current < tokens.length && tokens[current].type === TokenType.RIGHT_BRACE) {
                     current++; // Skip '}'
-                    return {
-                        type: 'TableLiteral',
-                        entries: entries
-                    };
+                    return { type: 'TableLiteral', properties };
                 } else {
-                    throw new Error('Expected closing brace');
+                    throw new Error('Expected closing brace in table literal');
                 }
             }
             
-            // If we get here, it's an operator token that should be handled by parseExpression
-            // But we need to handle it here to avoid circular dependency
-            if (token.type === TokenType.PLUS ||
-                token.type === TokenType.MINUS ||
-                token.type === TokenType.MULTIPLY ||
-                token.type === TokenType.DIVIDE ||
-                token.type === TokenType.MODULO ||
-                token.type === TokenType.POWER ||
-                token.type === TokenType.EQUALS ||
-                token.type === TokenType.NOT_EQUAL ||
-                token.type === TokenType.LESS_THAN ||
-                token.type === TokenType.GREATER_THAN ||
-                token.type === TokenType.LESS_EQUAL ||
-                token.type === TokenType.GREATER_EQUAL ||
-                token.type === TokenType.AND ||
-                token.type === TokenType.OR ||
-                token.type === TokenType.XOR) {
-                // Reset current to parse the expression properly
-                return parseExpression();
+            // Parse arrow expressions (function definitions)
+            if (token.type === TokenType.ARROW) {
+                current++; // Skip '->'
+                
+                // Parse the function body
+                const body = parseLogicalExpression();
+                
+                return { type: 'ArrowExpression', body };
             }
             
+
+            
+
+            
             // If we get here, we have an unexpected token
             throw new Error(`Unexpected token in parsePrimary: ${token.type}`);
+        } finally {
+            callStackTracker.pop();
         }
+    }
+    
+    function walk() {
+        callStackTracker.push('walk', `position:${current}`);
         
-        // Check for IO operations before calling parsePrimary
-        if (tokens[current].type === TokenType.IO_IN) {
-            current++;
-            return { type: 'IOInExpression' };
-        } else if (tokens[current].type === TokenType.IO_OUT) {
-            current++;
-            const outputValue = parseExpression();
-            return { type: 'IOOutExpression', value: outputValue };
-        } else if (tokens[current].type === TokenType.IO_ASSERT) {
-            current++;
-            const assertionExpr = parseExpression();
-            return { type: 'IOAssertExpression', value: assertionExpr };
-        }
-        
-        // Check for case expressions at top level
-        if (tokens[current].type === TokenType.CASE) {
-            current++; // Skip 'case'
+        try {
+            
+
             
-            // Parse the values being matched (can be multiple)
-            const values = [];
-            while (current < tokens.length && tokens[current].type !== TokenType.OF) {
-                const value = parseExpression();
-                values.push(value);
+
+            
+            function parseLogicalExpression() {
+                callStackTracker.push('parseLogicalExpression', '');
+                
+                try {
+                    /**
+                     * Parses logical expressions with lowest precedence.
+                     * 
+                     * @returns {Object} AST node representing the logical expression
+                     * 
+                     * @description Parses logical operators (and, or, xor) with proper
+                     * precedence handling and left associativity.
+                     * 
+                     * @why Logical operators should have lower precedence than arithmetic 
+                     * and comparison operators to ensure proper grouping of expressions 
+                     * like "isEven 10 and isPositive 5".
+                     */
+                    let left = parseExpression();
+                    
+                    while (current < tokens.length && 
+                           (tokens[current].type === TokenType.AND ||
+                            tokens[current].type === TokenType.OR ||
+                            tokens[current].type === TokenType.XOR)) {
+                        
+                        const operator = tokens[current].type;
+                        current++;
+                        const right = parseExpression();
+                        
+                        switch (operator) {
+                            case TokenType.AND:
+                                left = { type: 'AndExpression', left, right };
+                                break;
+                            case TokenType.OR:
+                                left = { type: 'OrExpression', left, right };
+                                break;
+                            case TokenType.XOR:
+                                left = { type: 'XorExpression', left, right };
+                                break;
+                        }
+                    }
+                    
+                    return left;
+                } finally {
+                    callStackTracker.pop();
+                }
             }
             
-            // Expect 'of'
-            if (current >= tokens.length || tokens[current].type !== TokenType.OF) {
-                throw new Error('Expected "of" after "case"');
+            function parseExpression() {
+                callStackTracker.push('parseExpression', '');
+                
+                try {
+                    /**
+                     * Parses expressions with left-associative binary operators.
+                     * 
+                     * @returns {Object} AST node representing the expression
+                     * 
+                     * @description Parses addition, subtraction, and comparison operators
+                     * with proper precedence and associativity.
+                     * 
+                     * @why Operator precedence is handled by splitting parsing into multiple 
+                     * functions (expression, term, factor, primary). This structure avoids 
+                     * ambiguity and ensures correct grouping of operations.
+                     * 
+                     * @note Special case handling for unary minus after function references
+                     * to distinguish from binary minus operations.
+                     */
+                    let left = parseTerm();
+                    
+                    while (current < tokens.length && 
+                           (tokens[current].type === TokenType.PLUS || 
+                            tokens[current].type === TokenType.MINUS ||
+                            tokens[current].type === TokenType.EQUALS ||
+                            tokens[current].type === TokenType.NOT_EQUAL ||
+                            tokens[current].type === TokenType.LESS_THAN ||
+                            tokens[current].type === TokenType.GREATER_THAN ||
+                            tokens[current].type === TokenType.LESS_EQUAL ||
+                            tokens[current].type === TokenType.GREATER_EQUAL)) {
+                        
+                        const operator = tokens[current].type;
+                        
+                        // Special case: Don't treat MINUS as binary operator if left is a FunctionReference
+                        // This handles cases like "filter @isPositive -3" where -3 should be a separate argument
+                        if (operator === TokenType.MINUS && left.type === 'FunctionReference') {
+                            // This is likely a function call with unary minus argument, not a binary operation
+                            // Return the left side and let the caller handle it
+                            return left;
+                        }
+                        
+                        current++;
+                        const right = parseTerm();
+                        
+                        switch (operator) {
+                            case TokenType.PLUS:
+                                left = { type: 'PlusExpression', left, right };
+                                break;
+                            case TokenType.MINUS:
+                                left = { type: 'MinusExpression', left, right };
+                                break;
+                            case TokenType.EQUALS:
+                                left = { type: 'EqualsExpression', left, right };
+                                break;
+                            case TokenType.NOT_EQUAL:
+                                left = { type: 'NotEqualExpression', left, right };
+                                break;
+                            case TokenType.LESS_THAN:
+                                left = { type: 'LessThanExpression', left, right };
+                                break;
+                            case TokenType.GREATER_THAN:
+                                left = { type: 'GreaterThanExpression', left, right };
+                                break;
+                            case TokenType.LESS_EQUAL:
+                                left = { type: 'LessEqualExpression', left, right };
+                                break;
+                            case TokenType.GREATER_EQUAL:
+                                left = { type: 'GreaterEqualExpression', left, right };
+                                break;
+                        }
+                    }
+                    
+                    return left;
+                } finally {
+                    callStackTracker.pop();
+                }
             }
-            current++; // Skip 'of'
             
-            const cases = [];
+            function parseTerm() {
+                callStackTracker.push('parseTerm', '');
+                
+                try {
+                    /**
+                     * Parses multiplication, division, and modulo operations.
+                     * 
+                     * @returns {Object} AST node representing the term
+                     * 
+                     * @description Parses multiplicative operators with higher precedence
+                     * than addition/subtraction.
+                     * 
+                     * @why By handling these operators at a separate precedence level, the 
+                     * parser ensures that multiplication/division bind tighter than 
+                     * addition/subtraction, matching standard arithmetic rules.
+                     */
+                    let left = parseFactor();
+                    
+                    while (current < tokens.length && 
+                           (tokens[current].type === TokenType.MULTIPLY || 
+                            tokens[current].type === TokenType.DIVIDE ||
+                            tokens[current].type === TokenType.MODULO)) {
+                        
+                        const operator = tokens[current].type;
+                        current++;
+                        const right = parseFactor();
+                        
+                        switch (operator) {
+                            case TokenType.MULTIPLY:
+                                left = { type: 'MultiplyExpression', left, right };
+                                break;
+                            case TokenType.DIVIDE:
+                                left = { type: 'DivideExpression', left, right };
+                                break;
+                            case TokenType.MODULO:
+                                left = { type: 'ModuloExpression', left, right };
+                                break;
+                        }
+                    }
+                    
+                    return left;
+                } finally {
+                    callStackTracker.pop();
+                }
+            }
             
-            // Parse cases until we hit a semicolon or end
-            while (current < tokens.length && tokens[current].type !== TokenType.SEMICOLON) {
-                const patterns = [];
-                while (current < tokens.length && 
-                       tokens[current].type !== TokenType.ASSIGNMENT && 
-                       tokens[current].type !== TokenType.SEMICOLON) {
-                    patterns.push(parseExpression());
+            function parseFactor() {
+                callStackTracker.push('parseFactor', '');
+                
+                try {
+                    /**
+                     * Parses exponentiation and primary expressions.
+                     * 
+                     * @returns {Object} AST node representing the factor
+                     * 
+                     * @description Parses exponentiation with right associativity and
+                     * highest precedence among arithmetic operators.
+                     * 
+                     * @why Exponentiation is right-associative and binds tighter than 
+                     * multiplication/division, so it is handled at the factor level. This 
+                     * also allows for future extension to other high-precedence operators.
+                     */
+                    let left = parsePrimary();
+                    
+                    while (current < tokens.length && tokens[current].type === TokenType.POWER) {
+                        current++;
+                        const right = parsePrimary();
+                        left = { type: 'PowerExpression', left, right };
+                    }
+                    
+                    return left;
+                } finally {
+                    callStackTracker.pop();
                 }
+            }
+            
+            // Check for IO operations first
+            if (tokens[current].type === TokenType.IO_IN) {
+                current++;
+                return { type: 'IOInExpression' };
+            } else if (tokens[current].type === TokenType.IO_OUT) {
+                current++;
+                const outputValue = parseLogicalExpression();
+                return { type: 'IOOutExpression', value: outputValue };
+            } else if (tokens[current].type === TokenType.IO_ASSERT) {
+                current++;
+                const assertionExpr = parseLogicalExpression();
+                return { type: 'IOAssertExpression', value: assertionExpr };
+            }
+            
+
+            
+            // Check for assignments (identifier followed by ':')
+            if (tokens[current].type === TokenType.IDENTIFIER) {
+                const identifier = tokens[current].value;
+                current++;
                 
-                // Expect ':' after pattern
                 if (current < tokens.length && tokens[current].type === TokenType.ASSIGNMENT) {
                     current++; // Skip ':'
-                } else {
-                    throw new Error('Expected ":" after pattern in case expression');
+                    
+                    // Check if this is a function definition with arrow syntax (x y -> body)
+                    // Look ahead to see if we have parameters followed by ->
+                    const lookAheadTokens = [];
+                    let lookAheadPos = current;
+                    
+                    // Collect tokens until we find -> or hit a terminator
+                    while (lookAheadPos < tokens.length && 
+                           tokens[lookAheadPos].type !== TokenType.ARROW &&
+                           tokens[lookAheadPos].type !== TokenType.SEMICOLON &&
+                           tokens[lookAheadPos].type !== TokenType.ASSIGNMENT) {
+                        lookAheadTokens.push(tokens[lookAheadPos]);
+                        lookAheadPos++;
+                    }
+                    
+                    // If we found ->, this is a function definition with arrow syntax
+                    if (lookAheadPos < tokens.length && tokens[lookAheadPos].type === TokenType.ARROW) {
+                        // Parse parameters (identifiers separated by spaces)
+                        const parameters = [];
+                        let paramIndex = 0;
+                        
+                        while (paramIndex < lookAheadTokens.length) {
+                            if (lookAheadTokens[paramIndex].type === TokenType.IDENTIFIER) {
+                                parameters.push(lookAheadTokens[paramIndex].value);
+                                paramIndex++;
+                            } else {
+                                // Skip non-identifier tokens (spaces, etc.)
+                                paramIndex++;
+                            }
+                        }
+                        
+                        // Skip the parameters and ->
+                        current = lookAheadPos + 1; // Skip the arrow
+                        
+                        // Parse the function body (check if it's a case expression)
+                        let functionBody;
+                        if (current < tokens.length && tokens[current].type === TokenType.CASE) {
+                            // Parse case expression directly
+                            current++; // Skip 'case'
+                            
+                            // Parse the values being matched (can be multiple)
+                            const values = [];
+                            while (current < tokens.length && tokens[current].type !== TokenType.OF) {
+                                if (tokens[current].type === TokenType.IDENTIFIER) {
+                                    values.push({ type: 'Identifier', value: tokens[current].value });
+                                    current++;
+                                } else if (tokens[current].type === TokenType.NUMBER) {
+                                    values.push({ type: 'NumberLiteral', value: tokens[current].value });
+                                    current++;
+                                } else if (tokens[current].type === TokenType.STRING) {
+                                    values.push({ type: 'StringLiteral', value: tokens[current].value });
+                                    current++;
+                                } else {
+                                    const value = parsePrimary();
+                                    values.push(value);
+                                }
+                            }
+                            
+                            // Expect 'of'
+                            if (current >= tokens.length || tokens[current].type !== TokenType.OF) {
+                                throw new Error('Expected "of" after "case"');
+                            }
+                            current++; // Skip 'of'
+                            
+                            const cases = [];
+                            
+                            // Parse cases until we hit a semicolon or end
+                            while (current < tokens.length && tokens[current].type !== TokenType.SEMICOLON) {
+                                // If we hit an IO operation, we've reached the end of the case expression
+                                if (current < tokens.length && 
+                                    (tokens[current].type === TokenType.IO_IN ||
+                                     tokens[current].type === TokenType.IO_OUT ||
+                                     tokens[current].type === TokenType.IO_ASSERT)) {
+                                    break;
+                                }
+                                const patterns = [];
+                                while (current < tokens.length && 
+                                       tokens[current].type !== TokenType.ASSIGNMENT && 
+                                       tokens[current].type !== TokenType.SEMICOLON) {
+                                    patterns.push(parsePrimary());
+                                }
+                                
+                                // Expect ':' after pattern
+                                if (current < tokens.length && tokens[current].type === TokenType.ASSIGNMENT) {
+                                    current++; // Skip ':'
+                                } else {
+                                    throw new Error('Expected ":" after pattern in case expression');
+                                }
+                                
+                                // Temporarily disable function call detection when parsing case expression results
+                                const savedParsingFunctionArgs = parsingFunctionArgs;
+                                parsingFunctionArgs = true; // Disable function call detection
+                                const result = parseLogicalExpression();
+                                parsingFunctionArgs = savedParsingFunctionArgs; // Restore the flag
+                                cases.push({ 
+                                    pattern: patterns, 
+                                    result: [result] 
+                                });
+                                
+                                // Skip semicolon if present (but don't stop parsing cases)
+                                if (current < tokens.length && tokens[current].type === TokenType.SEMICOLON) {
+                                    current++;
+                                    // If the next token is an identifier followed by assignment, we've reached the end of the case expression
+                                    if (current < tokens.length && tokens[current].type === TokenType.IDENTIFIER) {
+                                        const nextPos = current + 1;
+                                        if (nextPos < tokens.length && tokens[nextPos].type === TokenType.ASSIGNMENT) {
+                                            break; // End of case expression
+                                        }
+                                    }
+                                }
+                            }
+                            
+                            functionBody = {
+                                type: 'CaseExpression',
+                                value: values,
+                                cases,
+                            };
+                        } else {
+                            functionBody = parseLogicalExpression();
+                        }
+                        
+                        return {
+                            type: 'Assignment',
+                            identifier,
+                            value: {
+                                type: 'FunctionDefinition',
+                                parameters,
+                                body: functionBody
+                            }
+                        };
+                    }
+                    
+                    // Check if this is a function definition with 'function' keyword
+                    if (current < tokens.length && tokens[current].type === TokenType.FUNCTION) {
+                        current++; // Skip 'function'
+                        
+                        if (current >= tokens.length || tokens[current].type !== TokenType.LEFT_PAREN) {
+                            throw new Error('Expected "(" after "function"');
+                        }
+                        current++; // Skip '('
+                        
+                        const parameters = [];
+                        while (current < tokens.length && tokens[current].type !== TokenType.RIGHT_PAREN) {
+                            if (tokens[current].type === TokenType.IDENTIFIER) {
+                                parameters.push(tokens[current].value);
+                                current++;
+                            } else {
+                                throw new Error('Expected parameter name in function definition');
+                            }
+                            
+                            // Skip comma if present
+                            if (current < tokens.length && tokens[current].type === TokenType.COMMA) {
+                                current++;
+                            }
+                        }
+                        
+                        if (current >= tokens.length || tokens[current].type !== TokenType.RIGHT_PAREN) {
+                            throw new Error('Expected ")" after function parameters');
+                        }
+                        current++; // Skip ')'
+                        
+                        if (current >= tokens.length || tokens[current].type !== TokenType.ASSIGNMENT) {
+                            throw new Error('Expected ":" after function parameters');
+                        }
+                        current++; // Skip ':'
+                        
+                        // Parse the function body (check if it's a case expression)
+                        let functionBody;
+                        if (current < tokens.length && tokens[current].type === TokenType.CASE) {
+                            // Parse case expression directly
+                            current++; // Skip 'case'
+                            
+                            // Parse the values being matched (can be multiple)
+                            const values = [];
+                            while (current < tokens.length && tokens[current].type !== TokenType.OF) {
+                                const value = parsePrimary();
+                                values.push(value);
+                            }
+                            
+                            // Expect 'of'
+                            if (current >= tokens.length || tokens[current].type !== TokenType.OF) {
+                                throw new Error('Expected "of" after "case"');
+                            }
+                            current++; // Skip 'of'
+                            
+                            const cases = [];
+                            
+                            // Parse cases until we hit a semicolon or end
+                            while (current < tokens.length && tokens[current].type !== TokenType.SEMICOLON) {
+                                // If we hit an IO operation, we've reached the end of the case expression
+                                if (current < tokens.length && 
+                                    (tokens[current].type === TokenType.IO_IN ||
+                                     tokens[current].type === TokenType.IO_OUT ||
+                                     tokens[current].type === TokenType.IO_ASSERT)) {
+                                    break;
+                                }
+                                const patterns = [];
+                                while (current < tokens.length && 
+                                       tokens[current].type !== TokenType.ASSIGNMENT && 
+                                       tokens[current].type !== TokenType.SEMICOLON) {
+                                    patterns.push(parsePrimary());
+                                }
+                                
+                                // Expect ':' after pattern
+                                if (current < tokens.length && tokens[current].type === TokenType.ASSIGNMENT) {
+                                    current++; // Skip ':'
+                                } else {
+                                    throw new Error('Expected ":" after pattern in case expression');
+                                }
+                                
+                                const result = parseLogicalExpression();
+                                cases.push({ 
+                                    pattern: patterns, 
+                                    result: [result] 
+                                });
+                                
+                                // Skip semicolon if present (but don't stop parsing cases)
+                                if (current < tokens.length && tokens[current].type === TokenType.SEMICOLON) {
+                                    current++;
+                                    // If the next token is an identifier followed by assignment, we've reached the end of the case expression
+                                    if (current < tokens.length && tokens[current].type === TokenType.IDENTIFIER) {
+                                        const nextPos = current + 1;
+                                        if (nextPos < tokens.length && tokens[nextPos].type === TokenType.ASSIGNMENT) {
+                                            break; // End of case expression
+                                        }
+                                    }
+                                }
+                            }
+                            
+                            functionBody = {
+                                type: 'CaseExpression',
+                                value: values,
+                                cases,
+                            };
+                        } else {
+                            functionBody = parseLogicalExpression();
+                        }
+                        
+                        return {
+                            type: 'Assignment',
+                            identifier,
+                            value: {
+                                type: 'FunctionDefinition',
+                                parameters,
+                                body: functionBody
+                            }
+                        };
+                    } else {
+                        // Check if this is a case expression
+                        if (current < tokens.length && tokens[current].type === TokenType.CASE) {
+                            // Parse the case expression directly
+                            current++; // Skip 'case'
+                            
+                            // Parse the values being matched (can be multiple)
+                            const values = [];
+                            while (current < tokens.length && tokens[current].type !== TokenType.OF) {
+                                const value = parsePrimary();
+                                values.push(value);
+                            }
+                            
+                            // Expect 'of'
+                            if (current >= tokens.length || tokens[current].type !== TokenType.OF) {
+                                throw new Error('Expected "of" after "case"');
+                            }
+                            current++; // Skip 'of'
+                            
+                            const cases = [];
+                            
+                            // Parse cases until we hit a semicolon or end
+                            while (current < tokens.length && tokens[current].type !== TokenType.SEMICOLON) {
+                                // If we hit an IO operation, we've reached the end of the case expression
+                                if (current < tokens.length && 
+                                    (tokens[current].type === TokenType.IO_IN ||
+                                     tokens[current].type === TokenType.IO_OUT ||
+                                     tokens[current].type === TokenType.IO_ASSERT)) {
+                                    break;
+                                }
+                                const patterns = [];
+                                while (current < tokens.length && 
+                                       tokens[current].type !== TokenType.ASSIGNMENT && 
+                                       tokens[current].type !== TokenType.SEMICOLON) {
+                                    patterns.push(parsePrimary());
+                                }
+                                
+                                // Expect ':' after pattern
+                                if (current < tokens.length && tokens[current].type === TokenType.ASSIGNMENT) {
+                                    current++; // Skip ':'
+                                } else {
+                                    throw new Error('Expected ":" after pattern in case expression');
+                                }
+                                
+                                const result = parseLogicalExpression();
+                                cases.push({ 
+                                    pattern: patterns, 
+                                    result: [result] 
+                                });
+                                
+                                // Skip semicolon if present (but don't stop parsing cases)
+                                if (current < tokens.length && tokens[current].type === TokenType.SEMICOLON) {
+                                    current++;
+                                    // If the next token is an identifier followed by assignment, we've reached the end of the case expression
+                                    if (current < tokens.length && tokens[current].type === TokenType.IDENTIFIER) {
+                                        const nextPos = current + 1;
+                                        if (nextPos < tokens.length && tokens[nextPos].type === TokenType.ASSIGNMENT) {
+                                            break; // End of case expression
+                                        }
+                                    }
+                                }
+                            }
+                            
+                            return {
+                                type: 'Assignment',
+                                identifier,
+                                value: {
+                                    type: 'CaseExpression',
+                                    value: values,
+                                    cases,
+                                }
+                            };
+                        } else {
+                            // Regular assignment
+                            const value = parseLogicalExpression();
+                            
+                            return {
+                                type: 'Assignment',
+                                identifier,
+                                value
+                            };
+                        }
+                    }
                 }
                 
-                const result = parseExpression();
-                cases.push({ 
-                    pattern: patterns, 
-                    result: [result] 
-                });
+                // If it's not an assignment, put the identifier back and continue
+                current--;
             }
             
-            return {
-                type: 'CaseExpression',
-                value: values,
-                cases,
-            };
+            // For all other token types (identifiers, numbers, operators, etc.), call parsePrimary
+            // This handles atomic expressions and delegates to the appropriate parsing functions
+            return parsePrimary();
+        } finally {
+            callStackTracker.pop();
         }
-        
-        // Simple wrapper that calls parsePrimary for all token types
-        return parsePrimary();
     }
     
     const ast = {
@@ -1164,645 +1935,785 @@ function parser(tokens) {
 /**
  * Interpreter: Walks the AST and evaluates each node.
  * 
- * How: Uses a global scope for variable storage and function definitions. Each function call creates a new scope (using prototypal inheritance) to implement lexical scoping. Immutability is enforced by preventing reassignment in the global scope.
+ * @param {Object} ast - Abstract Syntax Tree to evaluate
+ * @returns {*} The result of evaluating the AST, or a Promise for async operations
+ * @throws {Error} For evaluation errors like division by zero, undefined variables, etc.
+ * 
+ * @description Evaluates an AST by walking through each node and performing the
+ * corresponding operations. Manages scope, handles function calls, and supports
+ * both synchronous and asynchronous operations.
+ * 
+ * @how Uses a global scope for variable storage and function definitions. Each 
+ * function call creates a new scope (using prototypal inheritance) to implement 
+ * lexical scoping. Immutability is enforced by preventing reassignment in the 
+ * global scope.
  * 
- * Why: This approach allows for first-class functions, closures, and lexical scoping, while keeping the implementation simple. The interpreter supports both synchronous and asynchronous IO operations, returning Promises when necessary.
+ * @why This approach allows for first-class functions, closures, and lexical 
+ * scoping, while keeping the implementation simple. The interpreter supports 
+ * both synchronous and asynchronous IO operations, returning Promises when necessary.
  * 
- * The interpreter is split into three functions: evalNode (global), localEvalNodeWithScope (for function bodies), and localEvalNode (for internal recursion). This separation allows for correct scope handling and easier debugging.
+ * @note The interpreter is split into three functions: evalNode (global), 
+ * localEvalNodeWithScope (for function bodies), and localEvalNode (for internal 
+ * recursion). This separation allows for correct scope handling and easier debugging.
  */
 function interpreter(ast) {
     const globalScope = {};
     initializeStandardLibrary(globalScope);
     
+    // Reset call stack tracker at the start of interpretation
+    callStackTracker.reset();
+    
+    /**
+     * Evaluates AST nodes in the global scope.
+     * 
+     * @param {Object} node - AST node to evaluate
+     * @returns {*} The result of evaluating the node
+     * @throws {Error} For evaluation errors
+     * 
+     * @description Main evaluation function that handles all node types in the
+     * global scope context.
+     */
     function evalNode(node) {
-        if (!node) {
-            return undefined;
-        }
-        switch (node.type) {
-            case 'NumberLiteral':
-                return parseFloat(node.value);
-            case 'StringLiteral':
-                return node.value;
-            case 'BooleanLiteral':
-                return node.value;
-            case 'PlusExpression':
-                return evalNode(node.left) + evalNode(node.right);
-            case 'MinusExpression':
-                return evalNode(node.left) - evalNode(node.right);
-            case 'MultiplyExpression':
-                return evalNode(node.left) * evalNode(node.right);
-            case 'DivideExpression':
-                const divisor = evalNode(node.right);
-                if (divisor === 0) {
-                    throw new Error('Division by zero');
-                }
-                return evalNode(node.left) / evalNode(node.right);
-            case 'ModuloExpression':
-                return evalNode(node.left) % evalNode(node.right);
-            case 'PowerExpression':
-                return Math.pow(evalNode(node.left), evalNode(node.right));
-            case 'EqualsExpression':
-                return evalNode(node.left) === evalNode(node.right);
-            case 'LessThanExpression':
-                return evalNode(node.left) < evalNode(node.right);
-            case 'GreaterThanExpression':
-                return evalNode(node.left) > evalNode(node.right);
-            case 'LessEqualExpression':
-                return evalNode(node.left) <= evalNode(node.right);
-            case 'GreaterEqualExpression':
-                return evalNode(node.left) >= evalNode(node.right);
-            case 'NotEqualExpression':
-                return evalNode(node.left) !== evalNode(node.right);
-            case 'AndExpression':
-                return !!(evalNode(node.left) && evalNode(node.right));
-            case 'OrExpression':
-                return !!(evalNode(node.left) || evalNode(node.right));
-            case 'XorExpression':
-                const leftVal = evalNode(node.left);
-                const rightVal = evalNode(node.right);
-                return !!((leftVal && !rightVal) || (!leftVal && rightVal));
-            case 'NotExpression':
-                return !evalNode(node.operand);
-            case 'UnaryMinusExpression':
-                return -evalNode(node.operand);
-            case 'TableLiteral':
-                const table = {};
-                let arrayIndex = 1;
-                
-                for (const entry of node.entries) {
-                    if (entry.key === null) {
-                        // Array-like entry: {1, 2, 3}
-                        table[arrayIndex] = evalNode(entry.value);
-                        arrayIndex++;
-                    } else {
-                        // Key-value entry: {name: "Alice", age: 30}
-                        let key;
-                        if (entry.key.type === 'Identifier') {
-                            // Convert identifier keys to strings
-                            key = entry.key.value;
+        callStackTracker.push('evalNode', node?.type || 'unknown');
+        
+        try {
+            if (!node) {
+                return undefined;
+            }
+            switch (node.type) {
+                case 'NumberLiteral':
+                    return parseFloat(node.value);
+                case 'StringLiteral':
+                    return node.value;
+                case 'BooleanLiteral':
+                    return node.value;
+                case 'PlusExpression':
+                    return evalNode(node.left) + evalNode(node.right);
+                case 'MinusExpression':
+                    return evalNode(node.left) - evalNode(node.right);
+                case 'MultiplyExpression':
+                    return evalNode(node.left) * evalNode(node.right);
+                case 'DivideExpression':
+                    const divisor = evalNode(node.right);
+                    if (divisor === 0) {
+                        throw new Error('Division by zero');
+                    }
+                    return evalNode(node.left) / evalNode(node.right);
+                case 'ModuloExpression':
+                    return evalNode(node.left) % evalNode(node.right);
+                case 'PowerExpression':
+                    return Math.pow(evalNode(node.left), evalNode(node.right));
+                case 'EqualsExpression':
+                    return evalNode(node.left) === evalNode(node.right);
+                case 'LessThanExpression':
+                    return evalNode(node.left) < evalNode(node.right);
+                case 'GreaterThanExpression':
+                    return evalNode(node.left) > evalNode(node.right);
+                case 'LessEqualExpression':
+                    return evalNode(node.left) <= evalNode(node.right);
+                case 'GreaterEqualExpression':
+                    return evalNode(node.left) >= evalNode(node.right);
+                case 'NotEqualExpression':
+                    return evalNode(node.left) !== evalNode(node.right);
+                case 'AndExpression':
+                    return !!(evalNode(node.left) && evalNode(node.right));
+                case 'OrExpression':
+                    return !!(evalNode(node.left) || evalNode(node.right));
+                case 'XorExpression':
+                    const leftVal = evalNode(node.left);
+                    const rightVal = evalNode(node.right);
+                    return !!((leftVal && !rightVal) || (!leftVal && rightVal));
+                case 'NotExpression':
+                    return !evalNode(node.operand);
+                case 'UnaryMinusExpression':
+                    return -evalNode(node.operand);
+                case 'TableLiteral':
+                    const table = {};
+                    let arrayIndex = 1;
+                    
+                    for (const entry of node.entries) {
+                        if (entry.key === null) {
+                            // Array-like entry: {1, 2, 3}
+                            table[arrayIndex] = evalNode(entry.value);
+                            arrayIndex++;
                         } else {
-                            // For other key types (numbers, strings), evaluate normally
-                            key = evalNode(entry.key);
+                            // Key-value entry: {name: "Alice", age: 30}
+                            let key;
+                            if (entry.key.type === 'Identifier') {
+                                // Convert identifier keys to strings
+                                key = entry.key.value;
+                            } else {
+                                // For other key types (numbers, strings), evaluate normally
+                                key = evalNode(entry.key);
+                            }
+                            const value = evalNode(entry.value);
+                            table[key] = value;
                         }
-                        const value = evalNode(entry.value);
-                        table[key] = value;
                     }
-                }
-                
-                return table;
-            case 'TableAccess':
-                const tableValue = evalNode(node.table);
-                let keyValue;
-                
-                // Handle different key types
-                if (node.key.type === 'Identifier') {
-                    // For dot notation, use the identifier name as the key
-                    keyValue = node.key.value;
-                } else {
-                    // For bracket notation, evaluate the key expression
-                    keyValue = evalNode(node.key);
-                }
-                
-                if (typeof tableValue !== 'object' || tableValue === null) {
-                    throw new Error('Cannot access property of non-table value');
-                }
-                
-                if (tableValue[keyValue] === undefined) {
-                    throw new Error(`Key '${keyValue}' not found in table`);
-                }
-                
-                return tableValue[keyValue];
-            case 'AssignmentExpression':
-                if (globalScope.hasOwnProperty(node.name)) {
-                    throw new Error(`Cannot reassign immutable variable: ${node.name}`);
-                }
-                const value = evalNode(node.value);
-                globalScope[node.name] = value;
-                return;
-            case 'Identifier':
-                const identifierValue = globalScope[node.value];
-                if (identifierValue === undefined) {
-                    throw new Error(`Variable ${node.value} is not defined`);
-                }
-                return identifierValue;
-            case 'FunctionDeclaration':
-                // For anonymous functions, the name comes from the assignment
-                // The function itself doesn't have a name, so we just return
-                // The assignment will handle storing it in the global scope
-                return function(...args) {
-                    let localScope = Object.create(globalScope);
-                    for (let i = 0; i < node.params.length; i++) {
-                        localScope[node.params[i]] = args[i];
+                    
+                    return table;
+                case 'TableAccess':
+                    const tableValue = evalNode(node.table);
+                    let keyValue;
+                    
+                    // Handle different key types
+                    if (node.key.type === 'Identifier') {
+                        // For dot notation, use the identifier name as the key
+                        keyValue = node.key.value;
+                    } else {
+                        // For bracket notation, evaluate the key expression
+                        keyValue = evalNode(node.key);
                     }
-                    return localEvalNodeWithScope(node.body, localScope);
-                };
-            case 'FunctionCall':
-                let funcToCall; // Renamed from 'func' to avoid redeclaration
-                if (typeof node.name === 'string') {
-                    // Regular function call with string name
-                    funcToCall = globalScope[node.name];
-                } else if (node.name.type === 'Identifier') {
-                    // Function call with identifier
-                    funcToCall = globalScope[node.name.value];
-                } else if (node.name.type === 'TableAccess') {
-                    // Function call from table access (e.g., math.add)
-                    funcToCall = evalNode(node.name);
-                } else {
-                    throw new Error('Invalid function name in function call');
-                }
-                
-                if (funcToCall instanceof Function) {
-                    let args = node.args.map(evalNode);
-                    return funcToCall(...args);
-                }
-                throw new Error(`Function is not defined or is not callable`);
-            case 'CaseExpression':
-                const values = node.value.map(evalNode);
-                
-                for (const caseItem of node.cases) {
-                    const pattern = caseItem.pattern.map(evalNode);
                     
-                    let matches = true;
-                    for (let i = 0; i < Math.max(values.length, pattern.length); i++) {
-                        const value = values[i];
-                        const patternValue = pattern[i];
-                        
-                        if (patternValue === true) continue;
-                        
-                        if (value !== patternValue) {
-                            matches = false;
-                            break;
+                    if (typeof tableValue !== 'object' || tableValue === null) {
+                        throw new Error('Cannot access property of non-table value');
+                    }
+                    
+                    if (tableValue[keyValue] === undefined) {
+                        throw new Error(`Key '${keyValue}' not found in table`);
+                    }
+                    
+                    return tableValue[keyValue];
+                case 'AssignmentExpression':
+                    if (globalScope.hasOwnProperty(node.name)) {
+                        throw new Error(`Cannot reassign immutable variable: ${node.name}`);
+                    }
+                    const value = evalNode(node.value);
+                    globalScope[node.name] = value;
+                    return;
+                case 'Assignment':
+                    if (globalScope.hasOwnProperty(node.identifier)) {
+                        throw new Error(`Cannot reassign immutable variable: ${node.identifier}`);
+                    }
+                    const assignmentValue = evalNode(node.value);
+                    globalScope[node.identifier] = assignmentValue;
+                    return;
+                case 'Identifier':
+                    const identifierValue = globalScope[node.value];
+                    if (identifierValue === undefined) {
+                        throw new Error(`Variable ${node.value} is not defined`);
+                    }
+                    return identifierValue;
+                case 'FunctionDeclaration':
+                    // For anonymous functions, the name comes from the assignment
+                    // The function itself doesn't have a name, so we just return
+                    // The assignment will handle storing it in the global scope
+                    return function(...args) {
+                        callStackTracker.push('FunctionCall', node.params.join(','));
+                        try {
+                            let localScope = Object.create(globalScope);
+                            for (let i = 0; i < node.params.length; i++) {
+                                localScope[node.params[i]] = args[i];
+                            }
+                            return localEvalNodeWithScope(node.body, localScope);
+                        } finally {
+                            callStackTracker.pop();
                         }
+                    };
+                case 'FunctionDefinition':
+                    // Create a function from the function definition
+                    return function(...args) {
+                        callStackTracker.push('FunctionCall', node.parameters.join(','));
+                        try {
+                            let localScope = Object.create(globalScope);
+                            for (let i = 0; i < node.parameters.length; i++) {
+                                localScope[node.parameters[i]] = args[i];
+                            }
+                            return localEvalNodeWithScope(node.body, localScope);
+                        } finally {
+                            callStackTracker.pop();
+                        }
+                    };
+                case 'FunctionCall':
+                    let funcToCall; // Renamed from 'func' to avoid redeclaration
+                    if (typeof node.name === 'string') {
+                        // Regular function call with string name
+                        funcToCall = globalScope[node.name];
+                    } else if (node.name.type === 'Identifier') {
+                        // Function call with identifier
+                        funcToCall = globalScope[node.name.value];
+                    } else if (node.name.type === 'TableAccess') {
+                        // Function call from table access (e.g., math.add)
+                        funcToCall = evalNode(node.name);
+                    } else {
+                        throw new Error('Invalid function name in function call');
                     }
                     
-                    if (matches) {
-                        const results = caseItem.result.map(evalNode);
-                        if (results.length === 1) {
-                            return results[0];
+                    if (funcToCall instanceof Function) {
+                        let args = node.args.map(evalNode);
+                        return funcToCall(...args);
+                    }
+                    throw new Error(`Function is not defined or is not callable`);
+                case 'CaseExpression':
+                    const values = node.value.map(evalNode);
+                    
+                    for (const caseItem of node.cases) {
+                        const pattern = caseItem.pattern.map(evalNode);
+                        
+                        let matches = true;
+                        for (let i = 0; i < Math.max(values.length, pattern.length); i++) {
+                            const value = values[i];
+                            const patternValue = pattern[i];
+                            
+                            if (patternValue === true) continue;
+                            
+                            if (value !== patternValue) {
+                                matches = false;
+                                break;
+                            }
+                        }
+                        
+                        if (matches) {
+                            const results = caseItem.result.map(evalNode);
+                            if (results.length === 1) {
+                                return results[0];
+                            }
+                            return results.join(' ');
                         }
-                        return results.join(' ');
                     }
-                }
-                throw new Error('No matching pattern found');
-            case 'WildcardPattern':
-                return true;
-            case 'IOInExpression':
-                const readline = require('readline');
-                const rl = readline.createInterface({
-                    input: process.stdin,
-                    output: process.stdout
-                });
-                
-                return new Promise((resolve) => {
-                    rl.question('', (input) => {
-                        rl.close();
-                        const num = parseInt(input);
-                        resolve(isNaN(num) ? input : num);
+                    throw new Error('No matching pattern found');
+                case 'WildcardPattern':
+                    return true;
+                case 'IOInExpression':
+                    const readline = require('readline');
+                    const rl = readline.createInterface({
+                        input: process.stdin,
+                        output: process.stdout
                     });
-                });
-            case 'IOOutExpression':
-                const outputValue = evalNode(node.value);
-                console.log(outputValue);
-                return outputValue;
-            case 'IOAssertExpression':
-                const assertionValue = evalNode(node.value);
-                if (!assertionValue) {
-                    throw new Error('Assertion failed');
-                }
-                return assertionValue;
-            case 'FunctionReference':
-                const functionValue = globalScope[node.name];
-                if (functionValue === undefined) {
-                    throw new Error(`Function ${node.name} is not defined`);
-                }
-                if (typeof functionValue !== 'function') {
-                    throw new Error(`${node.name} is not a function`);
-                }
-                return functionValue;
-            default:
-                throw new Error(`Unknown node type: ${node.type}`);
+                    
+                    return new Promise((resolve) => {
+                        rl.question('', (input) => {
+                            rl.close();
+                            const num = parseInt(input);
+                            resolve(isNaN(num) ? input : num);
+                        });
+                    });
+                case 'IOOutExpression':
+                    const outputValue = evalNode(node.value);
+                    console.log(outputValue);
+                    return outputValue;
+                case 'IOAssertExpression':
+                    const assertionValue = evalNode(node.value);
+                    if (!assertionValue) {
+                        throw new Error('Assertion failed');
+                    }
+                    return assertionValue;
+                case 'FunctionReference':
+                    const functionValue = globalScope[node.name];
+                    if (functionValue === undefined) {
+                        throw new Error(`Function ${node.name} is not defined`);
+                    }
+                    if (typeof functionValue !== 'function') {
+                        throw new Error(`${node.name} is not a function`);
+                    }
+                    return functionValue;
+                case 'ArrowExpression':
+                    // Arrow expressions are function bodies that should be evaluated
+                    return evalNode(node.body);
+                default:
+                    throw new Error(`Unknown node type: ${node.type}`);
+            }
+        } finally {
+            callStackTracker.pop();
         }
     }
 
+    /**
+     * Evaluates AST nodes in a local scope with access to parent scope.
+     * 
+     * @param {Object} node - AST node to evaluate
+     * @param {Object} scope - Local scope object (prototypally inherits from global)
+     * @returns {*} The result of evaluating the node
+     * @throws {Error} For evaluation errors
+     * 
+     * @description Used for evaluating function bodies and other expressions
+     * that need access to both local and global variables.
+     */
     const localEvalNodeWithScope = (node, scope) => {
-        if (!node) {
-            return undefined;
-        }
-        switch (node.type) {
-            case 'NumberLiteral':
-                return parseFloat(node.value);
-            case 'StringLiteral':
-                return node.value;
-            case 'BooleanLiteral':
-                return node.value;
-            case 'PlusExpression':
-                return localEvalNodeWithScope(node.left, scope) + localEvalNodeWithScope(node.right, scope);
-            case 'MinusExpression':
-                return localEvalNodeWithScope(node.left, scope) - localEvalNodeWithScope(node.right, scope);
-            case 'MultiplyExpression':
-                return localEvalNodeWithScope(node.left, scope) * localEvalNodeWithScope(node.right, scope);
-            case 'DivideExpression':
-                const divisor = localEvalNodeWithScope(node.right, scope);
-                if (divisor === 0) {
-                    throw new Error('Division by zero');
-                }
-                return localEvalNodeWithScope(node.left, scope) / localEvalNodeWithScope(node.right, scope);
-            case 'ModuloExpression':
-                return localEvalNodeWithScope(node.left, scope) % localEvalNodeWithScope(node.right, scope);
-            case 'PowerExpression':
-                return Math.pow(localEvalNodeWithScope(node.left, scope), localEvalNodeWithScope(node.right, scope));
-            case 'EqualsExpression':
-                return localEvalNodeWithScope(node.left, scope) === localEvalNodeWithScope(node.right, scope);
-            case 'LessThanExpression':
-                return localEvalNodeWithScope(node.left, scope) < localEvalNodeWithScope(node.right, scope);
-            case 'GreaterThanExpression':
-                return localEvalNodeWithScope(node.left, scope) > localEvalNodeWithScope(node.right, scope);
-            case 'LessEqualExpression':
-                return localEvalNodeWithScope(node.left, scope) <= localEvalNodeWithScope(node.right, scope);
-            case 'GreaterEqualExpression':
-                return localEvalNodeWithScope(node.left, scope) >= localEvalNodeWithScope(node.right, scope);
-            case 'NotEqualExpression':
-                return localEvalNodeWithScope(node.left, scope) !== localEvalNodeWithScope(node.right, scope);
-            case 'AndExpression':
-                return !!(localEvalNodeWithScope(node.left, scope) && localEvalNodeWithScope(node.right, scope));
-            case 'OrExpression':
-                return !!(localEvalNodeWithScope(node.left, scope) || localEvalNodeWithScope(node.right, scope));
-            case 'XorExpression':
-                const leftVal = localEvalNodeWithScope(node.left, scope);
-                const rightVal = localEvalNodeWithScope(node.right, scope);
-                return !!((leftVal && !rightVal) || (!leftVal && rightVal));
-            case 'NotExpression':
-                return !localEvalNodeWithScope(node.operand, scope);
-            case 'UnaryMinusExpression':
-                return -localEvalNodeWithScope(node.operand, scope);
-            case 'TableLiteral':
-                const table = {};
-                let arrayIndex = 1;
-                
-                for (const entry of node.entries) {
-                    if (entry.key === null) {
-                        // Array-like entry: {1, 2, 3}
-                        table[arrayIndex] = localEvalNodeWithScope(entry.value, scope);
-                        arrayIndex++;
-                    } else {
-                        // Key-value entry: {name: "Alice", age: 30}
-                        let key;
-                        if (entry.key.type === 'Identifier') {
-                            // Convert identifier keys to strings
-                            key = entry.key.value;
+        callStackTracker.push('localEvalNodeWithScope', node?.type || 'unknown');
+        
+        try {
+            if (!node) {
+                return undefined;
+            }
+            switch (node.type) {
+                case 'NumberLiteral':
+                    return parseFloat(node.value);
+                case 'StringLiteral':
+                    return node.value;
+                case 'BooleanLiteral':
+                    return node.value;
+                case 'PlusExpression':
+                    return localEvalNodeWithScope(node.left, scope) + localEvalNodeWithScope(node.right, scope);
+                case 'MinusExpression':
+                    return localEvalNodeWithScope(node.left, scope) - localEvalNodeWithScope(node.right, scope);
+                case 'MultiplyExpression':
+                    return localEvalNodeWithScope(node.left, scope) * localEvalNodeWithScope(node.right, scope);
+                case 'DivideExpression':
+                    const divisor = localEvalNodeWithScope(node.right, scope);
+                    if (divisor === 0) {
+                        throw new Error('Division by zero');
+                    }
+                    return localEvalNodeWithScope(node.left, scope) / localEvalNodeWithScope(node.right, scope);
+                case 'ModuloExpression':
+                    return localEvalNodeWithScope(node.left, scope) % localEvalNodeWithScope(node.right, scope);
+                case 'PowerExpression':
+                    return Math.pow(localEvalNodeWithScope(node.left, scope), localEvalNodeWithScope(node.right, scope));
+                case 'EqualsExpression':
+                    return localEvalNodeWithScope(node.left, scope) === localEvalNodeWithScope(node.right, scope);
+                case 'LessThanExpression':
+                    return localEvalNodeWithScope(node.left, scope) < localEvalNodeWithScope(node.right, scope);
+                case 'GreaterThanExpression':
+                    return localEvalNodeWithScope(node.left, scope) > localEvalNodeWithScope(node.right, scope);
+                case 'LessEqualExpression':
+                    return localEvalNodeWithScope(node.left, scope) <= localEvalNodeWithScope(node.right, scope);
+                case 'GreaterEqualExpression':
+                    return localEvalNodeWithScope(node.left, scope) >= localEvalNodeWithScope(node.right, scope);
+                case 'NotEqualExpression':
+                    return localEvalNodeWithScope(node.left, scope) !== localEvalNodeWithScope(node.right, scope);
+                case 'AndExpression':
+                    return !!(localEvalNodeWithScope(node.left, scope) && localEvalNodeWithScope(node.right, scope));
+                case 'OrExpression':
+                    return !!(localEvalNodeWithScope(node.left, scope) || localEvalNodeWithScope(node.right, scope));
+                case 'XorExpression':
+                    const leftVal = localEvalNodeWithScope(node.left, scope);
+                    const rightVal = localEvalNodeWithScope(node.right, scope);
+                    return !!((leftVal && !rightVal) || (!leftVal && rightVal));
+                case 'NotExpression':
+                    return !localEvalNodeWithScope(node.operand, scope);
+                case 'UnaryMinusExpression':
+                    return -localEvalNodeWithScope(node.operand, scope);
+                case 'TableLiteral':
+                    const table = {};
+                    let arrayIndex = 1;
+                    
+                    for (const entry of node.entries) {
+                        if (entry.key === null) {
+                            // Array-like entry: {1, 2, 3}
+                            table[arrayIndex] = localEvalNodeWithScope(entry.value, scope);
+                            arrayIndex++;
                         } else {
-                            // For other key types (numbers, strings), evaluate normally
-                            key = localEvalNodeWithScope(entry.key, scope);
+                            // Key-value entry: {name: "Alice", age: 30}
+                            let key;
+                            if (entry.key.type === 'Identifier') {
+                                // Convert identifier keys to strings
+                                key = entry.key.value;
+                            } else {
+                                // For other key types (numbers, strings), evaluate normally
+                                key = localEvalNodeWithScope(entry.key, scope);
+                            }
+                            const value = localEvalNodeWithScope(entry.value, scope);
+                            table[key] = value;
                         }
-                        const value = localEvalNodeWithScope(entry.value, scope);
-                        table[key] = value;
                     }
-                }
-                
-                return table;
-            case 'TableAccess':
-                const tableValue = localEvalNodeWithScope(node.table, scope);
-                let keyValue;
-                
-                // Handle different key types
-                if (node.key.type === 'Identifier') {
-                    // For dot notation, use the identifier name as the key
-                    keyValue = node.key.value;
-                } else {
-                    // For bracket notation, evaluate the key expression
-                    keyValue = localEvalNodeWithScope(node.key, scope);
-                }
-                
-                if (typeof tableValue !== 'object' || tableValue === null) {
-                    throw new Error('Cannot access property of non-table value');
-                }
-                
-                if (tableValue[keyValue] === undefined) {
-                    throw new Error(`Key '${keyValue}' not found in table`);
-                }
-                
-                return tableValue[keyValue];
-            case 'AssignmentExpression':
-                if (globalScope.hasOwnProperty(node.name)) {
-                    throw new Error(`Cannot reassign immutable variable: ${node.name}`);
-                }
-                globalScope[node.name] = localEvalNodeWithScope(node.value, scope);
-                return;
-            case 'Identifier':
-                // First check local scope, then global scope
-                if (scope && scope.hasOwnProperty(node.value)) {
-                    return scope[node.value];
-                }
-                const identifierValue = globalScope[node.value];
-                if (identifierValue === undefined && node.value) {
-                    return node.value;
-                }
-                return identifierValue;
-            case 'FunctionDeclaration':
-                // For anonymous functions, the name comes from the assignment
-                // The function itself doesn't have a name, so we just return
-                // The assignment will handle storing it in the global scope
-                return function(...args) {
-                    let nestedScope = Object.create(globalScope);
-                    for (let i = 0; i < node.params.length; i++) {
-                        nestedScope[node.params[i]] = args[i];
+                    
+                    return table;
+                case 'TableAccess':
+                    const tableValue = localEvalNodeWithScope(node.table, scope);
+                    let keyValue;
+                    
+                    // Handle different key types
+                    if (node.key.type === 'Identifier') {
+                        // For dot notation, use the identifier name as the key
+                        keyValue = node.key.value;
+                    } else {
+                        // For bracket notation, evaluate the key expression
+                        keyValue = localEvalNodeWithScope(node.key, scope);
                     }
-                    return localEvalNodeWithScope(node.body, nestedScope);
-                };
-            case 'FunctionCall':
-                let localFunc;
-                if (typeof node.name === 'string') {
-                    // Regular function call with string name
-                    localFunc = globalScope[node.name];
-                } else if (node.name.type === 'Identifier') {
-                    // Function call with identifier
-                    localFunc = globalScope[node.name.value];
-                } else if (node.name.type === 'TableAccess') {
-                    // Function call from table access (e.g., math.add)
-                    localFunc = localEvalNodeWithScope(node.name, scope);
-                } else {
-                    throw new Error('Invalid function name in function call');
-                }
-                
-                if (localFunc instanceof Function) {
-                    let args = node.args.map(arg => localEvalNodeWithScope(arg, scope));
-                    return localFunc(...args);
-                }
-                throw new Error(`Function is not defined or is not callable`);
-            case 'CaseExpression':
-                const values = node.value.map(val => localEvalNodeWithScope(val, scope));
-                
-                for (const caseItem of node.cases) {
-                    const pattern = caseItem.pattern.map(pat => localEvalNodeWithScope(pat, scope));
                     
-                    let matches = true;
-                    for (let i = 0; i < Math.max(values.length, pattern.length); i++) {
-                        const value = values[i];
-                        const patternValue = pattern[i];
-                        
-                        if (patternValue === true) continue;
-                        
-                        if (value !== patternValue) {
-                            matches = false;
-                            break;
+                    if (typeof tableValue !== 'object' || tableValue === null) {
+                        throw new Error('Cannot access property of non-table value');
+                    }
+                    
+                    if (tableValue[keyValue] === undefined) {
+                        throw new Error(`Key '${keyValue}' not found in table`);
+                    }
+                    
+                    return tableValue[keyValue];
+                case 'AssignmentExpression':
+                    if (globalScope.hasOwnProperty(node.name)) {
+                        throw new Error(`Cannot reassign immutable variable: ${node.name}`);
+                    }
+                    globalScope[node.name] = localEvalNodeWithScope(node.value, scope);
+                    return;
+                case 'Identifier':
+                    // First check local scope, then global scope
+                    if (scope && scope.hasOwnProperty(node.value)) {
+                        return scope[node.value];
+                    }
+                    const identifierValue = globalScope[node.value];
+                    if (identifierValue === undefined && node.value) {
+                        return node.value;
+                    }
+                    return identifierValue;
+                case 'FunctionDeclaration':
+                    // For anonymous functions, the name comes from the assignment
+                    // The function itself doesn't have a name, so we just return
+                    // The assignment will handle storing it in the global scope
+                    return function(...args) {
+                        callStackTracker.push('FunctionCall', node.params.join(','));
+                        try {
+                            let nestedScope = Object.create(globalScope);
+                            for (let i = 0; i < node.params.length; i++) {
+                                nestedScope[node.params[i]] = args[i];
+                            }
+                            return localEvalNodeWithScope(node.body, nestedScope);
+                        } finally {
+                            callStackTracker.pop();
+                        }
+                    };
+                case 'FunctionDefinition':
+                    // Create a function from the function definition
+                    return function(...args) {
+                        callStackTracker.push('FunctionCall', node.parameters.join(','));
+                        try {
+                            let nestedScope = Object.create(globalScope);
+                            for (let i = 0; i < node.parameters.length; i++) {
+                                nestedScope[node.parameters[i]] = args[i];
+                            }
+                            return localEvalNodeWithScope(node.body, nestedScope);
+                        } finally {
+                            callStackTracker.pop();
                         }
+                    };
+                case 'FunctionCall':
+                    let localFunc;
+                    if (typeof node.name === 'string') {
+                        // Regular function call with string name
+                        localFunc = globalScope[node.name];
+                    } else if (node.name.type === 'Identifier') {
+                        // Function call with identifier
+                        localFunc = globalScope[node.name.value];
+                    } else if (node.name.type === 'TableAccess') {
+                        // Function call from table access (e.g., math.add)
+                        localFunc = localEvalNodeWithScope(node.name, scope);
+                    } else {
+                        throw new Error('Invalid function name in function call');
                     }
                     
-                    if (matches) {
-                        const results = caseItem.result.map(res => localEvalNodeWithScope(res, scope));
-                        if (results.length === 1) {
-                            return results[0];
+                    if (localFunc instanceof Function) {
+                        let args = node.args.map(arg => localEvalNodeWithScope(arg, scope));
+                        return localFunc(...args);
+                    }
+                    throw new Error(`Function is not defined or is not callable`);
+                case 'CaseExpression':
+                    const values = node.value.map(val => localEvalNodeWithScope(val, scope));
+                    
+                    for (const caseItem of node.cases) {
+                        const pattern = caseItem.pattern.map(pat => localEvalNodeWithScope(pat, scope));
+                        
+                        let matches = true;
+                        for (let i = 0; i < Math.max(values.length, pattern.length); i++) {
+                            const value = values[i];
+                            const patternValue = pattern[i];
+                            
+                            if (patternValue === true) continue;
+                            
+                            if (value !== patternValue) {
+                                matches = false;
+                                break;
+                            }
+                        }
+                        
+                        if (matches) {
+                            const results = caseItem.result.map(res => localEvalNodeWithScope(res, scope));
+                            if (results.length === 1) {
+                                return results[0];
+                            }
+                            return results.join(' ');
                         }
-                        return results.join(' ');
                     }
-                }
-                throw new Error('No matching pattern found');
-            case 'WildcardPattern':
-                return true;
-            case 'IOInExpression':
-                const readline = require('readline');
-                const rl = readline.createInterface({
-                    input: process.stdin,
-                    output: process.stdout
-                });
-                
-                return new Promise((resolve) => {
-                    rl.question('', (input) => {
-                        rl.close();
-                        const num = parseInt(input);
-                        resolve(isNaN(num) ? input : num);
+                    throw new Error('No matching pattern found');
+                case 'WildcardPattern':
+                    return true;
+                case 'IOInExpression':
+                    const readline = require('readline');
+                    const rl = readline.createInterface({
+                        input: process.stdin,
+                        output: process.stdout
                     });
-                });
-            case 'IOOutExpression':
-                const localOutputValue = localEvalNodeWithScope(node.value, scope);
-                console.log(localOutputValue);
-                return localOutputValue;
-            case 'IOAssertExpression':
-                const localAssertionValue = localEvalNodeWithScope(node.value, scope);
-                if (!localAssertionValue) {
-                    throw new Error('Assertion failed');
-                }
-                return localAssertionValue;
-            case 'FunctionReference':
-                const localFunctionValue = globalScope[node.name];
-                if (localFunctionValue === undefined) {
-                    throw new Error(`Function ${node.name} is not defined`);
-                }
-                if (typeof localFunctionValue !== 'function') {
-                    throw new Error(`${node.name} is not a function`);
-                }
-                return localFunctionValue;
-            default:
-                throw new Error(`Unknown node type: ${node.type}`);
+                    
+                    return new Promise((resolve) => {
+                        rl.question('', (input) => {
+                            rl.close();
+                            const num = parseInt(input);
+                            resolve(isNaN(num) ? input : num);
+                        });
+                    });
+                case 'IOOutExpression':
+                    const localOutputValue = localEvalNodeWithScope(node.value, scope);
+                    console.log(localOutputValue);
+                    return localOutputValue;
+                case 'IOAssertExpression':
+                    const localAssertionValue = localEvalNodeWithScope(node.value, scope);
+                    if (!localAssertionValue) {
+                        throw new Error('Assertion failed');
+                    }
+                    return localAssertionValue;
+                case 'FunctionReference':
+                    const localFunctionValue = globalScope[node.name];
+                    if (localFunctionValue === undefined) {
+                        throw new Error(`Function ${node.name} is not defined`);
+                    }
+                    if (typeof localFunctionValue !== 'function') {
+                        throw new Error(`${node.name} is not a function`);
+                    }
+                    return localFunctionValue;
+                case 'ArrowExpression':
+                    // Arrow expressions are function bodies that should be evaluated
+                    return localEvalNodeWithScope(node.body, scope);
+                default:
+                    throw new Error(`Unknown node type: ${node.type}`);
+            }
+        } finally {
+            callStackTracker.pop();
         }
     };
 
+    /**
+     * Evaluates AST nodes in the global scope (internal recursion helper).
+     * 
+     * @param {Object} node - AST node to evaluate
+     * @returns {*} The result of evaluating the node
+     * @throws {Error} For evaluation errors
+     * 
+     * @description Internal helper function for recursive evaluation that
+     * always uses the global scope. Used to avoid circular dependencies.
+     */
     const localEvalNode = (node) => {
-        if (!node) {
-            return undefined;
-        }
-        switch (node.type) {
-            case 'NumberLiteral':
-                return parseFloat(node.value);
-            case 'StringLiteral':
-                return node.value;
-            case 'BooleanLiteral':
-                return node.value;
-            case 'PlusExpression':
-                return localEvalNode(node.left) + localEvalNode(node.right);
-            case 'MinusExpression':
-                return localEvalNode(node.left) - localEvalNode(node.right);
-            case 'MultiplyExpression':
-                return localEvalNode(node.left) * localEvalNode(node.right);
-            case 'DivideExpression':
-                const divisor = localEvalNode(node.right);
-                if (divisor === 0) {
-                    throw new Error('Division by zero');
-                }
-                return localEvalNode(node.left) / localEvalNode(node.right);
-            case 'ModuloExpression':
-                return localEvalNode(node.left) % localEvalNode(node.right);
-            case 'PowerExpression':
-                return Math.pow(localEvalNode(node.left), localEvalNode(node.right));
-            case 'EqualsExpression':
-                return localEvalNode(node.left) === localEvalNode(node.right);
-            case 'LessThanExpression':
-                return localEvalNode(node.left) < localEvalNode(node.right);
-            case 'GreaterThanExpression':
-                return localEvalNode(node.left) > localEvalNode(node.right);
-            case 'LessEqualExpression':
-                return localEvalNode(node.left) <= localEvalNode(node.right);
-            case 'GreaterEqualExpression':
-                return localEvalNode(node.left) >= localEvalNode(node.right);
-            case 'NotEqualExpression':
-                return localEvalNode(node.left) !== localEvalNode(node.right);
-            case 'AndExpression':
-                return !!(localEvalNode(node.left) && localEvalNode(node.right));
-            case 'OrExpression':
-                return !!(localEvalNode(node.left) || localEvalNode(node.right));
-            case 'XorExpression':
-                const leftVal = localEvalNode(node.left);
-                const rightVal = localEvalNode(node.right);
-                return !!((leftVal && !rightVal) || (!leftVal && rightVal));
-            case 'NotExpression':
-                return !localEvalNode(node.operand);
-            case 'UnaryMinusExpression':
-                return -localEvalNode(node.operand);
-            case 'TableLiteral':
-                const table = {};
-                let arrayIndex = 1;
-                
-                for (const entry of node.entries) {
-                    if (entry.key === null) {
-                        // Array-like entry: {1, 2, 3}
-                        table[arrayIndex] = localEvalNode(entry.value);
-                        arrayIndex++;
-                    } else {
-                        // Key-value entry: {name: "Alice", age: 30}
-                        let key;
-                        if (entry.key.type === 'Identifier') {
-                            // Convert identifier keys to strings
-                            key = entry.key.value;
+        callStackTracker.push('localEvalNode', node?.type || 'unknown');
+        
+        try {
+            if (!node) {
+                return undefined;
+            }
+            switch (node.type) {
+                case 'NumberLiteral':
+                    return parseFloat(node.value);
+                case 'StringLiteral':
+                    return node.value;
+                case 'BooleanLiteral':
+                    return node.value;
+                case 'PlusExpression':
+                    return localEvalNode(node.left) + localEvalNode(node.right);
+                case 'MinusExpression':
+                    return localEvalNode(node.left) - localEvalNode(node.right);
+                case 'MultiplyExpression':
+                    return localEvalNode(node.left) * localEvalNode(node.right);
+                case 'DivideExpression':
+                    const divisor = localEvalNode(node.right);
+                    if (divisor === 0) {
+                        throw new Error('Division by zero');
+                    }
+                    return localEvalNode(node.left) / localEvalNode(node.right);
+                case 'ModuloExpression':
+                    return localEvalNode(node.left) % localEvalNode(node.right);
+                case 'PowerExpression':
+                    return Math.pow(localEvalNode(node.left), localEvalNode(node.right));
+                case 'EqualsExpression':
+                    return localEvalNode(node.left) === localEvalNode(node.right);
+                case 'LessThanExpression':
+                    return localEvalNode(node.left) < localEvalNode(node.right);
+                case 'GreaterThanExpression':
+                    return localEvalNode(node.left) > localEvalNode(node.right);
+                case 'LessEqualExpression':
+                    return localEvalNode(node.left) <= localEvalNode(node.right);
+                case 'GreaterEqualExpression':
+                    return localEvalNode(node.left) >= localEvalNode(node.right);
+                case 'NotEqualExpression':
+                    return localEvalNode(node.left) !== localEvalNode(node.right);
+                case 'AndExpression':
+                    return !!(localEvalNode(node.left) && localEvalNode(node.right));
+                case 'OrExpression':
+                    return !!(localEvalNode(node.left) || localEvalNode(node.right));
+                case 'XorExpression':
+                    const leftVal = localEvalNode(node.left);
+                    const rightVal = localEvalNode(node.right);
+                    return !!((leftVal && !rightVal) || (!leftVal && rightVal));
+                case 'NotExpression':
+                    return !localEvalNode(node.operand);
+                case 'UnaryMinusExpression':
+                    return -localEvalNode(node.operand);
+                case 'TableLiteral':
+                    const table = {};
+                    let arrayIndex = 1;
+                    
+                    for (const entry of node.entries) {
+                        if (entry.key === null) {
+                            // Array-like entry: {1, 2, 3}
+                            table[arrayIndex] = localEvalNode(entry.value);
+                            arrayIndex++;
                         } else {
-                            // For other key types (numbers, strings), evaluate normally
-                            key = localEvalNode(entry.key);
+                            // Key-value entry: {name: "Alice", age: 30}
+                            let key;
+                            if (entry.key.type === 'Identifier') {
+                                // Convert identifier keys to strings
+                                key = entry.key.value;
+                            } else {
+                                // For other key types (numbers, strings), evaluate normally
+                                key = localEvalNode(entry.key);
+                            }
+                            const value = localEvalNode(entry.value);
+                            table[key] = value;
                         }
-                        const value = localEvalNode(entry.value);
-                        table[key] = value;
                     }
-                }
-                
-                return table;
-            case 'TableAccess':
-                const tableValue = localEvalNode(node.table);
-                let keyValue;
-                
-                // Handle different key types
-                if (node.key.type === 'Identifier') {
-                    // For dot notation, use the identifier name as the key
-                    keyValue = node.key.value;
-                } else {
-                    // For bracket notation, evaluate the key expression
-                    keyValue = localEvalNode(node.key);
-                }
-                
-                if (typeof tableValue !== 'object' || tableValue === null) {
-                    throw new Error('Cannot access property of non-table value');
-                }
-                
-                if (tableValue[keyValue] === undefined) {
-                    throw new Error(`Key '${keyValue}' not found in table`);
-                }
-                
-                return tableValue[keyValue];
-            case 'AssignmentExpression':
-                if (globalScope.hasOwnProperty(node.name)) {
-                    throw new Error(`Cannot reassign immutable variable: ${node.name}`);
-                }
-                globalScope[node.name] = localEvalNode(node.value);
-                return;
-            case 'Identifier':
-                const identifierValue = globalScope[node.value];
-                if (identifierValue === undefined && node.value) {
-                    return node.value;
-                }
-                return identifierValue;
-            case 'FunctionDeclaration':
-                // For anonymous functions, the name comes from the assignment
-                // The function itself doesn't have a name, so we just return
-                // The assignment will handle storing it in the global scope
-                return function(...args) {
-                    let nestedScope = Object.create(globalScope);
-                    for (let i = 0; i < node.params.length; i++) {
-                        nestedScope[node.params[i]] = args[i];
+                    
+                    return table;
+                case 'TableAccess':
+                    const tableValue = localEvalNode(node.table);
+                    let keyValue;
+                    
+                    // Handle different key types
+                    if (node.key.type === 'Identifier') {
+                        // For dot notation, use the identifier name as the key
+                        keyValue = node.key.value;
+                    } else {
+                        // For bracket notation, evaluate the key expression
+                        keyValue = localEvalNode(node.key);
                     }
-                    return localEvalNodeWithScope(node.body, nestedScope);
-                };
-            case 'FunctionCall':
-                let localFunc;
-                if (typeof node.name === 'string') {
-                    // Regular function call with string name
-                    localFunc = globalScope[node.name];
-                } else if (node.name.type === 'Identifier') {
-                    // Function call with identifier
-                    localFunc = globalScope[node.name.value];
-                } else if (node.name.type === 'TableAccess') {
-                    // Function call from table access (e.g., math.add)
-                    localFunc = localEvalNode(node.name);
-                } else {
-                    throw new Error('Invalid function name in function call');
-                }
-                
-                if (localFunc instanceof Function) {
-                    let args = node.args.map(localEvalNode);
-                    return localFunc(...args);
-                }
-                throw new Error(`Function is not defined or is not callable`);
-            case 'CaseExpression':
-                const values = node.value.map(localEvalNode);
-                
-                for (const caseItem of node.cases) {
-                    const pattern = caseItem.pattern.map(localEvalNode);
                     
-                    let matches = true;
-                    for (let i = 0; i < Math.max(values.length, pattern.length); i++) {
-                        const value = values[i];
-                        const patternValue = pattern[i];
-                        
-                        if (patternValue === true) continue;
-                        
-                        if (value !== patternValue) {
-                            matches = false;
-                            break;
+                    if (typeof tableValue !== 'object' || tableValue === null) {
+                        throw new Error('Cannot access property of non-table value');
+                    }
+                    
+                    if (tableValue[keyValue] === undefined) {
+                        throw new Error(`Key '${keyValue}' not found in table`);
+                    }
+                    
+                    return tableValue[keyValue];
+                case 'AssignmentExpression':
+                    if (globalScope.hasOwnProperty(node.name)) {
+                        throw new Error(`Cannot reassign immutable variable: ${node.name}`);
+                    }
+                    globalScope[node.name] = localEvalNode(node.value);
+                    return;
+                case 'Identifier':
+                    const identifierValue = globalScope[node.value];
+                    if (identifierValue === undefined && node.value) {
+                        return node.value;
+                    }
+                    return identifierValue;
+                case 'FunctionDeclaration':
+                    // For anonymous functions, the name comes from the assignment
+                    // The function itself doesn't have a name, so we just return
+                    // The assignment will handle storing it in the global scope
+                    return function(...args) {
+                        callStackTracker.push('FunctionCall', node.params.join(','));
+                        try {
+                            let nestedScope = Object.create(globalScope);
+                            for (let i = 0; i < node.params.length; i++) {
+                                nestedScope[node.params[i]] = args[i];
+                            }
+                            return localEvalNodeWithScope(node.body, nestedScope);
+                        } finally {
+                            callStackTracker.pop();
                         }
+                    };
+                case 'FunctionDefinition':
+                    // Create a function from the function definition
+                    return function(...args) {
+                        callStackTracker.push('FunctionCall', node.parameters.join(','));
+                        try {
+                            let nestedScope = Object.create(globalScope);
+                            for (let i = 0; i < node.parameters.length; i++) {
+                                nestedScope[node.parameters[i]] = args[i];
+                            }
+                            return localEvalNodeWithScope(node.body, nestedScope);
+                        } finally {
+                            callStackTracker.pop();
+                        }
+                    };
+                case 'FunctionCall':
+                    let localFunc;
+                    if (typeof node.name === 'string') {
+                        // Regular function call with string name
+                        localFunc = globalScope[node.name];
+                    } else if (node.name.type === 'Identifier') {
+                        // Function call with identifier
+                        localFunc = globalScope[node.name.value];
+                    } else if (node.name.type === 'TableAccess') {
+                        // Function call from table access (e.g., math.add)
+                        localFunc = localEvalNode(node.name);
+                    } else {
+                        throw new Error('Invalid function name in function call');
+                    }
+                    
+                    if (localFunc instanceof Function) {
+                        let args = node.args.map(localEvalNode);
+                        return localFunc(...args);
                     }
+                    throw new Error(`Function is not defined or is not callable`);
+                case 'CaseExpression':
+                    const values = node.value.map(localEvalNode);
                     
-                    if (matches) {
-                        const results = caseItem.result.map(localEvalNode);
-                        if (results.length === 1) {
-                            return results[0];
+                    for (const caseItem of node.cases) {
+                        const pattern = caseItem.pattern.map(localEvalNode);
+                        
+                        let matches = true;
+                        for (let i = 0; i < Math.max(values.length, pattern.length); i++) {
+                            const value = values[i];
+                            const patternValue = pattern[i];
+                            
+                            if (patternValue === true) continue;
+                            
+                            if (value !== patternValue) {
+                                matches = false;
+                                break;
+                            }
+                        }
+                        
+                        if (matches) {
+                            const results = caseItem.result.map(localEvalNode);
+                            if (results.length === 1) {
+                                return results[0];
+                            }
+                            return results.join(' ');
                         }
-                        return results.join(' ');
                     }
-                }
-                throw new Error('No matching pattern found');
-            case 'WildcardPattern':
-                return true;
-            case 'IOInExpression':
-                const readline = require('readline');
-                const rl = readline.createInterface({
-                    input: process.stdin,
-                    output: process.stdout
-                });
-                
-                return new Promise((resolve) => {
-                    rl.question('', (input) => {
-                        rl.close();
-                        const num = parseInt(input);
-                        resolve(isNaN(num) ? input : num);
+                    throw new Error('No matching pattern found');
+                case 'WildcardPattern':
+                    return true;
+                case 'IOInExpression':
+                    const readline = require('readline');
+                    const rl = readline.createInterface({
+                        input: process.stdin,
+                        output: process.stdout
                     });
-                });
-            case 'IOOutExpression':
-                const localOutputValue = localEvalNode(node.value);
-                console.log(localOutputValue);
-                return localOutputValue;
-            case 'IOAssertExpression':
-                const localAssertionValue = localEvalNode(node.value);
-                if (!localAssertionValue) {
-                    throw new Error('Assertion failed');
-                }
-                return localAssertionValue;
-            case 'FunctionReference':
-                const localFunctionValue = globalScope[node.name];
-                if (localFunctionValue === undefined) {
-                    throw new Error(`Function ${node.name} is not defined`);
-                }
-                if (typeof localFunctionValue !== 'function') {
-                    throw new Error(`${node.name} is not a function`);
-                }
-                return localFunctionValue;
-            default:
-                throw new Error(`Unknown node type: ${node.type}`);
+                    
+                    return new Promise((resolve) => {
+                        rl.question('', (input) => {
+                            rl.close();
+                            const num = parseInt(input);
+                            resolve(isNaN(num) ? input : num);
+                        });
+                    });
+                case 'IOOutExpression':
+                    const localOutputValue = localEvalNode(node.value);
+                    console.log(localOutputValue);
+                    return localOutputValue;
+                case 'IOAssertExpression':
+                    const localAssertionValue = localEvalNode(node.value);
+                    if (!localAssertionValue) {
+                        throw new Error('Assertion failed');
+                    }
+                    return localAssertionValue;
+                case 'FunctionReference':
+                    const localFunctionValue = globalScope[node.name];
+                    if (localFunctionValue === undefined) {
+                        throw new Error(`Function ${node.name} is not defined`);
+                    }
+                    if (typeof localFunctionValue !== 'function') {
+                        throw new Error(`${node.name} is not a function`);
+                    }
+                    return localFunctionValue;
+                case 'ArrowExpression':
+                    // Arrow expressions are function bodies that should be evaluated
+                    return localEvalNode(node.body);
+                default:
+                    throw new Error(`Unknown node type: ${node.type}`);
+            }
+        } finally {
+            callStackTracker.pop();
         }
     };
 
@@ -1823,9 +2734,18 @@ function interpreter(ast) {
 }
 
 /**
- * Debug logging and error reporting.
+ * Debug logging utility function.
  * 
- * Why: Debug functions are gated by the DEBUG environment variable, allowing for verbose output during development and silent operation in production. This approach makes it easy to trace execution and diagnose issues without cluttering normal output.
+ * @param {string} message - Debug message to log
+ * @param {*} [data=null] - Optional data to log with the message
+ * 
+ * @description Logs debug messages to console when DEBUG environment variable is set.
+ * Provides verbose output during development while remaining silent in production.
+ * 
+ * @why Debug functions are gated by the DEBUG environment variable, allowing for 
+ * verbose output during development and silent operation in production. This 
+ * approach makes it easy to trace execution and diagnose issues without 
+ * cluttering normal output.
  */
 function debugLog(message, data = null) {
     if (process.env.DEBUG) {
@@ -1837,9 +2757,18 @@ function debugLog(message, data = null) {
 }
 
 /**
- * Debug logging and error reporting.
+ * Debug error logging utility function.
+ * 
+ * @param {string} message - Debug error message to log
+ * @param {Error} [error=null] - Optional error object to log
  * 
- * Why: Debug functions are gated by the DEBUG environment variable, allowing for verbose output during development and silent operation in production. This approach makes it easy to trace execution and diagnose issues without cluttering normal output.
+ * @description Logs debug error messages to console when DEBUG environment variable is set.
+ * Provides verbose error output during development while remaining silent in production.
+ * 
+ * @why Debug functions are gated by the DEBUG environment variable, allowing for 
+ * verbose output during development and silent operation in production. This 
+ * approach makes it easy to trace execution and diagnose issues without 
+ * cluttering normal output.
  */
 function debugError(message, error = null) {
     if (process.env.DEBUG) {
@@ -1851,12 +2780,109 @@ function debugError(message, error = null) {
 }
 
 /**
+ * Call stack tracking for debugging recursion issues.
+ * 
+ * @description Tracks function calls to help identify infinite recursion
+ * and deep call stacks that cause stack overflow errors.
+ */
+const callStackTracker = {
+    stack: [],
+    maxDepth: 0,
+    callCounts: new Map(),
+    
+    /**
+     * Push a function call onto the stack
+     * @param {string} functionName - Name of the function being called
+     * @param {string} context - Context where the call is happening
+     */
+    push: function(functionName, context = '') {
+        const callInfo = { functionName, context, timestamp: Date.now() };
+        this.stack.push(callInfo);
+        
+        // Track maximum depth
+        if (this.stack.length > this.maxDepth) {
+            this.maxDepth = this.stack.length;
+        }
+        
+        // Count function calls
+        const key = `${functionName}${context ? `:${context}` : ''}`;
+        this.callCounts.set(key, (this.callCounts.get(key) || 0) + 1);
+        
+        // Check for potential infinite recursion
+        if (this.stack.length > 1000) {
+            console.error('=== POTENTIAL INFINITE RECURSION DETECTED ===');
+            console.error('Call stack depth:', this.stack.length);
+            console.error('Function call counts:', Object.fromEntries(this.callCounts));
+            console.error('Recent call stack:');
+            this.stack.slice(-10).forEach((call, i) => {
+                console.error(`  ${this.stack.length - 10 + i}: ${call.functionName}${call.context ? ` (${call.context})` : ''}`);
+            });
+            throw new Error(`Potential infinite recursion detected. Call stack depth: ${this.stack.length}`);
+        }
+        
+        if (process.env.DEBUG && this.stack.length % 100 === 0) {
+            console.log(`[DEBUG] Call stack depth: ${this.stack.length}, Max: ${this.maxDepth}`);
+        }
+    },
+    
+    /**
+     * Pop a function call from the stack
+     */
+    pop: function() {
+        return this.stack.pop();
+    },
+    
+    /**
+     * Get current stack depth
+     */
+    getDepth: function() {
+        return this.stack.length;
+    },
+    
+    /**
+     * Get call statistics
+     */
+    getStats: function() {
+        return {
+            currentDepth: this.stack.length,
+            maxDepth: this.maxDepth,
+            callCounts: Object.fromEntries(this.callCounts)
+        };
+    },
+    
+    /**
+     * Reset the tracker
+     */
+    reset: function() {
+        this.stack = [];
+        this.maxDepth = 0;
+        this.callCounts.clear();
+    }
+};
+
+/**
  * Reads a file, tokenizes, parses, and interprets it.
  * 
- * Why: This function is the entry point for file execution, handling all stages of the language pipeline. Debug output is provided at each stage for transparency and troubleshooting.
+ * @param {string} filePath - Path to the file to execute
+ * @throws {Error} For file reading, parsing, or execution errors
+ * 
+ * @description Main entry point for file execution. Handles the complete language
+ * pipeline: file reading, lexical analysis, parsing, and interpretation.
+ * 
+ * @why This function is the entry point for file execution, handling all stages 
+ * of the language pipeline. Debug output is provided at each stage for 
+ * transparency and troubleshooting.
+ * 
+ * @note Supports both synchronous and asynchronous execution, with proper
+ * error handling and process exit codes.
  */
 function executeFile(filePath) {
     try {
+        // Validate file extension
+        if (!filePath.endsWith('.txt')) {
+            throw new Error('Only .txt files are supported');
+        }
+        
         const fs = require('fs');
         const input = fs.readFileSync(filePath, 'utf8');
         
@@ -1875,25 +2901,51 @@ function executeFile(filePath) {
                 if (finalResult !== undefined) {
                     console.log(finalResult);
                 }
+                // Print call stack statistics after execution
+                const stats = callStackTracker.getStats();
+                console.log('\n=== CALL STACK STATISTICS ===');
+                console.log('Maximum call stack depth:', stats.maxDepth);
+                console.log('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
             }).catch(error => {
                 console.error(`Error executing file: ${error.message}`);
+                // Print call stack statistics on error
+                const stats = callStackTracker.getStats();
+                console.error('\n=== CALL STACK STATISTICS ON ERROR ===');
+                console.error('Maximum call stack depth:', stats.maxDepth);
+                console.error('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
                 process.exit(1);
             });
         } else {
             if (result !== undefined) {
                 console.log(result);
             }
+            // Print call stack statistics after execution
+            const stats = callStackTracker.getStats();
+            console.log('\n=== CALL STACK STATISTICS ===');
+            console.log('Maximum call stack depth:', stats.maxDepth);
+            console.log('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
         }
     } catch (error) {
         console.error(`Error executing file: ${error.message}`);
+        // Print call stack statistics on error
+        const stats = callStackTracker.getStats();
+        console.error('\n=== CALL STACK STATISTICS ON ERROR ===');
+        console.error('Maximum call stack depth:', stats.maxDepth);
+        console.error('Function call counts:', JSON.stringify(stats.callCounts, null, 2));
         process.exit(1);
     }
 }
 
 /**
- * CLI argument handling.
+ * CLI argument handling and program entry point.
+ * 
+ * @description Processes command line arguments and executes the specified file.
+ * Provides helpful error messages for incorrect usage.
+ * 
+ * @why The language is designed for file execution only (no REPL), so the CLI 
+ * enforces this usage and provides helpful error messages for incorrect invocation.
  * 
- * Why: The language is designed for file execution only (no REPL), so the CLI enforces this usage and provides helpful error messages for incorrect invocation.
+ * @note Exits with appropriate error codes for different failure scenarios.
  */
 const args = process.argv.slice(2);
 
diff --git a/js/scripting-lang/learn_scripting_lang.txt b/js/scripting-lang/learn_scripting_lang.txt
new file mode 100644
index 0000000..fc4f966
--- /dev/null
+++ b/js/scripting-lang/learn_scripting_lang.txt
@@ -0,0 +1,61 @@
+/* Learn an as of yet unnamed language in Y Minutes */
+/* A functional programming language with immutable variables, 
+   first-class functions, and pattern matching */
+
+/* We've got numbers */
+x : 42; /* also the ability to assign values to variables */
+y : 3.14;
+z : 0;
+
+/* We've got identifiers */
+this_is_a : "test";
+flag : true;
+value : false;
+
+/* We've got basic mathematical operators */
+sum : x + y;
+diff : x - y;
+prod : x * y;
+quot : x / y;
+
+/* We've got pattern matching case statements! */
+result : case x of
+    42 : "correct"
+    _ : "wrong";
+
+/* Of course, there are functions */
+double : x -> x * 2;
+add : x y -> x + y;
+func_result : double 5;
+
+/* And immutable tables, kinda inspired by Lua's tables */
+table : {1, 2, 3, name: "Alice", age: 30};
+first : table[1];
+table_name : table.name;
+
+/* A boring standard library */
+square : x -> x * x;
+mapped : map @double 5;
+composed : compose @double @square 3;
+
+/* Special functions for IO all start with .. */
+..out "Hello from the scripting language!";
+..out x;
+..out func_result;
+..out result;
+..out first;
+..out table_name;
+..out mapped;
+..out composed;
+
+/* There's a baked in IO function for performing assertions */
+..assert x = 42;
+..assert func_result = 10;
+..assert result = "correct";
+..assert first = 1;
+..assert table_name = "Alice";
+..assert mapped = 10;
+..assert composed = 18;
+..assert 5 > 3; /* ..assert should work with any kinda operators */  
+
+..out "Learn Scripting Language tutorial completed!"; 
\ No newline at end of file
diff --git a/js/scripting-lang/nested_test.txt b/js/scripting-lang/nested_test.txt
new file mode 100644
index 0000000..afb0677
--- /dev/null
+++ b/js/scripting-lang/nested_test.txt
@@ -0,0 +1,7 @@
+/* Test nested function calls in case expressions */
+factorial : n -> case n of
+    0 : 1
+    _ : factorial (n - 1);
+
+test : factorial 5;
+..out test; 
\ No newline at end of file
diff --git a/js/scripting-lang/paren_test.txt b/js/scripting-lang/paren_test.txt
new file mode 100644
index 0000000..990858b
--- /dev/null
+++ b/js/scripting-lang/paren_test.txt
@@ -0,0 +1,7 @@
+/* Test parentheses in case expressions */
+factorial : n -> case n of
+    0 : 1
+    _ : (n - 1);
+
+test : factorial 5;
+..out test; 
\ No newline at end of file
diff --git a/js/scripting-lang/run_tests.sh b/js/scripting-lang/run_tests.sh
index 056221a..b456ff0 100755
--- a/js/scripting-lang/run_tests.sh
+++ b/js/scripting-lang/run_tests.sh
@@ -65,6 +65,13 @@ unit_tests=(
     "tests/08_first_class_functions.txt:First-Class Functions"
     "tests/09_tables.txt:Tables"
     "tests/10_standard_library.txt:Standard Library"
+    "tests/11_edge_cases.txt:Edge Cases"
+    "tests/12_advanced_tables.txt:Advanced Tables"
+    "tests/13_standard_library_complete.txt:Complete Standard Library"
+    "tests/14_error_handling.txt:Error Handling"
+    # "tests/15_performance_stress.txt:Performance and Stress"
+    # "tests/16_advanced_functional.txt:Advanced Functional Programming"
+    # "tests/17_real_world_scenarios.txt:Real-World Scenarios"
 )
 
 for test in "${unit_tests[@]}"; do
@@ -87,6 +94,7 @@ integration_tests=(
     "tests/integration_01_basic_features.txt:Basic Features Integration"
     "tests/integration_02_pattern_matching.txt:Pattern Matching Integration"
     "tests/integration_03_functional_programming.txt:Functional Programming Integration"
+    "tests/integration_04_mini_case_multi_param.txt:Multi-parameter case expression at top level"
 )
 
 for test in "${integration_tests[@]}"; do
diff --git a/js/scripting-lang/simple_case_test.txt b/js/scripting-lang/simple_case_test.txt
new file mode 100644
index 0000000..bfc4768
--- /dev/null
+++ b/js/scripting-lang/simple_case_test.txt
@@ -0,0 +1,7 @@
+/* Simple case expression test */
+factorial : n -> case n of
+    0 : 1
+    _ : 2;
+
+test : factorial 5;
+..out test; 
\ No newline at end of file
diff --git a/js/scripting-lang/simple_test.txt b/js/scripting-lang/simple_test.txt
new file mode 100644
index 0000000..5f1c5df
--- /dev/null
+++ b/js/scripting-lang/simple_test.txt
@@ -0,0 +1,4 @@
+/* Simple test */
+x : 5;
+y : x - 1;
+..out y; 
\ No newline at end of file
diff --git a/js/scripting-lang/table_basic_test.txt b/js/scripting-lang/table_basic_test.txt
deleted file mode 100644
index 172d95c..0000000
--- a/js/scripting-lang/table_basic_test.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Basic Table Tests */
-
-/* Test 1: Simple table creation */
-..out "=== Basic Table Tests ===";
-empty : {};
-numbers : {1, 2, 3};
-person : {name: "Alice", age: 30};
-
-..out "Empty table: ";
-..out empty;
-..out "Numbers: ";
-..out numbers;
-..out "Person: ";
-..out person;
-
-/* Test 2: Array access */
-first : numbers[1];
-second : numbers[2];
-third : numbers[3];
-
-..out "First: ";
-..out first;
-..out "Second: ";
-..out second;
-..out "Third: ";
-..out third;
-
-/* Test 3: Object access */
-name : person.name;
-age : person.age;
-
-..out "Name: ";
-..out name;
-..out "Age: ";
-..out age;
-
-/* Test 4: Mixed table */
-mixed : {1, name: "Bob", 2};
-
-first_mixed : mixed[1];
-name_mixed : mixed.name;
-second_mixed : mixed[2];
-
-..out "Mixed first: ";
-..out first_mixed;
-..out "Mixed name: ";
-..out name_mixed;
-..out "Mixed second: ";
-..out second_mixed;
-
-..out "Basic tests complete!"; 
\ No newline at end of file
diff --git a/js/scripting-lang/table_edge_cases_test.txt b/js/scripting-lang/table_edge_cases_test.txt
deleted file mode 100644
index 268f271..0000000
--- a/js/scripting-lang/table_edge_cases_test.txt
+++ /dev/null
@@ -1,304 +0,0 @@
-/* Table Edge Cases Tests */
-
-/* Test 1: Nested tables */
-..out "=== Test 1: Nested Tables ===";
-nested : {
-    outer: "value",
-    inner: {
-        deep: "nested",
-        numbers: {1, 2, 3}
-    }
-};
-
-outer_val : nested.outer;
-inner_table : nested.inner;
-deep_val : nested.inner.deep;
-inner_nums : nested.inner.numbers;
-first_num : nested.inner.numbers[1];
-
-..out "Outer: ";
-..out outer_val;
-..out "Inner table: ";
-..out inner_table;
-..out "Deep: ";
-..out deep_val;
-..out "Inner numbers: ";
-..out inner_nums;
-..out "First number: ";
-..out first_num;
-
-/* Test 2: Tables with different value types */
-..out "=== Test 2: Different Value Types ===";
-complex : {
-    number: 42,
-    string: "hello",
-    boolean: true,
-    array: {1, 2, 3},
-    object: {key: "value"}
-};
-
-num : complex.number;
-str : complex.string;
-bool : complex.boolean;
-arr : complex.array;
-obj : complex.object;
-
-..out "Number: ";
-..out num;
-..out "String: ";
-..out str;
-..out "Boolean: ";
-..out bool;
-..out "Array: ";
-..out arr;
-..out "Object: ";
-..out obj;
-
-/* Test 3: Tables with function references */
-..out "=== Test 3: Function References ===";
-double : x -> x * 2;
-square : x -> x * x;
-
-func_table : {
-    double_func: @double,
-    square_func: @square,
-    number: 5
-};
-
-double_ref : func_table.double_func;
-square_ref : func_table.square_func;
-table_num : func_table.number;
-
-..out "Double ref: ";
-..out double_ref;
-..out "Square ref: ";
-..out square_ref;
-..out "Table number: ";
-..out table_num;
-
-/* Test 4: Tables with arithmetic expressions */
-..out "=== Test 4: Arithmetic Expressions ===";
-math_table : {
-    sum: 5 + 3,
-    product: 4 * 6,
-    power: 2 ^ 3
-};
-
-sum_val : math_table.sum;
-prod_val : math_table.product;
-pow_val : math_table.power;
-
-..out "Sum: ";
-..out sum_val;
-..out "Product: ";
-..out prod_val;
-..out "Power: ";
-..out pow_val;
-
-/* Test 5: Tables with function calls */
-..out "=== Test 5: Function Calls ===";
-add : x y -> x + y;
-multiply : x y -> x * y;
-
-call_table : {
-    addition: add 3 4,
-    multiplication: multiply 5 6
-};
-
-add_result : call_table.addition;
-mult_result : call_table.multiplication;
-
-..out "Addition: ";
-..out add_result;
-..out "Multiplication: ";
-..out mult_result;
-
-/* Test 6: Tables with bracket notation access */
-..out "=== Test 6: Bracket Notation ===";
-bracket_test : {name: "John", age: 25};
-
-name_bracket : bracket_test["name"];
-age_bracket : bracket_test["age"];
-
-..out "Name (bracket): ";
-..out name_bracket;
-..out "Age (bracket): ";
-..out age_bracket;
-
-/* Test 7: Tables with string keys */
-..out "=== Test 7: String Keys ===";
-string_keys : {
-    "key1": "value1",
-    "key2": "value2"
-};
-
-val1 : string_keys.key1;
-val2 : string_keys["key2"];
-
-..out "Value 1: ";
-..out val1;
-..out "Value 2: ";
-..out val2;
-
-/* Test 8: Tables with numeric keys */
-..out "=== Test 8: Numeric Keys ===";
-numeric_keys : {
-    1: "one",
-    2: "two",
-    10: "ten"
-};
-
-one : numeric_keys[1];
-two : numeric_keys[2];
-ten : numeric_keys[10];
-
-..out "One: ";
-..out one;
-..out "Two: ";
-..out two;
-..out "Ten: ";
-..out ten;
-
-/* Test 9: Tables with boolean keys */
-..out "=== Test 9: Boolean Keys ===";
-bool_keys : {
-    true: "truth",
-    false: "falsehood"
-};
-
-truth : bool_keys[true];
-falsehood : bool_keys[false];
-
-..out "Truth: ";
-..out truth;
-..out "Falsehood: ";
-..out falsehood;
-
-/* Test 10: Tables with trailing commas */
-..out "=== Test 10: Trailing Commas ===";
-trailing : {
-    1,
-    2,
-    3,
-    key: "value",
-};
-
-first : trailing[1];
-second : trailing[2];
-third : trailing[3];
-key_val : trailing.key;
-
-..out "First: ";
-..out first;
-..out "Second: ";
-..out second;
-..out "Third: ";
-..out third;
-..out "Key: ";
-..out key_val;
-
-/* Test 11: Tables with leading commas */
-..out "=== Test 11: Leading Commas ===";
-leading : {
-    ,1,
-    ,2,
-    ,key: "value"
-};
-
-first_lead : leading[1];
-second_lead : leading[2];
-key_lead : leading.key;
-
-..out "First (leading): ";
-..out first_lead;
-..out "Second (leading): ";
-..out second_lead;
-..out "Key (leading): ";
-..out key_lead;
-
-/* Test 12: Tables with function definitions inside */
-..out "=== Test 12: Function Definitions Inside ===";
-func_def_table : {
-    add_func: x y -> x + y,
-    double_func: x -> x * 2,
-    name: "function_table"
-};
-
-add_func_ref : func_def_table.add_func;
-double_func_ref : func_def_table.double_func;
-func_name : func_def_table.name;
-
-..out "Add func ref: ";
-..out add_func_ref;
-..out "Double func ref: ";
-..out double_func_ref;
-..out "Func name: ";
-..out func_name;
-
-/* Test 13: Tables with case expressions inside */
-..out "=== Test 13: Case Expressions Inside ===";
-case_table : {
-    grade_func: score -> 
-        case score of
-            90 : "A"
-            80 : "B"
-            70 : "C"
-            _  : "F",
-    name: "case_table"
-};
-
-grade_func_ref : case_table.grade_func;
-case_name : case_table.name;
-
-..out "Grade func ref: ";
-..out grade_func_ref;
-..out "Case name: ";
-..out case_name;
-
-/* Test 14: Tables with standard library functions */
-..out "=== Test 14: Standard Library Functions ===";
-stdlib_table : {
-    map_func: @map,
-    compose_func: @compose,
-    pipe_func: @pipe,
-    name: "stdlib_table"
-};
-
-map_ref : stdlib_table.map_func;
-compose_ref : stdlib_table.compose_func;
-pipe_ref : stdlib_table.pipe_func;
-stdlib_name : stdlib_table.name;
-
-..out "Map ref: ";
-..out map_ref;
-..out "Compose ref: ";
-..out compose_ref;
-..out "Pipe ref: ";
-..out pipe_ref;
-..out "Stdlib name: ";
-..out stdlib_name;
-
-/* Test 15: Tables with IO operations */
-..out "=== Test 15: IO Operations ===";
-io_table : {
-    input_func: @..in,
-    output_func: @..out,
-    assert_func: @..assert,
-    name: "io_table"
-};
-
-input_ref : io_table.input_func;
-output_ref : io_table.output_func;
-assert_ref : io_table.assert_func;
-io_name : io_table.name;
-
-..out "Input ref: ";
-..out input_ref;
-..out "Output ref: ";
-..out output_ref;
-..out "Assert ref: ";
-..out assert_ref;
-..out "IO name: ";
-..out io_name;
-
-..out "Edge cases tests complete!"; 
\ No newline at end of file
diff --git a/js/scripting-lang/tests/10_standard_library.txt b/js/scripting-lang/tests/10_standard_library.txt
index 91b5610..e6f7160 100644
--- a/js/scripting-lang/tests/10_standard_library.txt
+++ b/js/scripting-lang/tests/10_standard_library.txt
@@ -35,19 +35,15 @@ piped : pipe @double @square 2;
 applied : apply @double 7;
 ..assert applied = 14;
 
-/* Reduce and Fold functions - COMMENTED OUT FOR DEBUGGING */
-/*
+/* Reduce and Fold functions */
 reduced : reduce @add 0 5;
 folded : fold @add 0 5;
 
 ..assert reduced = 5;
 ..assert folded = 5;
-*/
 
-/* Curry function - COMMENTED OUT FOR DEBUGGING */
-/*
+/* Curry function */
 curried : curry @add 3 4;
 ..assert curried = 7;
-*/
 
 ..out "Standard library test completed"; 
\ No newline at end of file
diff --git a/js/scripting-lang/tests/11_edge_cases.txt b/js/scripting-lang/tests/11_edge_cases.txt
new file mode 100644
index 0000000..ceb39b4
--- /dev/null
+++ b/js/scripting-lang/tests/11_edge_cases.txt
@@ -0,0 +1,50 @@
+/* Unit Test: Edge Cases and Error Conditions */
+/* Tests: Unary minus, complex expressions */
+
+/* Test unary minus operations */
+negative1 : -5;
+negative2 : -3.14;
+negative3 : -0;
+
+..assert negative1 = -5;
+..assert negative2 = -3.14;
+..assert negative3 = 0;
+
+/* Test complex unary minus expressions */
+complex_negative1 : -(-5);
+complex_negative2 : -(-(-3));
+complex_negative3 : -5 + 3;
+
+..assert complex_negative1 = 5;
+..assert complex_negative2 = -3;
+..assert complex_negative3 = -2;
+
+/* Test unary minus in function calls */
+abs : x -> case x of
+    x < 0 : -x
+    _ : x;
+
+abs1 : abs -5;
+abs2 : abs 5;
+
+..assert abs1 = 5;
+..assert abs2 = 5;
+
+/* Test complex nested expressions */
+nested1 : (1 + 2) * (3 - 4);
+nested2 : ((5 + 3) * 2) - 1;
+nested3 : -((2 + 3) * 4);
+
+..assert nested1 = -3;
+..assert nested2 = 15;
+..assert nested3 = -20;
+
+/* Test unary minus with function references */
+negate : x -> -x;
+negated1 : negate 5;
+negated2 : negate -3;
+
+..assert negated1 = -5;
+..assert negated2 = 3;
+
+..out "Edge cases test completed"; 
\ No newline at end of file
diff --git a/js/scripting-lang/tests/12_advanced_tables.txt b/js/scripting-lang/tests/12_advanced_tables.txt
new file mode 100644
index 0000000..3b2a326
--- /dev/null
+++ b/js/scripting-lang/tests/12_advanced_tables.txt
@@ -0,0 +1,85 @@
+/* Unit Test: Advanced Table Features */
+/* Tests: Nested tables, mixed types, array-like entries */
+
+/* Nested tables */
+nested_table : {
+    outer: {
+        inner: {
+            value: 42
+        }
+    }
+};
+
+/* Test nested access */
+nested_value1 : nested_table.outer.inner.value;
+..assert nested_value1 = 42;
+
+/* Tables with mixed types */
+mixed_advanced : {
+    1: "first",
+    name: "test",
+    nested: {
+        value: 100
+    }
+};
+
+/* Test mixed access */
+first : mixed_advanced[1];
+name : mixed_advanced.name;
+nested_value2 : mixed_advanced.nested.value;
+
+..assert first = "first";
+..assert name = "test";
+..assert nested_value2 = 100;
+
+/* Tables with boolean keys */
+bool_table : {
+    true: "yes",
+    false: "no"
+};
+
+/* Test boolean key access */
+yes : bool_table[true];
+no : bool_table[false];
+
+..assert yes = "yes";
+..assert no = "no";
+
+/* Tables with array-like entries and key-value pairs */
+comma_table : {
+    1, 2, 3,
+    key: "value",
+    4, 5
+};
+
+/* Test comma table access */
+first_comma : comma_table[1];
+second_comma : comma_table[2];
+key_comma : comma_table.key;
+fourth_comma : comma_table[4];
+
+..assert first_comma = 1;
+..assert second_comma = 2;
+..assert key_comma = "value";
+..assert fourth_comma = 4;
+
+/* Tables with numeric and string keys */
+mixed_keys : {
+    1: "one",
+    two: 2,
+    3: "three",
+    four: 4
+};
+
+/* Test mixed key access */
+one : mixed_keys[1];
+two : mixed_keys.two;
+three : mixed_keys[3];
+four : mixed_keys.four;
+
+..assert one = "one";
+..assert two = 2;
+..assert three = "three";
+..assert four = 4;
+
+..out "Advanced tables test completed"; 
\ No newline at end of file
diff --git a/js/scripting-lang/tests/13_standard_library_complete.txt b/js/scripting-lang/tests/13_standard_library_complete.txt
new file mode 100644
index 0000000..ed7749a
--- /dev/null
+++ b/js/scripting-lang/tests/13_standard_library_complete.txt
@@ -0,0 +1,97 @@
+/* Unit Test: Complete Standard Library */
+/* Tests: All built-in higher-order functions including reduce, fold, curry */
+
+/* Basic functions for testing */
+double : x -> x * 2;
+square : x -> x * x;
+add : x y -> x + y;
+isPositive : x -> x > 0;
+isEven : x -> x % 2 = 0;
+
+/* Map function */
+mapped1 : map @double 5;
+mapped2 : map @square 3;
+
+..assert mapped1 = 10;
+..assert mapped2 = 9;
+
+/* Compose function */
+composed : compose @double @square 3;
+..assert composed = 18;
+
+/* Pipe function */
+piped : pipe @double @square 2;
+..assert piped = 16;
+
+/* Apply function */
+applied : apply @double 7;
+..assert applied = 14;
+
+/* Filter function */
+filtered1 : filter @isPositive 5;
+filtered2 : filter @isPositive -3;
+
+..assert filtered1 = 5;
+..assert filtered2 = 0;
+
+/* Reduce function */
+reduced : reduce @add 0 5;
+..assert reduced = 5;
+
+/* Fold function */
+folded : fold @add 0 5;
+..assert folded = 5;
+
+/* Curry function */
+curried : curry @add 3 4;
+..assert curried = 7;
+
+/* Test partial application */
+compose_partial : compose @double @square;
+compose_result : compose_partial 3;
+..assert compose_result = 18;
+
+pipe_partial : pipe @double @square;
+pipe_result : pipe_partial 2;
+..assert pipe_result = 16;
+
+/* Test with negative numbers */
+negate : x -> -x;
+negative_compose : compose @double @negate 5;
+negative_pipe : pipe @negate @double 5;
+
+..assert negative_compose = -10;
+..assert negative_pipe = -10;
+
+/* Test with complex functions */
+complex_func : x -> x * x + 1;
+complex_compose : compose @double @complex_func 3;
+complex_pipe : pipe @complex_func @double 3;
+
+..assert complex_compose = 20;
+..assert complex_pipe = 20;
+
+/* Test filter with complex predicates */
+isLarge : x -> x > 10;
+filtered_large : filter @isLarge 15;
+filtered_small : filter @isLarge 5;
+
+..assert filtered_large = 15;
+..assert filtered_small = 0;
+
+/* Test reduce with different initial values */
+multiply : x y -> x * y;
+reduced_sum : reduce @add 10 5;
+reduced_mult : reduce @multiply 1 5;
+
+..assert reduced_sum = 15;
+..assert reduced_mult = 5;
+
+/* Test fold with different initial values */
+folded_sum : fold @add 10 5;
+folded_mult : fold @multiply 1 5;
+
+..assert folded_sum = 15;
+..assert folded_mult = 5;
+
+..out "Complete standard library test completed"; 
\ No newline at end of file
diff --git a/js/scripting-lang/tests/14_error_handling.txt b/js/scripting-lang/tests/14_error_handling.txt
new file mode 100644
index 0000000..ce485f7
--- /dev/null
+++ b/js/scripting-lang/tests/14_error_handling.txt
@@ -0,0 +1,65 @@
+/* Unit Test: Error Handling and Edge Cases */
+/* Tests: Error detection and handling */
+
+/* Test valid operations first to ensure basic functionality */
+valid_test : 5 + 3;
+..assert valid_test = 8;
+
+/* Test division by zero handling */
+/* This should be handled gracefully */
+safe_div : x y -> case y of
+    0 : "division by zero"
+    _ : x / y;
+
+div_result1 : safe_div 10 2;
+div_result2 : safe_div 10 0;
+
+..assert div_result1 = 5;
+..assert div_result2 = "division by zero";
+
+/* Test edge cases with proper handling */
+edge_case1 : case 0 of
+    0 : "zero"
+    _ : "other";
+
+edge_case2 : case "" of
+    "" : "empty string"
+    _ : "other";
+
+edge_case3 : case false of
+    false : "false"
+    _ : "other";
+
+..assert edge_case1 = "zero";
+..assert edge_case2 = "empty string";
+..assert edge_case3 = "false";
+
+/* Test complex error scenarios */
+complex_error_handling : input -> case input of
+    input < 0 : "negative"
+    input = 0 : "zero"
+    input > 100 : "too large"
+    _ : "valid";
+
+complex_result1 : complex_error_handling -5;
+complex_result2 : complex_error_handling 0;
+complex_result3 : complex_error_handling 150;
+complex_result4 : complex_error_handling 50;
+
+..assert complex_result1 = "negative";
+..assert complex_result2 = "zero";
+..assert complex_result3 = "too large";
+..assert complex_result4 = "valid";
+
+/* Test safe arithmetic operations */
+safe_add : x y -> case y of
+    0 : x
+    _ : x + y;
+
+safe_result1 : safe_add 5 3;
+safe_result2 : safe_add 5 0;
+
+..assert safe_result1 = 8;
+..assert safe_result2 = 5;
+
+..out "Error handling test completed successfully"; 
\ No newline at end of file
diff --git a/js/scripting-lang/tests/15_performance_stress.txt b/js/scripting-lang/tests/15_performance_stress.txt
new file mode 100644
index 0000000..7dab1f5
--- /dev/null
+++ b/js/scripting-lang/tests/15_performance_stress.txt
@@ -0,0 +1,131 @@
+/* Unit Test: Performance and Stress Testing */
+/* Tests: Large computations, nested functions, complex expressions */
+
+/* Test large arithmetic computations */
+large_sum : 0;
+large_sum : large_sum + 1;
+large_sum : large_sum + 2;
+large_sum : large_sum + 3;
+large_sum : large_sum + 4;
+large_sum : large_sum + 5;
+
+..assert large_sum = 15;
+
+/* Test nested function calls */
+nested_func1 : x -> x + 1;
+nested_func2 : x -> nested_func1 x;
+nested_func3 : x -> nested_func2 x;
+nested_func4 : x -> nested_func3 x;
+nested_func5 : x -> nested_func4 x;
+
+deep_nested : nested_func5 10;
+..assert deep_nested = 15;
+
+/* Test complex mathematical expressions */
+complex_math1 : (1 + 2) * (3 + 4) - (5 + 6);
+complex_math2 : ((2 ^ 3) + (4 * 5)) / (6 - 2);
+complex_math3 : -((1 + 2 + 3) * (4 + 5 + 6));
+
+..assert complex_math1 = 10;
+..assert complex_math2 = 7;
+..assert complex_math3 = -126;
+
+/* Test large table operations */
+large_table : {};
+large_table : {1: "one", 2: "two", 3: "three", 4: "four", 5: "five"};
+large_table : {large_table, 6: "six", 7: "seven", 8: "eight"};
+
+table_size : 8;
+..assert table_size = 8;
+
+/* Test recursive-like patterns with functions */
+accumulate : n -> case n of
+    0 : 0
+    _ : n + accumulate (n - 1);
+
+sum_10 : accumulate 10;
+..assert sum_10 = 55;
+
+/* Test complex case expressions */
+complex_case : x -> case x of
+    x < 0 : "negative"
+    x = 0 : "zero"
+    x < 10 : "small"
+    x < 100 : "medium"
+    x < 1000 : "large"
+    _ : "huge";
+
+case_test1 : complex_case -5;
+case_test2 : complex_case 0;
+case_test3 : complex_case 5;
+case_test4 : complex_case 50;
+case_test5 : complex_case 500;
+case_test6 : complex_case 5000;
+
+..assert case_test1 = "negative";
+..assert case_test2 = "zero";
+..assert case_test3 = "small";
+..assert case_test4 = "medium";
+..assert case_test5 = "large";
+..assert case_test6 = "huge";
+
+/* Test standard library with complex operations */
+double : x -> x * 2;
+square : x -> x * x;
+add : x y -> x + y;
+
+complex_std1 : compose @double @square 3;
+complex_std2 : pipe @square @double 4;
+complex_std3 : apply @add 5 3;
+
+..assert complex_std1 = 18;
+..assert complex_std2 = 32;
+..assert complex_std3 = 8;
+
+/* Test table with computed keys and nested structures */
+computed_table : {
+    (1 + 1): "two",
+    (2 * 3): "six",
+    (10 - 5): "five",
+    nested: {
+        (2 + 2): "four",
+        deep: {
+            (3 * 3): "nine"
+        }
+    }
+};
+
+computed_test1 : computed_table[2];
+computed_test2 : computed_table[6];
+computed_test3 : computed_table[5];
+computed_test4 : computed_table.nested[4];
+computed_test5 : computed_table.nested.deep[9];
+
+..assert computed_test1 = "two";
+..assert computed_test2 = "six";
+..assert computed_test3 = "five";
+..assert computed_test4 = "four";
+..assert computed_test5 = "nine";
+
+/* Test logical operations with complex expressions */
+complex_logic1 : (5 > 3) and (10 < 20) and (2 + 2 = 4);
+complex_logic2 : (1 > 5) or (10 = 10) or (3 < 2);
+complex_logic3 : not ((5 > 3) and (10 < 5));
+
+..assert complex_logic1 = true;
+..assert complex_logic2 = true;
+..assert complex_logic3 = true;
+
+/* Test function composition with multiple functions */
+f1 : x -> x + 1;
+f2 : x -> x * 2;
+f3 : x -> x - 1;
+f4 : x -> x / 2;
+
+composed1 : compose @f1 @f2 @f3 @f4 10;
+composed2 : pipe @f4 @f3 @f2 @f1 10;
+
+..assert composed1 = 10;
+..assert composed2 = 10;
+
+..out "Performance and stress test completed successfully"; 
\ No newline at end of file
diff --git a/js/scripting-lang/tests/16_advanced_functional.txt b/js/scripting-lang/tests/16_advanced_functional.txt
new file mode 100644
index 0000000..3da9d76
--- /dev/null
+++ b/js/scripting-lang/tests/16_advanced_functional.txt
@@ -0,0 +1,169 @@
+/* Unit Test: Advanced Functional Programming Patterns */
+/* Tests: Higher-order functions, currying, partial application, monadic patterns */
+
+/* Test function composition with multiple functions */
+id : x -> x;
+const : x y -> x;
+flip : f x y -> f y x;
+
+/* Test identity function */
+id_test : id 42;
+..assert id_test = 42;
+
+/* Test constant function */
+const_test : const 5 10;
+..assert const_test = 5;
+
+/* Test function flipping */
+sub : x y -> x - y;
+flipped_sub : flip @sub;
+flipped_result : flipped_sub 5 10;
+..assert flipped_result = 5;
+
+/* Test partial application patterns */
+partial1 : f x -> y -> f x y;
+partial2 : f x y -> f x y;
+
+add : x y -> x + y;
+add5 : partial1 @add 5;
+add5_result : add5 3;
+..assert add5_result = 8;
+
+/* Test function composition with multiple arguments */
+compose2 : f g x y -> f (g x y);
+compose3 : f g h x -> f (g (h x));
+
+double : x -> x * 2;
+square : x -> x * x;
+increment : x -> x + 1;
+
+composed1 : compose2 @double @add 3 4;
+composed2 : compose3 @double @square @increment 2;
+..assert composed1 = 14;
+..assert composed2 = 18;
+
+/* Test monadic-like patterns with Maybe simulation */
+maybe : x -> case x of
+    undefined : "Nothing"
+    null : "Nothing"
+    _ : "Just " + x;
+
+maybe_map : f m -> case m of
+    "Nothing" : "Nothing"
+    _ : f m;
+
+maybe_bind : m f -> case m of
+    "Nothing" : "Nothing"
+    _ : f m;
+
+maybe_test1 : maybe undefined;
+maybe_test2 : maybe 42;
+maybe_test3 : maybe_map @double "Just 5";
+maybe_test4 : maybe_bind "Just 3" @double;
+
+..assert maybe_test1 = "Nothing";
+..assert maybe_test2 = "Just 42";
+..assert maybe_test3 = "Just 10";
+..assert maybe_test4 = "Just 6";
+
+/* Test list-like operations with tables */
+list_map : f table -> {
+    f table[1],
+    f table[2],
+    f table[3]
+};
+
+list_filter : p table -> case p table[1] of
+    true : {table[1]}
+    false : {};
+
+list_reduce : f init table -> case table[1] of
+    undefined : init
+    _ : f init table[1];
+
+test_list : {1, 2, 3};
+mapped_list : list_map @double test_list;
+filtered_list : list_filter (x -> x > 1) test_list;
+reduced_list : list_reduce @add 0 test_list;
+
+..assert mapped_list[1] = 2;
+..assert mapped_list[2] = 4;
+..assert mapped_list[3] = 6;
+..assert filtered_list[1] = 2;
+..assert reduced_list = 1;
+
+/* Test point-free style programming */
+pointfree_add : add;
+pointfree_double : double;
+pointfree_compose : compose @pointfree_double @pointfree_add;
+
+pointfree_result : pointfree_compose 5 3;
+..assert pointfree_result = 16;
+
+/* Test function memoization pattern */
+memoize : f -> {
+    cache: {},
+    call: x -> case cache[x] of
+        undefined : cache[x] = f x
+        _ : cache[x]
+};
+
+expensive_func : x -> x * x + x + 1;
+memoized_func : memoize @expensive_func;
+
+memo_result1 : memoized_func.call 5;
+memo_result2 : memoized_func.call 5; /* Should use cache */
+..assert memo_result1 = 31;
+..assert memo_result2 = 31;
+
+/* Test continuation-passing style (CPS) */
+cps_add : x y k -> k (x + y);
+cps_multiply : x y k -> k (x * y);
+cps_square : x k -> k (x * x);
+
+cps_example : cps_add 3 4 (sum -> 
+    cps_multiply sum 2 (product -> 
+        cps_square product (result -> result)
+    )
+);
+..assert cps_example = 98;
+
+/* Test trampoline pattern for tail recursion simulation */
+trampoline : f -> case f of
+    f is function : trampoline (f)
+    _ : f;
+
+bounce : n -> case n of
+    0 : 0
+    _ : n + (n - 1);
+
+trampoline_result : trampoline @bounce 5;
+..assert trampoline_result = 15;
+
+/* Test applicative functor pattern */
+applicative : f x -> case f of
+    f is function : f x
+    _ : x;
+
+applicative_test : applicative @double 5;
+..assert applicative_test = 10;
+
+/* Test function pipelines */
+pipeline : x f1 f2 f3 -> f3 (f2 (f1 x));
+pipeline_result : pipeline 2 @increment @double @square;
+..assert pipeline_result = 36;
+
+/* Test function combinators */
+S : f g x -> f x (g x);
+K : x y -> x;
+I : x -> x;
+
+S_test : S @add @double 3;
+K_test : K 5 10;
+I_test : I 42;
+
+..assert S_test = 9;
+..assert K_test = 5;
+..assert I_test = 42;
+
+..out "Advanced functional programming test completed successfully"; 
\ No newline at end of file
diff --git a/js/scripting-lang/tests/17_real_world_scenarios.txt b/js/scripting-lang/tests/17_real_world_scenarios.txt
new file mode 100644
index 0000000..0a9fc49
--- /dev/null
+++ b/js/scripting-lang/tests/17_real_world_scenarios.txt
@@ -0,0 +1,219 @@
+/* Unit Test: Real-World Programming Scenarios */
+/* Tests: Practical use cases, data processing, business logic */
+
+/* Scenario 1: User Management System */
+/* Define user types and validation */
+isValidEmail : email -> case email of
+    email contains "@" : true
+    _ : false;
+
+isValidAge : age -> case age of
+    age >= 0 and age <= 120 : true
+    _ : false;
+
+createUser : name email age -> case (isValidEmail email) and (isValidAge age) of
+    true : {
+        name: name,
+        email: email,
+        age: age,
+        status: "active"
+    }
+    false : "invalid user data";
+
+user1 : createUser "Alice" "alice@example.com" 25;
+user2 : createUser "Bob" "invalid-email" 30;
+user3 : createUser "Charlie" "charlie@test.com" 150;
+
+..assert user1.name = "Alice";
+..assert user2 = "invalid user data";
+..assert user3 = "invalid user data";
+
+/* Scenario 2: Shopping Cart System */
+/* Product definitions */
+product1 : {id: 1, name: "Laptop", price: 999.99, category: "electronics"};
+product2 : {id: 2, name: "Book", price: 19.99, category: "books"};
+product3 : {id: 3, name: "Coffee", price: 4.99, category: "food"};
+
+/* Cart operations */
+addToCart : cart product -> {
+    cart,
+    product
+};
+
+calculateTotal : cart -> case cart of
+    cart is table : cart.product.price
+    _ : 0;
+
+applyDiscount : total discount -> case discount of
+    discount > 0 and discount <= 100 : total * (1 - discount / 100)
+    _ : total;
+
+cart : addToCart {} product1;
+cart : addToCart cart product2;
+total : calculateTotal cart;
+discounted : applyDiscount total 10;
+
+..assert total = 1019.98;
+..assert discounted = 917.982;
+
+/* Scenario 3: Data Processing Pipeline */
+/* Sample data */
+sales_data : {
+    {month: "Jan", sales: 1000, region: "North"},
+    {month: "Feb", sales: 1200, region: "North"},
+    {month: "Mar", sales: 800, region: "South"},
+    {month: "Apr", sales: 1500, region: "North"},
+    {month: "May", sales: 900, region: "South"}
+};
+
+/* Data processing functions */
+filterByRegion : data region -> case data of
+    data.region = region : data
+    _ : null;
+
+sumSales : data -> case data of
+    data is table : data.sales
+    _ : 0;
+
+calculateAverage : total count -> case count of
+    count > 0 : total / count
+    _ : 0;
+
+/* Process North region sales */
+north_sales : filterByRegion sales_data "North";
+north_total : sumSales north_sales;
+north_avg : calculateAverage north_total 3;
+
+..assert north_total = 3700;
+..assert north_avg = 1233.3333333333333;
+
+/* Scenario 4: Configuration Management */
+/* Environment configuration */
+getConfig : env -> case env of
+    "development" : {
+        database: "dev_db",
+        port: 3000,
+        debug: true,
+        log_level: "debug"
+    }
+    "production" : {
+        database: "prod_db",
+        port: 80,
+        debug: false,
+        log_level: "error"
+    }
+    "testing" : {
+        database: "test_db",
+        port: 3001,
+        debug: true,
+        log_level: "info"
+    }
+    _ : "unknown environment";
+
+dev_config : getConfig "development";
+prod_config : getConfig "production";
+
+..assert dev_config.debug = true;
+..assert prod_config.debug = false;
+..assert dev_config.port = 3000;
+..assert prod_config.port = 80;
+
+/* Scenario 5: Error Handling and Recovery */
+/* Robust function with error handling */
+safeDivide : x y -> case y of
+    0 : "division by zero error"
+    _ : x / y;
+
+safeParseNumber : str -> case str of
+    str is number : str
+    _ : "invalid number";
+
+processData : data -> case data of
+    data is number : data * 2
+    data is string : safeParseNumber data
+    _ : "unsupported data type";
+
+safe_result1 : safeDivide 10 2;
+safe_result2 : safeDivide 10 0;
+safe_result3 : processData 5;
+safe_result4 : processData "abc";
+
+..assert safe_result1 = 5;
+..assert safe_result2 = "division by zero error";
+..assert safe_result3 = 10;
+..assert safe_result4 = "invalid number";
+
+/* Scenario 6: Event Handling System */
+/* Event types and handlers */
+eventHandlers : {
+    "user.login": x -> "User logged in: " + x,
+    "user.logout": x -> "User logged out: " + x,
+    "order.created": x -> "Order created: " + x,
+    "order.completed": x -> "Order completed: " + x
+};
+
+handleEvent : event data -> case eventHandlers[event] of
+    handler : handler data
+    _ : "Unknown event: " + event;
+
+login_event : handleEvent "user.login" "alice@example.com";
+logout_event : handleEvent "user.logout" "bob@example.com";
+unknown_event : handleEvent "unknown.event" "data";
+
+..assert login_event = "User logged in: alice@example.com";
+..assert logout_event = "User logged out: bob@example.com";
+..assert unknown_event = "Unknown event: unknown.event";
+
+/* Scenario 7: Caching System */
+/* Simple cache implementation */
+cache : {};
+
+setCache : key value -> cache[key] = value;
+getCache : key -> case cache[key] of
+    undefined : "not found"
+    value : value;
+clearCache : key -> cache[key] = undefined;
+
+setCache "user.1" "Alice";
+setCache "user.2" "Bob";
+cache_result1 : getCache "user.1";
+cache_result2 : getCache "user.999";
+clearCache "user.1";
+cache_result3 : getCache "user.1";
+
+..assert cache_result1 = "Alice";
+..assert cache_result2 = "not found";
+..assert cache_result3 = "not found";
+
+/* Scenario 8: API Response Processing */
+/* Mock API responses */
+apiResponse : {
+    status: 200,
+    data: {
+        users: {
+            {id: 1, name: "Alice", active: true},
+            {id: 2, name: "Bob", active: false},
+            {id: 3, name: "Charlie", active: true}
+        },
+        total: 3
+    }
+};
+
+processApiResponse : response -> case response.status of
+    200 : response.data
+    404 : "not found"
+    500 : "server error"
+    _ : "unknown status";
+
+getActiveUsers : data -> case data.users of
+    users : case users.active of
+        true : users
+        _ : null;
+
+api_data : processApiResponse apiResponse;
+active_users : getActiveUsers api_data;
+
+..assert api_data.total = 3;
+..assert active_users = null; /* Simplified for this example */
+
+..out "Real-world scenarios test completed successfully"; 
\ No newline at end of file
diff --git a/js/scripting-lang/tests/integration_03_functional_programming.txt b/js/scripting-lang/tests/integration_03_functional_programming.txt
index d0c6682..8af6760 100644
--- a/js/scripting-lang/tests/integration_03_functional_programming.txt
+++ b/js/scripting-lang/tests/integration_03_functional_programming.txt
@@ -7,6 +7,7 @@
 double : x -> x * 2;
 square : x -> x * x;
 add1 : x -> x + 1;
+identity : x -> x;
 isEven : x -> x % 2 = 0;
 
 /* Function composition */
@@ -25,7 +26,7 @@ piped3 : pipe @add1 @double 5;
 
 ..assert piped1 = 36;
 ..assert piped2 = 8;
-..assert piped3 = 11;
+..assert piped3 = 12;
 
 /* Function application */
 applied1 : apply @double 7;
diff --git a/js/scripting-lang/tests/mini_case_multi_param.txt b/js/scripting-lang/tests/integration_04_mini_case_multi_param.txt
index be4b71d..be4b71d 100644
--- a/js/scripting-lang/tests/mini_case_multi_param.txt
+++ b/js/scripting-lang/tests/integration_04_mini_case_multi_param.txt