chore: rename AstGen methods, removed 'check' prefix
This commit is contained in:
parent
95d89b7bf9
commit
98f5215629
1 changed files with 117 additions and 117 deletions
234
src/AstGen.zig
234
src/AstGen.zig
|
|
@ -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),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue