aboutsummaryrefslogtreecommitdiff
path: root/src/AstGen.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-02-26 12:38:25 +0200
committerVeikka Tuominen <git@vexu.eu>2022-02-26 18:08:11 +0200
commitff72b8a8194573bc1d7f95cbf3228b363194c775 (patch)
treed5608b46018c2cd5c38314134e4d4e10100f7c04 /src/AstGen.zig
parentdb82c1b9820449f2d1e6ef54dd32ec3ffd3c583f (diff)
downloadzig-ff72b8a8194573bc1d7f95cbf3228b363194c775.tar.gz
zig-ff72b8a8194573bc1d7f95cbf3228b363194c775.zip
stage2: evaluate TypeOf arguments in a separate scope
Diffstat (limited to 'src/AstGen.zig')
-rw-r--r--src/AstGen.zig56
1 files changed, 41 insertions, 15 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 74e3ae17b1..45b074a848 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -2159,6 +2159,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.negate,
.negate_wrap,
.typeof,
+ .typeof_builtin,
.xor,
.optional_type,
.optional_payload_safe,
@@ -6875,29 +6876,54 @@ fn typeOf(
scope: *Scope,
rl: ResultLoc,
node: Ast.Node.Index,
- params: []const Ast.Node.Index,
+ args: []const Ast.Node.Index,
) InnerError!Zir.Inst.Ref {
- if (params.len < 1) {
+ if (args.len < 1) {
return gz.astgen.failNode(node, "expected at least 1 argument, found 0", .{});
}
- if (params.len == 1) {
- const expr_result = try reachableExpr(gz, scope, .none, params[0], node);
- const result = try gz.addUnNode(.typeof, expr_result, node);
- return rvalue(gz, rl, result, node);
+ const gpa = gz.astgen.gpa;
+ if (args.len == 1) {
+ const typeof_inst = try gz.makeBlockInst(.typeof_builtin, node);
+
+ var typeof_scope = gz.makeSubBlock(scope);
+ typeof_scope.force_comptime = false;
+ defer typeof_scope.unstack();
+
+ const ty_expr = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, args[0], node);
+ if (!gz.refIsNoReturn(ty_expr)) {
+ _ = try typeof_scope.addBreak(.break_inline, typeof_inst, ty_expr);
+ }
+ try typeof_scope.setBlockBody(typeof_inst);
+
+ // typeof_scope unstacked now, can add new instructions to gz
+ try gz.instructions.append(gpa, typeof_inst);
+ return rvalue(gz, rl, indexToRef(typeof_inst), node);
}
+ const payload_size: u32 = std.meta.fields(Zir.Inst.TypeOfPeer).len;
+ const payload_index = try reserveExtra(gz.astgen, payload_size + args.len);
+ var args_index = payload_index + payload_size;
+
+ const typeof_inst = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, args.len);
- const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{
+ var typeof_scope = gz.makeSubBlock(scope);
+ typeof_scope.force_comptime = false;
+
+ for (args) |arg, i| {
+ const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, arg, node);
+ gz.astgen.extra.items[args_index + i] = @enumToInt(param_ref);
+ }
+ _ = try typeof_scope.addBreak(.break_inline, refToIndex(typeof_inst).?, .void_value);
+
+ const body = typeof_scope.instructionsSlice();
+ gz.astgen.setExtra(payload_index, Zir.Inst.TypeOfPeer{
+ .body_len = @intCast(u32, body.len),
+ .body_index = @intCast(u32, gz.astgen.extra.items.len),
.src_node = gz.nodeIndexToRelative(node),
});
- var extra_index = try reserveExtra(gz.astgen, params.len);
- for (params) |param| {
- const param_ref = try reachableExpr(gz, scope, .none, param, node);
- gz.astgen.extra.items[extra_index] = @enumToInt(param_ref);
- extra_index += 1;
- }
+ try gz.astgen.extra.appendSlice(gpa, body);
+ typeof_scope.unstack();
- const result = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, params.len);
- return rvalue(gz, rl, result, node);
+ return rvalue(gz, rl, typeof_inst, node);
}
fn builtinCall(