ir: parse types
parent
59154a1c51
commit
7127c07f68
|
@ -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});
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue