feat: lower typed programs and interpret IR

This commit is contained in:
2026-10-09 22:47:05 +02:00
parent bc318a29ad
commit 98f3a04daf
20 changed files with 2328 additions and 85 deletions
+26 -2
View File
@@ -5,7 +5,7 @@
#! * op ....... -> '+' | '-' | '*' | '/'
#! * expr ..... -> identifier | literal | '(' expr ')' | '-' expr | expr op expr | expr '(' [expr {',' expr} [',']] ')'
#! * decl ..... -> identifier [type] assignment expr
#! * stmt ..... -> decl | expr
#! * stmt ..... -> decl | expr | 'return' [expr]
import "@std/debug"
import "@std/mem"
@@ -41,7 +41,7 @@ DeclKind :: enum {
}
StmtKind :: enum {
declaration, expression, invalid
declaration, expression, return_stmt, invalid
}
Mutability :: enum {
@@ -65,6 +65,7 @@ NodeKind :: enum {
expr_call,
stmt_expr,
stmt_decl,
stmt_return,
func_decl,
param_decl,
block,
@@ -151,6 +152,11 @@ CallExprView :: struct {
callee NodeId
}
ReturnView :: struct {
span Span
value ?NodeId
}
InvalidView :: struct {
span Span
diagnostic DiagnosticId
@@ -259,6 +265,14 @@ add_expression_stmt proc(builder @mut Builder, expression NodeId) NodeId ! mem.A
}, builder_span(builder, expression))
}
add_return_stmt proc(builder @mut Builder, span Span, value ?NodeId) NodeId ! mem.AllocError {
raw_value :: if (value) |id| id else no_node
return try add_node(builder, Node{
kind = .stmt_return,
main = NodeData{ node_id = raw_value },
}, span)
}
add_statement_decl proc(
builder @mut Builder,
span Span,
@@ -393,6 +407,7 @@ stmt_kind proc(tree @Tree, id NodeId) StmtKind {
return match get_node(&tree.storage, id).kind {
.stmt_decl: .declaration
.stmt_expr: .expression
.stmt_return: .return_stmt
.invalid_stmt: .invalid
else: unreachable
}
@@ -404,6 +419,15 @@ statement_expr proc(tree @Tree, id NodeId) NodeId {
return node.main.node_id
}
return_stmt proc(tree @Tree, id NodeId) ReturnView {
node :: get_node(&tree.storage, id)
debug.assert(node.kind == .stmt_return)
return ReturnView{
span = get_span(&tree.storage, id),
value = maybe_node_id(u32(node.main.node_id)),
}
}
statement_decl proc(tree @Tree, id NodeId) StatementDeclView {
node :: get_node(&tree.storage, id)
debug.assert(node.kind == .stmt_decl)
+8
View File
@@ -51,6 +51,14 @@ render_function proc(
try append_text(renderer, ast.source_text(tree, ast.node_span(tree, expression)))
try append_text(renderer, "\n")
}
.return_stmt: {
try append_text(renderer, " return")
if (ast.return_stmt(tree, statement).value) |value| {
try append_text(renderer, " ")
try append_text(renderer, ast.source_text(tree, ast.node_span(tree, value)))
}
try append_text(renderer, "\n")
}
.invalid: try append_text(renderer, " invalid statement\n")
}
}
-27
View File
@@ -1,27 +0,0 @@
import "@std/mem"
import "@std/testing"
import "@source/ast"
renders_semantic_debug_view test {
builder := ast.init_builder(mem.c_allocator, "value :: 42")
defer ast.deinit_builder(&builder)
value :: try ast.add_literal(&builder, .int, ast.Span{ start = 9, end = 11 })
declaration :: try ast.add_statement_decl(
&builder,
ast.Span{ start = 0, end = 11 },
ast.Span{ start = 0, end = 5 },
null,
.constant,
value,
)
declarations [1]ast.NodeId :: [declaration]
package :: try ast.add_package(&builder, ast.Span{ start = 0, end = 11 }, declarations[..])
tree := ast.finish(&builder, package)
defer ast.deinit(&tree)
renderer := init(mem.c_allocator)
defer deinit(&renderer)
try render(&renderer, &tree)
try testing.expect(mem.eql(u8, "package\n declaration value\n", renderer.bytes.items))
}