diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index 76915eee24..57087e9bcb 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -143,13 +143,8 @@ pub fn parseRoot(ctx: *ParseContext) !void { '@' => { const at_start = ctx.i; const ident = try skipToAndOver(ctx, ' '); - var ty: ?*Value = null; - if (eatByte(ctx, ':')) { - ty = try parseType(ctx); - skipSpace(ctx); - } - try requireEatBytes(ctx, "= "); - const inst = try parseInstruction(ctx); + const opt_type = try parseOptionalType(ctx); + const inst = try parseInstruction(ctx, opt_type); const ident_index = ctx.decls.items.len; if (try ctx.global_name_map.put(ident, ident_index)) |_| { return parseError(ctx, "redefinition of identifier '{}'", .{ident}); @@ -202,11 +197,27 @@ fn parseError(ctx: *ParseContext, comptime format: []const u8, args: var) error{ return error.ParseFailure; } -fn parseType(ctx: *ParseContext) !*Value { - return parseError(ctx, "TODO parse type", .{}); +/// Regardless of whether a `Type` is returned, it skips past the '='. +fn parseOptionalType(ctx: *ParseContext) !?Type { + skipSpace(ctx); + if (eatByte(ctx, ':')) { + const type_text_untrimmed = try skipToAndOver(ctx, '='); + skipSpace(ctx); + const type_text = mem.trim(u8, type_text_untrimmed, " \n"); + if (mem.eql(u8, type_text, "usize")) { + return Type.initTag(.int_usize); + } else { + return parseError(ctx, "TODO parse type '{}'", .{type_text}); + } + } else { + skipSpace(ctx); + try requireEatBytes(ctx, "="); + skipSpace(ctx); + return null; + } } -fn parseInstruction(ctx: *ParseContext) error{ OutOfMemory, ParseFailure }!*Inst { +fn parseInstruction(ctx: *ParseContext, opt_type: ?Type) error{ OutOfMemory, ParseFailure }!*Inst { switch (ctx.source[ctx.i]) { '"' => return parseStringLiteralConst(ctx), '0'...'9' => return parseIntegerLiteralConst(ctx), @@ -216,15 +227,26 @@ fn parseInstruction(ctx: *ParseContext) error{ OutOfMemory, ParseFailure }!*Inst inline for (Inst.all_types) |InstType| { const this_name = @tagName(std.meta.fieldInfo(InstType, "base").default_value.?.tag); if (mem.eql(u8, this_name, fn_name)) { - return parseInstructionGeneric(ctx, this_name, InstType); + return parseInstructionGeneric(ctx, this_name, InstType, opt_type); } } return parseError(ctx, "unknown instruction '{}'", .{fn_name}); } -fn parseInstructionGeneric(ctx: *ParseContext, comptime fn_name: []const u8, comptime InstType: type) !*Inst { +fn parseInstructionGeneric( + ctx: *ParseContext, + comptime fn_name: []const u8, + comptime InstType: type, + opt_type: ?Type, +) !*Inst { const inst_specific = try ctx.allocator.create(InstType); + if (@hasField(InstType, "ty")) { + inst_specific.ty = opt_type orelse { + return parseError(ctx, "instruction '" ++ fn_name ++ "' requires type", .{}); + }; + } + const Positionals = @TypeOf(inst_specific.positionals); inline for (@typeInfo(Positionals).Struct.fields) |arg_field| { @field(inst_specific.positionals, arg_field.name) = try parseParameterGeneric(ctx, arg_field.field_type); @@ -287,16 +309,8 @@ fn parseBody(ctx: *ParseContext) !Inst.Fn.Body { '%' => { const at_start = ctx.i; const ident = try skipToAndOver(ctx, ' '); - var ty: ?*Value = null; - if (eatByte(ctx, ':')) { - skipSpace(ctx); - ty = try parseType(ctx); - skipSpace(ctx); - } - skipSpace(ctx); - try requireEatBytes(ctx, "="); - skipSpace(ctx); - const inst = try parseInstruction(ctx); + const opt_type = try parseOptionalType(ctx); + const inst = try parseInstruction(ctx, opt_type); const ident_index = instructions.items.len; if (try name_map.put(ident, ident_index)) |_| { return parseError(ctx, "redefinition of identifier '{}'", .{ident}); diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig index fbc4fee25f..a111b61b58 100644 --- a/src-self-hosted/type.zig +++ b/src-self-hosted/type.zig @@ -24,9 +24,9 @@ pub const Type = extern union { } } - pub fn initTag(comptime tag: Tag) Type { - comptime assert(@enumToInt(tag) < Tag.no_payload_count); - return .{ .tag_if_small_enough = @enumToInt(tag) }; + pub fn initTag(comptime small_tag: Tag) Type { + comptime assert(@enumToInt(small_tag) < Tag.no_payload_count); + return .{ .tag_if_small_enough = @enumToInt(small_tag) }; } pub fn initPayload(payload: *Payload) Type { diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig index 8a9dd23764..3035cfbc06 100644 --- a/src-self-hosted/value.zig +++ b/src-self-hosted/value.zig @@ -37,9 +37,9 @@ pub const Value = extern union { bytes, }; - pub fn initTag(comptime tag: Tag) Value { - comptime assert(@enumToInt(tag) < Tag.no_payload_count); - return .{ .tag_if_small_enough = @enumToInt(tag) }; + pub fn initTag(comptime small_tag: Tag) Value { + comptime assert(@enumToInt(small_tag) < Tag.no_payload_count); + return .{ .tag_if_small_enough = @enumToInt(small_tag) }; } pub fn initPayload(payload: *Payload) Value {