feat: added Ir.Inst.Ref, global constant pool, lazy lowering in Sema
This commit is contained in:
parent
ce5385ebac
commit
e5e2b7c559
6 changed files with 615 additions and 534 deletions
281
src/AstGen.zig
281
src/AstGen.zig
|
|
@ -105,7 +105,8 @@ const GenIr = struct {
|
|||
) []Ir.Inst.Index {
|
||||
return if (self.instructions_top == unstacked_top)
|
||||
&[0]Ir.Inst.Index{}
|
||||
else if (self.instructions == stacked_block.instructions and stacked_block.instructions_top != unstacked_top)
|
||||
else if (self.instructions == stacked_block.instructions and
|
||||
stacked_block.instructions_top != unstacked_top)
|
||||
self.instructions.items[self.instructions_top..stacked_block.instructions_top]
|
||||
else
|
||||
self.instructions.items[self.instructions_top..];
|
||||
|
|
@ -127,24 +128,28 @@ const GenIr = struct {
|
|||
};
|
||||
}
|
||||
|
||||
fn add(gi: *GenIr, inst: Ir.Inst) !Ir.Inst.Index {
|
||||
fn add(gi: *GenIr, inst: Ir.Inst) !Ir.Inst.Ref {
|
||||
return (try gi.addAsIndex(inst)).toRef();
|
||||
}
|
||||
|
||||
fn addAsIndex(gi: *GenIr, inst: Ir.Inst) !Ir.Inst.Index {
|
||||
const gpa = gi.astgen.gpa;
|
||||
try gi.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
try gi.astgen.instructions.ensureUnusedCapacity(gpa, 1);
|
||||
|
||||
const inst_index: Ir.Inst.Index = @enumFromInt(gi.astgen.instructions.items.len);
|
||||
const new_index: Ir.Inst.Index = @enumFromInt(gi.astgen.instructions.items.len);
|
||||
gi.astgen.instructions.appendAssumeCapacity(inst);
|
||||
gi.instructions.appendAssumeCapacity(inst_index);
|
||||
return inst_index;
|
||||
gi.instructions.appendAssumeCapacity(new_index);
|
||||
return new_index;
|
||||
}
|
||||
|
||||
fn addInt(gi: *GenIr, value: u64) !Ir.Inst.Index {
|
||||
fn addInt(gi: *GenIr, value: u64) !Ir.Inst.Ref {
|
||||
return add(gi, .{ .tag = .integer, .data = .{
|
||||
.integer = .{ .value = value },
|
||||
} });
|
||||
}
|
||||
|
||||
fn addUnaryNode(gi: *GenIr, tag: Ir.Inst.Tag, arg: Ir.Inst.Index) !Ir.Inst.Index {
|
||||
fn addUnaryNode(gi: *GenIr, tag: Ir.Inst.Tag, arg: Ir.Inst.Ref) !Ir.Inst.Ref {
|
||||
return add(gi, .{ .tag = tag, .data = .{
|
||||
.un = .{ .lhs = arg },
|
||||
} });
|
||||
|
|
@ -153,15 +158,15 @@ const GenIr = struct {
|
|||
fn addBinaryNode(
|
||||
gi: *GenIr,
|
||||
tag: Ir.Inst.Tag,
|
||||
lhs: Ir.Inst.Index,
|
||||
rhs: Ir.Inst.Index,
|
||||
) !Ir.Inst.Index {
|
||||
lhs: Ir.Inst.Ref,
|
||||
rhs: Ir.Inst.Ref,
|
||||
) !Ir.Inst.Ref {
|
||||
return add(gi, .{ .tag = tag, .data = .{
|
||||
.bin = .{ .lhs = lhs, .rhs = rhs },
|
||||
} });
|
||||
}
|
||||
|
||||
fn addDeclRef(gi: *GenIr, decl_ref: Ir.NullTerminatedString) !Ir.Inst.Index {
|
||||
fn addDeclRef(gi: *GenIr, decl_ref: Ir.NullTerminatedString) !Ir.Inst.Ref {
|
||||
return add(gi, .{ .tag = .decl_ref, .data = .{
|
||||
.string = .{
|
||||
.start = decl_ref,
|
||||
|
|
@ -185,8 +190,16 @@ const GenIr = struct {
|
|||
return makePayloadNode(gi, .declaration);
|
||||
}
|
||||
|
||||
fn makeBlockInst(gi: *GenIr) !Ir.Inst.Index {
|
||||
return makePayloadNode(gi, .block);
|
||||
fn makeBlockInst(gi: *GenIr, tag: Ir.Inst.Tag) !Ir.Inst.Index {
|
||||
const inst_index: Ir.Inst.Index = @enumFromInt(gi.astgen.instructions.items.len);
|
||||
const gpa = gi.astgen.gpa;
|
||||
try gi.astgen.instructions.append(gpa, .{
|
||||
.tag = tag,
|
||||
.data = .{
|
||||
.payload = .{ .payload_index = undefined },
|
||||
},
|
||||
});
|
||||
return inst_index;
|
||||
}
|
||||
|
||||
fn addKnot(self: *GenIr) !Ir.Inst.Index {
|
||||
|
|
@ -331,7 +344,7 @@ fn setDeclaration(
|
|||
|
||||
fn setCondBrPayload(
|
||||
condbr: Ir.Inst.Index,
|
||||
cond: Ir.Inst.Index,
|
||||
cond: Ir.Inst.Ref,
|
||||
then_block: *GenIr,
|
||||
else_block: *GenIr,
|
||||
) !void {
|
||||
|
|
@ -374,6 +387,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
|
|||
astgen.extra.items[i] = switch (field.type) {
|
||||
u32 => @field(extra, field.name),
|
||||
Ir.Inst.Index => @intFromEnum(@field(extra, field.name)),
|
||||
Ir.Inst.Ref => @intFromEnum(@field(extra, field.name)),
|
||||
Ir.NullTerminatedString => @intFromEnum(@field(extra, field.name)),
|
||||
else => @compileError("bad field type"),
|
||||
};
|
||||
|
|
@ -444,9 +458,9 @@ fn unaryOp(
|
|||
scope: *Scope,
|
||||
expr_node: *const Ast.Node,
|
||||
op: Ir.Inst.Tag,
|
||||
) InnerError!Ir.Inst.Index {
|
||||
assert(expr_node.data.bin.lhs != null);
|
||||
const lhs = try expr(gi, scope, expr_node.data.bin.lhs orelse unreachable);
|
||||
) InnerError!Ir.Inst.Ref {
|
||||
const data = expr_node.data.bin;
|
||||
const lhs = try expr(gi, scope, data.lhs.?);
|
||||
return gi.addUnaryNode(op, lhs);
|
||||
}
|
||||
|
||||
|
|
@ -455,12 +469,11 @@ fn binaryOp(
|
|||
scope: *Scope,
|
||||
expr_node: *const Ast.Node,
|
||||
op: Ir.Inst.Tag,
|
||||
) InnerError!Ir.Inst.Index {
|
||||
) InnerError!Ir.Inst.Ref {
|
||||
const data = expr_node.data.bin;
|
||||
assert(data.lhs != null and data.rhs != null);
|
||||
|
||||
const lhs = try expr(gi, scope, data.lhs orelse unreachable);
|
||||
const rhs = try expr(gi, scope, data.rhs orelse unreachable);
|
||||
const lhs = try expr(gi, scope, data.lhs.?);
|
||||
const rhs = try expr(gi, scope, data.rhs.?);
|
||||
return gi.addBinaryNode(op, lhs, rhs);
|
||||
}
|
||||
|
||||
|
|
@ -490,23 +503,14 @@ fn logicalOp(
|
|||
gen.setLabel(else_label);
|
||||
}
|
||||
|
||||
fn trueLiteral(gi: *GenIr) InnerError!Ir.Inst.Index {
|
||||
return gi.add(.{ .tag = .true_literal, .data = undefined });
|
||||
}
|
||||
|
||||
fn falseLiteral(gi: *GenIr) InnerError!Ir.Inst.Index {
|
||||
return gi.add(.{ .tag = .false_literal, .data = undefined });
|
||||
}
|
||||
|
||||
fn numberLiteral(gen: *GenIr, node: *const Ast.Node) InnerError!Ir.Inst.Index {
|
||||
fn numberLiteral(gen: *GenIr, node: *const Ast.Node) InnerError!Ir.Inst.Ref {
|
||||
const lexeme = sliceFromNode(gen.astgen, node);
|
||||
const int_value = try std.fmt.parseUnsigned(u64, lexeme, 10);
|
||||
return gen.addInt(int_value);
|
||||
}
|
||||
|
||||
fn stringLiteral(gi: *GenIr, node: *const Ast.Node) InnerError!Ir.Inst.Index {
|
||||
const astgen = gi.astgen;
|
||||
const str = try astgen.stringFromNode(node);
|
||||
fn stringLiteral(gi: *GenIr, node: *const Ast.Node) InnerError!Ir.Inst.Ref {
|
||||
const str = try gi.astgen.stringFromNode(node);
|
||||
return gi.add(.{
|
||||
.tag = .string,
|
||||
.data = .{ .string = .{
|
||||
|
|
@ -515,47 +519,46 @@ fn stringLiteral(gi: *GenIr, node: *const Ast.Node) InnerError!Ir.Inst.Index {
|
|||
});
|
||||
}
|
||||
|
||||
fn stringExpr(gen: *GenIr, expr_node: *const Ast.Node) InnerError!Ir.Inst.Index {
|
||||
assert(expr_node.data.bin.lhs != null);
|
||||
const first_node = expr_node.data.bin.lhs orelse unreachable;
|
||||
fn stringExpr(gen: *GenIr, expr_node: *const Ast.Node) InnerError!Ir.Inst.Ref {
|
||||
const first_node = expr_node.data.bin.lhs.?;
|
||||
return stringLiteral(gen, first_node);
|
||||
}
|
||||
|
||||
fn identifier(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.Inst.Index {
|
||||
fn identifier(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.Inst.Ref {
|
||||
const astgen = gi.astgen;
|
||||
const str = try astgen.stringFromNode(node);
|
||||
if (scope.lookup(str)) |decl| {
|
||||
return gi.addUnaryNode(.load_local, decl.inst_index);
|
||||
return gi.addUnaryNode(.load, decl.inst_index.toRef());
|
||||
}
|
||||
return gi.addDeclRef(str);
|
||||
}
|
||||
|
||||
fn expr(block: *GenIr, scope: *Scope, optional_expr: ?*const Ast.Node) InnerError!Ir.Inst.Index {
|
||||
const expr_node = optional_expr orelse unreachable;
|
||||
fn expr(gi: *GenIr, scope: *Scope, optional_expr: ?*const Ast.Node) InnerError!Ir.Inst.Ref {
|
||||
const expr_node = optional_expr.?;
|
||||
switch (expr_node.tag) {
|
||||
.file => unreachable,
|
||||
.true_literal => return trueLiteral(block),
|
||||
.false_literal => return falseLiteral(block),
|
||||
.number_literal => return numberLiteral(block, expr_node),
|
||||
.string_literal => return stringLiteral(block, expr_node),
|
||||
.string_expr => return stringExpr(block, expr_node),
|
||||
.empty_string => return stringLiteral(block, expr_node),
|
||||
.identifier => return identifier(block, scope, expr_node),
|
||||
.add_expr => return binaryOp(block, scope, expr_node, .add),
|
||||
.subtract_expr => return binaryOp(block, scope, expr_node, .sub),
|
||||
.multiply_expr => return binaryOp(block, scope, expr_node, .mul),
|
||||
.divide_expr => return binaryOp(block, scope, expr_node, .div),
|
||||
.mod_expr => return binaryOp(block, scope, expr_node, .mod),
|
||||
.negate_expr => return unaryOp(block, scope, expr_node, .neg),
|
||||
.true_literal => return .bool_true,
|
||||
.false_literal => return .bool_false,
|
||||
.number_literal => return numberLiteral(gi, expr_node),
|
||||
.string_literal => return stringLiteral(gi, expr_node),
|
||||
.string_expr => return stringExpr(gi, expr_node),
|
||||
.empty_string => return stringLiteral(gi, expr_node),
|
||||
.identifier => return identifier(gi, scope, expr_node),
|
||||
.add_expr => return binaryOp(gi, scope, expr_node, .add),
|
||||
.subtract_expr => return binaryOp(gi, scope, expr_node, .sub),
|
||||
.multiply_expr => return binaryOp(gi, scope, expr_node, .mul),
|
||||
.divide_expr => return binaryOp(gi, scope, expr_node, .div),
|
||||
.mod_expr => return binaryOp(gi, scope, expr_node, .mod),
|
||||
.negate_expr => return unaryOp(gi, scope, expr_node, .neg),
|
||||
.logical_and_expr => unreachable,
|
||||
.logical_or_expr => unreachable,
|
||||
.logical_not_expr => return unaryOp(block, scope, expr_node, .not),
|
||||
.logical_equality_expr => return binaryOp(block, scope, expr_node, .cmp_eq),
|
||||
.logical_inequality_expr => return binaryOp(block, scope, expr_node, .cmp_neq),
|
||||
.logical_greater_expr => return binaryOp(block, scope, expr_node, .cmp_gt),
|
||||
.logical_greater_or_equal_expr => return binaryOp(block, scope, expr_node, .cmp_gte),
|
||||
.logical_lesser_expr => return binaryOp(block, scope, expr_node, .cmp_lt),
|
||||
.logical_lesser_or_equal_expr => return binaryOp(block, scope, expr_node, .cmp_lte),
|
||||
.logical_not_expr => return unaryOp(gi, scope, expr_node, .not),
|
||||
.logical_equality_expr => return binaryOp(gi, scope, expr_node, .cmp_eq),
|
||||
.logical_inequality_expr => return binaryOp(gi, scope, expr_node, .cmp_neq),
|
||||
.logical_greater_expr => return binaryOp(gi, scope, expr_node, .cmp_gt),
|
||||
.logical_greater_or_equal_expr => return binaryOp(gi, scope, expr_node, .cmp_gte),
|
||||
.logical_lesser_expr => return binaryOp(gi, scope, expr_node, .cmp_lt),
|
||||
.logical_lesser_or_equal_expr => return binaryOp(gi, scope, expr_node, .cmp_lte),
|
||||
.call_expr => unreachable,
|
||||
.choice_expr => unreachable,
|
||||
.choice_start_expr => unreachable,
|
||||
|
|
@ -588,22 +591,28 @@ fn expr(block: *GenIr, scope: *Scope, optional_expr: ?*const Ast.Node) InnerErro
|
|||
.ref_parameter_decl => unreachable,
|
||||
.argument_list => unreachable,
|
||||
.parameter_list => unreachable,
|
||||
.switch_stmt => unreachable,
|
||||
.switch_case => unreachable,
|
||||
.if_stmt => unreachable,
|
||||
.multi_if_stmt => unreachable,
|
||||
.if_branch => unreachable,
|
||||
.else_branch => unreachable,
|
||||
.switch_stmt => unreachable, // Handled in switchStmt
|
||||
.switch_case => unreachable, // Handled in switchStmt
|
||||
.if_stmt => unreachable, // Handled in ifStmt
|
||||
.multi_if_stmt => unreachable, // Handled in multiIfStmt
|
||||
.if_branch => unreachable, // Handled in ifStmt and multiIfStmt
|
||||
.else_branch => unreachable, // Handled in switchStmt, multiIfStmt, and ifStmt
|
||||
.content => unreachable,
|
||||
.inline_logic_expr => unreachable,
|
||||
.invalid => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
fn exprStmt(gen: *GenIr, scope: *Scope, stmt_node: *const Ast.Node) InnerError!Ir.Inst.Index {
|
||||
fn exprStmt(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.Inst.Ref {
|
||||
// TODO: Maybe we should introduce a unary node type to avoid optional checks?
|
||||
const expr_node = stmt_node.data.bin.lhs.?;
|
||||
return expr(gen, scope, expr_node);
|
||||
const expr_node = node.data.bin.lhs.?;
|
||||
return expr(gi, scope, expr_node);
|
||||
}
|
||||
|
||||
fn inlineLogicExpr(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.Inst.Ref {
|
||||
// TODO: Maybe we should introduce a unary node type to avoid optional checks?
|
||||
const main_node = node.data.bin.lhs.?;
|
||||
return expr(gi, scope, main_node);
|
||||
}
|
||||
|
||||
fn validateSwitchProngs(gen: *GenIr, stmt_node: *const Ast.Node) InnerError!void {
|
||||
|
|
@ -633,96 +642,11 @@ fn validateSwitchProngs(gen: *GenIr, stmt_node: *const Ast.Node) InnerError!void
|
|||
}
|
||||
}
|
||||
|
||||
fn switchStmt(
|
||||
gen: *GenIr,
|
||||
parent_scope: *Scope,
|
||||
stmt_node: *const Ast.Node,
|
||||
) InnerError!void {
|
||||
const gpa = gen.astgen.gpa;
|
||||
var child_scope = try gen.astgen.createScope(parent_scope);
|
||||
defer child_scope.deinit();
|
||||
|
||||
const label_index = try gen.makeLabel();
|
||||
gen.setExit(label_index);
|
||||
|
||||
const eval_expr = stmt_node.data.switch_stmt.condition_expr;
|
||||
const case_list = stmt_node.data.switch_stmt.cases;
|
||||
|
||||
// NOTE: We're going to create an array of label indexes here, since we
|
||||
// may create additional labels while traversing nested expressions.
|
||||
var label_list: std.ArrayList(usize) = .empty;
|
||||
defer label_list.deinit(gpa);
|
||||
try label_list.ensureUnusedCapacity(gpa, case_list.len);
|
||||
|
||||
const stack_slot = try gen.makeStackSlot();
|
||||
try expr(gen, child_scope, eval_expr);
|
||||
try gen.emitConstInst(.store, stack_slot);
|
||||
try gen.emitSimpleInst(.pop);
|
||||
|
||||
for (case_list) |case_stmt| {
|
||||
const case_label_index = try gen.makeLabel();
|
||||
label_list.appendAssumeCapacity(case_label_index);
|
||||
|
||||
switch (case_stmt.tag) {
|
||||
.switch_case => {
|
||||
const case_eval_expr = case_stmt.data.bin.lhs orelse unreachable;
|
||||
switch (case_eval_expr.tag) {
|
||||
.number_literal, .true_literal, .false_literal => {},
|
||||
else => return gen.fail(.invalid_switch_case, case_stmt),
|
||||
}
|
||||
|
||||
try gen.emitConstInst(.load, stack_slot);
|
||||
try expr(gen, child_scope, case_eval_expr);
|
||||
try gen.emitSimpleInst(.cmp_eq);
|
||||
|
||||
const fixup_offset = try gen.emitJumpInst(.jmp_t);
|
||||
_ = try gen.makeFixup(.{
|
||||
.mode = .relative,
|
||||
.label_index = case_label_index,
|
||||
.code_offset = fixup_offset,
|
||||
});
|
||||
try gen.emitSimpleInst(.pop);
|
||||
},
|
||||
.else_branch => {
|
||||
const fixup_offset = try gen.emitJumpInst(.jmp);
|
||||
_ = try gen.makeFixup(.{
|
||||
.mode = .relative,
|
||||
.label_index = case_label_index,
|
||||
.code_offset = fixup_offset,
|
||||
});
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
for (case_list, label_list.items) |case_stmt, case_label_index| {
|
||||
gen.setLabel(case_label_index);
|
||||
|
||||
switch (case_stmt.tag) {
|
||||
.switch_case => {
|
||||
try gen.emitSimpleInst(.pop);
|
||||
},
|
||||
.else_branch => {},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
const block_stmt = case_stmt.data.bin.rhs;
|
||||
try blockStmt(gen, child_scope, block_stmt);
|
||||
const fixup_offset = try gen.emitJumpInst(.jmp);
|
||||
_ = try gen.makeFixup(.{
|
||||
.mode = .relative,
|
||||
.label_index = gen.exit_label,
|
||||
.code_offset = fixup_offset,
|
||||
});
|
||||
}
|
||||
|
||||
gen.setLabel(gen.exit_label);
|
||||
}
|
||||
|
||||
fn ifStmt(
|
||||
parent_block: *GenIr,
|
||||
scope: *Scope,
|
||||
stmt_node: *const Ast.Node,
|
||||
) InnerError!Ir.Inst.Index {
|
||||
) InnerError!Ir.Inst.Ref {
|
||||
const astgen = parent_block.astgen;
|
||||
const cond_expr = stmt_node.data.switch_stmt.condition_expr.?;
|
||||
try validateSwitchProngs(parent_block, stmt_node);
|
||||
|
|
@ -736,7 +660,7 @@ fn ifStmt(
|
|||
|
||||
const cond_inst = try expr(&block_scope, scope, cond_expr);
|
||||
const condbr = try block_scope.addCondBr(.condbr);
|
||||
const block = try parent_block.makeBlockInst();
|
||||
const block = try parent_block.makeBlockInst(.block);
|
||||
try block_scope.setBlockBody(block); // unstacks block
|
||||
try parent_block.instructions.append(astgen.gpa, block);
|
||||
|
||||
|
|
@ -757,14 +681,14 @@ fn ifStmt(
|
|||
}
|
||||
|
||||
try setCondBrPayload(condbr, cond_inst, &then_block, &else_block);
|
||||
return @enumFromInt(0);
|
||||
return condbr.toRef();
|
||||
}
|
||||
|
||||
fn ifChain(
|
||||
parent_block: *GenIr,
|
||||
scope: *Scope,
|
||||
branch_list: []const *Ast.Node,
|
||||
) InnerError!Ir.Inst.Index {
|
||||
) InnerError!Ir.Inst.Ref {
|
||||
const gpa = parent_block.astgen.gpa;
|
||||
if (branch_list.len == 0) return @enumFromInt(0);
|
||||
if (branch_list[0].data.bin.lhs == null) {
|
||||
|
|
@ -781,7 +705,7 @@ fn ifChain(
|
|||
const body_node = branch.data.bin.rhs.?;
|
||||
const cond_inst = try expr(&block_scope, scope, cond_expr);
|
||||
const condbr = try block_scope.addCondBr(.condbr);
|
||||
const block_inst = try parent_block.makeBlockInst();
|
||||
const block_inst = try parent_block.makeBlockInst(.block);
|
||||
try block_scope.setBlockBody(block_inst);
|
||||
try parent_block.instructions.append(gpa, block_inst);
|
||||
|
||||
|
|
@ -803,7 +727,7 @@ fn multiIfStmt(
|
|||
parent_block: *GenIr,
|
||||
scope: *Scope,
|
||||
stmt_node: *const Ast.Node,
|
||||
) InnerError!Ir.Inst.Index {
|
||||
) InnerError!Ir.Inst.Ref {
|
||||
try validateSwitchProngs(parent_block, stmt_node);
|
||||
|
||||
const branch_list = stmt_node.data.switch_stmt.cases;
|
||||
|
|
@ -817,19 +741,9 @@ fn multiIfStmt(
|
|||
return @enumFromInt(0);
|
||||
}
|
||||
|
||||
fn inlineLogicExpr(
|
||||
gen: *GenIr,
|
||||
scope: *Scope,
|
||||
expr_node: *const Ast.Node,
|
||||
) InnerError!Ir.Inst.Index {
|
||||
const main_node = expr_node.data.bin.lhs;
|
||||
assert(main_node != null);
|
||||
return expr(gen, scope, main_node);
|
||||
}
|
||||
|
||||
fn contentExpr(block: *GenIr, scope: *Scope, expr_node: *const Ast.Node) InnerError!Ir.Inst.Index {
|
||||
fn contentExpr(block: *GenIr, scope: *Scope, expr_node: *const Ast.Node) InnerError!Ir.Inst.Ref {
|
||||
// FIXME: This is a placeholder until we figure out what this function should be returning.
|
||||
var last_inst: Ir.Inst.Index = undefined;
|
||||
var last_inst: Ir.Inst.Ref = undefined;
|
||||
// TODO: Make sure that this is not nullable.
|
||||
const node_list = expr_node.data.list.items.?;
|
||||
for (node_list) |child_node| {
|
||||
|
|
@ -838,29 +752,30 @@ fn contentExpr(block: *GenIr, scope: *Scope, expr_node: *const Ast.Node) InnerEr
|
|||
.inline_logic_expr => try inlineLogicExpr(block, scope, child_node),
|
||||
.if_stmt => try ifStmt(block, scope, child_node),
|
||||
.multi_if_stmt => try multiIfStmt(block, scope, child_node),
|
||||
//.switch_stmt => try switchStmt(gen, scope, child_node),
|
||||
//.switch_stmt => try switchStmt(block, scope, child_node),
|
||||
else => unreachable,
|
||||
};
|
||||
last_inst = try block.add(.{ .tag = .content_push, .data = undefined });
|
||||
last_inst = try block.addUnaryNode(.content_push, last_inst);
|
||||
}
|
||||
return last_inst;
|
||||
}
|
||||
|
||||
fn contentStmt(gen: *GenIr, scope: *Scope, stmt_node: *const Ast.Node) InnerError!Ir.Inst.Index {
|
||||
const expr_node = stmt_node.data.bin.lhs orelse unreachable;
|
||||
fn contentStmt(gen: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!Ir.Inst.Ref {
|
||||
const expr_node = node.data.bin.lhs.?;
|
||||
const expr_ref = try contentExpr(gen, scope, expr_node);
|
||||
return gen.addUnaryNode(.content_flush, expr_ref);
|
||||
}
|
||||
|
||||
fn assignStmt(gi: *GenIr, scope: *Scope, stmt_node: *const Ast.Node) InnerError!void {
|
||||
fn assignStmt(gi: *GenIr, scope: *Scope, node: *const Ast.Node) InnerError!void {
|
||||
const astgen = gi.astgen;
|
||||
const identifier_node = stmt_node.data.bin.lhs orelse unreachable;
|
||||
const expr_node = stmt_node.data.bin.rhs orelse unreachable;
|
||||
const identifier_node = node.data.bin.lhs.?;
|
||||
const expr_node = node.data.bin.rhs.?;
|
||||
const name_ref = try astgen.stringFromNode(identifier_node);
|
||||
|
||||
// TODO: Support globals as well
|
||||
if (scope.lookup(name_ref)) |decl| {
|
||||
const expr_result = try expr(gi, scope, expr_node);
|
||||
_ = try gi.addBinaryNode(.store_local, decl.inst_index, expr_result);
|
||||
_ = try gi.addBinaryNode(.store, decl.inst_index.toRef(), expr_result);
|
||||
return;
|
||||
}
|
||||
return gi.fail(.unknown_identifier, identifier_node);
|
||||
|
|
@ -949,13 +864,13 @@ fn tempDecl(gi: *GenIr, scope: *Scope, decl_node: *const Ast.Node) !void {
|
|||
return gi.fail(.redefined_identifier, decl_node);
|
||||
}
|
||||
|
||||
const alloc_inst = try gi.add(.{ .tag = .alloc_local, .data = undefined });
|
||||
const alloc_inst = try gi.add(.{ .tag = .alloc, .data = undefined });
|
||||
const expr_result = try expr(gi, scope, expr_node);
|
||||
_ = try gi.addBinaryNode(.store_local, alloc_inst, expr_result);
|
||||
_ = try gi.addBinaryNode(.store, alloc_inst, expr_result);
|
||||
|
||||
return scope.insert(name_ref, .{
|
||||
.decl_node = decl_node,
|
||||
.inst_index = alloc_inst,
|
||||
.inst_index = alloc_inst.toIndex().?,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue