chore: rename AstGen methods, removed 'check' prefix

This commit is contained in:
Brett Broadhurst 2026-03-08 06:26:16 -06:00
parent 95d89b7bf9
commit 98f5215629
Failed to generate hash of commit

View file

@ -20,7 +20,7 @@ constants: std.ArrayListUnmanaged(CodeUnit.Constant) = .empty,
knots: std.ArrayListUnmanaged(CodeUnit.Knot) = .empty, knots: std.ArrayListUnmanaged(CodeUnit.Knot) = .empty,
errors: std.ArrayListUnmanaged(Ast.Error) = .empty, errors: std.ArrayListUnmanaged(Ast.Error) = .empty,
pub const CheckError = error{ pub const InnerError = error{
OutOfMemory, OutOfMemory,
SemanticError, SemanticError,
TooManyConstants, TooManyConstants,
@ -305,39 +305,39 @@ fn createScope(astgen: *AstGen, parent_scope: ?*Scope) !*Scope {
return child_scope; return child_scope;
} }
fn checkUnaryOp( fn unaryOp(
gen: *CodeGen, gen: *CodeGen,
scope: *Scope, scope: *Scope,
node: *const Ast.Node, node: *const Ast.Node,
op: Story.Opcode, op: Story.Opcode,
) CheckError!void { ) InnerError!void {
try checkExpr(gen, scope, node.data.bin.lhs); try expr(gen, scope, node.data.bin.lhs);
try gen.emitSimpleInst(op); try gen.emitSimpleInst(op);
} }
fn checkBinaryOp( fn binaryOp(
gen: *CodeGen, gen: *CodeGen,
scope: *Scope, scope: *Scope,
node: *const Ast.Node, node: *const Ast.Node,
op: Story.Opcode, op: Story.Opcode,
) CheckError!void { ) InnerError!void {
const data = node.data.bin; const data = node.data.bin;
assert(data.lhs != null and data.rhs != null); assert(data.lhs != null and data.rhs != null);
try checkExpr(gen, scope, data.lhs); try expr(gen, scope, data.lhs);
try checkExpr(gen, scope, data.rhs); try expr(gen, scope, data.rhs);
try gen.emitSimpleInst(op); try gen.emitSimpleInst(op);
} }
fn checkLogicalOp( fn logicalOp(
gen: *CodeGen, gen: *CodeGen,
scope: *Scope, scope: *Scope,
node: *const Ast.Node, node: *const Ast.Node,
op: Story.Opcode, op: Story.Opcode,
) CheckError!void { ) InnerError!void {
const data = node.data.bin; const data = node.data.bin;
assert(data.lhs != null and data.rhs != null); assert(data.lhs != null and data.rhs != null);
try checkExpr(gen, scope, data.lhs); try expr(gen, scope, data.lhs);
const else_label = try gen.makeLabel(); const else_label = try gen.makeLabel();
const fixup_offset = try gen.emitJumpInst(op); const fixup_offset = try gen.emitJumpInst(op);
@ -351,19 +351,19 @@ fn checkLogicalOp(
const rhs_label = try gen.makeLabel(); const rhs_label = try gen.makeLabel();
gen.setLabel(rhs_label); gen.setLabel(rhs_label);
try checkExpr(gen, scope, data.rhs); try expr(gen, scope, data.rhs);
gen.setLabel(else_label); gen.setLabel(else_label);
} }
fn checkTrueLiteral(gen: *CodeGen, _: *const Ast.Node) CheckError!void { fn trueLiteral(gen: *CodeGen, _: *const Ast.Node) InnerError!void {
try gen.emitSimpleInst(.true); try gen.emitSimpleInst(.true);
} }
fn checkFalseLiteral(gen: *CodeGen, _: *const Ast.Node) CheckError!void { fn falseLiteral(gen: *CodeGen, _: *const Ast.Node) InnerError!void {
try gen.emitSimpleInst(.false); try gen.emitSimpleInst(.false);
} }
fn checkNumberLiteral(gen: *CodeGen, node: *const Ast.Node) CheckError!void { fn numberLiteral(gen: *CodeGen, node: *const Ast.Node) InnerError!void {
const lexeme = sliceFromNode(gen.astgen, node); const lexeme = sliceFromNode(gen.astgen, node);
const number_value = try std.fmt.parseUnsigned(i64, lexeme, 10); const number_value = try std.fmt.parseUnsigned(i64, lexeme, 10);
const constant_id = try gen.makeConstant(.{ .number = number_value }); const constant_id = try gen.makeConstant(.{ .number = number_value });
@ -371,20 +371,20 @@ fn checkNumberLiteral(gen: *CodeGen, node: *const Ast.Node) CheckError!void {
try gen.emitConstInst(.load_const, constant_id); try gen.emitConstInst(.load_const, constant_id);
} }
fn checkStringLiteral(gen: *CodeGen, node: *const Ast.Node) CheckError!void { fn stringLiteral(gen: *CodeGen, node: *const Ast.Node) InnerError!void {
const string_ref = try gen.astgen.stringFromNode(node); const string_ref = try gen.astgen.stringFromNode(node);
const constant_id = try gen.makeConstant(.{ .string = string_ref }); const constant_id = try gen.makeConstant(.{ .string = string_ref });
try gen.emitConstInst(.load_const, constant_id); try gen.emitConstInst(.load_const, constant_id);
} }
fn checkStringExpr(gen: *CodeGen, node: *const Ast.Node) CheckError!void { fn stringExpr(gen: *CodeGen, node: *const Ast.Node) InnerError!void {
assert(node.data.bin.lhs != null); assert(node.data.bin.lhs != null);
const expr_node = node.data.bin.lhs orelse return; const expr_node = node.data.bin.lhs orelse return;
return checkStringLiteral(gen, expr_node); return stringLiteral(gen, expr_node);
} }
fn checkIdentifier(gen: *CodeGen, scope: *Scope, node: *const Ast.Node) CheckError!void { fn identifier(gen: *CodeGen, scope: *Scope, node: *const Ast.Node) InnerError!void {
const name_ref = try gen.astgen.stringFromNode(node); const name_ref = try gen.astgen.stringFromNode(node);
if (scope.lookup(name_ref)) |symbol| switch (symbol) { if (scope.lookup(name_ref)) |symbol| switch (symbol) {
@ -402,47 +402,47 @@ fn checkIdentifier(gen: *CodeGen, scope: *Scope, node: *const Ast.Node) CheckErr
return gen.fail(.unknown_identifier, node); return gen.fail(.unknown_identifier, node);
} }
fn checkExpr(gen: *CodeGen, scope: *Scope, expr: ?*const Ast.Node) CheckError!void { fn expr(gen: *CodeGen, scope: *Scope, optional_expr: ?*const Ast.Node) InnerError!void {
const expr_node = expr orelse return; const expr_node = optional_expr orelse return;
switch (expr_node.tag) { switch (expr_node.tag) {
.true_literal => try checkTrueLiteral(gen, expr_node), .true_literal => try trueLiteral(gen, expr_node),
.false_literal => try checkFalseLiteral(gen, expr_node), .false_literal => try falseLiteral(gen, expr_node),
.number_literal => try checkNumberLiteral(gen, expr_node), .number_literal => try numberLiteral(gen, expr_node),
.string_literal => try checkStringLiteral(gen, expr_node), .string_literal => try stringLiteral(gen, expr_node),
.string_expr => try checkStringExpr(gen, expr_node), .string_expr => try stringExpr(gen, expr_node),
.identifier => try checkIdentifier(gen, scope, expr_node), .identifier => try identifier(gen, scope, expr_node),
.add_expr => try checkBinaryOp(gen, scope, expr_node, .add), .add_expr => try binaryOp(gen, scope, expr_node, .add),
.subtract_expr => try checkBinaryOp(gen, scope, expr_node, .sub), .subtract_expr => try binaryOp(gen, scope, expr_node, .sub),
.multiply_expr => try checkBinaryOp(gen, scope, expr_node, .mul), .multiply_expr => try binaryOp(gen, scope, expr_node, .mul),
.divide_expr => try checkBinaryOp(gen, scope, expr_node, .div), .divide_expr => try binaryOp(gen, scope, expr_node, .div),
.mod_expr => try checkBinaryOp(gen, scope, expr_node, .mod), .mod_expr => try binaryOp(gen, scope, expr_node, .mod),
.negate_expr => try checkUnaryOp(gen, scope, expr_node, .neg), .negate_expr => try unaryOp(gen, scope, expr_node, .neg),
.logical_and_expr => try checkLogicalOp(gen, scope, expr_node, .jmp_f), .logical_and_expr => try logicalOp(gen, scope, expr_node, .jmp_f),
.logical_or_expr => try checkLogicalOp(gen, scope, expr_node, .jmp_t), .logical_or_expr => try logicalOp(gen, scope, expr_node, .jmp_t),
.logical_not_expr => try checkUnaryOp(gen, scope, expr_node, .not), .logical_not_expr => try unaryOp(gen, scope, expr_node, .not),
.logical_equality_expr => try checkBinaryOp(gen, scope, expr_node, .cmp_eq), .logical_equality_expr => try binaryOp(gen, scope, expr_node, .cmp_eq),
.logical_inequality_expr => { .logical_inequality_expr => {
try gen.emitSimpleInst(.not); try gen.emitSimpleInst(.not);
try checkBinaryOp(gen, scope, expr_node, .cmp_eq); try binaryOp(gen, scope, expr_node, .cmp_eq);
}, },
.logical_greater_expr => try checkBinaryOp(gen, scope, expr_node, .cmp_gt), .logical_greater_expr => try binaryOp(gen, scope, expr_node, .cmp_gt),
.logical_greater_or_equal_expr => try checkBinaryOp(gen, scope, expr_node, .cmp_gte), .logical_greater_or_equal_expr => try binaryOp(gen, scope, expr_node, .cmp_gte),
.logical_lesser_expr => try checkBinaryOp(gen, scope, expr_node, .cmp_lt), .logical_lesser_expr => try binaryOp(gen, scope, expr_node, .cmp_lt),
.logical_lesser_or_equal_expr => try checkBinaryOp(gen, scope, expr_node, .cmp_lte), .logical_lesser_or_equal_expr => try binaryOp(gen, scope, expr_node, .cmp_lte),
else => return error.NotImplemented, else => return error.NotImplemented,
} }
} }
fn checkExprStmt(gen: *CodeGen, scope: *Scope, stmt: *const Ast.Node) CheckError!void { fn exprStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) InnerError!void {
const expr_node = stmt.data.bin.lhs orelse return; const expr_node = stmt_node.data.bin.lhs orelse return;
try checkExpr(gen, scope, expr_node); try expr(gen, scope, expr_node);
try gen.emitSimpleInst(.pop); try gen.emitSimpleInst(.pop);
} }
fn validateSwitchProngs(gen: *CodeGen, stmt: *const Ast.Node) CheckError!void { fn validateSwitchProngs(gen: *CodeGen, stmt_node: *const Ast.Node) InnerError!void {
var stmt_has_block: bool = false; var stmt_has_block: bool = false;
var stmt_has_else: bool = false; var stmt_has_else: bool = false;
const case_list = stmt.data.switch_stmt.cases; const case_list = stmt_node.data.switch_stmt.cases;
const last_prong = case_list[case_list.len - 1]; const last_prong = case_list[case_list.len - 1];
for (case_list) |case_stmt| { for (case_list) |case_stmt| {
switch (case_stmt.tag) { switch (case_stmt.tag) {
@ -466,11 +466,11 @@ fn validateSwitchProngs(gen: *CodeGen, stmt: *const Ast.Node) CheckError!void {
} }
} }
fn checkIfStmt(gen: *CodeGen, parent_scope: *Scope, stmt: *const Ast.Node) CheckError!void { fn ifStmt(gen: *CodeGen, parent_scope: *Scope, stmt_node: *const Ast.Node) InnerError!void {
const case_list = stmt.data.switch_stmt.cases; const case_list = stmt_node.data.switch_stmt.cases;
const eval_expr = stmt.data.switch_stmt.condition_expr; const eval_expr = stmt_node.data.switch_stmt.condition_expr;
if (eval_expr) |expr_node| { if (eval_expr) |expr_node| {
try validateSwitchProngs(gen, stmt); try validateSwitchProngs(gen, stmt_node);
const first_prong = case_list[0]; const first_prong = case_list[0];
const last_prong = case_list[case_list.len - 1]; const last_prong = case_list[case_list.len - 1];
@ -482,7 +482,7 @@ fn checkIfStmt(gen: *CodeGen, parent_scope: *Scope, stmt: *const Ast.Node) Check
var child_scope = try gen.astgen.createScope(parent_scope); var child_scope = try gen.astgen.createScope(parent_scope);
defer child_scope.deinit(); defer child_scope.deinit();
try checkExpr(gen, child_scope, expr_node); try expr(gen, child_scope, expr_node);
const else_label = try gen.makeLabel(); const else_label = try gen.makeLabel();
const end_label = try gen.makeLabel(); const end_label = try gen.makeLabel();
@ -493,7 +493,7 @@ fn checkIfStmt(gen: *CodeGen, parent_scope: *Scope, stmt: *const Ast.Node) Check
.code_offset = then_br, .code_offset = then_br,
}); });
try gen.emitSimpleInst(.pop); try gen.emitSimpleInst(.pop);
try checkBlockStmt(gen, child_scope, then_stmt); try blockStmt(gen, child_scope, then_stmt);
const else_br = try gen.emitJumpInst(.jmp); const else_br = try gen.emitJumpInst(.jmp);
_ = try gen.makeFixup(.{ _ = try gen.makeFixup(.{
@ -506,19 +506,19 @@ fn checkIfStmt(gen: *CodeGen, parent_scope: *Scope, stmt: *const Ast.Node) Check
if (else_stmt) |else_node| { if (else_stmt) |else_node| {
const block_stmt = else_node.data.bin.rhs; const block_stmt = else_node.data.bin.rhs;
try checkBlockStmt(gen, child_scope, block_stmt); try blockStmt(gen, child_scope, block_stmt);
} }
gen.setLabel(end_label); gen.setLabel(end_label);
} else { } else {
return gen.fail(.expected_expression, stmt); return gen.fail(.expected_expression, stmt_node);
} }
} }
fn checkMultiIfStmt( fn multiIfStmt(
gen: *CodeGen, gen: *CodeGen,
parent_scope: *Scope, parent_scope: *Scope,
stmt_node: *const Ast.Node, stmt_node: *const Ast.Node,
) CheckError!void { ) InnerError!void {
const gpa = gen.astgen.gpa; const gpa = gen.astgen.gpa;
try validateSwitchProngs(gen, stmt_node); try validateSwitchProngs(gen, stmt_node);
const case_list = stmt_node.data.switch_stmt.cases; const case_list = stmt_node.data.switch_stmt.cases;
@ -539,7 +539,7 @@ fn checkMultiIfStmt(
switch (case_stmt.tag) { switch (case_stmt.tag) {
.if_branch => { .if_branch => {
const lhs = case_stmt.data.bin.lhs orelse unreachable; const lhs = case_stmt.data.bin.lhs orelse unreachable;
try checkExpr(gen, child_scope, lhs); try expr(gen, child_scope, lhs);
const fixup_offset = try gen.emitJumpInst(.jmp_t); const fixup_offset = try gen.emitJumpInst(.jmp_t);
_ = try gen.makeFixup(.{ _ = try gen.makeFixup(.{
@ -572,7 +572,7 @@ fn checkMultiIfStmt(
}, },
else => unreachable, else => unreachable,
} }
try checkBlockStmt(gen, child_scope, body_stmt); try blockStmt(gen, child_scope, body_stmt);
const fixup_inst = try gen.emitJumpInst(.jmp); const fixup_inst = try gen.emitJumpInst(.jmp);
_ = try gen.makeFixup(.{ _ = try gen.makeFixup(.{
@ -585,11 +585,11 @@ fn checkMultiIfStmt(
gen.setLabel(gen.exit_label); gen.setLabel(gen.exit_label);
} }
fn checkSwitchStmt( fn switchStmt(
gen: *CodeGen, gen: *CodeGen,
parent_scope: *Scope, parent_scope: *Scope,
stmt_node: *const Ast.Node, stmt_node: *const Ast.Node,
) CheckError!void { ) InnerError!void {
const gpa = gen.astgen.gpa; const gpa = gen.astgen.gpa;
var child_scope = try gen.astgen.createScope(parent_scope); var child_scope = try gen.astgen.createScope(parent_scope);
defer child_scope.deinit(); defer child_scope.deinit();
@ -607,7 +607,7 @@ fn checkSwitchStmt(
try label_list.ensureUnusedCapacity(gpa, case_list.len); try label_list.ensureUnusedCapacity(gpa, case_list.len);
const stack_slot = try gen.makeStackSlot(); const stack_slot = try gen.makeStackSlot();
try checkExpr(gen, child_scope, eval_expr); try expr(gen, child_scope, eval_expr);
try gen.emitConstInst(.store, stack_slot); try gen.emitConstInst(.store, stack_slot);
try gen.emitSimpleInst(.pop); try gen.emitSimpleInst(.pop);
@ -624,7 +624,7 @@ fn checkSwitchStmt(
} }
try gen.emitConstInst(.load, stack_slot); try gen.emitConstInst(.load, stack_slot);
try checkExpr(gen, child_scope, case_eval_expr); try expr(gen, child_scope, case_eval_expr);
try gen.emitSimpleInst(.cmp_eq); try gen.emitSimpleInst(.cmp_eq);
const fixup_offset = try gen.emitJumpInst(.jmp_t); const fixup_offset = try gen.emitJumpInst(.jmp_t);
@ -658,7 +658,7 @@ fn checkSwitchStmt(
} }
const block_stmt = case_stmt.data.bin.rhs; const block_stmt = case_stmt.data.bin.rhs;
try checkBlockStmt(gen, child_scope, block_stmt); try blockStmt(gen, child_scope, block_stmt);
const fixup_offset = try gen.emitJumpInst(.jmp); const fixup_offset = try gen.emitJumpInst(.jmp);
_ = try gen.makeFixup(.{ _ = try gen.makeFixup(.{
.mode = .relative, .mode = .relative,
@ -670,47 +670,47 @@ fn checkSwitchStmt(
gen.setLabel(gen.exit_label); gen.setLabel(gen.exit_label);
} }
fn checkInlineLogicExpr( fn inlineLogicExpr(
gen: *CodeGen, gen: *CodeGen,
scope: *Scope, scope: *Scope,
expr_node: *const Ast.Node, expr_node: *const Ast.Node,
) CheckError!void { ) InnerError!void {
const main_node = expr_node.data.bin.lhs; const main_node = expr_node.data.bin.lhs;
assert(main_node != null); assert(main_node != null);
return checkExpr(gen, scope, main_node); return expr(gen, scope, main_node);
} }
fn checkContentExpr( fn contentExpr(
gen: *CodeGen, gen: *CodeGen,
scope: *Scope, scope: *Scope,
expr_node: *const Ast.Node, expr_node: *const Ast.Node,
) CheckError!void { ) InnerError!void {
const node_list = expr_node.data.list.items orelse return; const node_list = expr_node.data.list.items orelse return;
for (node_list) |child_node| { for (node_list) |child_node| {
switch (child_node.tag) { switch (child_node.tag) {
.string_literal => { .string_literal => {
try checkStringLiteral(gen, child_node); try stringLiteral(gen, child_node);
try gen.emitSimpleInst(.stream_push); try gen.emitSimpleInst(.stream_push);
}, },
.inline_logic_expr => { .inline_logic_expr => {
try checkInlineLogicExpr(gen, scope, child_node); try inlineLogicExpr(gen, scope, child_node);
try gen.emitSimpleInst(.stream_push); try gen.emitSimpleInst(.stream_push);
}, },
.if_stmt => try checkIfStmt(gen, scope, child_node), .if_stmt => try ifStmt(gen, scope, child_node),
.multi_if_stmt => try checkMultiIfStmt(gen, scope, child_node), .multi_if_stmt => try multiIfStmt(gen, scope, child_node),
.switch_stmt => try checkSwitchStmt(gen, scope, child_node), .switch_stmt => try switchStmt(gen, scope, child_node),
else => return error.NotImplemented, else => return error.NotImplemented,
} }
} }
} }
fn checkContentStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) CheckError!void { fn contentStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) InnerError!void {
const expr_node = stmt_node.data.bin.lhs orelse return; const expr_node = stmt_node.data.bin.lhs orelse return;
try checkContentExpr(gen, scope, expr_node); try contentExpr(gen, scope, expr_node);
try gen.emitSimpleInst(.stream_flush); try gen.emitSimpleInst(.stream_flush);
} }
fn checkAssignStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) CheckError!void { fn assignStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) InnerError!void {
const identifier_node = stmt_node.data.bin.lhs orelse unreachable; const identifier_node = stmt_node.data.bin.lhs orelse unreachable;
const expr_node = stmt_node.data.bin.rhs orelse unreachable; const expr_node = stmt_node.data.bin.rhs orelse unreachable;
const name_ref = try gen.astgen.stringFromNode(identifier_node); const name_ref = try gen.astgen.stringFromNode(identifier_node);
@ -720,13 +720,13 @@ fn checkAssignStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) Che
if (data.is_constant) { if (data.is_constant) {
return gen.fail(.assignment_to_const, identifier_node); return gen.fail(.assignment_to_const, identifier_node);
} }
try checkExpr(gen, scope, expr_node); try expr(gen, scope, expr_node);
try gen.emitConstInst(.store_global, data.constant_slot); try gen.emitConstInst(.store_global, data.constant_slot);
try gen.emitSimpleInst(.pop); try gen.emitSimpleInst(.pop);
return; return;
}, },
.local => |data| { .local => |data| {
try checkExpr(gen, scope, expr_node); try expr(gen, scope, expr_node);
try gen.emitConstInst(.store, data.stack_slot); try gen.emitConstInst(.store, data.stack_slot);
try gen.emitSimpleInst(.pop); try gen.emitSimpleInst(.pop);
return; return;
@ -736,7 +736,7 @@ fn checkAssignStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) Che
return gen.fail(.unknown_identifier, identifier_node); return gen.fail(.unknown_identifier, identifier_node);
} }
fn checkChoiceStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) CheckError!void { fn choiceStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) InnerError!void {
const Choice = struct { const Choice = struct {
label_index: usize, label_index: usize,
start_expression: ?*const Ast.Node, start_expression: ?*const Ast.Node,
@ -761,11 +761,11 @@ fn checkChoiceStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) Che
const label_index = try gen.makeLabel(); const label_index = try gen.makeLabel();
if (branch_expr_data.start_expr) |node| { if (branch_expr_data.start_expr) |node| {
try checkStringLiteral(gen, node); try stringLiteral(gen, node);
try gen.emitSimpleInst(.stream_push); try gen.emitSimpleInst(.stream_push);
} }
if (branch_expr_data.option_expr) |node| { if (branch_expr_data.option_expr) |node| {
try checkStringLiteral(gen, node); try stringLiteral(gen, node);
try gen.emitSimpleInst(.stream_push); try gen.emitSimpleInst(.stream_push);
} }
@ -793,24 +793,24 @@ fn checkChoiceStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) Che
gen.setLabel(choice.label_index); gen.setLabel(choice.label_index);
if (choice.start_expression) |expr_node| { if (choice.start_expression) |expr_node| {
try checkStringLiteral(gen, expr_node); try stringLiteral(gen, expr_node);
try gen.emitSimpleInst(.stream_push); try gen.emitSimpleInst(.stream_push);
} }
if (choice.inner_expression) |expr_node| { if (choice.inner_expression) |expr_node| {
try checkStringLiteral(gen, expr_node); try stringLiteral(gen, expr_node);
try gen.emitSimpleInst(.stream_push); try gen.emitSimpleInst(.stream_push);
} }
try gen.emitSimpleInst(.stream_flush); try gen.emitSimpleInst(.stream_flush);
if (choice.block_stmt) |block| { if (choice.block_stmt) |block| {
try checkBlockStmt(gen, scope, block); try blockStmt(gen, scope, block);
} else { } else {
try gen.emitSimpleInst(.exit); try gen.emitSimpleInst(.exit);
} }
} }
} }
fn checkVarDecl(gen: *CodeGen, scope: *Scope, decl_node: *const Ast.Node) !void { fn varDecl(gen: *CodeGen, scope: *Scope, decl_node: *const Ast.Node) !void {
const identifier_node = decl_node.data.bin.lhs orelse unreachable; const identifier_node = decl_node.data.bin.lhs orelse unreachable;
const expr_node = decl_node.data.bin.rhs orelse unreachable; const expr_node = decl_node.data.bin.rhs orelse unreachable;
const name_ref = try gen.astgen.stringFromNode(identifier_node); const name_ref = try gen.astgen.stringFromNode(identifier_node);
@ -840,7 +840,7 @@ fn checkVarDecl(gen: *CodeGen, scope: *Scope, decl_node: *const Ast.Node) !void
}; };
try scope.insert(name_ref, decl_symbol); try scope.insert(name_ref, decl_symbol);
try checkExpr(gen, scope, expr_node); try expr(gen, scope, expr_node);
switch (decl_symbol) { switch (decl_symbol) {
.local => |data| { .local => |data| {
@ -854,28 +854,28 @@ fn checkVarDecl(gen: *CodeGen, scope: *Scope, decl_node: *const Ast.Node) !void
try gen.emitSimpleInst(.pop); try gen.emitSimpleInst(.pop);
} }
fn checkStmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) CheckError!void { fn stmt(gen: *CodeGen, scope: *Scope, stmt_node: *const Ast.Node) InnerError!void {
switch (stmt_node.tag) { switch (stmt_node.tag) {
.var_decl => try checkVarDecl(gen, scope, stmt_node), .var_decl => try varDecl(gen, scope, stmt_node),
.const_decl => try checkVarDecl(gen, scope, stmt_node), .const_decl => try varDecl(gen, scope, stmt_node),
.temp_decl => try checkVarDecl(gen, scope, stmt_node), .temp_decl => try varDecl(gen, scope, stmt_node),
.assign_stmt => try checkAssignStmt(gen, scope, stmt_node), .assign_stmt => try assignStmt(gen, scope, stmt_node),
.content_stmt => try checkContentStmt(gen, scope, stmt_node), .content_stmt => try contentStmt(gen, scope, stmt_node),
.choice_stmt => try checkChoiceStmt(gen, scope, stmt_node), .choice_stmt => try choiceStmt(gen, scope, stmt_node),
.expr_stmt => try checkExprStmt(gen, scope, stmt_node), .expr_stmt => try exprStmt(gen, scope, stmt_node),
else => return error.NotImplemented, else => return error.NotImplemented,
} }
} }
fn checkBlockStmt( fn blockStmt(
gen: *CodeGen, gen: *CodeGen,
parent_scope: *Scope, parent_scope: *Scope,
block_stmt: ?*const Ast.Node, block_stmt: ?*const Ast.Node,
) CheckError!void { ) InnerError!void {
if (block_stmt) |stmt| { if (block_stmt) |stmt_node| {
const block_scope = try gen.astgen.createScope(parent_scope); const block_scope = try gen.astgen.createScope(parent_scope);
const children = stmt.data.list.items orelse return; const children = stmt_node.data.list.items orelse return;
for (children) |child_stmt| try checkStmt(gen, block_scope, child_stmt); for (children) |child_stmt| try stmt(gen, block_scope, child_stmt);
} else { } else {
const fixup_offset = try gen.emitJumpInst(.jmp); const fixup_offset = try gen.emitJumpInst(.jmp);
_ = try gen.makeFixup(.{ _ = try gen.makeFixup(.{
@ -886,11 +886,11 @@ fn checkBlockStmt(
} }
} }
fn checkDefaultBlock( fn defaultBlock(
gen: *CodeGen, gen: *CodeGen,
parent_scope: *Scope, parent_scope: *Scope,
body_node: *const Ast.Node, body_node: *const Ast.Node,
) CheckError!void { ) InnerError!void {
const name_ref = try gen.astgen.stringFromBytes("$__main__$"); const name_ref = try gen.astgen.stringFromBytes("$__main__$");
const exit_label = try gen.makeLabel(); const exit_label = try gen.makeLabel();
defer gen.setExit(exit_label); defer gen.setExit(exit_label);
@ -898,17 +898,17 @@ fn checkDefaultBlock(
gen.chunk_name_ref = name_ref; gen.chunk_name_ref = name_ref;
const block_scope = try gen.astgen.createScope(parent_scope); const block_scope = try gen.astgen.createScope(parent_scope);
try checkBlockStmt(gen, block_scope, body_node); try blockStmt(gen, block_scope, body_node);
gen.setLabel(exit_label); gen.setLabel(exit_label);
try gen.emitSimpleInst(.exit); try gen.emitSimpleInst(.exit);
try gen.finalize(); try gen.finalize();
} }
fn checkStitchDecl(_: *CodeGen, _: *Scope, _: *const Ast.Node) CheckError!void {} fn stitchDecl(_: *CodeGen, _: *Scope, _: *const Ast.Node) InnerError!void {}
fn checkFunctionDecl(_: *CodeGen, _: *Scope, _: *const Ast.Node) CheckError!void {} fn functionDecl(_: *CodeGen, _: *Scope, _: *const Ast.Node) InnerError!void {}
fn checkKnotDecl(gen: *CodeGen, scope: *Scope, decl_node: *const Ast.Node) CheckError!void { fn knotDecl(gen: *CodeGen, scope: *Scope, decl_node: *const Ast.Node) InnerError!void {
const prototype_node = decl_node.data.knot_decl.prototype; const prototype_node = decl_node.data.knot_decl.prototype;
const nested_decls_list = decl_node.data.knot_decl.children orelse return; const nested_decls_list = decl_node.data.knot_decl.children orelse return;
const identifier_node = prototype_node.data.bin.lhs orelse unreachable; const identifier_node = prototype_node.data.bin.lhs orelse unreachable;
@ -922,19 +922,19 @@ fn checkKnotDecl(gen: *CodeGen, scope: *Scope, decl_node: *const Ast.Node) Check
var start_index: usize = 0; var start_index: usize = 0;
const first_child = nested_decls_list[0]; const first_child = nested_decls_list[0];
if (first_child.tag == .block_stmt) { if (first_child.tag == .block_stmt) {
try checkBlockStmt(&block_gen, knot_scope, first_child); try blockStmt(&block_gen, knot_scope, first_child);
if (nested_decls_list.len > 1) start_index += 1 else return; if (nested_decls_list.len > 1) start_index += 1 else return;
} }
for (nested_decls_list[start_index..]) |nested_decl_node| { for (nested_decls_list[start_index..]) |nested_decl_node| {
switch (decl_node.tag) { switch (decl_node.tag) {
.stitch_decl => try checkStitchDecl(gen, knot_scope, nested_decl_node), .stitch_decl => try stitchDecl(gen, knot_scope, nested_decl_node),
.function_decl => try checkFunctionDecl(gen, knot_scope, nested_decl_node), .function_decl => try functionDecl(gen, knot_scope, nested_decl_node),
else => unreachable, else => unreachable,
} }
} }
} }
fn checkFile(astgen: *AstGen, scope: *Scope, file_node: *const Ast.Node) CheckError!void { fn file(astgen: *AstGen, scope: *Scope, file_node: *const Ast.Node) InnerError!void {
const nested_decls_list = file_node.data.list.items orelse return; const nested_decls_list = file_node.data.list.items orelse return;
if (nested_decls_list.len == 0) return; if (nested_decls_list.len == 0) return;
@ -954,20 +954,20 @@ fn checkFile(astgen: *AstGen, scope: *Scope, file_node: *const Ast.Node) CheckEr
var start_index: usize = 0; var start_index: usize = 0;
const first_child = nested_decls_list[0]; const first_child = nested_decls_list[0];
if (first_child.tag == .block_stmt) { if (first_child.tag == .block_stmt) {
try checkDefaultBlock(&gen, scope, first_child); try defaultBlock(&gen, scope, first_child);
if (nested_decls_list.len > 1) start_index += 1 else return; if (nested_decls_list.len > 1) start_index += 1 else return;
} }
for (nested_decls_list[start_index..]) |child_node| { for (nested_decls_list[start_index..]) |child_node| {
switch (child_node.tag) { switch (child_node.tag) {
.knot_decl => try checkKnotDecl(&gen, scope, child_node), .knot_decl => try knotDecl(&gen, scope, child_node),
.stitch_decl => try checkStitchDecl(&gen, scope, child_node), .stitch_decl => try stitchDecl(&gen, scope, child_node),
.function_decl => try checkFunctionDecl(&gen, scope, child_node), .function_decl => try functionDecl(&gen, scope, child_node),
else => unreachable, else => unreachable,
} }
} }
} }
fn insertDecl(astgen: *AstGen, parent_scope: *Scope, proto_node: *const Ast.Node) CheckError!void { fn insertDecl(astgen: *AstGen, parent_scope: *Scope, proto_node: *const Ast.Node) InnerError!void {
const identifier_node = proto_node.data.bin.lhs orelse unreachable; const identifier_node = proto_node.data.bin.lhs orelse unreachable;
const name_ref = try astgen.stringFromNode(identifier_node); const name_ref = try astgen.stringFromNode(identifier_node);
@ -1031,7 +1031,7 @@ fn collectRootDecls(
astgen: *AstGen, astgen: *AstGen,
parent_scope: *Scope, parent_scope: *Scope,
root_node: *const Ast.Node, root_node: *const Ast.Node,
) CheckError!void { ) InnerError!void {
const root_decl_list = root_node.data.list.items orelse return; const root_decl_list = root_node.data.list.items orelse return;
for (root_decl_list) |root_decl_node| switch (root_decl_node.tag) { for (root_decl_list) |root_decl_node| switch (root_decl_node.tag) {
.knot_decl => { .knot_decl => {
@ -1080,7 +1080,7 @@ pub fn generate(gpa: std.mem.Allocator, tree: *const Ast) !CodeUnit {
const root_node = tree.root orelse unreachable; const root_node = tree.root orelse unreachable;
try collectRootDecls(&astgen, file_scope, root_node); try collectRootDecls(&astgen, file_scope, root_node);
try checkFile(&astgen, file_scope, root_node); try file(&astgen, file_scope, root_node);
return .{ return .{
.string_bytes = try astgen.string_bytes.toOwnedSlice(gpa), .string_bytes = try astgen.string_bytes.toOwnedSlice(gpa),