aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorjacob gw <jacoblevgw@gmail.com>2021-03-26 17:54:41 -0400
committerAndrew Kelley <andrew@ziglang.org>2021-03-28 18:22:01 -0700
commit0005b346375f1fbe7bc42c22d658e3218bbd599d (patch)
treed88211b36f2be7689a138bf0d5f1a2e62f695323 /src/Sema.zig
parentf80f8a7a7835db5f8b13aab23b4ee79e88c25e63 (diff)
downloadzig-0005b346375f1fbe7bc42c22d658e3218bbd599d.tar.gz
zig-0005b346375f1fbe7bc42c22d658e3218bbd599d.zip
stage2: implement sema for @errorToInt and @intToError
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 0c3215d2a2..cb788afda1 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -177,6 +177,8 @@ pub fn analyzeBody(
.error_set => try sema.zirErrorSet(block, inst),
.error_union_type => try sema.zirErrorUnionType(block, inst),
.error_value => try sema.zirErrorValue(block, inst),
+ .error_to_int => try sema.zirErrorToInt(block, inst),
+ .int_to_error => try sema.zirIntToError(block, inst),
.field_ptr => try sema.zirFieldPtr(block, inst),
.field_ptr_named => try sema.zirFieldPtrNamed(block, inst),
.field_val => try sema.zirFieldVal(block, inst),
@@ -1460,6 +1462,65 @@ fn zirErrorValue(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
});
}
+fn zirErrorToInt(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ const inst_data = sema.code.instructions.items(.data)[inst].un_node;
+ const src = inst_data.src();
+ const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
+ const op = try sema.resolveInst(inst_data.operand);
+ const op_coerced = try sema.coerce(block, Type.initTag(.anyerror), op, operand_src);
+
+ if (op_coerced.value()) |val| {
+ const payload = try sema.arena.create(Value.Payload.U64);
+ payload.* = .{
+ .base = .{ .tag = .int_u64 },
+ .data = (try sema.mod.getErrorValue(val.castTag(.@"error").?.data.name)).value,
+ };
+ return sema.mod.constInst(sema.arena, src, .{
+ .ty = Type.initTag(.u16),
+ .val = Value.initPayload(&payload.base),
+ });
+ }
+
+ try sema.requireRuntimeBlock(block, src);
+ return block.addUnOp(src, Type.initTag(.u16), .error_to_int, op_coerced);
+}
+
+fn zirIntToError(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ const inst_data = sema.code.instructions.items(.data)[inst].un_node;
+ const src = inst_data.src();
+ const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
+
+ const op = try sema.resolveInst(inst_data.operand);
+
+ if (try sema.resolveDefinedValue(block, operand_src, op)) |value| {
+ const int = value.toUnsignedInt();
+ if (int > sema.mod.global_error_set.count() or int == 0)
+ return sema.mod.fail(&block.base, operand_src, "integer value {d} represents no error", .{int});
+ const payload = try sema.arena.create(Value.Payload.Error);
+ payload.* = .{
+ .base = .{ .tag = .@"error" },
+ .data = .{ .name = sema.mod.error_name_list.items[int] },
+ };
+ return sema.mod.constInst(sema.arena, src, .{
+ .ty = Type.initTag(.anyerror),
+ .val = Value.initPayload(&payload.base),
+ });
+ }
+ try sema.requireRuntimeBlock(block, src);
+ if (block.wantSafety()) {
+ return sema.mod.fail(&block.base, src, "TODO: get max errors in compilation", .{});
+ // const is_gt_max = @panic("TODO get max errors in compilation");
+ // try sema.addSafetyCheck(block, is_gt_max, .invalid_error_code);
+ }
+ return block.addUnOp(src, Type.initTag(.anyerror), .int_to_error, op);
+}
+
fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
@@ -3242,6 +3303,7 @@ pub const PanicId = enum {
unreach,
unwrap_null,
unwrap_errunion,
+ invalid_error_code,
};
fn addSafetyCheck(sema: *Sema, parent_block: *Scope.Block, ok: *Inst, panic_id: PanicId) !void {