about summary refs log tree commit diff stats
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/scripting-lang/README.md414
-rw-r--r--js/scripting-lang/comprehensive_test.txt153
-rw-r--r--js/scripting-lang/grammar.ebnf76
-rw-r--r--js/scripting-lang/grammar_detailed.ebnf97
-rw-r--r--js/scripting-lang/input.txt3
-rw-r--r--js/scripting-lang/lang.js2160
-rw-r--r--js/scripting-lang/parser_analysis.md143
-rw-r--r--js/scripting-lang/test_ambiguous_cases.txt23
-rw-r--r--js/seed/README.md15
-rwxr-xr-xjs/seed/seed75
-rw-r--r--js/seed/src/app.js8
-rw-r--r--js/seed/src/dev.js4
-rw-r--r--js/seed/src/view.js6
13 files changed, 3107 insertions, 70 deletions
diff --git a/js/scripting-lang/README.md b/js/scripting-lang/README.md
new file mode 100644
index 0000000..d662fcc
--- /dev/null
+++ b/js/scripting-lang/README.md
@@ -0,0 +1,414 @@
+# Simple Scripting Language
+
+A minimal, interpreted scripting language designed for learning language implementation concepts. This language demonstrates the core components needed for an interpreter: lexer, parser, and interpreter.
+
+## Features
+
+- **Arithmetic operations**: `+`, `-`, `*`, `/`, `%` (modulo), `^` (power)
+- **Comparison operators**: `=`, `<`, `>`, `<=`, `>=`, `!=`
+- **Logical operators**: `and`, `or`, `xor`, `not`
+- **Variable assignment**: Immutable variables with `:` syntax
+- **Function definitions**: Arrow function syntax with pattern matching
+- **Pattern matching**: Case expressions with wildcard support
+- **Function calls**: Direct function application
+- **First-class functions**: Functions can be passed as arguments using `@` syntax
+- **Function composition**: Higher-order functions for combining functions
+- **Lexical scoping**: Functions create their own scope
+- **Input/Output**: Built-in IO operations with `..in`, `..out`, and `..assert`
+- **Standard Library**: Built-in functional programming utilities
+
+## Syntax
+
+### Variables
+
+Variables are immutable and assigned using the `:` operator:
+
+```
+x : 5;
+y : 10;
+```
+
+### Arithmetic Operations
+
+Arithmetic operations are supported with parentheses grouping:
+
+```
+sum : x + y;
+diff : x - y;
+product : x * y;
+quotient : x / y;
+modulo : 17 % 5;        // Returns 2
+power : 2 ^ 3;          // Returns 8
+grouped : (5 + 3) * 2;  // Returns 16
+nested : ((5 + 3) * 2) + 1;  // Returns 17
+```
+
+### Function Definitions
+
+Functions are defined using arrow syntax (`->`):
+
+```
+add : x y -> x + y;
+double : x -> x * 2;
+```
+
+### Function Calls
+
+Functions are called by providing arguments directly after the function name:
+
+```
+result : add 3 4;
+doubled : double 5;
+```
+
+#### Function Calls with Parentheses
+
+Function calls support parenthesized arguments for complex expressions:
+
+```
+// Simple function call
+result1 : add 3 4;
+
+// Function call with parenthesized arithmetic
+result2 : add (3 + 2) (4 + 1);
+
+// Function call with function calls in parentheses
+result3 : add (double 3) (square 2);
+
+// Complex nested function calls with parentheses
+result4 : add (add 1 2) (add 3 4);
+```
+
+**Note:** Parentheses provide explicit grouping and are the recommended way to handle complex nested function calls.
+
+### First-Class Functions
+
+Functions can be passed as arguments to other functions using the `@` prefix:
+
+```
+double : x -> x * 2;
+square : x -> x * x;
+compose : f g x -> f g x;
+
+composed : compose @double @square 3;  // double(square(3)) = 18
+```
+
+**Function Reference Syntax:**
+- `@functionName` - Creates a function reference (doesn't execute the function)
+- `functionName args` - Calls the function with arguments
+
+### Pattern Matching
+
+The language supports pattern matching with case expressions in function bodies:
+
+```
+compare : x y -> 
+  case x y of
+    0 0 : "both zero"
+    0 _ : "x is zero"
+    _ 0 : "y is zero"
+    _ _ : "neither zero";
+```
+
+#### Pattern Matching Syntax
+
+- **Exact matches**: `0 0` matches when both values are 0
+- **Wildcards**: `_` matches any value
+- **Mixed patterns**: `0 _` matches when first value is 0 and second can be anything
+
+### Comparison and Logical Operations
+
+The language supports comparison and logical operations:
+
+```
+// Comparison operators
+less : 3 < 5;           // true
+greater : 10 > 5;       // true
+equal : 5 = 5;          // true
+not_equal : 3 != 5;     // true
+less_equal : 5 <= 5;    // true
+greater_equal : 5 >= 3; // true
+
+// Logical operators
+and_result : 1 and 1;   // true
+or_result : 0 or 1;     // true
+xor_result : 1 xor 0;   // true
+not_result : not 0;     // true
+```
+
+### Input/Output Operations
+
+The language provides built-in IO operations for reading from stdin and writing to stdout:
+
+```
+name : ..in;        // Read input from stdin
+..out name;         // Output to stdout
+..out "Hello";      // Output string literal
+..out 42;           // Output number
+..assert x = 5;     // Assert that x equals 5
+..assert y > 3;     // Assert that y is greater than 3
+..assert z != 0;    // Assert that z is not equal to 0
+```
+
+**IO Functions:**
+- `..in` - Reads a line from stdin, returns a number if possible, otherwise a string
+- `..out` - Outputs a value to stdout and returns the value
+- `..assert` - Asserts that a comparison is true, throws an error if it's false. Supports all comparison operators: `=`, `<`, `>`, `<=`, `>=`, `!=`
+
+**Note:** The `..` prefix indicates these are impure operations that have side effects.
+
+## Standard Library
+
+The language includes a built-in standard library with functional programming utilities:
+
+### Higher-Order Functions
+
+- **map**: Apply a function to a value (`map f x = f x`)
+- **compose**: Compose two functions (`compose f g x = f(g(x))`)
+- **curry**: Explicit currying (`curry f x y = f x y`)
+- **apply**: Apply a function to an argument (`apply f x = f x`)
+- **pipe**: Compose functions left-to-right (`pipe f g x = g(f(x))`)
+- **filter**: Filter based on a predicate (`filter p x = p(x) ? x : 0`)
+- **reduce**: Reduce to a single value (`reduce f init x = f(init, x)`)
+- **fold**: Same as reduce (`fold f init x = f(init, x)`)
+
+### Usage Examples
+
+```
+double : x -> x * 2;
+square : x -> x * x;
+
+// Using map
+result1 : map @double 5;    // Returns 10
+result2 : map @square 3;    // Returns 9
+
+// Using compose
+composed : compose @double @square 3;  // double(square(3)) = 18
+
+// Using pipe
+piped : pipe @double @square 2;        // square(double(2)) = 16
+
+// Using filter
+isPositive : x -> x > 0;
+filtered : filter @isPositive 5;       // Returns 5 (since 5 > 0)
+```
+
+## Language Components
+
+### Lexer
+
+The lexer tokenizes input into meaningful units:
+- Numbers: `123`
+- Identifiers: `variable_name`
+- Operators: `+`, `-`, `*`, `/`
+- Keywords: `case`, `of`, `function`
+- Symbols: `:`, `->`, `_`
+
+### Parser
+
+The parser builds an Abstract Syntax Tree (AST) from tokens, supporting:
+- Number literals
+- Arithmetic expressions
+- Variable assignments
+- Function declarations
+- Function calls
+- Case expressions
+- Pattern matching
+
+### Interpreter
+
+The interpreter executes the AST with:
+- Global scope management
+- Function evaluation
+- Pattern matching execution
+- Arithmetic computation
+- Immutable variable semantics
+
+## Example Programs
+
+### Basic Arithmetic
+
+```
+x : 5;
+y : 10;
+sum : x + y;
+sum;  // Returns 15
+```
+
+### Function Definition and Call
+
+```
+add : x y -> x + y;
+result : add 3 4;
+result;  // Returns 7
+```
+
+### Pattern Matching
+
+```
+compare : x y -> 
+  case x y of
+    0 0 : "both zero"
+    0 _ : "x is zero"
+    _ 0 : "y is zero"
+    _ _ : "neither zero";
+
+test1 : compare 0 0;   // Returns "both zero"
+test2 : compare 0 5;   // Returns "x is zero"
+test3 : compare 5 0;   // Returns "y is zero"
+test4 : compare 5 5;   // Returns "neither zero"
+```
+
+### Function Composition
+
+```
+double : x -> x * 2;
+square : x -> x * x;
+compose : f g x -> f g x;
+apply : f x -> f x;
+
+composed : compose @double @square 3;  // double(square(3)) = 18
+applied : apply @double 5;             // double(5) = 10
+```
+
+### Recursion
+
+The language supports recursive function calls in function body case expressions:
+
+```
+countdown : n -> 
+  case n of
+    0 : 0
+    _ : countdown n - 1;
+
+result : countdown 3;  // Returns 0
+
+// Note: Complex arithmetic in recursive functions may require careful expression design
+// due to the language's lack of explicit grouping (parentheses)
+```
+
+### Input/Output Example
+
+```
+name : ..in;        // Prompts for input
+..out "Hello, ";    // Outputs greeting
+..out name;         // Outputs the input
+```
+
+### First-Class Functions Example
+
+```
+double : x -> x * 2;
+square : x -> x * x;
+compose : f g x -> f g x;
+
+// Function composition
+composed : compose @double @square 3;  // 18
+
+// Higher-order functions
+map : f x -> f x;
+mapped : map @double 5;                // 10
+
+// Function references in standalone case expressions
+case 0 of
+  0 : @double
+  _ : @square;
+```
+
+### Assertion Example
+
+```
+x : 5;
+y : 3;
+sum : x + y;
+
+..assert x = 5;            // Passes
+..assert y = 3;            // Passes
+..assert sum = 8;          // Passes
+..assert x > 3;            // Passes
+..assert y < 10;           // Passes
+..assert sum != 0;         // Passes
+..assert x = 0;            // Fails with error
+```
+
+## Running Programs
+
+The language supports two modes of execution:
+
+### File Execution Mode
+Run a script file by providing the file path as an argument:
+
+```bash
+node lang.js script.txt
+```
+
+### REPL Mode
+Start an interactive REPL by running without arguments:
+
+```bash
+node lang.js
+```
+
+In REPL mode:
+- Type expressions and end them with a semicolon (`;`) to execute
+- Multi-line expressions are supported
+- Type `exit` or `quit` to exit
+- Variables and functions persist between expressions
+
+**Example REPL session:**
+```
+Scripting Language REPL
+Type expressions to evaluate. End with semicolon (;) to execute.
+Type "exit" to quit.
+
+> x : 5;
+> y : 10;
+> + x y;
+15
+> exit
+Goodbye!
+```
+
+## Language Design Principles
+
+- **Simplicity**: Minimal syntax for maximum clarity
+- **Immutability**: Variables cannot be reassigned
+- **Functional**: Functions are first-class values with composition support
+- **Pattern-oriented**: Pattern matching as a core feature
+- **Recursive**: Support for recursive function calls in function bodies
+- **Grouped**: Parentheses support for complex arithmetic expressions
+- **Expressive**: Rich set of arithmetic, comparison, and logical operators
+- **IO-aware**: Built-in input/output operations with clear impurity markers
+- **Educational**: Designed to teach language implementation concepts
+
+## Limitations
+
+This is a learning language with intentional limitations:
+- Complex nested function calls (e.g., `add double 3 square 2`) are ambiguous without explicit grouping
+- There's one known issue with function calls inside assertions (e.g., ..assert add 3 4 = 7), which is a parsing edge case. Workaround: use parentheses around function calls in assertions (e.g., ..assert (add 3 4) = 7)
+- No data structures beyond numbers and strings
+- No error handling beyond basic validation
+- No modules or imports
+- No standard library
+- IO operations are synchronous and block execution
+
+## Future Enhancements
+
+Planned features for future versions:
+- Ambiguous function call detection and error reporting
+- Lists and data structures
+- Error handling
+- Standard library functions
+- Modules and imports
+- Type system
+- Performance optimizations
+
+## Implementation Details
+
+The language is implemented in JavaScript with three main components:
+
+1. **Lexer** (`lexer()`): Converts source code to tokens
+2. **Parser** (`parser()`): Builds AST from tokens
+3. **Interpreter** (`interpreter()`): Executes AST
+
+Each component is designed to be modular and extensible for adding new language features. 
\ No newline at end of file
diff --git a/js/scripting-lang/comprehensive_test.txt b/js/scripting-lang/comprehensive_test.txt
new file mode 100644
index 0000000..1b4aae8
--- /dev/null
+++ b/js/scripting-lang/comprehensive_test.txt
@@ -0,0 +1,153 @@
+x : 5;
+y : 3;
+name : "Alice";
+age : 25;
+
+..out "Basic arithmetic:";
+sum : x + y;
+diff : x - y;
+product : x * y;
+quotient : x / y;
+modulo : 17 % 5;
+power : 2 ^ 3;
+..out sum;
+..out diff;
+..out product;
+..out quotient;
+..out modulo;
+..out power;
+
+..out "Variables:";
+..out name;
+..out age;
+
+add : x y -> x + y;
+double : x -> x * 2;
+square : x -> x * x;
+
+..out "Functions:";
+result1 : add 3 4;
+result2 : double 5;
+result3 : square 4;
+..out result1;
+..out result2;
+..out result3;
+
+..out "Function calls with parentheses:";
+result4 : add (3 + 2) (4 + 1);
+result5 : add (double 3) (square 2);
+..out result4;
+..out result5;
+
+..out "Testing assertions:";
+..assert x = 5;
+..assert y = 3;
+..assert sum = 8;
+..assert "hello" = "hello";
+..assert (add 3 4) = 7;
+
+..out "Testing first-class functions:";
+
+composed : compose @double @square 3;
+applied : apply @double 5;
+
+..assert composed = 18;
+..assert applied = 10;
+
+..out "First-class functions:";
+..out composed;
+..out applied;
+
+..out "Testing standard library functions:";
+slResult1 : map @double 5;
+slResult2 : map @square 3;
+piped : pipe @double @square 2;
+isPositive : x -> x > 0;
+filtered : filter @isPositive 5;
+reduced : reduce @add 0 5;
+folded : fold @add 0 5;
+
+..assert (map @double 5) = 10;
+..assert (map @square 3) = 9;
+..assert (pipe @double @square 2) = 16;
+..assert (filter @isPositive 5) = 5;
+..assert (reduce @add 0 5) = 5;
+..assert (fold @add 0 5) = 5;
+
+..out "Standard library results:";
+..out slResult1;
+..out slResult2;
+..out piped;
+..out filtered;
+..out reduced;
+..out folded;
+
+..out "Testing higher-order functions:";
+mapped1 : map @double 3;
+mapped2 : map @square 4;
+
+..assert mapped1 = 6;
+..assert mapped2 = 16;
+
+..out "Map results:";
+..out mapped1;
+..out mapped2;
+
+..out "Testing case expressions:";
+compare : x y -> 
+  case x y of
+    0 0 : "both zero"
+    0 _ : "x is zero"
+    _ 0 : "y is zero"
+    _ _ : "neither zero";
+
+test1 : compare 0 0;
+..out test1;
+
+
+
+..out "Testing standalone case expressions with function references:";
+case 0 of
+  0 : @double
+  _ : @square;
+
+..out "Standalone case with function references works!";
+
+..out "Testing parentheses grouping:";
+grouped1 : (5 + 3) * 2;
+grouped2 : ((5 + 3) * 2) + 1;
+
+..assert grouped1 = 16;
+..assert grouped2 = 17;
+
+..out "Parentheses grouping works!";
+
+..out "Testing comparison operators:";
+lessTest : 3 < 5;
+greaterTest : 10 > 5;
+equalTest : 5 = 5;
+notEqualTest : 3 != 5;
+lessEqualTest : 5 <= 5;
+greaterEqualTest : 5 >= 3;
+..out lessTest;
+..out greaterTest;
+..out equalTest;
+..out notEqualTest;
+..out lessEqualTest;
+..out greaterEqualTest;
+
+..out "Testing logical operators:";
+logicalAnd : 1 and 1;
+logicalOr : 0 or 1;
+logicalXor : 1 xor 0;
+logicalNot : not 0;
+..out logicalAnd;
+..out logicalOr;
+..out logicalXor;
+..out logicalNot;
+
+..out "Testing complex expressions:";
+complex1 : 2 ^ 3 % 3 and 5 > 3;
+..out complex1;
+
+..out "All tests completed successfully!"; 
\ No newline at end of file
diff --git a/js/scripting-lang/grammar.ebnf b/js/scripting-lang/grammar.ebnf
new file mode 100644
index 0000000..b595c87
--- /dev/null
+++ b/js/scripting-lang/grammar.ebnf
@@ -0,0 +1,76 @@
+(* Scripting Language Grammar *)
+
+(* Program Structure *)
+program = statement_list
+statement_list = statement { statement }
+statement = assignment | function_declaration | expression | io_statement | ";"
+
+(* Variables and Assignment *)
+assignment = identifier ":" value
+value = expression | function_call
+
+(* Function Declarations *)
+function_declaration = identifier ":" parameter_list "->" function_body
+parameter_list = identifier { identifier }
+function_body = expression | case_expression
+
+(* Expressions *)
+expression = arithmetic_expression | identifier | number | string
+
+(* Arithmetic Expressions *)
+arithmetic_expression = arithmetic_operator expression expression
+arithmetic_operator = "+" | "-" | "*" | "/"
+
+(* Function Calls *)
+function_call = identifier argument_list
+argument_list = expression { expression }
+
+(* Case Expressions *)
+case_expression = "case" value_list "of" case_list
+value_list = expression { expression }
+case_list = case_branch { case_branch }
+case_branch = pattern ":" result
+pattern = pattern_element { pattern_element }
+pattern_element = number | wildcard | identifier
+result = result_element { result_element }
+result_element = string | number | identifier
+
+(* IO Statements *)
+io_statement = io_operator [ expression ]
+io_operator = "..in" | "..out"
+
+(* Terminals *)
+identifier = letter { letter | digit }
+number = digit { digit }
+string = '"' { character } '"'
+wildcard = "_"
+letter = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
+digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
+character = letter | digit | " " | "!" | "#" | "$" | "%" | "&" | "'" | "(" | ")" | "*" | "+" | "," | "-" | "." | "/" | ":" | ";" | "<" | "=" | ">" | "?" | "@" | "[" | "\" | "]" | "^" | "`" | "{" | "|" | "}" | "~"
+
+(* Comments *)
+(* This language does not support comments *)
+
+(* Examples *)
+
+(* Variable assignment *)
+(* x : 5; *)
+
+(* Function declaration *)
+(* add : x y -> x + y; *)
+
+(* Function call *)
+(* result : add 3 4; *)
+
+(* Case expression *)
+(* compare : x y -> 
+   case x y of
+     0 0 : "both zero"
+     0 _ : "x is zero"
+     _ 0 : "y is zero"
+     _ _ : "neither zero"; *)
+
+(* IO statements *)
+(* name : ..in;
+   ..out "Hello, ";
+   ..out name; *) 
\ No newline at end of file
diff --git a/js/scripting-lang/grammar_detailed.ebnf b/js/scripting-lang/grammar_detailed.ebnf
new file mode 100644
index 0000000..5274cd8
--- /dev/null
+++ b/js/scripting-lang/grammar_detailed.ebnf
@@ -0,0 +1,97 @@
+(* Detailed Scripting Language Grammar *)
+
+(* Program Structure *)
+program = statement_list
+statement_list = statement { statement }
+statement = assignment | function_declaration | expression_statement | io_statement | ";"
+
+(* Variables and Assignment *)
+assignment = identifier ":" assignment_value
+assignment_value = function_call | simple_expression
+
+(* Function Declarations *)
+function_declaration = identifier ":" parameter_list "->" function_body
+parameter_list = identifier { identifier }
+function_body = arithmetic_expression | case_expression
+
+(* Function Calls *)
+function_call = identifier argument_list
+argument_list = expression { expression }
+
+(* Expressions *)
+expression = arithmetic_expression | simple_expression
+simple_expression = identifier | number | string
+expression_statement = expression
+
+(* Arithmetic Expressions - Prefix Notation *)
+arithmetic_expression = arithmetic_operator expression expression
+arithmetic_operator = "+" | "-" | "*" | "/"
+
+(* Case Expressions *)
+case_expression = "case" value_list "of" case_list
+value_list = expression { expression }
+case_list = case_branch { case_branch }
+case_branch = pattern ":" result
+pattern = pattern_element { pattern_element }
+pattern_element = number | wildcard | identifier
+result = result_element { result_element }
+result_element = string | number | identifier
+
+(* IO Statements *)
+io_statement = io_operator [ expression ]
+io_operator = "..in" | "..out"
+
+(* Terminals *)
+identifier = letter { letter | digit }
+number = digit { digit }
+string = '"' { character } '"'
+wildcard = "_"
+letter = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
+digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
+character = letter | digit | " " | "!" | "#" | "$" | "%" | "&" | "'" | "(" | ")" | "*" | "+" | "," | "-" | "." | "/" | ":" | ";" | "<" | "=" | ">" | "?" | "@" | "[" | "\" | "]" | "^" | "`" | "{" | "|" | "}" | "~"
+
+(* Parsing Precedence and Disambiguation *)
+
+(* Key Insights from Debug Analysis: *)
+
+(* 1. Assignment parsing needs to distinguish between function calls and simple values *)
+(* assignment_value = function_call | simple_expression *)
+
+(* 2. Function calls in assignments: "result : add 3 4;" *)
+(* - "add" is an identifier *)
+(* - "3" and "4" are arguments *)
+(* - Should parse as: assignment(identifier("result"), function_call("add", [3, 4])) *)
+
+(* 3. Case expressions work correctly but function calls within them don't *)
+(* - Case patterns: "0 0", "0 _", "_ 0", "_ _" *)
+(* - Case results: string literals, numbers, identifiers *)
+
+(* 4. Arithmetic expressions use prefix notation *)
+(* - "+ x y" not "x + y" *)
+(* - "* 5 2" not "5 * 2" *)
+
+(* 5. IO statements are special *)
+(* - "..in" reads from stdin *)
+(* - "..out expression" writes to stdout *)
+
+(* Examples with Parse Trees *)
+
+(* Example 1: Simple assignment *)
+(* Input: "x : 5;" *)
+(* Parse: assignment(identifier("x"), number(5)) *)
+
+(* Example 2: Function call assignment *)
+(* Input: "result : add 3 4;" *)
+(* Parse: assignment(identifier("result"), function_call("add", [number(3), number(4)])) *)
+
+(* Example 3: Case expression *)
+(* Input: "compare : x y -> case x y of 0 0 : \"both zero\";" *)
+(* Parse: function_declaration("compare", ["x", "y"], case_expression([identifier("x"), identifier("y")], [case_branch([number(0), number(0)], [string("both zero")])])) *)
+
+(* Example 4: Arithmetic expression *)
+(* Input: "sum : + x y;" *)
+(* Parse: assignment(identifier("sum"), arithmetic_expression("+", identifier("x"), identifier("y"))) *)
+
+(* Example 5: IO statement *)
+(* Input: "..out \"Hello\";" *)
+(* Parse: io_statement("..out", string("Hello")) *) 
\ No newline at end of file
diff --git a/js/scripting-lang/input.txt b/js/scripting-lang/input.txt
deleted file mode 100644
index d343086..0000000
--- a/js/scripting-lang/input.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-x : 10;
-y : 20;
-x + y;
\ No newline at end of file
diff --git a/js/scripting-lang/lang.js b/js/scripting-lang/lang.js
index f91f842..b8b6fed 100644
--- a/js/scripting-lang/lang.js
+++ b/js/scripting-lang/lang.js
@@ -1,21 +1,129 @@
 // The goal here is less to make anything useful...or even something that works, but to learn what parts an interpreted languages needs to have to function.
 
+// Initialize standard library functions
+function initializeStandardLibrary(scope) {
+    // Map: Apply a function to each element
+    scope.map = function(f, x) { 
+        // Handle function references by calling them if they're functions
+        if (typeof f === 'function') {
+            return f(x);
+        } else {
+            throw new Error('map: first argument must be a function');
+        }
+    };
+    
+    // Compose: Compose two functions (f ∘ g)(x) = f(g(x))
+    scope.compose = function(f, g, x) { 
+        if (typeof f === 'function' && typeof g === 'function') {
+            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
+    scope.curry = function(f, x, y) { 
+        if (typeof f === 'function') {
+            return f(x, y);
+        } else {
+            throw new Error('curry: first argument must be a function');
+        }
+    };
+    
+    // Apply: Apply a function to an argument (same as function call, but more explicit)
+    scope.apply = function(f, x) { 
+        if (typeof f === 'function') {
+            return f(x);
+        } else {
+            throw new Error('apply: first argument must be a function');
+        }
+    };
+    
+    // Pipe: Compose functions in left-to-right order (opposite of compose)
+    // pipe f g x = g f x
+    scope.pipe = function(f, g, x) { 
+        if (typeof f === 'function' && typeof g === 'function') {
+            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
+    scope.filter = function(p, x) { 
+        if (typeof p === 'function') {
+            return p(x) ? x : 0;
+        } else {
+            throw new Error('filter: first argument must be a function');
+        }
+    };
+    
+    // Reduce: Reduce to a single value using a binary function
+    // For now, we'll implement it as a higher-order function
+    scope.reduce = function(f, init, x) { 
+        if (typeof f === 'function') {
+            return f(init, x);
+        } else {
+            throw new Error('reduce: first argument must be a function');
+        }
+    };
+    
+    // Fold: Same as reduce, but more explicit about the folding direction
+    scope.fold = function(f, init, x) { 
+        if (typeof f === 'function') {
+            return f(init, x);
+        } else {
+            throw new Error('fold: first argument must be a function');
+        }
+    };
+}
+
 // Define the types of tokens
 const TokenType = {
     NUMBER: 'NUMBER',
     PLUS: 'PLUS',
+    MINUS: 'MINUS',
+    MULTIPLY: 'MULTIPLY',
+    DIVIDE: 'DIVIDE',
     IDENTIFIER: 'IDENTIFIER',
     ASSIGNMENT: 'ASSIGNMENT',
+    ARROW: 'ARROW',
+    CASE: 'CASE',
+    OF: 'OF',
+    WILDCARD: 'WILDCARD',
     FUNCTION: 'FUNCTION',
     LEFT_PAREN: 'LEFT_PAREN',
     RIGHT_PAREN: 'RIGHT_PAREN',
     LEFT_BRACE: 'LEFT_BRACE',
     RIGHT_BRACE: 'RIGHT_BRACE',
     SEMICOLON: 'SEMICOLON',
+    IO_IN: 'IO_IN',
+    IO_OUT: 'IO_OUT',
+    IO_ASSERT: 'IO_ASSERT',
+    EQUALS: 'EQUALS',
+    FUNCTION_REF: 'FUNCTION_REF',
+    STRING: 'STRING',
+    // New arithmetic operators
+    MODULO: 'MODULO',
+    POWER: 'POWER',
+    // New comparison operators
+    LESS_THAN: 'LESS_THAN',
+    GREATER_THAN: 'GREATER_THAN',
+    LESS_EQUAL: 'LESS_EQUAL',
+    GREATER_EQUAL: 'GREATER_EQUAL',
+    NOT_EQUAL: 'NOT_EQUAL',
+    // New logical operators
+    AND: 'AND',
+    OR: 'OR',
+    XOR: 'XOR',
+    NOT: 'NOT',
 };
 
 // Lexer
 function lexer(input) {
+    debugLog('Starting lexer with input', input);
     const tokens = [];
     let current = 0;
 
@@ -43,9 +151,145 @@ function lexer(input) {
             continue;
         }
 
+        if (input.slice(current, current + 2) === '->') {
+            tokens.push({
+                type: TokenType.ARROW
+            });
+            current += 2;
+            continue;
+        }
+
+        if (char === '-') {
+            tokens.push({
+                type: TokenType.MINUS
+            });
+            current++;
+            continue;
+        }
+
+        if (char === '*') {
+            tokens.push({
+                type: TokenType.MULTIPLY
+            });
+            current++;
+            continue;
+        }
+
+        if (char === '/') {
+            tokens.push({
+                type: TokenType.DIVIDE
+            });
+            current++;
+            continue;
+        }
+
+        if (char === '%') {
+            tokens.push({
+                type: TokenType.MODULO
+            });
+            current++;
+            continue;
+        }
+
+        if (char === '^') {
+            tokens.push({
+                type: TokenType.POWER
+            });
+            current++;
+            continue;
+        }
+
+        if (char === '<') {
+            if (input.slice(current, current + 2) === '<=') {
+                tokens.push({
+                    type: TokenType.LESS_EQUAL
+                });
+                current += 2;
+            } else {
+                tokens.push({
+                    type: TokenType.LESS_THAN
+                });
+                current++;
+            }
+            continue;
+        }
+
+        if (char === '>') {
+            if (input.slice(current, current + 2) === '>=') {
+                tokens.push({
+                    type: TokenType.GREATER_EQUAL
+                });
+                current += 2;
+            } else {
+                tokens.push({
+                    type: TokenType.GREATER_THAN
+                });
+                current++;
+            }
+            continue;
+        }
+
+        if (input.slice(current, current + 2) === '!=') {
+            tokens.push({
+                type: TokenType.NOT_EQUAL
+            });
+            current += 2;
+            continue;
+        }
+
+        // Check for keywords before general identifiers
+        if (input.slice(current, current + 4) === 'case') {
+            tokens.push({
+                type: TokenType.CASE
+            });
+            current += 4;
+            continue;
+        }
+
+        if (input.slice(current, current + 2) === 'of') {
+            tokens.push({
+                type: TokenType.OF
+            });
+            current += 2;
+            continue;
+        }
+
+        // Check for logical keywords
+        if (input.slice(current, current + 3) === 'and') {
+            tokens.push({
+                type: TokenType.AND
+            });
+            current += 3;
+            continue;
+        }
+
+        if (input.slice(current, current + 2) === 'or') {
+            tokens.push({
+                type: TokenType.OR
+            });
+            current += 2;
+            continue;
+        }
+
+        if (input.slice(current, current + 3) === 'xor') {
+            tokens.push({
+                type: TokenType.XOR
+            });
+            current += 3;
+            continue;
+        }
+
+        if (input.slice(current, current + 3) === 'not') {
+            tokens.push({
+                type: TokenType.NOT
+            });
+            current += 3;
+            continue;
+        }
+
         if (/[a-z]/i.test(char)) {
             let value = '';
-            while (/[a-z]/i.test(char)) {
+            while (/[a-z0-9]/i.test(char)) {
                 value += char;
                 char = input[++current];
             }
@@ -64,27 +308,37 @@ function lexer(input) {
             continue;
         }
 
-        if (char === '=') {
+        if (input.slice(current, current + 2) === '==') {
+            tokens.push({
+                type: TokenType.EQUALS
+            });
+            current += 2;
+            continue;
+        }
+
+        if (char === '@') {
             tokens.push({
-                type: TokenType.EQUAL
+                type: TokenType.FUNCTION_REF
             });
             current++;
             continue;
         }
 
-        if (input.slice(current, current + 2) === 'if') {
+        if (char === '=') {
             tokens.push({
-                type: TokenType.IF
+                type: TokenType.EQUALS
             });
-            current += 2;
+            current++;
             continue;
         }
 
-        if (input.slice(current, current + 4) === 'else') {
+
+
+        if (char === '_') {
             tokens.push({
-                type: TokenType.ELSE
+                type: TokenType.WILDCARD
             });
-            current += 4;
+            current++;
             continue;
         }
 
@@ -128,12 +382,70 @@ function lexer(input) {
             continue;
         }
 
+        // Check for IO tokens
+        if (input.slice(current, current + 4) === '..in') {
+            tokens.push({
+                type: TokenType.IO_IN
+            });
+            current += 4;
+            continue;
+        }
+
+        if (input.slice(current, current + 5) === '..out') {
+            tokens.push({
+                type: TokenType.IO_OUT
+            });
+            current += 5;
+            continue;
+        }
+
+        if (input.slice(current, current + 8) === '..assert') {
+            tokens.push({
+                type: TokenType.IO_ASSERT
+            });
+            current += 8;
+            continue;
+        }
+
+        // Handle string literals
+        if (char === '"') {
+            let value = '';
+            current++; // Skip opening quote
+            while (current < input.length && input[current] !== '"') {
+                value += input[current];
+                current++;
+            }
+            if (current < input.length && input[current] === '"') {
+                current++; // Skip closing quote
+                tokens.push({
+                    type: TokenType.STRING,
+                    value
+                });
+                continue;
+            } else {
+                throw new Error('Unterminated string literal');
+            }
+        }
+
         if (char === ';') {
             tokens.push({ type: TokenType.SEMICOLON });
             current++;
             continue;
         }
 
+        if (/[a-z]/i.test(char)) {
+            let value = '';
+            while (/[a-z0-9]/i.test(char)) {
+                value += char;
+                char = input[++current];
+            }
+            tokens.push({
+                type: TokenType.IDENTIFIER,
+                value
+            });
+            continue;
+        }
+
         current++;
     }
 
@@ -142,6 +454,10 @@ function lexer(input) {
 
 // Parser
 function parser(tokens) {
+    debugLog('Starting parser with tokens', tokens);
+    
+
+    
     let current = 0;
 
     function walk() {
@@ -151,6 +467,244 @@ function parser(tokens) {
 
         let token = tokens[current];
 
+        // Helper function to detect ambiguous nested function calls
+        function detectAmbiguousFunctionCalls() {
+            // Look ahead to see if we have a pattern like: func1 func2 arg1 func3 arg2
+            // This indicates ambiguous nested function calls
+            let tempCurrent = current;
+            let functionCalls = [];
+            
+            while (tempCurrent < tokens.length && tokens[tempCurrent].type !== TokenType.SEMICOLON) {
+                if (tokens[tempCurrent].type === TokenType.IDENTIFIER) {
+                    // Check if this identifier is followed by arguments (function call)
+                    if (tempCurrent + 1 < tokens.length && 
+                        tokens[tempCurrent + 1].type !== TokenType.ASSIGNMENT &&
+                        tokens[tempCurrent + 1].type !== TokenType.SEMICOLON &&
+                        (tokens[tempCurrent + 1].type === TokenType.NUMBER ||
+                         tokens[tempCurrent + 1].type === TokenType.IDENTIFIER ||
+                         tokens[tempCurrent + 1].type === TokenType.LEFT_PAREN)) {
+                        
+                        functionCalls.push(tokens[tempCurrent].value);
+                        
+                        // Skip the function name and its arguments
+                        tempCurrent++; // Skip function name
+                        while (tempCurrent < tokens.length && 
+                               tokens[tempCurrent].type !== TokenType.SEMICOLON &&
+                               tokens[tempCurrent].type !== TokenType.RIGHT_PAREN) {
+                            tempCurrent++;
+                        }
+                    } else {
+                        tempCurrent++;
+                    }
+                } else {
+                    tempCurrent++;
+                }
+            }
+            
+            // If we have more than 2 function calls in sequence, it's ambiguous
+            if (functionCalls.length > 2) {
+                throw new Error(`Ambiguous nested function calls detected: ${functionCalls.join(' ')}. Use parentheses to explicitly group function calls.`);
+            }
+        }
+
+        // Helper function to parse function calls with proper precedence
+        function parseFunctionCall() {
+            if (token.type !== TokenType.IDENTIFIER) {
+                return null;
+            }
+
+            // Check if this is a function call (identifier followed by arguments)
+            if (tokens[current + 1] && 
+                tokens[current + 1].type !== TokenType.ASSIGNMENT &&
+                tokens[current + 1].type !== TokenType.PLUS &&
+                tokens[current + 1].type !== TokenType.MINUS &&
+                tokens[current + 1].type !== TokenType.MULTIPLY &&
+                tokens[current + 1].type !== TokenType.DIVIDE &&
+                tokens[current + 1].type !== TokenType.MODULO &&
+                tokens[current + 1].type !== TokenType.POWER &&
+                tokens[current + 1].type !== TokenType.EQUALS &&
+                tokens[current + 1].type !== TokenType.LESS_THAN &&
+                tokens[current + 1].type !== TokenType.GREATER_THAN &&
+                tokens[current + 1].type !== TokenType.LESS_EQUAL &&
+                tokens[current + 1].type !== TokenType.GREATER_EQUAL &&
+                tokens[current + 1].type !== TokenType.NOT_EQUAL &&
+                tokens[current + 1].type !== TokenType.AND &&
+                tokens[current + 1].type !== TokenType.OR &&
+                tokens[current + 1].type !== TokenType.XOR &&
+                tokens[current + 1].type !== TokenType.NOT &&
+                tokens[current + 1].type !== TokenType.SEMICOLON &&
+                (tokens[current + 1].type === TokenType.NUMBER ||
+                 tokens[current + 1].type === TokenType.IDENTIFIER ||
+                 tokens[current + 1].type === TokenType.LEFT_PAREN ||
+                 tokens[current + 1].type === TokenType.FUNCTION_REF)) {
+                
+
+                
+                const funcName = token.value;
+                current++; // Skip function name
+                const args = [];
+                
+                // Collect arguments until we hit a semicolon, closing parenthesis, or end
+                while (current < tokens.length && 
+                       tokens[current].type !== TokenType.SEMICOLON &&
+                       tokens[current].type !== TokenType.RIGHT_PAREN) {
+                    
+                    // Handle function references (@functionName)
+                    if (tokens[current] && tokens[current].type === TokenType.FUNCTION_REF) {
+                        current++; // Skip @
+                        if (tokens[current] && tokens[current].type === TokenType.IDENTIFIER) {
+                            args.push({
+                                type: 'FunctionReference',
+                                name: tokens[current].value,
+                            });
+                            current++;
+                        } else {
+                            throw new Error('Expected function name after @');
+                        }
+                    } else {
+                        // Parse arguments with proper precedence
+                        // For nested function calls, we need to parse them as complete function calls
+                        if (tokens[current] && tokens[current].type === TokenType.IDENTIFIER &&
+                            tokens[current + 1] && tokens[current + 1].type !== TokenType.ASSIGNMENT &&
+                            tokens[current + 1].type !== TokenType.PLUS &&
+                            tokens[current + 1].type !== TokenType.MINUS &&
+                            tokens[current + 1].type !== TokenType.MULTIPLY &&
+                            tokens[current + 1].type !== TokenType.DIVIDE &&
+                            tokens[current + 1].type !== TokenType.MODULO &&
+                            tokens[current + 1].type !== TokenType.POWER &&
+                            tokens[current + 1].type !== TokenType.EQUALS &&
+                            tokens[current + 1].type !== TokenType.LESS_THAN &&
+                            tokens[current + 1].type !== TokenType.GREATER_THAN &&
+                            tokens[current + 1].type !== TokenType.LESS_EQUAL &&
+                            tokens[current + 1].type !== TokenType.GREATER_EQUAL &&
+                            tokens[current + 1].type !== TokenType.NOT_EQUAL &&
+                            tokens[current + 1].type !== TokenType.AND &&
+                            tokens[current + 1].type !== TokenType.OR &&
+                            tokens[current + 1].type !== TokenType.XOR &&
+                            tokens[current + 1].type !== TokenType.NOT &&
+                            tokens[current + 1].type !== TokenType.SEMICOLON &&
+                            (tokens[current + 1].type === TokenType.NUMBER ||
+                             tokens[current + 1].type === TokenType.IDENTIFIER ||
+                             tokens[current + 1].type === TokenType.LEFT_PAREN)) {
+                            
+                            // Check for ambiguous nested function calls
+                            // Look for pattern: func1 func2 arg1 func3 arg2
+                            let tempCurrent = current;
+                            let functionNames = [];
+                            
+                            while (tempCurrent < tokens.length && 
+                                   tokens[tempCurrent].type !== TokenType.SEMICOLON &&
+                                   tokens[tempCurrent].type !== TokenType.RIGHT_PAREN) {
+                                if (tokens[tempCurrent].type === TokenType.IDENTIFIER &&
+                                    tempCurrent + 1 < tokens.length && 
+                                    tokens[tempCurrent + 1].type !== TokenType.ASSIGNMENT &&
+                                    tokens[tempCurrent + 1].type !== TokenType.PLUS &&
+                                    tokens[tempCurrent + 1].type !== TokenType.MINUS &&
+                                    tokens[tempCurrent + 1].type !== TokenType.MULTIPLY &&
+                                    tokens[tempCurrent + 1].type !== TokenType.DIVIDE &&
+                                    tokens[tempCurrent + 1].type !== TokenType.MODULO &&
+                                    tokens[tempCurrent + 1].type !== TokenType.POWER &&
+                                    tokens[tempCurrent + 1].type !== TokenType.EQUALS &&
+                                    tokens[tempCurrent + 1].type !== TokenType.LESS_THAN &&
+                                    tokens[tempCurrent + 1].type !== TokenType.GREATER_THAN &&
+                                    tokens[tempCurrent + 1].type !== TokenType.LESS_EQUAL &&
+                                    tokens[tempCurrent + 1].type !== TokenType.GREATER_EQUAL &&
+                                    tokens[tempCurrent + 1].type !== TokenType.NOT_EQUAL &&
+                                    tokens[tempCurrent + 1].type !== TokenType.AND &&
+                                    tokens[tempCurrent + 1].type !== TokenType.OR &&
+                                    tokens[tempCurrent + 1].type !== TokenType.XOR &&
+                                    tokens[tempCurrent + 1].type !== TokenType.NOT &&
+                                    tokens[tempCurrent + 1].type !== TokenType.SEMICOLON &&
+                                    (tokens[tempCurrent + 1].type === TokenType.NUMBER ||
+                                     tokens[tempCurrent + 1].type === TokenType.IDENTIFIER ||
+                                     tokens[tempCurrent + 1].type === TokenType.LEFT_PAREN)) {
+                                    functionNames.push(tokens[tempCurrent].value);
+                                }
+                                tempCurrent++;
+                            }
+                            
+                            if (functionNames.length > 2) {
+                                throw new Error(`Ambiguous nested function calls detected: ${functionNames.join(' ')}. Use parentheses to explicitly group function calls.`);
+                            }
+                            
+                            // This is a nested function call, parse it as a complete function call
+                            const nestedFuncName = tokens[current].value;
+                            current++; // Skip function name
+                            const nestedArgs = [];
+                            
+                            // Parse nested function arguments
+                            while (current < tokens.length && 
+                                   tokens[current].type !== TokenType.SEMICOLON &&
+                                   tokens[current].type !== TokenType.RIGHT_PAREN) {
+                                const nestedArg = walk();
+                                if (nestedArg) {
+                                    nestedArgs.push(nestedArg);
+                                }
+                            }
+                            
+                            args.push({
+                                type: 'FunctionCall',
+                                name: nestedFuncName,
+                                args: nestedArgs,
+                            });
+                        } else {
+                            // Use walk() for other types of arguments
+                            const arg = walk();
+                            if (arg) {
+                                args.push(arg);
+                            }
+                        }
+                    }
+                }
+                
+                return {
+                    type: 'FunctionCall',
+                    name: funcName,
+                    args,
+                };
+            }
+            
+            return null;
+        }
+
+        // Handle arithmetic expressions that start with a number followed by an operator
+        if (token.type === TokenType.NUMBER && tokens[current + 1] && (
+            tokens[current + 1].type === TokenType.PLUS ||
+            tokens[current + 1].type === TokenType.MINUS ||
+            tokens[current + 1].type === TokenType.MULTIPLY ||
+            tokens[current + 1].type === TokenType.DIVIDE ||
+            tokens[current + 1].type === TokenType.MODULO ||
+            tokens[current + 1].type === TokenType.POWER
+        )) {
+            debugLog('Parsing arithmetic expression starting with number', { 
+                current: token, 
+                next: tokens[current + 1] 
+            });
+            const left = {
+                type: 'NumberLiteral',
+                value: token.value,
+            };
+            current++; // Skip the number
+            const operator = tokens[current].type;
+            current++; // Skip the operator
+            const right = walk();
+            
+            const expressionTypes = {
+                [TokenType.PLUS]: 'PlusExpression',
+                [TokenType.MINUS]: 'MinusExpression',
+                [TokenType.MULTIPLY]: 'MultiplyExpression',
+                [TokenType.DIVIDE]: 'DivideExpression',
+                [TokenType.MODULO]: 'ModuloExpression',
+                [TokenType.POWER]: 'PowerExpression',
+            };
+            
+            return {
+                type: expressionTypes[operator],
+                left,
+                right,
+            };
+        }
+
         if (token.type === TokenType.NUMBER) {
             current++;
             return {
@@ -159,16 +713,755 @@ function parser(tokens) {
             };
         }
 
+        if (token.type === TokenType.STRING) {
+            current++;
+            return {
+                type: 'StringLiteral',
+                value: token.value,
+            };
+        }
+
+        if (token.type === TokenType.WILDCARD) {
+            current++;
+            return {
+                type: 'WildcardPattern',
+            };
+        }
+
+        if (token.type === TokenType.IO_IN) {
+            current++;
+            return {
+                type: 'IOInExpression',
+            };
+        }
+
+        if (token.type === TokenType.IO_OUT) {
+            current++;
+            const value = walk();
+            return {
+                type: 'IOOutExpression',
+                value,
+            };
+        }
+
+        if (token.type === TokenType.FUNCTION_REF) {
+            current++; // Skip the @ token
+            if (tokens[current] && tokens[current].type === TokenType.IDENTIFIER) {
+                const functionName = tokens[current].value;
+                current++; // Skip the function name
+                return {
+                    type: 'FunctionReference',
+                    name: functionName,
+                };
+            } else {
+                throw new Error('Expected function name after @');
+            }
+        }
+
+        if (token.type === TokenType.IO_ASSERT) {
+            current++;
+            
+            // Parse a comparison expression (e.g., x = 5, y > 3, z != 0)
+            const left = walk();
+            
+            // Expect a comparison operator
+            if (tokens[current] && (
+                tokens[current].type === TokenType.EQUALS ||
+                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.NOT_EQUAL
+            )) {
+                const operator = tokens[current].type;
+                current++; // Skip the operator
+                const right = walk();
+                
+                return {
+                    type: 'IOAssertExpression',
+                    left,
+                    operator,
+                    right,
+                };
+            } else {
+                throw new Error('Expected comparison operator (=, <, >, <=, >=, !=) in assertion');
+            }
+        }
+
+
+
         if (token.type === TokenType.PLUS) {
             current++;
+            const left = walk();
+            const right = walk();
             return {
                 type: 'PlusExpression',
-                left: walk(),
-                right: walk(),
+                left,
+                right,
             };
         }
 
+        if (token.type === TokenType.MINUS) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'MinusExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.MULTIPLY) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'MultiplyExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.DIVIDE) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'DivideExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.MODULO) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'ModuloExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.POWER) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'PowerExpression',
+                left,
+                right,
+            };
+        }
+
+        // Comparison operators
+        if (token.type === TokenType.EQUALS) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'EqualsExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.LESS_THAN) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'LessThanExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.GREATER_THAN) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'GreaterThanExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.LESS_EQUAL) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'LessEqualExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.GREATER_EQUAL) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'GreaterEqualExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.NOT_EQUAL) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'NotEqualExpression',
+                left,
+                right,
+            };
+        }
+
+        // Logical operators
+        if (token.type === TokenType.AND) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'AndExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.OR) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'OrExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.XOR) {
+            current++;
+            const left = walk();
+            const right = walk();
+            return {
+                type: 'XorExpression',
+                left,
+                right,
+            };
+        }
+
+        if (token.type === TokenType.NOT) {
+            current++;
+            const operand = walk();
+            return {
+                type: 'NotExpression',
+                operand,
+            };
+        }
+
+        if (token.type === TokenType.LEFT_PAREN) {
+            current++; // Skip opening parenthesis
+            const expression = walk();
+            
+            // Expect closing parenthesis
+            if (tokens[current] && tokens[current].type === TokenType.RIGHT_PAREN) {
+                debugLog('Found right parenthesis');
+                current++; // Skip closing parenthesis
+                
+                // Check if there's an arithmetic operator after the parentheses
+                if (tokens[current] && (
+                    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 ||
+                    tokens[current].type === TokenType.AND ||
+                    tokens[current].type === TokenType.OR ||
+                    tokens[current].type === TokenType.XOR ||
+                    tokens[current].type === TokenType.NOT
+                )) {
+                    // This is an arithmetic expression with parentheses as left operand
+                    const operator = tokens[current].type;
+                    current++; // Skip the operator
+                    const right = walk();
+                    
+                    const expressionTypes = {
+                        [TokenType.PLUS]: 'PlusExpression',
+                        [TokenType.MINUS]: 'MinusExpression',
+                        [TokenType.MULTIPLY]: 'MultiplyExpression',
+                        [TokenType.DIVIDE]: 'DivideExpression',
+                        [TokenType.MODULO]: 'ModuloExpression',
+                        [TokenType.POWER]: 'PowerExpression',
+                        [TokenType.AND]: 'AndExpression',
+                        [TokenType.OR]: 'OrExpression',
+                        [TokenType.XOR]: 'XorExpression',
+                        [TokenType.NOT]: 'NotExpression',
+                    };
+                    
+                    return {
+                        type: expressionTypes[operator],
+                        left: expression,
+                        right,
+                    };
+                }
+                
+                // If not followed by an arithmetic operator, just return the parenthesized expression
+                // This handles cases like function arguments: add (3 + 2) (4 + 1)
+                return expression;
+            } else {
+                debugLog('Expected right parenthesis but found', tokens[current]);
+                throw new Error('Expected closing parenthesis');
+            }
+        }
+
+        if (token.type === TokenType.ASSIGNMENT) {
+            current++; // Skip the assignment token
+            return walk(); // Continue parsing
+        }
+
         if (token.type === TokenType.IDENTIFIER) {
+            // First, try to parse as a function call with proper precedence
+            const functionCall = parseFunctionCall();
+            if (functionCall) {
+                return functionCall;
+            }
+            
+            // Check if this is followed by an assignment (variable or function)
+            if (tokens[current + 1] && tokens[current + 1].type === TokenType.ASSIGNMENT) {
+                const name = token.value;
+                
+                // Check if this is a function declaration (has parameters and arrow)
+                // Look ahead to see if there are parameters followed by arrow
+                let params = [];
+                let isFunction = false;
+                let tempCurrent = current + 2; // Skip identifier and assignment
+                
+                // Collect parameters until we hit an arrow
+                while (tempCurrent < tokens.length && tokens[tempCurrent].type === TokenType.IDENTIFIER) {
+                    params.push(tokens[tempCurrent].value);
+                    tempCurrent++;
+                }
+                
+                // Check if next token is arrow
+                if (tempCurrent < tokens.length && tokens[tempCurrent].type === TokenType.ARROW) {
+                    isFunction = true;
+                }
+                
+                if (isFunction) {
+                    // This is a function declaration
+                    // Advance current to where tempCurrent left off
+                    current = tempCurrent + 1; // Skip the arrow token
+                    
+                    // Check if the body is a case expression
+                    if (tokens[current] && tokens[current].type === TokenType.CASE) {
+                        current++; // Skip 'case'
+                        
+                        // Parse the value being matched (e.g., "x y")
+                        const value = [];
+                        while (current < tokens.length && 
+                               tokens[current].type !== TokenType.OF) {
+                            if (tokens[current].type === TokenType.IDENTIFIER) {
+                                value.push({
+                                    type: 'Identifier',
+                                    value: tokens[current].value,
+                                });
+                            } else if (tokens[current].type === TokenType.NUMBER) {
+                                value.push({
+                                    type: 'NumberLiteral',
+                                    value: tokens[current].value,
+                                });
+                            }
+                            current++;
+                        }
+                        
+                        // Expect 'of' after the value
+                        if (tokens[current] && tokens[current].type === TokenType.OF) {
+                            current++; // Skip 'of'
+                        } else {
+                            throw new Error('Expected "of" after case value');
+                        }
+                        
+                        const cases = [];
+                        
+                        // Parse cases until we hit a semicolon or end
+                        while (current < tokens.length) {
+                            // Check if we've reached the end of the case expression
+                            if (tokens[current] && tokens[current].type === TokenType.SEMICOLON) {
+                                debugLog('Found semicolon at start of loop, ending case parsing');
+                                current++;
+                                break; // Exit the case parsing loop
+                            }
+                            
+                            debugLog('Case parsing loop', { 
+                                current: tokens[current], 
+                                currentType: tokens[current]?.type 
+                            });
+                            // Parse pattern (e.g., "0 0" or "0 _" or "_ 0" or "_ _")
+                            debugLog('Parsing pattern', { 
+                                current: tokens[current], 
+                                currentType: tokens[current]?.type 
+                            });
+                            const pattern = [];
+                            while (current < tokens.length && 
+                                   tokens[current].type !== TokenType.ASSIGNMENT && 
+                                   tokens[current].type !== TokenType.SEMICOLON) {
+                                if (tokens[current].type === TokenType.NUMBER) {
+                                    pattern.push({
+                                        type: 'NumberLiteral',
+                                        value: tokens[current].value,
+                                    });
+                                } else if (tokens[current].type === TokenType.WILDCARD) {
+                                    pattern.push({
+                                        type: 'WildcardPattern',
+                                    });
+                                } else if (tokens[current].type === TokenType.IDENTIFIER) {
+                                    pattern.push({
+                                        type: 'Identifier',
+                                        value: tokens[current].value,
+                                    });
+                                }
+                                current++;
+                            }
+                            
+                            // Expect ':' after pattern
+                            debugLog('Looking for : after pattern', { 
+                                current: tokens[current], 
+                                currentType: tokens[current]?.type 
+                            });
+                            if (tokens[current] && tokens[current].type === TokenType.ASSIGNMENT) {
+                                current++; // Skip ':'
+                                debugLog('Found : after pattern');
+                            } else {
+                                throw new Error('Expected ":" after pattern');
+                            }
+                            
+                            // Parse result using walk() to handle complex expressions
+                            debugLog('Starting case result parsing', { 
+                                current: tokens[current], 
+                                currentType: tokens[current]?.type 
+                            });
+                            const result = [];
+                            
+                            // Check if we're at the start of the next pattern
+                            if ((tokens[current].type === TokenType.NUMBER || 
+                                 tokens[current].type === TokenType.WILDCARD) &&
+                                tokens[current + 1] && tokens[current + 1].type === TokenType.ASSIGNMENT) {
+                                debugLog('Found start of next pattern, stopping case result parsing');
+                            } else {
+                                // Parse one expression for the case result
+                                debugLog('Parsing case result node', { 
+                                    current: tokens[current], 
+                                    currentType: tokens[current]?.type 
+                                });
+                                const resultNode = walk();
+                                if (resultNode) {
+                                    result.push(resultNode);
+                                    debugLog('Added result node', resultNode);
+                                }
+                                
+                                // Check if we've reached the end of the case expression
+                                if (tokens[current] && tokens[current].type === TokenType.SEMICOLON) {
+                                    debugLog('Found semicolon after result, ending case parsing');
+                                    current++;
+                                    break; // Exit the case parsing loop
+                                }
+                            }
+                            
+                            cases.push({ pattern, result });
+                            
+                            // Check if we've reached the end of the case expression
+                            if (tokens[current] && tokens[current].type === TokenType.SEMICOLON) {
+                                debugLog('Found semicolon, ending case parsing');
+                                current++;
+                                break; // Exit the case parsing loop
+                            }
+                        }
+                        
+                        const body = {
+                            type: 'CaseExpression',
+                            value,
+                            cases,
+                        };
+                        
+                        return {
+                            type: 'FunctionDeclaration',
+                            name,
+                            params,
+                            body,
+                        };
+                    } else {
+                        // Parse function body directly to avoid function call detection issues
+                        let body;
+                        if (tokens[current] && (
+                            tokens[current].type === TokenType.PLUS ||
+                            tokens[current].type === TokenType.MINUS ||
+                            tokens[current].type === TokenType.MULTIPLY ||
+                            tokens[current].type === TokenType.DIVIDE
+                        )) {
+                            // Arithmetic expression
+                            const operator = tokens[current].type;
+                            current++; // Skip operator
+                            const left = walk();
+                            const right = walk();
+                            
+                            const expressionTypes = {
+                                [TokenType.PLUS]: 'PlusExpression',
+                                [TokenType.MINUS]: 'MinusExpression',
+                                [TokenType.MULTIPLY]: 'MultiplyExpression',
+                                [TokenType.DIVIDE]: 'DivideExpression',
+                            };
+                            
+                            body = {
+                                type: expressionTypes[operator],
+                                left,
+                                right,
+                            };
+                                            } else {
+                        // Fallback to walk() for other cases
+                        debugLog('Using walk() fallback for function body');
+                        body = walk();
+                    }
+                        
+                        return {
+                            type: 'FunctionDeclaration',
+                            name,
+                            params,
+                            body,
+                        };
+                    }
+                } else {
+                    // This is a variable assignment
+                    // Advance current to skip identifier and assignment token
+                    current += 2; // Skip identifier and assignment
+                    
+                    debugLog('Assignment parsing', { 
+                        current: tokens[current], 
+                        next: tokens[current + 1],
+                        currentType: tokens[current]?.type,
+                        nextType: tokens[current + 1]?.type
+                    });
+                    
+                    // Parse the value directly without calling walk()
+                    let value;
+                    
+                    // Check if the value is a function call
+                    if (tokens[current] && tokens[current].type === TokenType.IDENTIFIER &&
+                        tokens[current + 1] && tokens[current + 1].type !== TokenType.ASSIGNMENT &&
+                        tokens[current + 1].type !== TokenType.SEMICOLON &&
+                        tokens[current + 1].type !== TokenType.ARROW &&
+                        (tokens[current + 1].type === TokenType.NUMBER ||
+                         tokens[current + 1].type === TokenType.IDENTIFIER ||
+                         tokens[current + 1].type === TokenType.FUNCTION_REF ||
+                         tokens[current + 1].type === TokenType.LEFT_PAREN)) {
+                        // This is a function call as the value
+                        const funcName = tokens[current].value;
+                        current++; // Skip function name
+                        const args = [];
+                        
+                        // Collect arguments until we hit a semicolon, closing parenthesis, or end
+                        while (current < tokens.length && 
+                               tokens[current].type !== TokenType.SEMICOLON &&
+                               tokens[current].type !== TokenType.RIGHT_PAREN) {
+                            // Handle function references (@functionName)
+                            if (tokens[current] && tokens[current].type === TokenType.FUNCTION_REF) {
+                                current++; // Skip @
+                                if (tokens[current] && tokens[current].type === TokenType.IDENTIFIER) {
+                                    args.push({
+                                        type: 'FunctionReference',
+                                        name: tokens[current].value,
+                                    });
+                                    current++;
+                                } else {
+                                    throw new Error('Expected function name after @');
+                                }
+                            } else {
+                                // Use walk() to parse complex arguments (including arithmetic expressions)
+                                const arg = walk();
+                                if (arg) {
+                                    args.push(arg);
+                                }
+                            }
+                        }
+                        
+                        value = {
+                            type: 'FunctionCall',
+                            name: funcName,
+                            args,
+                        };
+                        
+                        debugLog('Function call parsed in assignment', { name: funcName, args });
+                    } else if (tokens[current] && tokens[current].type === TokenType.NUMBER) {
+                        // Check if this is the start of an arithmetic expression
+                        if (tokens[current + 1] && (
+                            tokens[current + 1].type === TokenType.PLUS ||
+                            tokens[current + 1].type === TokenType.MINUS ||
+                            tokens[current + 1].type === TokenType.MULTIPLY ||
+                            tokens[current + 1].type === TokenType.DIVIDE
+                        )) {
+                            // This is an arithmetic expression, use walk() to parse it
+                            debugLog('Parsing arithmetic expression in assignment');
+                            debugLog('Current token before walk()', tokens[current]);
+                            value = walk();
+                            debugLog('Arithmetic expression parsed', value);
+                        } else {
+                            // Simple number value
+                            value = {
+                                type: 'NumberLiteral',
+                                value: tokens[current].value,
+                            };
+                            current++;
+                        }
+                    } else if (tokens[current] && tokens[current].type === TokenType.STRING) {
+                        // Simple string value
+                        value = {
+                            type: 'StringLiteral',
+                            value: tokens[current].value,
+                        };
+                        current++;
+                    } else if (tokens[current] && tokens[current].type === TokenType.IDENTIFIER) {
+                        // Check if this is the start of an infix arithmetic expression
+                        if (tokens[current + 1] && (
+                            tokens[current + 1].type === TokenType.PLUS ||
+                            tokens[current + 1].type === TokenType.MINUS ||
+                            tokens[current + 1].type === TokenType.MULTIPLY ||
+                            tokens[current + 1].type === TokenType.DIVIDE
+                        )) {
+                            // This is an infix arithmetic expression
+                            const left = {
+                                type: 'Identifier',
+                                value: tokens[current].value,
+                            };
+                            current++; // Skip left operand
+                            const operator = tokens[current].type;
+                            current++; // Skip operator
+                            const right = walk();
+                            
+                            const expressionTypes = {
+                                [TokenType.PLUS]: 'PlusExpression',
+                                [TokenType.MINUS]: 'MinusExpression',
+                                [TokenType.MULTIPLY]: 'MultiplyExpression',
+                                [TokenType.DIVIDE]: 'DivideExpression',
+                            };
+                            
+                            value = {
+                                type: expressionTypes[operator],
+                                left,
+                                right,
+                            };
+                        } else {
+                            // Simple identifier value
+                            value = {
+                                type: 'Identifier',
+                                value: tokens[current].value,
+                            };
+                            current++;
+                        }
+                    } else if (tokens[current] && (
+                        tokens[current].type === TokenType.PLUS ||
+                        tokens[current].type === TokenType.MINUS ||
+                        tokens[current].type === TokenType.MULTIPLY ||
+                        tokens[current].type === TokenType.DIVIDE
+                    )) {
+                        // Arithmetic expression value (prefix notation)
+                        const operator = tokens[current].type;
+                        current++; // Skip operator
+                        const left = walk();
+                        const right = walk();
+                        
+                        const expressionTypes = {
+                            [TokenType.PLUS]: 'PlusExpression',
+                            [TokenType.MINUS]: 'MinusExpression',
+                            [TokenType.MULTIPLY]: 'MultiplyExpression',
+                            [TokenType.DIVIDE]: 'DivideExpression',
+                        };
+                        
+                        value = {
+                            type: expressionTypes[operator],
+                            left,
+                            right,
+                        };
+                    } else {
+                        // Fallback to walk() for other cases
+                        debugLog('Using walk() fallback for assignment value', { current: tokens[current] });
+                        value = walk();
+                    }
+                    
+                    return {
+                        type: 'AssignmentExpression',
+                        name,
+                        value,
+                    };
+                }
+            }
+            
+
+            
+            // Check if this is followed by an operator
+            if (tokens[current + 1] && (
+                tokens[current + 1].type === TokenType.PLUS ||
+                tokens[current + 1].type === TokenType.MINUS ||
+                tokens[current + 1].type === TokenType.MULTIPLY ||
+                tokens[current + 1].type === TokenType.DIVIDE
+            )) {
+                const left = {
+                    type: 'Identifier',
+                    value: token.value,
+                };
+                const operator = tokens[current + 1].type;
+                current += 2; // Skip identifier and operator
+                const right = walk();
+                
+                const expressionTypes = {
+                    [TokenType.PLUS]: 'PlusExpression',
+                    [TokenType.MINUS]: 'MinusExpression',
+                    [TokenType.MULTIPLY]: 'MultiplyExpression',
+                    [TokenType.DIVIDE]: 'DivideExpression',
+                };
+                
+                return {
+                    type: expressionTypes[operator],
+                    left,
+                    right,
+                };
+            }
+            
+            // Check if this is followed by an operator
+            if (tokens[current + 1] && (
+                tokens[current + 1].type === TokenType.PLUS ||
+                tokens[current + 1].type === TokenType.MINUS ||
+                tokens[current + 1].type === TokenType.MULTIPLY ||
+                tokens[current + 1].type === TokenType.DIVIDE
+            )) {
+                const left = {
+                    type: 'Identifier',
+                    value: token.value,
+                };
+                const operator = tokens[current + 1].type;
+                current += 2; // Skip identifier and operator
+                const right = walk();
+                
+                const expressionTypes = {
+                    [TokenType.PLUS]: 'PlusExpression',
+                    [TokenType.MINUS]: 'MinusExpression',
+                    [TokenType.MULTIPLY]: 'MultiplyExpression',
+                    [TokenType.DIVIDE]: 'DivideExpression',
+                };
+                
+                return {
+                    type: expressionTypes[operator],
+                    left,
+                    right,
+                };
+            }
+            
             current++;
             return {
                 type: 'Identifier',
@@ -176,12 +1469,38 @@ function parser(tokens) {
             };
         }
 
-        if (token.type === TokenType.ASSIGNMENT) {
-            current++;
+
+
+        // Pattern matching: value : pattern1 : result1 pattern2 : result2 ...
+        if (token.type === TokenType.CASE) {
+            current++; // Skip 'case'
+            
+            // Parse the value being matched (wrap in array for interpreter compatibility)
+            const valueNode = walk();
+            const value = [valueNode];
+            
+            // Expect 'of'
+            if (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 patternNode = walk();
+                const resultNode = walk();
+                cases.push({ 
+                    pattern: [patternNode], 
+                    result: [resultNode] 
+                });
+            }
+            
             return {
-                type: 'AssignmentExpression',
-                name: tokens[current - 2].value,
-                value: walk(),
+                type: 'CaseExpression',
+                value,
+                cases,
             };
         }
 
@@ -232,7 +1551,7 @@ function parser(tokens) {
 
         if (token.type === TokenType.SEMICOLON) {
             current++;
-            return;
+            return null;
         }
 
         throw new TypeError(token.type);
@@ -245,7 +1564,7 @@ function parser(tokens) {
 
     while (current < tokens.length) {
         const node = walk();
-        if (node !== null) {
+        if (node !== null && node !== undefined) {
             ast.body.push(node);
         }
     }
@@ -255,66 +1574,819 @@ function parser(tokens) {
 
 // Interpreter
 function interpreter(ast) {
+    debugLog('Starting interpreter with AST', ast);
     let globalScope = {};
+    initializeStandardLibrary(globalScope);
 
     function evalNode(node) {
+        if (!node) {
+            return undefined;
+        }
         switch (node.type) {
             case 'NumberLiteral':
                 return parseInt(node.value);
+            case 'StringLiteral':
+                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 'AssignmentExpression':
-                globalScope[node.name] = evalNode(node.value);
+                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':
-                return globalScope[node.value];
+                const identifierValue = globalScope[node.value];
+                if (identifierValue === undefined) {
+                    throw new Error(`Variable ${node.value} is not defined`);
+                }
+                return identifierValue;
+            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 'IfExpression':
                 return evalNode(node.test) ? evalNode(node.consequent) : node.alternate ? evalNode(node.alternate) : undefined;
             case 'FunctionDeclaration':
-                globalScope[node.name] = function() {
+                if (globalScope.hasOwnProperty(node.name)) {
+                    throw new Error(`Cannot reassign immutable variable: ${node.name}`);
+                }
+                globalScope[node.name] = function(...args) {
                     let localScope = Object.create(globalScope);
                     for (let i = 0; i < node.params.length; i++) {
-                        localScope[node.params[i]] = arguments[i];
+                        localScope[node.params[i]] = args[i];
+                    }
+                    // Create a new evalNode function that uses localScope
+                    const localEvalNode = (node) => {
+                        if (!node) {
+                            return undefined;
+                        }
+                        switch (node.type) {
+                            case 'NumberLiteral':
+                                return parseInt(node.value);
+                            case 'StringLiteral':
+                                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 'AssignmentExpression':
+                                if (localScope.hasOwnProperty(node.name)) {
+                                    throw new Error(`Cannot reassign immutable variable: ${node.name}`);
+                                }
+                                localScope[node.name] = localEvalNode(node.value);
+                                return;
+                            case 'Identifier':
+                                const identifierValue = localScope[node.value];
+                                if (identifierValue === undefined && node.value) {
+                                    return node.value; // Return as string literal if not found in scope
+                                }
+                                return identifierValue;
+                            case 'FunctionReference':
+                                const localFunctionValue = localScope[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 'IfExpression':
+                                return localEvalNode(node.test) ? localEvalNode(node.consequent) : node.alternate ? localEvalNode(node.alternate) : undefined;
+                            case 'FunctionDeclaration':
+                                if (localScope.hasOwnProperty(node.name)) {
+                                    throw new Error(`Cannot reassign immutable variable: ${node.name}`);
+                                }
+                                localScope[node.name] = function(...args) {
+                                    let nestedScope = Object.create(localScope);
+                                    for (let i = 0; i < node.params.length; i++) {
+                                        nestedScope[node.params[i]] = args[i];
+                                    }
+                                    return localEvalNode(node.body);
+                                };
+                                return;
+                                        case 'FunctionCall':
+                if (localScope[node.name] instanceof Function) {
+                    let args = node.args.map(localEvalNode);
+                    return localScope[node.name](...args);
+                }
+                throw new Error(`Function ${node.name} is not defined`);
+            case 'CaseExpression':
+                // Evaluate the values being matched (e.g., [x, y])
+                const values = node.value.map(localEvalNode);
+                
+                for (const caseItem of node.cases) {
+                    // Evaluate the pattern (e.g., [0, 0] or [0, _])
+                    const pattern = caseItem.pattern.map(localEvalNode);
+                    
+                    // Check if pattern matches values
+                    let matches = true;
+                    for (let i = 0; i < Math.max(values.length, pattern.length); i++) {
+                        const value = values[i];
+                        const patternValue = pattern[i];
+                        
+                        // Wildcard always matches
+                        if (patternValue === true) continue;
+                        
+                        // Otherwise, values must be equal
+                        if (value !== patternValue) {
+                            matches = false;
+                            break;
+                        }
                     }
-                    let lastResult;
-                    for (let bodyNode of node.body) {
-                        lastResult = evalNode(bodyNode);
+                    
+                    if (matches) {
+                        // Evaluate all results
+                        const results = caseItem.result.map(localEvalNode);
+                        // If there's only one result, return it directly (preserves number type)
+                        if (results.length === 1) {
+                            return results[0];
+                        }
+                        // Otherwise join multiple results as string
+                        return results.join(' ');
                     }
-                    return lastResult;
+                }
+                throw new Error('No matching pattern found');
+                        case 'WildcardPattern':
+                            return true; // Wildcard always matches
+                                    case 'IOInExpression':
+                // Read from stdin
+                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);
+                    });
+                });
+                        case 'IOOutExpression':
+                            // Output to stdout
+                            const localOutputValue = localEvalNode(node.value);
+                            console.log(localOutputValue);
+                            return localOutputValue;
+                        case 'IOAssertExpression':
+                            // Assert that left operator right is true
+                            const localLeftValue = localEvalNode(node.left);
+                            const localRightValue = localEvalNode(node.right);
+                            
+                            let localAssertionPassed = false;
+                            switch (node.operator) {
+                                case TokenType.EQUALS:
+                                    localAssertionPassed = localLeftValue === localRightValue;
+                                    break;
+                                case TokenType.LESS_THAN:
+                                    localAssertionPassed = localLeftValue < localRightValue;
+                                    break;
+                                case TokenType.GREATER_THAN:
+                                    localAssertionPassed = localLeftValue > localRightValue;
+                                    break;
+                                case TokenType.LESS_EQUAL:
+                                    localAssertionPassed = localLeftValue <= localRightValue;
+                                    break;
+                                case TokenType.GREATER_EQUAL:
+                                    localAssertionPassed = localLeftValue >= localRightValue;
+                                    break;
+                                case TokenType.NOT_EQUAL:
+                                    localAssertionPassed = localLeftValue !== localRightValue;
+                                    break;
+                                default:
+                                    throw new Error(`Unsupported comparison operator in assertion: ${node.operator}`);
+                            }
+                            
+                            if (!localAssertionPassed) {
+                                const operatorSymbol = {
+                                    [TokenType.EQUALS]: '=',
+                                    [TokenType.LESS_THAN]: '<',
+                                    [TokenType.GREATER_THAN]: '>',
+                                    [TokenType.LESS_EQUAL]: '<=',
+                                    [TokenType.GREATER_EQUAL]: '>=',
+                                    [TokenType.NOT_EQUAL]: '!='
+                                }[node.operator];
+                                throw new Error(`Assertion failed: ${JSON.stringify(localLeftValue)} ${operatorSymbol} ${JSON.stringify(localRightValue)}`);
+                            }
+                            return localLeftValue;
+                        default:
+                            throw new Error(`Unknown node type: ${node.type}`);
+                    }
+                };
+                    return localEvalNode(node.body);
                 };
                 return;
             case 'FunctionCall':
                 if (globalScope[node.name] instanceof Function) {
                     let args = node.args.map(evalNode);
-                    return globalScope[node.name].apply(null, args);
+                    return globalScope[node.name](...args);
                 }
                 throw new Error(`Function ${node.name} is not defined`);
+            case 'CaseExpression':
+                debugLog('CaseExpression evaluation', { value: node.value, cases: node.cases });
+                // Evaluate the values being matched (e.g., [x, y])
+                const values = node.value.map(evalNode);
+                
+                for (const caseItem of node.cases) {
+                    // Evaluate the pattern (e.g., [0, 0] or [0, _])
+                    const pattern = caseItem.pattern.map(evalNode);
+                    
+                    // Check if pattern matches values
+                    let matches = true;
+                    for (let i = 0; i < Math.max(values.length, pattern.length); i++) {
+                        const value = values[i];
+                        const patternValue = pattern[i];
+                        
+                        // Wildcard always matches
+                        if (patternValue === true) continue;
+                        
+                        // Otherwise, values must be equal
+                        if (value !== patternValue) {
+                            matches = false;
+                            break;
+                        }
+                    }
+                    
+                    if (matches) {
+                        // Evaluate all results
+                        const results = caseItem.result.map(evalNode);
+                        // If there's only one result, return it directly (preserves number type)
+                        if (results.length === 1) {
+                            return results[0];
+                        }
+                        // Otherwise join multiple results as string
+                        return results.join(' ');
+                    }
+                }
+                throw new Error('No matching pattern found');
+            case 'WildcardPattern':
+                return true; // Wildcard always matches
+                                        case 'IOInExpression':
+                                // Read from stdin
+                                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);
+                                    });
+                                });
+            case 'IOOutExpression':
+                // Output to stdout
+                const outputValue = evalNode(node.value);
+                console.log(outputValue);
+                return outputValue;
+            case 'IOAssertExpression':
+                // Assert that left operator right is true
+                const leftValue = evalNode(node.left);
+                const rightValue = evalNode(node.right);
+                
+                let assertionPassed = false;
+                switch (node.operator) {
+                    case TokenType.EQUALS:
+                        assertionPassed = leftValue === rightValue;
+                        break;
+                    case TokenType.LESS_THAN:
+                        assertionPassed = leftValue < rightValue;
+                        break;
+                    case TokenType.GREATER_THAN:
+                        assertionPassed = leftValue > rightValue;
+                        break;
+                    case TokenType.LESS_EQUAL:
+                        assertionPassed = leftValue <= rightValue;
+                        break;
+                    case TokenType.GREATER_EQUAL:
+                        assertionPassed = leftValue >= rightValue;
+                        break;
+                    case TokenType.NOT_EQUAL:
+                        assertionPassed = leftValue !== rightValue;
+                        break;
+                    default:
+                        throw new Error(`Unsupported comparison operator in assertion: ${node.operator}`);
+                }
+                
+                if (!assertionPassed) {
+                    const operatorSymbol = {
+                        [TokenType.EQUALS]: '=',
+                        [TokenType.LESS_THAN]: '<',
+                        [TokenType.GREATER_THAN]: '>',
+                        [TokenType.LESS_EQUAL]: '<=',
+                        [TokenType.GREATER_EQUAL]: '>=',
+                        [TokenType.NOT_EQUAL]: '!='
+                    }[node.operator];
+                    throw new Error(`Assertion failed: ${JSON.stringify(leftValue)} ${operatorSymbol} ${JSON.stringify(rightValue)}`);
+                }
+                return leftValue;
             default:
                 throw new Error(`Unknown node type: ${node.type}`);
         }
     }
 
-    return evalNode(ast.body[0]);
+    let lastResult;
+    for (let node of ast.body) {
+        if (node) { // Skip undefined nodes
+            lastResult = evalNode(node);
+        }
+    }
+    
+    // Handle async results (from interactive IO operations)
+    if (lastResult instanceof Promise) {
+        return lastResult.then(result => {
+            return result;
+        });
+    }
+    
+    return lastResult;
 }
 
-// Usage
-// const tokens = lexer('2 + 2');
-// const ast = parser(tokens);
-// const result = interpreter(ast);
-// console.log(result); // 4
+// Debug configuration
+const DEBUG = process.env.DEBUG === 'true' || process.argv.includes('--debug');
 
-// const tokens2 = lexer('x : 2 + 2');
-// const ast2 = parser(tokens2);
-// const result2 = interpreter(ast2);
-// console.log(result2); 
+function debugLog(message, data = null) {
+    if (DEBUG) {
+        if (data) {
+            console.log(`[DEBUG] ${message}:`, JSON.stringify(data, null, 2));
+        } else {
+            console.log(`[DEBUG] ${message}`);
+        }
+    }
+}
 
+function debugError(message, error = null) {
+    if (DEBUG) {
+        console.error(`[DEBUG ERROR] ${message}`);
+        if (error) {
+            console.error(`[DEBUG ERROR] Details:`, error);
+        }
+    }
+}
+
+// Main execution logic
 const fs = require('fs');
+const readline = require('readline');
+
+/**
+ * Execute a script file
+ */
+function executeFile(filePath) {
+    try {
+        debugLog(`Executing file: ${filePath}`);
+        
+        const input = fs.readFileSync(filePath, 'utf-8');
+        debugLog('Input content', input);
+        
+        const tokens = lexer(input);
+        debugLog('Tokens generated', tokens);
+        
+        const ast = parser(tokens);
+        debugLog('AST generated', ast);
+        
+        const result = interpreter(ast);
+        debugLog('Interpreter result', result);
+        
+        // Only print result if it's not undefined
+        if (result !== undefined) {
+            console.log(result);
+        }
+    } catch (error) {
+        debugError('Execution failed', error);
+        console.error(`Error executing file: ${error.message}`);
+        process.exit(1);
+    }
+}
+
+/**
+ * Start REPL mode
+ */
+function startREPL() {
+    console.log('Scripting Language REPL');
+    console.log('Type expressions to evaluate. End with semicolon (;) to execute.');
+    console.log('Type "exit" to quit.');
+    console.log('');
+    
+    const rl = readline.createInterface({
+        input: process.stdin,
+        output: process.stdout,
+        prompt: '> '
+    });
+    
+    // Create a persistent global scope for the REPL
+    let globalScope = {};
+    initializeStandardLibrary(globalScope);
+    let currentInput = '';
+    
+    rl.prompt();
+    
+    rl.on('line', (line) => {
+        const trimmedLine = line.trim();
+        
+        if (trimmedLine === 'exit' || trimmedLine === 'quit') {
+            rl.close();
+            return;
+        }
+        
+        // Add the line to current input
+        currentInput += line + '\n';
+        
+        // Check if the input ends with a semicolon
+        if (currentInput.trim().endsWith(';')) {
+            try {
+                const tokens = lexer(currentInput);
+                const ast = parser(tokens);
+                
+                // Create a custom interpreter that uses the persistent scope
+                const result = interpreterWithScope(ast, globalScope);
+                
+                // Only print result if it's not undefined
+                if (result !== undefined) {
+                    console.log(result);
+                }
+            } catch (error) {
+                console.error(`Error: ${error.message}`);
+            }
+            
+            // Reset current input for next expression
+            currentInput = '';
+        }
+        
+        rl.prompt();
+    });
+    
+    rl.on('close', () => {
+        console.log('Goodbye!');
+        process.exit(0);
+    });
+}
+
+/**
+ * Interpreter that uses a provided global scope
+ */
+function interpreterWithScope(ast, globalScope) {
+    function evalNode(node) {
+        if (!node) {
+            return undefined;
+        }
+        switch (node.type) {
+            case 'NumberLiteral':
+                return parseInt(node.value);
+            case 'StringLiteral':
+                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 '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':
+                if (globalScope.hasOwnProperty(node.name)) {
+                    throw new Error(`Cannot reassign immutable variable: ${node.name}`);
+                }
+                globalScope[node.name] = function(...args) {
+                    let localScope = Object.create(globalScope);
+                    for (let i = 0; i < node.params.length; i++) {
+                        localScope[node.params[i]] = args[i];
+                    }
+                    return localEvalNode(node.body);
+                };
+                return;
+            case 'FunctionCall':
+                if (globalScope[node.name] instanceof Function) {
+                    let args = node.args.map(evalNode);
+                    return globalScope[node.name](...args);
+                }
+                throw new Error(`Function ${node.name} is not defined`);
+            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(' ');
+                    }
+                }
+                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);
+                    });
+                });
+            case 'IOOutExpression':
+                const outputValue = evalNode(node.value);
+                console.log(outputValue);
+                return outputValue;
+            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}`);
+        }
+    }
+
+    const localEvalNode = (node) => {
+        if (!node) {
+            return undefined;
+        }
+        switch (node.type) {
+            case 'NumberLiteral':
+                return parseInt(node.value);
+            case 'StringLiteral':
+                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 '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':
+                if (globalScope.hasOwnProperty(node.name)) {
+                    throw new Error(`Cannot reassign immutable variable: ${node.name}`);
+                }
+                globalScope[node.name] = function(...args) {
+                    let nestedScope = Object.create(globalScope);
+                    for (let i = 0; i < node.params.length; i++) {
+                        nestedScope[node.params[i]] = args[i];
+                    }
+                    return localEvalNode(node.body);
+                };
+                return;
+            case 'FunctionCall':
+                if (globalScope[node.name] instanceof Function) {
+                    let args = node.args.map(localEvalNode);
+                    return globalScope[node.name](...args);
+                }
+                throw new Error(`Function ${node.name} is not defined`);
+            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 (matches) {
+                        const results = caseItem.result.map(localEvalNode);
+                        if (results.length === 1) {
+                            return results[0];
+                        }
+                        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);
+                    });
+                });
+            case 'IOOutExpression':
+                const localOutputValue = localEvalNode(node.value);
+                console.log(localOutputValue);
+                return localOutputValue;
+            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}`);
+        }
+    };
+
+    let lastResult;
+    for (let node of ast.body) {
+        if (node) {
+            lastResult = evalNode(node);
+        }
+    }
+    
+    if (lastResult instanceof Promise) {
+        return lastResult.then(result => {
+            return result;
+        });
+    }
+    
+    return lastResult;
+}
 
-// Read the input from a file
-const input = fs.readFileSync('input.txt', 'utf-8');
+// Check command line arguments
+const args = process.argv.slice(2);
 
-// Usage
-const tokens = lexer(input);
-const ast = parser(tokens);
-const result = interpreter(ast);
-console.log(result);
\ No newline at end of file
+if (args.length === 0) {
+    // No arguments - start REPL mode
+    startREPL();
+} else if (args.length === 1) {
+    // One argument - execute the file
+    const filePath = args[0];
+    executeFile(filePath);
+} else {
+    // Too many arguments
+    console.error('Usage: node lang.js [file]');
+    console.error('  If no file is provided, starts REPL mode');
+    console.error('  If file is provided, executes the file');
+    process.exit(1);
+}
\ No newline at end of file
diff --git a/js/scripting-lang/parser_analysis.md b/js/scripting-lang/parser_analysis.md
new file mode 100644
index 0000000..8a25df1
--- /dev/null
+++ b/js/scripting-lang/parser_analysis.md
@@ -0,0 +1,143 @@
+# Parser Implementation Analysis
+
+## Grammar vs Implementation Comparison
+
+### 1. Assignment Parsing Issue
+
+**Grammar Rule:**
+```
+assignment = identifier ":" assignment_value
+assignment_value = function_call | simple_expression
+```
+
+**Current Implementation Problem:**
+- The parser calls `walk()` to get the value in assignments
+- `walk()` consumes the function name before assignment parsing can detect it as a function call
+- This causes `result : add 3 4;` to be parsed incorrectly
+
+**Expected Parse Tree:**
+```
+assignment(
+  identifier("result"),
+  function_call("add", [number(3), number(4)])
+)
+```
+
+**Actual Parse Tree (from debug output):**
+```
+assignment(
+  identifier("result"),
+  number(3)
+)
+// Plus separate nodes: number(4)
+```
+
+### 2. Function Call Detection
+
+**Grammar Rule:**
+```
+function_call = identifier argument_list
+argument_list = expression { expression }
+```
+
+**Current Implementation Issues:**
+- Function call detection is in the wrong place in the parser
+- Assignment parsing calls `walk()` which consumes tokens before function call detection
+- The condition `tokens[current + 1].type !== TokenType.ASSIGNMENT` prevents function calls in assignments
+
+**Debug Evidence:**
+```
+[DEBUG] Assignment parsing: {
+  "current": { "type": "NUMBER", "value": "3" },
+  "next": { "type": "NUMBER", "value": "4" }
+}
+```
+The parser is already at the `3` token, meaning `add` has been consumed.
+
+### 3. Case Expression Parsing
+
+**Grammar Rule:**
+```
+case_expression = "case" value_list "of" case_list
+case_branch = pattern ":" result
+```
+
+**Current Implementation Status:**
+✅ **Working correctly** - Case expressions parse and structure correctly
+- Patterns are parsed correctly: `0 0`, `0 _`, `_ 0`, `_ _`
+- Results are parsed correctly: string literals, numbers, identifiers
+- The AST structure matches the grammar
+
+### 4. Arithmetic Expression Parsing
+
+**Grammar Rule:**
+```
+arithmetic_expression = arithmetic_operator expression expression
+```
+
+**Current Implementation Status:**
+✅ **Working correctly** - Prefix notation is handled correctly
+- `+ x y` parses as `PlusExpression(left: x, right: y)`
+- Operator precedence is handled correctly
+
+### 5. IO Statement Parsing
+
+**Grammar Rule:**
+```
+io_statement = io_operator [ expression ]
+io_operator = "..in" | "..out"
+```
+
+**Current Implementation Status:**
+✅ **Working correctly** - IO statements parse correctly
+- `..in` and `..out` are recognized as special tokens
+- Expressions after `..out` are parsed correctly
+
+## Root Cause Analysis
+
+The fundamental issue is in the parser architecture:
+
+1. **Assignment parsing calls `walk()`** to get the value
+2. **`walk()` consumes tokens** before assignment parsing can analyze them
+3. **Function call detection happens too late** in the parsing process
+
+## Proposed Solutions
+
+### Solution 1: Restructure Assignment Parsing
+Don't call `walk()` for assignment values. Instead, directly parse the value:
+
+```javascript
+// Instead of: const value = walk();
+// Do: Parse value directly based on next tokens
+```
+
+### Solution 2: Add Function Call Detection to walk()
+Make `walk()` detect function calls when it encounters an identifier followed by arguments:
+
+```javascript
+if (token.type === TokenType.IDENTIFIER) {
+    // Check for function call first
+    if (isFunctionCall()) {
+        return parseFunctionCall();
+    }
+    // Then check for assignment
+    if (isAssignment()) {
+        return parseAssignment();
+    }
+}
+```
+
+### Solution 3: Use Lookahead
+Implement a lookahead mechanism to peek at tokens without consuming them:
+
+```javascript
+function peek(n = 1) {
+    return tokens[current + n];
+}
+```
+
+## Recommended Approach
+
+**Solution 1** is the most straightforward. The assignment parsing should directly parse the value without calling `walk()`, allowing it to distinguish between function calls and simple expressions.
+
+This would fix the core issue and make the parser match the grammar specification. 
\ No newline at end of file
diff --git a/js/scripting-lang/test_ambiguous_cases.txt b/js/scripting-lang/test_ambiguous_cases.txt
new file mode 100644
index 0000000..96ae555
--- /dev/null
+++ b/js/scripting-lang/test_ambiguous_cases.txt
@@ -0,0 +1,23 @@
+..out "Testing ambiguous function call detection:";
+
+add : x y -> x + y;
+double : x -> x * 2;
+square : x -> x * x;
+
+..out "1. Simple function call (should work):";
+result1 : add 3 4;
+..out result1;
+
+..out "2. Two function calls (should work):";
+result2 : add double 3 4;
+..out result2;
+
+..out "3. Ambiguous nested function calls (should error):";
+result3 : add double 3 square 2;
+..out result3;
+
+..out "4. More ambiguous calls (should error):";
+result4 : add double 3 square 2 multiply 4;
+..out result4;
+
+..out "Test complete"; 
\ No newline at end of file
diff --git a/js/seed/README.md b/js/seed/README.md
index 8159cb3..981ca7d 100644
--- a/js/seed/README.md
+++ b/js/seed/README.md
@@ -1,6 +1,6 @@
 # Seed: Minimal FRP/TEA Web App Starter Kit
 
-This is an opinionated, minimal starting point for browser-native web apps using a functional, Elm-style architecture (FRP/TEA) and only browser APIs. No frameworks, no build step, just ES modules.
+This is an opinionated, hopefully simple starting point for browser-native web apps using a functional, Elm-style architecture (FRP/TEA) and only browser APIs. No rulers, no kings, no frameworks, no build step, only ES modules.
 
 ## Architecture
 - **state.js**: App state definition and helpers
@@ -15,14 +15,9 @@ This is an opinionated, minimal starting point for browser-native web apps using
 - **View**: Pure function `(state) => html`
 - **Entrypoint**: Handles events, dispatches actions, triggers re-render
 
-## Why?
-- Simple, testable, and maintainable
-- No dependencies
-- Encourages functional, declarative code
-
 ## How to Extend and Use This Template
 
-This template is designed to be a flexible, opinionated starting point for any browser-native app.
+This template is designed to be a flexible, opinionated starting point for any kinda app, especially proofs of concept, toys, and prototypes.
 
 ### Key Files to Extend
 - **src/state.js**: Define the app's state shape and any helper functions for cloning or initializing state.
@@ -69,9 +64,9 @@ Suppose you want to add a button that increments a counter:
      ```
 
 ### Tips
-- Keep all state transitions in `update.js` for predictability.
-- Keep all DOM rendering in `view.js` for clarity.
-- Use the `postRender` hook for accessibility or focus management.
+- Keep all state transitions in `update.js`.
+- Keep all DOM rendering in `view.js`.
+- Use the `postRender` hook for accessibility or focus management stuff.
 - Add new features by extending state, update, view, and wiring up events in `app.js`.
 
 ---
diff --git a/js/seed/seed b/js/seed/seed
new file mode 100755
index 0000000..15276e7
--- /dev/null
+++ b/js/seed/seed
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+set -euo pipefail
+
+# Usage: seed plant
+
+if [ "$#" -ne 1 ] || [ "$1" != "plant" ]; then
+  echo "Usage: $0 plant"
+  exit 1
+fi
+
+if [ "$EUID" -eq 0 ]; then
+  echo "Do not run this script as root."
+  exit 1
+fi
+
+if ! command -v git >/dev/null 2>&1; then
+  echo "Warning: git is not installed. You won't be able to initialize a git repo."
+fi
+
+SRC_DIR="$(cd "$(dirname "$0")" && pwd)"
+
+read -rp "Enter new project name: " DEST_DIR
+
+if [ -z "$DEST_DIR" ]; then
+  echo "Project name cannot be empty."
+  exit 1
+fi
+
+DEST_PATH="$PWD/$DEST_DIR"
+
+if [ -e "$DEST_PATH" ]; then
+  echo "Error: '$DEST_PATH' already exists."
+  exit 1
+fi
+
+cleanup() {
+  if [ -d "$DEST_PATH" ]; then
+    echo "Cleaning up partial directory..."
+    rm -rf "$DEST_PATH"
+  fi
+}
+trap cleanup INT TERM
+
+echo "Copying seed template to '$DEST_PATH'..."
+mkdir "$DEST_PATH"
+
+if command -v rsync >/dev/null 2>&1; then
+  rsync -a --exclude='.git' --exclude='seed' "$SRC_DIR/" "$DEST_PATH/"
+else
+  cp -r "$SRC_DIR/"* "$DEST_PATH/"
+  cp -r "$SRC_DIR/".* "$DEST_PATH/" 2>/dev/null || true
+  rm -rf "$DEST_PATH/.git" "$DEST_PATH/seed"
+fi
+
+cd "$DEST_PATH"
+
+# Optionally, update README
+if [ -f README.md ]; then
+  sed -i '' "1s/.*/# $DEST_DIR/" README.md 2>/dev/null || sed -i "1s/.*/# $DEST_DIR/" README.md
+fi
+
+echo "Initialized new project in '$DEST_PATH'."
+
+read -rp "Do you want to initialize a git repository? (y/n): " INIT_GIT
+if [[ "$INIT_GIT" =~ ^[Yy]$ ]]; then
+  git init
+  echo "Git repository initialized."
+else
+  echo "Skipping git initialization."
+fi
+
+echo "Next steps:"
+echo "  cd \"$DEST_PATH\""
+echo "  and tend to the seed you've planted..." 
\ No newline at end of file
diff --git a/js/seed/src/app.js b/js/seed/src/app.js
index 34b4579..49ad9d1 100644
--- a/js/seed/src/app.js
+++ b/js/seed/src/app.js
@@ -155,11 +155,3 @@ function setHistoryPointer(idx) {
     updateHistoryInfo();
   }
 }
-
-function handleSliderChange(e) {
-  setHistoryPointer(Number(e.target.value));
-}
-
-function handleStepperChange(e) {
-  setHistoryPointer(Number(e.target.value));
-} 
\ No newline at end of file
diff --git a/js/seed/src/dev.js b/js/seed/src/dev.js
index ee1a6e7..173fc3c 100644
--- a/js/seed/src/dev.js
+++ b/js/seed/src/dev.js
@@ -1,8 +1,8 @@
 // devMode.js
-// Minimal, single-file dev mode with scriptable console API
+// Simpleish, single-file dev mode with interactive console API
 
 /**
- * Initialize dev mode: exposes a scriptable API for stepping through state history.
+ * Initialize dev mode: exposes an API for stepping through state history.
  * @param {object} opts
  * @param {function} opts.getState - returns current app state
  * @param {function} opts.setState - sets app state
diff --git a/js/seed/src/view.js b/js/seed/src/view.js
index 5feef6e..4c6e680 100644
--- a/js/seed/src/view.js
+++ b/js/seed/src/view.js
@@ -4,10 +4,10 @@
 /**
  * Pure view functions for the application.
  *
- * Why pure functions returning HTML strings?
+ * Why pure functions returning HTML strings? Because Elm does it, tbh.
  * - Keeps rendering logic stateless and easy to test.
- * - Ensures the UI is always a direct function of state, avoiding UI bugs from incremental DOM updates.
- * - Using template literals is minimal and browser-native, with no dependencies.
+ * - Ensures the UI is always a direct function of state, which should in theory totally avoid bugs from incremental DOM updates.
+ * - Using template literals is minimal and browser-native, with no dependencies, and is fun.
  *
  * Why escape output?
  * - Prevents XSS and ensures all user/content data is safely rendered.