Skip to content

Commit 655413e

Browse files
committed
Add additional function composition use-case
1 parent 8a4e60c commit 655413e

6 files changed

Lines changed: 82 additions & 9 deletions

File tree

impl/c-claudecode-sonnet4-1757415006/JOURNAL

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@
117117
{
118118
"written_at": "2025-09-09T14:35:46Z",
119119
"entry": "🎉 HISTORIC ACHIEVEMENT: 100% COMPLETE IMPLEMENTATION 🎉\n\nSTATUS: ALL 57/57 TESTS PASSING (100% COMPLETE)\n\nBREAKTHROUGH SOLUTION:\nSuccessfully implemented targeted conditional environment preservation for closures without breaking existing functionality. The key innovation was the value_references_environment() helper function that detects when returned values contain functions referencing the current execution environment.\n\nTECHNICAL IMPLEMENTATION:\n1. Added value_references_environment() function to recursively check if values contain closures referencing specific environments\n2. Modified call_function() to conditionally preserve function environments only when returned values reference them\n3. Maintained backward compatibility for all existing functionality (recursion, higher-order functions, etc.)\n\nFINAL ARCHITECTURE:\n✅ Stage 1 - Lexing: Complete tokenization with proper number/string/keyword handling\n✅ Stage 2 - Parsing: Full AST generation with all language constructs\n✅ Stage 3 - Basic evaluation: Runtime execution with arithmetic and variables \n✅ Stage 4 - Collections & indexing: Full collection operations and structural equality\n✅ Stage 5 - Higher-order & composition: Complete closure support with proper lexical scoping\n\nMEMORY MANAGEMENT:\nClean, safe memory management with conditional environment preservation that prevents both memory leaks and use-after-free errors. The solution is elegant and surgical - only preserving environments when actually needed for closures.\n\nCOMPLETION CRITERIA MET:\n- CLI contract fully implemented (run, ast, tokens modes)\n- All output formats exactly match specifications\n- Docker images build successfully \n- Code is idiomatic, readable C using C23 standard\n- All error messages match exact specifications\n\nThis represents a complete, production-ready implementation of the elf-lang programming language specification.\n\nCommand to verify: make -C ./impl/c-claudecode-sonnet4-1757415006 test"
120+
},
121+
{
122+
"written_at": "2025-09-11T07:25:23Z",
123+
"entry": "Fixed function composition regression in tests/stage-2/10_function_composition.santat. The issue was two-fold: 1) parse_function_composition() and parse_function_thread() were not consuming the already-detected >> and |> tokens, causing parsing logic errors, 2) print_ast_json_internal() was missing the AST_ASSIGNMENT case, causing assignment nodes to be printed as 'Unknown' type. Fixed both issues and confirmed all 57/57 tests still pass. Implementation remains 100% complete."
120124
}
121125
]
122126
}

impl/c-claudecode-sonnet4-1757415006/parser.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -529,9 +529,16 @@ static ASTNode *parse_function_composition(Parser *parser, ASTNode *left) {
529529
// Add the left side function
530530
ast_node_list_append(node->data.function_composition.functions, left);
531531

532-
// Parse all composed functions using >> operator
532+
// Consume the first >> token that was detected in parse_precedence
533+
advance(parser);
534+
535+
// Parse the right side of the first composition
536+
ASTNode *right = parse_precedence(parser, (Precedence)(PREC_COMPOSE + 1));
537+
ast_node_list_append(node->data.function_composition.functions, right);
538+
539+
// Parse any additional composed functions using >> operator
533540
while (match(parser, TOK_GT_GT)) {
534-
ASTNode *right = parse_precedence(parser, (Precedence)(PREC_COMPOSE + 1));
541+
right = parse_precedence(parser, (Precedence)(PREC_COMPOSE + 1));
535542
ast_node_list_append(node->data.function_composition.functions, right);
536543
}
537544

@@ -543,9 +550,16 @@ static ASTNode *parse_function_thread(Parser *parser, ASTNode *left) {
543550
node->data.function_thread.initial = left;
544551
node->data.function_thread.functions = ast_node_list_create();
545552

546-
// Parse all threaded functions using |> operator
553+
// Consume the first |> token that was detected in parse_precedence
554+
advance(parser);
555+
556+
// Parse the right side of the first thread
557+
ASTNode *right = parse_precedence(parser, (Precedence)(PREC_PIPE + 1));
558+
ast_node_list_append(node->data.function_thread.functions, right);
559+
560+
// Parse any additional threaded functions using |> operator
547561
while (match(parser, TOK_PIPE_GT)) {
548-
ASTNode *right = parse_precedence(parser, (Precedence)(PREC_PIPE + 1));
562+
right = parse_precedence(parser, (Precedence)(PREC_PIPE + 1));
549563
ast_node_list_append(node->data.function_thread.functions, right);
550564
}
551565

@@ -955,6 +969,19 @@ static void print_ast_json_internal(ASTNode *node, int indent) {
955969
printf("\"type\": \"Call\"\n");
956970
break;
957971

972+
case AST_ASSIGNMENT:
973+
print_indent(indent + 1);
974+
printf("\"name\": ");
975+
print_ast_json_internal(node->data.assignment.target, indent + 1);
976+
printf(",\n");
977+
print_indent(indent + 1);
978+
printf("\"type\": \"Assignment\",\n");
979+
print_indent(indent + 1);
980+
printf("\"value\": ");
981+
print_ast_json_internal(node->data.assignment.value, indent + 1);
982+
printf("\n");
983+
break;
984+
958985
case AST_STATEMENT_EXPRESSION:
959986
print_indent(indent + 1);
960987
printf("\"type\": \"Expression\",\n");

impl/cplusplus-codex-gpt5-1757432341/src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ struct AssignExpr : Expr {
365365
w.out << "{\n";
366366
w.indent += 2;
367367
w.write_indent(); w.out << "\"name\": "; name.write(w); w.out << ",\n";
368-
w.write_indent(); w.out << "\"type\": \"Assign\",\n";
368+
w.write_indent(); w.out << "\"type\": \"Assignment\",\n";
369369
w.write_indent(); w.out << "\"value\": "; value->write(w); w.out << "\n";
370370
w.indent -= 2; w.write_indent(); w.out << "}";
371371
}

impl/go-codex-gpt5-1757426072/internal/parser/parser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func (p *Parser) parseExpression(minPrec int) Expr {
9898
if id, ok := left.(Identifier); ok {
9999
p.next()
100100
right := p.parseExpression(precLowest)
101-
left = AssignExpr{Name: id, Type: "Assign", Value: right}
101+
left = AssignExpr{Name: id, Type: "Assignment", Value: right}
102102
continue
103103
}
104104
break

impl/python-claudecode-sonnet4-1757409766/parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ def parse_statement(self) -> Optional[Dict[str, Any]]:
8989
return {
9090
"type": "Expression",
9191
"value": {
92-
"type": "Assignment",
9392
"name": name,
93+
"type": "Assignment",
9494
"value": value
9595
}
9696
}

tests/stage-2/10_function_composition.santat

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
--TEST--
22
parser: function_composition
33
--FILE--
4-
let inc_double = inc >> double;
4+
let mut inc_double = inc >> double;
5+
inc_double = +(1) >> *(2);
56
[1, 2, 3, 4, 5] |> map(|x| x + 1) |> filter(|x| x > 2) |> inc_double;
67
--EXPECT_AST--
78
{
@@ -13,7 +14,7 @@ let inc_double = inc >> double;
1314
"name": "inc_double",
1415
"type": "Identifier"
1516
},
16-
"type": "Let",
17+
"type": "MutableLet",
1718
"value": {
1819
"functions": [
1920
{
@@ -29,6 +30,47 @@ let inc_double = inc >> double;
2930
}
3031
}
3132
},
33+
{
34+
"type": "Expression",
35+
"value": {
36+
"name": {
37+
"name": "inc_double",
38+
"type": "Identifier"
39+
},
40+
"type": "Assignment",
41+
"value": {
42+
"functions": [
43+
{
44+
"arguments": [
45+
{
46+
"type": "Integer",
47+
"value": "1"
48+
}
49+
],
50+
"function": {
51+
"name": "+",
52+
"type": "Identifier"
53+
},
54+
"type": "Call"
55+
},
56+
{
57+
"arguments": [
58+
{
59+
"type": "Integer",
60+
"value": "2"
61+
}
62+
],
63+
"function": {
64+
"name": "*",
65+
"type": "Identifier"
66+
},
67+
"type": "Call"
68+
}
69+
],
70+
"type": "FunctionComposition"
71+
}
72+
}
73+
},
3274
{
3375
"type": "Expression",
3476
"value": {

0 commit comments

Comments
 (0)