feat: execute local assignments and while loops

This commit is contained in:
2026-10-10 00:17:12 +02:00
parent 021cbecac8
commit b35a68dff8
16 changed files with 1440 additions and 170 deletions
+70 -4
View File
@@ -1,13 +1,13 @@
#! grammar:
#! * type ..... -> identifier
#! * assignment -> :: | :=
#! * binding ... -> :: | :=
#! * literal .. -> int | float | string | 'true' | 'false'
#! * op ....... -> '+' | '-' | '*' | '/' | '==' | '!=' | '<' | '<=' | '>' | '>='
#! * expr ..... -> identifier | literal | '(' expr ')' | '-' expr | expr op expr | expr '(' [expr {',' expr} [',']] ')'
#! * decl ..... -> identifier [type] assignment expr
#! * decl ..... -> identifier [type] binding expr
#! * block .... -> '{' {stmt} '}'
#! * arm ...... -> block | stmt (single statements become canonical blocks)
#! * stmt ..... -> decl | expr | 'return' [expr] | 'if' expr arm ['else' arm]
#! * stmt ..... -> decl | expr | identifier '=' expr | 'return' [expr] | 'if' expr arm ['else' arm] | 'while' expr arm
#! braceless guards require parentheses unless the condition is a call; else binds to the nearest if.
import "@std/debug"
@@ -47,7 +47,11 @@ DeclKind :: enum {
StmtKind :: enum {
declaration,
expression,
return_stmt, if_stmt, invalid
assignment_stmt,
return_stmt,
if_stmt,
while_stmt,
invalid
}
Mutability :: enum {
@@ -78,6 +82,8 @@ NodeKind :: enum {
stmt_decl,
stmt_return,
stmt_if,
stmt_assignment,
stmt_while,
func_decl,
param_decl,
block,
@@ -176,6 +182,18 @@ IfView :: struct {
else_block ?NodeId
}
AssignmentView :: struct {
span Span
target NodeId
value NodeId
}
WhileView :: struct {
span Span
condition NodeId
body NodeId
}
InvalidView :: struct {
span Span
diagnostic DiagnosticId
@@ -309,6 +327,32 @@ add_if_stmt proc(
}, span)
}
add_assignment_stmt proc(
builder @mut Builder,
span Span,
target NodeId,
value NodeId,
) NodeId ! mem.AllocError {
return try add_node(builder, Node{
kind = .stmt_assignment,
main = NodeData{ node_id = target },
data0 = NodeData{ node_id = value },
}, span)
}
add_while_stmt proc(
builder @mut Builder,
span Span,
condition NodeId,
body NodeId,
) NodeId ! mem.AllocError {
return try add_node(builder, Node{
kind = .stmt_while,
main = NodeData{ node_id = condition },
data0 = NodeData{ node_id = body },
}, span)
}
add_statement_decl proc(
builder @mut Builder,
span Span,
@@ -445,6 +489,8 @@ stmt_kind proc(tree @Tree, id NodeId) StmtKind {
.stmt_expr: .expression
.stmt_return: .return_stmt
.stmt_if: .if_stmt
.stmt_assignment: .assignment_stmt
.stmt_while: .while_stmt
.invalid_stmt: .invalid
else: unreachable
}
@@ -476,6 +522,26 @@ if_stmt proc(tree @Tree, id NodeId) IfView {
}
}
assignment_stmt proc(tree @Tree, id NodeId) AssignmentView {
node :: get_node(&tree.storage, id)
debug.assert(node.kind == .stmt_assignment)
return AssignmentView{
span = get_span(&tree.storage, id),
target = node.main.node_id,
value = node.data0.node_id,
}
}
while_stmt proc(tree @Tree, id NodeId) WhileView {
node :: get_node(&tree.storage, id)
debug.assert(node.kind == .stmt_while)
return WhileView{
span = get_span(&tree.storage, id),
condition = node.main.node_id,
body = node.data0.node_id,
}
}
statement_decl proc(tree @Tree, id NodeId) StatementDeclView {
node :: get_node(&tree.storage, id)
debug.assert(node.kind == .stmt_decl)
+15
View File
@@ -77,6 +77,21 @@ render_block proc(renderer @mut Renderer, tree @ast.Tree, block ast.NodeId, dept
try render_block(renderer, tree, alternative, depth + 1)
}
}
.assignment_stmt: {
assignment :: ast.assignment_stmt(tree, statement)
try append_text(renderer, "assignment ")
try append_text(renderer, ast.source_text(tree, ast.node_span(tree, assignment.target)))
try append_text(renderer, " = ")
try append_text(renderer, ast.source_text(tree, ast.node_span(tree, assignment.value)))
try append_text(renderer, "\n")
}
.while_stmt: {
loop :: ast.while_stmt(tree, statement)
try append_text(renderer, "while ")
try append_text(renderer, ast.source_text(tree, ast.node_span(tree, loop.condition)))
try append_text(renderer, "\n")
try render_block(renderer, tree, loop.body, depth + 1)
}
.invalid: try append_text(renderer, "invalid statement\n")
}
}