about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--js/scripting-lang/baba-yaga-c/ROADMAP.md21
-rw-r--r--js/scripting-lang/baba-yaga-c/src/parser.c19
-rw-r--r--js/scripting-lang/baba-yaga-c/test_arithmetic.txt2
-rw-r--r--js/scripting-lang/baba-yaga-c/test_countdown.txt2
-rw-r--r--js/scripting-lang/baba-yaga-c/test_countdown_call.txt1
-rw-r--r--js/scripting-lang/baba-yaga-c/test_factorial.txt1
-rw-r--r--js/scripting-lang/baba-yaga-c/test_factorial_call.txt1
-rw-r--r--js/scripting-lang/baba-yaga-c/test_integration_factorial.txt12
-rw-r--r--js/scripting-lang/baba-yaga-c/test_integration_factorial_call.txt25
-rw-r--r--js/scripting-lang/baba-yaga-c/test_integration_simple.txt10
-rw-r--r--js/scripting-lang/baba-yaga-c/test_simple.txt2
-rw-r--r--js/scripting-lang/baba-yaga-c/test_simple_out.txt1
12 files changed, 97 insertions, 0 deletions
diff --git a/js/scripting-lang/baba-yaga-c/ROADMAP.md b/js/scripting-lang/baba-yaga-c/ROADMAP.md
index e827ff3..963c46f 100644
--- a/js/scripting-lang/baba-yaga-c/ROADMAP.md
+++ b/js/scripting-lang/baba-yaga-c/ROADMAP.md
@@ -75,6 +75,27 @@ All advanced features including partial application are now working.
 **Task 3.1**: Fix Test 22 parser edge case to achieve 26/27 tests passing
 **Task 3.2**: Fix Integration Test 02 file reading issue to achieve 27/27 tests passing
 
+## **Integration Test 02 Segfault Investigation**
+
+### Findings So Far
+- Recursive function calls (e.g., `factorial 5`) cause a segmentation fault **only when run from a file**, not when piped via `cat` or `echo`.
+- Non-recursive function calls, arithmetic, and function definitions all work as expected.
+- The segfault occurs instantly, not after deep recursion (not a stack overflow).
+- The function is defined in the global scope, and recursive lookup should work.
+- The bug is **not** in the recursion logic itself.
+
+### Hypothesis
+- The root cause is likely a memory or buffer issue in file reading, string handling, or tokenization.
+- There may be a difference in how the source buffer is loaded from a file vs. piped input (e.g., BOM, encoding, or invisible characters).
+
+### Next Steps
+1. Add debug output to print the raw contents of the buffer loaded by `read_file()` for `tests/integration_02_pattern_matching.txt` before it is passed to the interpreter.
+2. Compare the buffer content from file vs. piped input.
+3. Check for buffer overflows, uninitialized memory, or off-by-one errors in file reading and tokenization.
+4. Check for non-ASCII, BOM, or invisible characters in the test file.
+
+---
+
 ## Technical Notes
 
 ### **Partial Application Implementation**
diff --git a/js/scripting-lang/baba-yaga-c/src/parser.c b/js/scripting-lang/baba-yaga-c/src/parser.c
index 6c94913..c490bd4 100644
--- a/js/scripting-lang/baba-yaga-c/src/parser.c
+++ b/js/scripting-lang/baba-yaga-c/src/parser.c
@@ -2666,6 +2666,14 @@ static ASTNode* parser_parse_when_expression(Parser* parser) {
         // Parse pattern
         ASTNode* pattern = parser_parse_when_pattern(parser);
         if (!pattern) break;
+        
+        // Debug: Show current token before consuming 'then'
+        Token* current_token = parser_peek(parser);
+        if (current_token) {
+            DEBUG_TRACE("Before consuming 'then', current token type=%d, lexeme='%s'", 
+                       current_token->type, current_token->lexeme ? current_token->lexeme : "NULL");
+        }
+        
         // Expect 'then'
         Token* then_token = parser_consume(parser, TOKEN_KEYWORD_THEN, "Expected 'then' after pattern in when case");
         if (!then_token) { ast_destroy_node(pattern); break; }
@@ -2770,6 +2778,7 @@ static ASTNode* parser_parse_when_pattern(Parser* parser) {
         if (token->type == TOKEN_IDENTIFIER || 
             token->type == TOKEN_NUMBER || 
             token->type == TOKEN_STRING ||
+            token->type == TOKEN_BOOLEAN ||
             (token->type == TOKEN_IDENTIFIER && token->lexeme && strcmp(token->lexeme, "_") == 0)) {
             literal_count++;
         } else if (token->type == TOKEN_LPAREN) {
@@ -2851,6 +2860,9 @@ static ASTNode* parser_parse_when_pattern(Parser* parser) {
                 } else if (lit_token->type == TOKEN_STRING) {
                     /* String pattern */
                     literals[i] = ast_literal_node(baba_yaga_value_string(lit_token->lexeme), lit_token->line, lit_token->column);
+                } else if (lit_token->type == TOKEN_BOOLEAN) {
+                    /* Boolean pattern */
+                    literals[i] = ast_literal_node(baba_yaga_value_boolean(lit_token->literal.boolean), lit_token->line, lit_token->column);
                 } else {
                     /* Cleanup on error */
                     for (int j = 0; j < i; j++) {
@@ -2944,6 +2956,13 @@ static ASTNode* parser_parse_when_pattern(Parser* parser) {
             return NULL;
         }
         DEBUG_TRACE("Parsed pattern test expression");
+        
+        // Debug: Show current token after parsing pattern
+        Token* after_token = parser_peek(parser);
+        if (after_token) {
+            DEBUG_TRACE("After parsing pattern, current token type=%d, lexeme='%s'", 
+                       after_token->type, after_token->lexeme ? after_token->lexeme : "NULL");
+        }
     }
     
     DEBUG_TRACE("parser_parse_when_pattern success");
diff --git a/js/scripting-lang/baba-yaga-c/test_arithmetic.txt b/js/scripting-lang/baba-yaga-c/test_arithmetic.txt
new file mode 100644
index 0000000..19d3ec7
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/test_arithmetic.txt
@@ -0,0 +1,2 @@
+test : n -> n - 1;
+test : n -> n - 1; result : test 5;
diff --git a/js/scripting-lang/baba-yaga-c/test_countdown.txt b/js/scripting-lang/baba-yaga-c/test_countdown.txt
new file mode 100644
index 0000000..e474c77
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/test_countdown.txt
@@ -0,0 +1,2 @@
+countdown : n -> when n is 0 then 0 _ then countdown (n - 1);
+countdown : n -> when n is 0 then 0 _ then countdown (n - 1); result : countdown 3;
diff --git a/js/scripting-lang/baba-yaga-c/test_countdown_call.txt b/js/scripting-lang/baba-yaga-c/test_countdown_call.txt
new file mode 100644
index 0000000..e06f875
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/test_countdown_call.txt
@@ -0,0 +1 @@
+countdown : n -> when n is 0 then 0 _ then countdown (n - 1); result : countdown 3;
diff --git a/js/scripting-lang/baba-yaga-c/test_factorial.txt b/js/scripting-lang/baba-yaga-c/test_factorial.txt
new file mode 100644
index 0000000..07248f8
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/test_factorial.txt
@@ -0,0 +1 @@
+factorial : n -> when n is 0 then 1 _ then n * (factorial (n - 1));
diff --git a/js/scripting-lang/baba-yaga-c/test_factorial_call.txt b/js/scripting-lang/baba-yaga-c/test_factorial_call.txt
new file mode 100644
index 0000000..ceb1727
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/test_factorial_call.txt
@@ -0,0 +1 @@
+factorial : n -> when n is 0 then 1 _ then n * (factorial (n - 1)); fact5 : factorial 5;
diff --git a/js/scripting-lang/baba-yaga-c/test_integration_factorial.txt b/js/scripting-lang/baba-yaga-c/test_integration_factorial.txt
new file mode 100644
index 0000000..c396568
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/test_integration_factorial.txt
@@ -0,0 +1,12 @@
+/* Integration Test: Pattern Matching */
+/* Combines: case expressions, functions, recursion, complex patterns */
+
+..out "=== Integration Test: Pattern Matching ===";
+
+/* Recursive factorial with case expressions */
+factorial : n -> 
+  when n is
+    0 then 1
+    _ then n * (factorial (n - 1));
+
+/* Pattern matching with multiple parameters */
diff --git a/js/scripting-lang/baba-yaga-c/test_integration_factorial_call.txt b/js/scripting-lang/baba-yaga-c/test_integration_factorial_call.txt
new file mode 100644
index 0000000..ae9483d
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/test_integration_factorial_call.txt
@@ -0,0 +1,25 @@
+/* Integration Test: Pattern Matching */
+/* Combines: case expressions, functions, recursion, complex patterns */
+
+..out "=== Integration Test: Pattern Matching ===";
+
+/* Recursive factorial with case expressions */
+factorial : n -> 
+  when n is
+    0 then 1
+    _ then n * (factorial (n - 1));
+
+/* Pattern matching with multiple parameters */
+classify : x y -> 
+  when x y is
+    0 0 then "both zero"
+    0 _ then "x is zero"
+    _ 0 then "y is zero"
+    _ _ then when x is
+            0 then "x is zero (nested)"
+            _ then when y is
+                  0 then "y is zero (nested)"
+                  _ then "neither zero";
+
+/* Test factorial */
+fact5 : factorial 5;
diff --git a/js/scripting-lang/baba-yaga-c/test_integration_simple.txt b/js/scripting-lang/baba-yaga-c/test_integration_simple.txt
new file mode 100644
index 0000000..f540fcb
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/test_integration_simple.txt
@@ -0,0 +1,10 @@
+/* Integration Test: Pattern Matching */
+/* Combines: case expressions, functions, recursion, complex patterns */
+
+..out "=== Integration Test: Pattern Matching ===";
+
+/* Recursive factorial with case expressions */
+factorial : n -> 
+  when n is
+    0 then 1
+    _ then n * (factorial (n - 1));
diff --git a/js/scripting-lang/baba-yaga-c/test_simple.txt b/js/scripting-lang/baba-yaga-c/test_simple.txt
new file mode 100644
index 0000000..c17b99b
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/test_simple.txt
@@ -0,0 +1,2 @@
+simple : n -> n;
+simple : n -> n; result : simple 5;
diff --git a/js/scripting-lang/baba-yaga-c/test_simple_out.txt b/js/scripting-lang/baba-yaga-c/test_simple_out.txt
new file mode 100644
index 0000000..6b1ea29
--- /dev/null
+++ b/js/scripting-lang/baba-yaga-c/test_simple_out.txt
@@ -0,0 +1 @@
+x : 5; ..out x;