stage2 支持左值的引用绑定

This commit is contained in:
zzy committed 2026-09-29 23:00:24 +08:00
1 parent 40cffa9cb5
commit 0e38858785
4 files changed
+200 -198

No files matched your search

+74 -74
View File
@@ -182,7 +182,7 @@ fn is_assign_arith(op: Punct): bool {
fn int_lit_u64(n: *Node): u64 {
match n.body {
.ExprIntLit(x) => {
.ExprIntLit(&x) => {
var out: u64 = 0;
match BigInt.to_u64(&out, x.value) { .Ok => {}, .Err(e) => {} }
ret out;
@@ -217,14 +217,14 @@ fn emit_zero_value(self: *Ast2Ir, tid: usize): usize {
var variants = Vec.blank(@sizeof(usize), @alignof(usize));
match tn.node {
.Bool => { is_bool = true; },
.Int(x) => { is_int = true; },
.Float(x) => { is_float = true; },
.Ptr(x) => { is_ptr = true; },
.Fn(x) => { is_fn = true; },
.Array(x) => { is_arr = true; arr_len = x.len; arr_elem = x.element; },
.Struct(x) => { is_struct = true; variants = x.variants; },
.Shape(x) => { is_shape = true; variants = x.variants; },
.Union(x) => { is_union = true; variants = x.variants; },
.Int(&x) => { is_int = true; },
.Float(&x) => { is_float = true; },
.Ptr(&x) => { is_ptr = true; },
.Fn(&x) => { is_fn = true; },
.Array(&x) => { is_arr = true; arr_len = x.len; arr_elem = x.element; },
.Struct(&x) => { is_struct = true; variants = x.variants; },
.Shape(&x) => { is_shape = true; variants = x.variants; },
.Union(&x) => { is_union = true; variants = x.variants; },
_ => { ret 0; },
}
if is_bool { ret IrBuilder.type_const_bool(self.ir, tid, false); }
@@ -717,7 +717,7 @@ fn ast2ir_intrin_field(self: *Ast2Ir, n: *Node, in: Intrin): usize {
fn ast2ir_intrin_len(self: *Ast2Ir, n: *Node): usize {
var obj_ref: usize = 0;
var fname = ByteView.empty();
match n.body { .ExprField(x) => { obj_ref = x.obj; fname = x.name; }, _ => {} }
match n.body { .ExprField(&x) => { obj_ref = x.obj; fname = x.name; }, _ => {} }
var obj = Ast.node(self.ast, obj_ref);
var recv_lang = node_lang(obj);
var recv = ltn(self, recv_lang);
@@ -748,7 +748,7 @@ fn emit_lvalue(self: *Ast2Ir, ref: usize): usize {
var n = Ast.node(self.ast, ref);
if n == null { ret 0; }
match n.body {
.ExprIdent(x) => {
.ExprIdent(&x) => {
var d = defn(self, n.resolved_def_id);
if d != null && @enum2int(d.kind) == @enum2int(DefKind.Fn) { ret 0; }
var g: usize = 0;
@@ -762,12 +762,12 @@ fn emit_lvalue(self: *Ast2Ir, ref: usize): usize {
if !ir_map_get(self, n.resolved_def_id, &slot) { ret 0; }
ret slot;
},
.ExprUnary(x) => {
.ExprUnary(&x) => {
if !punct_is(x.op, .Mul) { ret 0; }
ret emit_expr(self, x.operand);
},
.ExprField(x) => { ret lvalue_field(self, n, x.obj, x.name); },
.ExprIndex(x) => { ret lvalue_index(self, n, x.obj, x.index); },
.ExprField(&x) => { ret lvalue_field(self, n, x.obj, x.name); },
.ExprIndex(&x) => { ret lvalue_index(self, n, x.obj, x.index); },
_ => { ret 0; },
}
ret 0;
@@ -844,7 +844,7 @@ fn lvalue_index(self: *Ast2Ir, n: *Node, obj_ref: usize, index_ref: usize): usiz
}
fn is_int_lit(n: *Node): bool {
match n.body { .ExprIntLit(x) => { ret true; }, _ => { ret false; } }
match n.body { .ExprIntLit(&x) => { ret true; }, _ => { ret false; } }
ret false;
}
@@ -902,7 +902,7 @@ fn ir_float_cast(self: *Ast2Ir, ft: usize, tt: usize, v: usize): usize {
fn emit_cast(self: *Ast2Ir, n: *Node): usize {
var eref: usize = 0;
var tref: usize = 0;
match n.body { .ExprCast(x) => { eref = x.expr; tref = x.type_expr; }, _ => {} }
match n.body { .ExprCast(&x) => { eref = x.expr; tref = x.type_expr; }, _ => {} }
var v = emit_expr_raw(self, eref);
if v == 0 { ret 0; }
var src = Ast.node(self.ast, eref);
@@ -921,7 +921,7 @@ fn emit_cast(self: *Ast2Ir, n: *Node): usize {
fn ast2ir_field_from_value(self: *Ast2Ir, n: *Node): usize {
var obj_ref: usize = 0;
var field_name = ByteView.empty();
match n.body { .ExprField(x) => { obj_ref = x.obj; field_name = x.name; }, _ => {} }
match n.body { .ExprField(&x) => { obj_ref = x.obj; field_name = x.name; }, _ => {} }
var obj = Ast.node(self.ast, obj_ref);
if obj == null { ret 0; }
var obj_lang = node_lang(obj);
@@ -959,7 +959,7 @@ fn ast2ir_enum_variant(self: *Ast2Ir, n: *Node): usize {
var tn = irt(self, t);
if tn == null { ret 0; }
var field_name = ByteView.empty();
match n.body { .ExprField(x) => { field_name = x.name; }, _ => {} }
match n.body { .ExprField(&x) => { field_name = x.name; }, _ => {} }
var vidx: usize = 0;
if !TypeTable.agg_member_idx(&self.sema.types.ir, t, field_name, &vidx) { ret 0; }
var tag_ir: usize = 0;
@@ -1001,39 +1001,39 @@ fn emit_expr_raw(self: *Ast2Ir, ref: usize): usize {
var n = Ast.node(self.ast, ref);
if n == null { ret 0; }
match n.body {
.ExprIntLit(x) => { ret emit_int_lit(self, n); },
.ExprFloatLit(x) => { ret IrBuilder.type_const_float(self.ir, node_ir(self, n), 0.0); },
.ExprCharLit(x) => { ret IrBuilder.type_const_char(self.ir, node_ir(self, n), x.value); },
.ExprStringLit(sl) => { ret emit_string_lit(self, n, sl.data); },
.ExprBoolLit(x) => { ret IrBuilder.type_const_bool(self.ir, node_ir(self, n), x.value); },
.ExprIntLit(&x) => { ret emit_int_lit(self, n); },
.ExprFloatLit(&x) => { ret IrBuilder.type_const_float(self.ir, node_ir(self, n), 0.0); },
.ExprCharLit(&x) => { ret IrBuilder.type_const_char(self.ir, node_ir(self, n), x.value); },
.ExprStringLit(&sl) => { ret emit_string_lit(self, n, sl.data); },
.ExprBoolLit(&x) => { ret IrBuilder.type_const_bool(self.ir, node_ir(self, n), x.value); },
.ExprNullLit => { ret IrBuilder.type_const_ptr(self.ir, node_ir(self, n), 0); },
.ExprUndefinedLit => { ret 0; },
.ExprIdent(x) => { ret emit_ident(self, n); },
.ExprUnary(x) => { ret emit_unary(self, n, ref, x.op, x.operand); },
.ExprBinary(x) => { ret emit_binary(self, n, x.op, x.left, x.right); },
.ExprCall(x) => { ret emit_call(self, n, x.callee, x.args); },
.ExprField(x) => { ret emit_field(self, n, ref, x.obj, x.name); },
.ExprIndex(x) => {
.ExprIdent(&x) => { ret emit_ident(self, n); },
.ExprUnary(&x) => { ret emit_unary(self, n, ref, x.op, x.operand); },
.ExprBinary(&x) => { ret emit_binary(self, n, x.op, x.left, x.right); },
.ExprCall(&x) => { ret emit_call(self, n, x.callee, x.args); },
.ExprField(&x) => { ret emit_field(self, n, ref, x.obj, x.name); },
.ExprIndex(&x) => {
var ptr = emit_lvalue(self, ref);
if ptr == 0 { ret 0; }
ret IrBuilder.mem_load(self.ir, node_ir(self, n), ptr);
},
.ExprCast(x) => { ret emit_cast(self, n); },
.ExprTuple(x) => { ret emit_tuple(self, n, x.items); },
.ExprArrayLit(x) => { ret emit_array_lit(self, n, x.elems); },
.ExprAggregateLit(x) => { ret emit_aggregate_lit(self, n, x.name, x.fields); },
.ExprBlock(x) => { ret emit_block(self, n, x.stmts, x.tail_expr); },
.ExprIf(x) => { ret emit_if_like(self, ref); },
.ExprIfvar(x) => { ret emit_if_like(self, ref); },
.ExprMatch(x) => { ret emit_match(self, n, x.matched_expr, x.arms); },
.ExprWhile(x) => { ret emit_loop_like(self, ref); },
.ExprLoop(x) => { ret emit_loop_like(self, ref); },
.ExprFor(x) => {
.ExprCast(&x) => { ret emit_cast(self, n); },
.ExprTuple(&x) => { ret emit_tuple(self, n, x.items); },
.ExprArrayLit(&x) => { ret emit_array_lit(self, n, x.elems); },
.ExprAggregateLit(&x) => { ret emit_aggregate_lit(self, n, x.name, x.fields); },
.ExprBlock(&x) => { ret emit_block(self, n, x.stmts, x.tail_expr); },
.ExprIf(&x) => { ret emit_if_like(self, ref); },
.ExprIfvar(&x) => { ret emit_if_like(self, ref); },
.ExprMatch(&x) => { ret emit_match(self, n, x.matched_expr, x.arms); },
.ExprWhile(&x) => { ret emit_loop_like(self, ref); },
.ExprLoop(&x) => { ret emit_loop_like(self, ref); },
.ExprFor(&x) => {
Diag.err(self.diag, n.span, .UnhandledNode, "for is not implemented yet");
ret 0;
},
.ExprSlice(x) => { ret emit_slice(self, n, x.obj, x.begin, x.end); },
.ExprComptimeCall(x) => {
.ExprSlice(&x) => { ret emit_slice(self, n, x.obj, x.begin, x.end); },
.ExprComptimeCall(&x) => {
var in = IntrinOps.lookup_call(x.name);
if @enum2int(in) == @enum2int(Intrin.None) { ret 0; }
ret ast2ir_intrin_call(self, n, in, x.args);
@@ -1262,12 +1262,12 @@ fn emit_call(self: *Ast2Ir, n: *Node, callee_ref: usize, args: Vec): usize {
}
fn is_ident(n: *Node): bool {
match n.body { .ExprIdent(x) => { ret true; }, _ => { ret false; } }
match n.body { .ExprIdent(&x) => { ret true; }, _ => { ret false; } }
ret false;
}
fn ident_name(n: *Node): ByteView {
match n.body { .ExprIdent(x) => { ret x.name; }, _ => { ret ByteView.empty(); } }
match n.body { .ExprIdent(&x) => { ret x.name; }, _ => { ret ByteView.empty(); } }
ret ByteView.empty();
}
@@ -1688,7 +1688,7 @@ fn emit_if_like(self: *Ast2Ir, ref: usize): usize {
var n = Ast.node(self.ast, ref);
if n == null { ret 0; }
var is_ifvar = false;
match n.body { .ExprIfvar(x) => { is_ifvar = true; }, _ => {} }
match n.body { .ExprIfvar(&x) => { is_ifvar = true; }, _ => {} }
var result_t = node_ir(self, n);
var need_result = false;
@@ -1704,7 +1704,7 @@ fn emit_if_like(self: *Ast2Ir, ref: usize): usize {
var else_ref: usize = 0;
if is_ifvar {
var vd_ref: usize = 0;
match n.body { .ExprIfvar(x) => { vd_ref = x.var_decl; }, _ => {} }
match n.body { .ExprIfvar(&x) => { vd_ref = x.var_decl; }, _ => {} }
var vd = Ast.node(self.ast, vd_ref);
if vd == null { ret 0; }
var slot = emit_var_decl(self, vd);
@@ -1763,7 +1763,7 @@ fn emit_loop_like(self: *Ast2Ir, ref: usize): usize {
var n = Ast.node(self.ast, ref);
if n == null { ret 0; }
var is_while = false;
match n.body { .ExprWhile(x) => { is_while = true; }, _ => {} }
match n.body { .ExprWhile(&x) => { is_while = true; }, _ => {} }
var result_t = node_ir(self, n);
var need_result = false;
@@ -1783,7 +1783,7 @@ fn emit_loop_like(self: *Ast2Ir, ref: usize): usize {
if is_while {
head_blk = IrBuilder.block_begin(self.ir);
var cond: usize = 0;
match n.body { .ExprWhile(x) => { cond = emit_expr(self, x.cond); }, _ => {} }
match n.body { .ExprWhile(&x) => { cond = emit_expr(self, x.cond); }, _ => {} }
if cond == 0 { ret 0; }
br = IrBuilder.control_br(self.ir, cond);
IrBuilder.block_end(self.ir);
@@ -1884,7 +1884,7 @@ fn emit_break_stmt(self: *Ast2Ir, n: *Node): usize {
var lbl = ByteView.empty();
var expr_ref: usize = 0;
match n.body {
.StatementBreak(x) => { lbl = label_name_of(self, x.label); expr_ref = x.expr; },
.StatementBreak(&x) => { lbl = label_name_of(self, x.label); expr_ref = x.expr; },
_ => {},
}
var target_index = self.loop_stack.len - 1;
@@ -1913,24 +1913,24 @@ fn emit_stmt(self: *Ast2Ir, ref: usize) {
var n = Ast.node(self.ast, ref);
if n == null { ret; }
match n.body {
.StatementRet(x) => {
.StatementRet(&x) => {
var ret_ir = to_ir_type(self, self.cur_ret_lang);
var v: usize = 0;
if x.expr != 0 { v = emit_expr(self, x.expr); }
emit_deferred_until(self, self.cur_defer_base);
if !self.ir.terminated { ignore_usize(IrBuilder.control_ret(self.ir, ret_ir, v)); }
},
.StatementDefer(x) => { if x.body != 0 { push_u(&self.defer_stack, x.body); } },
.StatementComptime(x) => { if x.body != 0 { ignore_usize(emit_expr(self, x.body)); } },
.StatementDecl(x) => { if x.decl != 0 { emit_decl(self, x.decl); } },
.StatementExpr(x) => { if x.expr != 0 { ignore_usize(emit_expr(self, x.expr)); } },
.ExprIf(x) => { ignore_usize(emit_if_like(self, ref)); },
.ExprIfvar(x) => { ignore_usize(emit_if_like(self, ref)); },
.ExprWhile(x) => { ignore_usize(emit_loop_like(self, ref)); },
.ExprLoop(x) => { ignore_usize(emit_loop_like(self, ref)); },
.StatementBreak(x) => { ignore_usize(emit_break_stmt(self, n)); },
.StatementContinue(x) => { emit_continue_stmt(self, n); },
.ExprBlock(x) => { ignore_usize(emit_expr(self, ref)); },
.StatementDefer(&x) => { if x.body != 0 { push_u(&self.defer_stack, x.body); } },
.StatementComptime(&x) => { if x.body != 0 { ignore_usize(emit_expr(self, x.body)); } },
.StatementDecl(&x) => { if x.decl != 0 { emit_decl(self, x.decl); } },
.StatementExpr(&x) => { if x.expr != 0 { ignore_usize(emit_expr(self, x.expr)); } },
.ExprIf(&x) => { ignore_usize(emit_if_like(self, ref)); },
.ExprIfvar(&x) => { ignore_usize(emit_if_like(self, ref)); },
.ExprWhile(&x) => { ignore_usize(emit_loop_like(self, ref)); },
.ExprLoop(&x) => { ignore_usize(emit_loop_like(self, ref)); },
.StatementBreak(&x) => { ignore_usize(emit_break_stmt(self, n)); },
.StatementContinue(&x) => { emit_continue_stmt(self, n); },
.ExprBlock(&x) => { ignore_usize(emit_expr(self, ref)); },
_ => { ignore_usize(emit_expr(self, ref)); },
}
}
@@ -1938,7 +1938,7 @@ fn emit_stmt(self: *Ast2Ir, ref: usize) {
fn emit_continue_stmt(self: *Ast2Ir, n: *Node) {
if self.loop_stack.len == 0 { ret; }
var lbl = ByteView.empty();
match n.body { .StatementContinue(x) => { lbl = label_name_of(self, x.label); }, _ => {} }
match n.body { .StatementContinue(&x) => { lbl = label_name_of(self, x.label); }, _ => {} }
var target_index = self.loop_stack.len - 1;
if lbl.len != 0 { target_index = find_loop_with_label(self, lbl); }
if target_index == ~(0 as usize) { ret; }
@@ -1957,8 +1957,8 @@ fn emit_decl(self: *Ast2Ir, ref: usize) {
var n = Ast.node(self.ast, ref);
if n == null { ret; }
match n.body {
.VarDecl(x) => { if self.ir.current_fn != 0 { ignore_usize(emit_var_decl(self, n)); } },
.ConstDecl(x) => { if self.ir.current_fn != 0 { ignore_usize(emit_var_decl(self, n)); } },
.VarDecl(&x) => { if self.ir.current_fn != 0 { ignore_usize(emit_var_decl(self, n)); } },
.ConstDecl(&x) => { if self.ir.current_fn != 0 { ignore_usize(emit_var_decl(self, n)); } },
_ => {},
}
}
@@ -1982,7 +1982,7 @@ fn emit_fn_reserve(self: *Ast2Ir, n: *Node): usize {
}
fn fn_name_of(n: *Node): ByteView {
match n.body { .FnDecl(x) => { ret x.name; }, _ => { ret ByteView.empty(); } }
match n.body { .FnDecl(&x) => { ret x.name; }, _ => { ret ByteView.empty(); } }
ret ByteView.empty();
}
@@ -2018,7 +2018,7 @@ fn emit_fn_body(self: *Ast2Ir, n: *Node) {
var params = Vec.blank(@sizeof(usize), @alignof(usize));
var body_ref: usize = 0;
match n.body { .FnDecl(x) => { params = x.params; body_ref = x.body; }, _ => {} }
match n.body { .FnDecl(&x) => { params = x.params; body_ref = x.body; }, _ => {} }
var i: usize = 0;
while i < params.len {
var pref = list_at(params, i);
@@ -2071,7 +2071,7 @@ fn fn_ret(e: LangEntry): usize {
fn emit_aggregate_fns_reserve(self: *Ast2Ir, te: *Node) {
var members = Vec.blank(@sizeof(usize), @alignof(usize));
match te.body { .TypeAggregate(x) => { members = x.members; }, _ => { ret; } }
match te.body { .TypeAggregate(&x) => { members = x.members; }, _ => { ret; } }
var i: usize = 0;
while i < members.len {
var mn = Ast.node(self.ast, list_at(members, i));
@@ -2093,7 +2093,7 @@ fn emit_aggregate_fns_reserve(self: *Ast2Ir, te: *Node) {
fn emit_aggregate_fns_body(self: *Ast2Ir, te: *Node) {
var members = Vec.blank(@sizeof(usize), @alignof(usize));
match te.body { .TypeAggregate(x) => { members = x.members; }, _ => { ret; } }
match te.body { .TypeAggregate(&x) => { members = x.members; }, _ => { ret; } }
var i: usize = 0;
while i < members.len {
var mn = Ast.node(self.ast, list_at(members, i));
@@ -2114,7 +2114,7 @@ fn emit_aggregate_fns_body(self: *Ast2Ir, te: *Node) {
}
fn is_type_aggregate(n: *Node): bool {
match n.body { .TypeAggregate(x) => { ret true; }, _ => { ret false; } }
match n.body { .TypeAggregate(&x) => { ret true; }, _ => { ret false; } }
ret false;
}
@@ -2123,14 +2123,14 @@ fn emit_container_reserve(self: *Ast2Ir, ref: usize) {
if n == null { ret; }
var is_tlb = false;
var tlb_block: usize = 0;
match n.body { .TopLevelBlock(x) => { is_tlb = true; tlb_block = x.block; }, _ => {} }
match n.body { .TopLevelBlock(&x) => { is_tlb = true; tlb_block = x.block; }, _ => {} }
if is_tlb {
if tlb_block != 0 { emit_container_reserve(self, tlb_block); }
ret;
}
var decls = Vec.blank(@sizeof(usize), @alignof(usize));
var is_cm = false;
match n.body { .ContainerMembers(x) => { is_cm = true; decls = x.declarations; }, _ => {} }
match n.body { .ContainerMembers(&x) => { is_cm = true; decls = x.declarations; }, _ => {} }
if !is_cm { ret; }
var i: usize = 0;
while i < decls.len {
@@ -2161,14 +2161,14 @@ fn emit_container_body(self: *Ast2Ir, ref: usize) {
if n == null { ret; }
var is_tlb = false;
var tlb_block: usize = 0;
match n.body { .TopLevelBlock(x) => { is_tlb = true; tlb_block = x.block; }, _ => {} }
match n.body { .TopLevelBlock(&x) => { is_tlb = true; tlb_block = x.block; }, _ => {} }
if is_tlb {
if tlb_block != 0 { emit_container_body(self, tlb_block); }
ret;
}
var decls = Vec.blank(@sizeof(usize), @alignof(usize));
var is_cm = false;
match n.body { .ContainerMembers(x) => { is_cm = true; decls = x.declarations; }, _ => {} }
match n.body { .ContainerMembers(&x) => { is_cm = true; decls = x.declarations; }, _ => {} }
if !is_cm { ret; }
var i: usize = 0;
while i < decls.len {
@@ -2195,7 +2195,7 @@ fn emit_container_body(self: *Ast2Ir, ref: usize) {
}
fn is_pattern_ident(n: *Node): bool {
match n.body { .PatternIdent(x) => { ret true; }, _ => { ret false; } }
match n.body { .PatternIdent(&x) => { ret true; }, _ => { ret false; } }
ret false;
}