authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-18 22:42:35+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-18 22:42:35+03:00
loge4aefc6d0f9b08a98f566cb8280a6195c08f7a82
treef78b06d39025fd8bc1e40647023e9012eb80987b
parent2b45e23477605e15fecec3566b3dc90b71e2f7a7
signature Commit is signed but in an unrecognized format.

stage2: split ref from lvalue and add compile error for invalid assignments


3 files changed, 153 insertions(+), 23 deletions(-)

src-self-hosted/astgen.zig+145-15
......@@ -20,6 +20,8 @@ pub const ResultLoc = union(enum) {
2020 /// The expression must generate a pointer rather than a value. For example, the left hand side
2121 /// of an assignment uses an "LValue" result location.
2222 lvalue,
23 /// The expression must generate a pointer
24 ref,
2325 /// The expression will be type coerced into this type, but it will be evaluated as an rvalue.
2426 ty: *zir.Inst,
2527 /// The expression must store its result into this typed pointer.
......@@ -46,6 +48,132 @@ pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*z
4648
4749/// Turn Zig AST into untyped ZIR istructions.
4850pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerError!*zir.Inst {
51 if (rl == .lvalue) {
52 switch (node.tag) {
53 .Root => unreachable,
54 .Use => unreachable,
55 .TestDecl => unreachable,
56 .DocComment => unreachable,
57 .VarDecl => unreachable,
58 .SwitchCase => unreachable,
59 .SwitchElse => unreachable,
60 .Else => unreachable,
61 .Payload => unreachable,
62 .PointerPayload => unreachable,
63 .PointerIndexPayload => unreachable,
64 .ErrorTag => unreachable,
65 .FieldInitializer => unreachable,
66 .ContainerField => unreachable,
67
68 .Assign,
69 .AssignBitAnd,
70 .AssignBitOr,
71 .AssignBitShiftLeft,
72 .AssignBitShiftRight,
73 .AssignBitXor,
74 .AssignDiv,
75 .AssignSub,
76 .AssignSubWrap,
77 .AssignMod,
78 .AssignAdd,
79 .AssignAddWrap,
80 .AssignMul,
81 .AssignMulWrap,
82 .Add,
83 .AddWrap,
84 .Sub,
85 .SubWrap,
86 .Mul,
87 .MulWrap,
88 .Div,
89 .Mod,
90 .BitAnd,
91 .BitOr,
92 .BitShiftLeft,
93 .BitShiftRight,
94 .BitXor,
95 .BangEqual,
96 .EqualEqual,
97 .GreaterThan,
98 .GreaterOrEqual,
99 .LessThan,
100 .LessOrEqual,
101 .ArrayCat,
102 .ArrayMult,
103 .BoolAnd,
104 .BoolOr,
105 .Asm,
106 .StringLiteral,
107 .IntegerLiteral,
108 .Call,
109 .Unreachable,
110 .Return,
111 .If,
112 .While,
113 .BoolNot,
114 .AddressOf,
115 .FloatLiteral,
116 .UndefinedLiteral,
117 .BoolLiteral,
118 .NullLiteral,
119 .OptionalType,
120 .Block,
121 .LabeledBlock,
122 .Break,
123 .PtrType,
124 .GroupedExpression,
125 .ArrayType,
126 .ArrayTypeSentinel,
127 .EnumLiteral,
128 .MultilineStringLiteral,
129 .CharLiteral,
130 .Defer,
131 .Catch,
132 .ErrorUnion,
133 .MergeErrorSets,
134 .Range,
135 .OrElse,
136 .Await,
137 .BitNot,
138 .Negation,
139 .NegationWrap,
140 .Resume,
141 .Try,
142 .SliceType,
143 .Slice,
144 .ArrayInitializer,
145 .ArrayInitializerDot,
146 .StructInitializer,
147 .StructInitializerDot,
148 .Switch,
149 .For,
150 .Suspend,
151 .Continue,
152 .AnyType,
153 .ErrorType,
154 .FnProto,
155 .AnyFrameType,
156 .ErrorSetDecl,
157 .ContainerDecl,
158 .Comptime,
159 .Nosuspend,
160 => return mod.failNode(scope, node, "invalid left-hand side to assignment", .{}),
161
162 // @field can be assigned to
163 .BuiltinCall => {
164 const call = node.castTag(.BuiltinCall).?;
165 const tree = scope.tree();
166 const builtin_name = tree.tokenSlice(call.builtin_token);
167
168 if (!mem.eql(u8, builtin_name, "@field")) {
169 return mod.failNode(scope, node, "invalid left-hand side to assignment", .{});
170 }
171 },
172
173 // can be assigned to
174 .UnwrapOptional, .Deref, .Period, .ArrayAccess, .Identifier => {},
175 }
176 }
49177 switch (node.tag) {
50178 .Root => unreachable, // Top-level declaration.
51179 .Use => unreachable, // Top-level declaration.
......@@ -60,6 +188,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
60188 .PointerIndexPayload => unreachable, // Handled explicitly.
61189 .ErrorTag => unreachable, // Handled explicitly.
62190 .FieldInitializer => unreachable, // Handled explicitly.
191 .ContainerField => unreachable, // Handled explicitly.
63192
64193 .Assign => return rlWrapVoid(mod, scope, rl, node, try assign(mod, scope, node.castTag(.Assign).?)),
65194 .AssignBitAnd => return rlWrapVoid(mod, scope, rl, node, try assignOp(mod, scope, node.castTag(.AssignBitAnd).?, .bitand)),
......@@ -165,7 +294,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
165294 .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}),
166295 .Comptime => return mod.failNode(scope, node, "TODO implement astgen.expr for .Comptime", .{}),
167296 .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}),
168 .ContainerField => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerField", .{}),
169297 }
170298}
171299
......@@ -188,7 +316,7 @@ fn breakExpr(mod: *Module, parent_scope: *Scope, node: *ast.Node.ControlFlowExpr
188316 // proper type inference requires peer type resolution on the block's
189317 // break operand expressions.
190318 const branch_rl: ResultLoc = switch (label.result_loc) {
191 .discard, .none, .ty, .ptr, .lvalue => label.result_loc,
319 .discard, .none, .ty, .ptr, .lvalue, .ref => label.result_loc,
192320 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = label.block_inst },
193321 };
194322 const operand = try expr(mod, parent_scope, branch_rl, rhs);
......@@ -427,7 +555,7 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr
427555}
428556
429557fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
430 return expr(mod, scope, .lvalue, node.rhs);
558 return expr(mod, scope, .ref, node.rhs);
431559}
432560
433561fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
......@@ -541,9 +669,9 @@ fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Si
541669 const tree = scope.tree();
542670 const src = tree.token_locs[node.rtoken].start;
543671
544 const operand = try expr(mod, scope, .lvalue, node.lhs);
672 const operand = try expr(mod, scope, .ref, node.lhs);
545673 const unwrapped_ptr = try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand);
546 if (rl == .lvalue) return unwrapped_ptr;
674 if (rl == .lvalue or rl == .ref) return unwrapped_ptr;
547675
548676 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, unwrapped_ptr));
549677}
......@@ -718,13 +846,13 @@ const CondKind = union(enum) {
718846 return try expr(mod, &block_scope.base, .{ .ty = bool_type }, cond_node);
719847 },
720848 .optional => {
721 const cond_ptr = try expr(mod, &block_scope.base, .lvalue, cond_node);
849 const cond_ptr = try expr(mod, &block_scope.base, .ref, cond_node);
722850 self.* = .{ .optional = cond_ptr };
723851 const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, cond_ptr);
724852 return try addZIRUnOp(mod, &block_scope.base, src, .isnonnull, result);
725853 },
726854 .err_union => {
727 const err_ptr = try expr(mod, &block_scope.base, .lvalue, cond_node);
855 const err_ptr = try expr(mod, &block_scope.base, .ref, cond_node);
728856 self.* = .{ .err_union = err_ptr };
729857 const result = try addZIRUnOp(mod, &block_scope.base, src, .deref, err_ptr);
730858 return try addZIRUnOp(mod, &block_scope.base, src, .iserr, result);
......@@ -819,7 +947,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
819947 // proper type inference requires peer type resolution on the if's
820948 // branches.
821949 const branch_rl: ResultLoc = switch (rl) {
822 .discard, .none, .ty, .ptr, .lvalue => rl,
950 .discard, .none, .ty, .ptr, .lvalue, .ref => rl,
823951 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = block },
824952 };
825953
......@@ -949,7 +1077,7 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
9491077 // proper type inference requires peer type resolution on the while's
9501078 // branches.
9511079 const branch_rl: ResultLoc = switch (rl) {
952 .discard, .none, .ty, .ptr, .lvalue => rl,
1080 .discard, .none, .ty, .ptr, .lvalue, .ref => rl,
9531081 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = while_block },
9541082 };
9551083
......@@ -1080,7 +1208,7 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
10801208 .local_ptr => {
10811209 const local_ptr = s.cast(Scope.LocalPtr).?;
10821210 if (mem.eql(u8, local_ptr.name, ident_name)) {
1083 if (rl == .lvalue) {
1211 if (rl == .lvalue or rl == .ref) {
10841212 return local_ptr.ptr;
10851213 } else {
10861214 const result = try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr);
......@@ -1344,7 +1472,8 @@ fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) I
13441472 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
13451473 return result;
13461474 },
1347 .lvalue => {
1475 .lvalue => unreachable,
1476 .ref => {
13481477 const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]);
13491478 return addZIRUnOp(mod, scope, result.src, .ref, result);
13501479 },
......@@ -1395,9 +1524,10 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa
13951524 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
13961525 return result;
13971526 },
1398 .lvalue => {
1399 const operand = try expr(mod, scope, .lvalue, params[1]);
1400 const result = try addZIRBinOp(mod, scope, src, .bitcast_lvalue, dest_type, operand);
1527 .lvalue => unreachable,
1528 .ref => {
1529 const operand = try expr(mod, scope, .ref, params[1]);
1530 const result = try addZIRBinOp(mod, scope, src, .bitcast_ref, dest_type, operand);
14011531 return result;
14021532 },
14031533 .ty => |result_ty| {
......@@ -1662,7 +1792,7 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr
16621792 _ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
16631793 return result;
16641794 },
1665 .lvalue => {
1795 .lvalue, .ref => {
16661796 // We need a pointer but we have a value.
16671797 return addZIRUnOp(mod, scope, result.src, .ref, result);
16681798 },
src-self-hosted/zir.zig+5-5
......@@ -62,11 +62,11 @@ pub const Inst = struct {
6262 bitand,
6363 /// TODO delete this instruction, it has no purpose.
6464 bitcast,
65 /// An arbitrary typed pointer, which is to be used as an L-Value, is pointer-casted
66 /// to a new L-Value. The destination type is given by LHS. The cast is to be evaluated
65 /// An arbitrary typed pointer is pointer-casted to a new Pointer.
66 /// The destination type is given by LHS. The cast is to be evaluated
6767 /// as if it were a bit-cast operation from the operand pointer element type to the
6868 /// provided destination type.
69 bitcast_lvalue,
69 bitcast_ref,
7070 /// A typed result location pointer is bitcasted to a new result location pointer.
7171 /// The new result location pointer has an inferred type.
7272 bitcast_result_ptr,
......@@ -258,7 +258,7 @@ pub const Inst = struct {
258258 .ensure_result_non_error,
259259 .bitcast_result_ptr,
260260 .ref,
261 .bitcast_lvalue,
261 .bitcast_ref,
262262 .typeof,
263263 .single_const_ptr_type,
264264 .single_mut_ptr_type,
......@@ -349,7 +349,7 @@ pub const Inst = struct {
349349 .@"asm",
350350 .bitand,
351351 .bitcast,
352 .bitcast_lvalue,
352 .bitcast_ref,
353353 .bitcast_result_ptr,
354354 .bitor,
355355 .block,
src-self-hosted/zir_sema.zig+3-3
......@@ -29,7 +29,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
2929 .alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?),
3030 .alloc_inferred => return analyzeInstAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred).?),
3131 .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?),
32 .bitcast_lvalue => return analyzeInstBitCastLValue(mod, scope, old_inst.castTag(.bitcast_lvalue).?),
32 .bitcast_ref => return analyzeInstBitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?),
3333 .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?),
3434 .block => return analyzeInstBlock(mod, scope, old_inst.castTag(.block).?),
3535 .@"break" => return analyzeInstBreak(mod, scope, old_inst.castTag(.@"break").?),
......@@ -299,8 +299,8 @@ fn analyzeInstCoerceResultBlockPtr(
299299 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstCoerceResultBlockPtr", .{});
300300}
301301
302fn analyzeInstBitCastLValue(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
303 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitCastLValue", .{});
302fn analyzeInstBitCastRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
303 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitCastRef", .{});
304304}
305305
306306fn analyzeInstBitCastResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {