diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-02-26 12:38:25 +0200 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2022-02-26 18:08:11 +0200 |
| commit | ff72b8a8194573bc1d7f95cbf3228b363194c775 (patch) | |
| tree | d5608b46018c2cd5c38314134e4d4e10100f7c04 /src/AstGen.zig | |
| parent | db82c1b9820449f2d1e6ef54dd32ec3ffd3c583f (diff) | |
| download | zig-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.zig | 56 |
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( |
