Commit 7127c07f68
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});
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 {
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 {