authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-18 20:22:54-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-19 19:31:50-04:00
log7127c07f688ca80af78847de647cdd2499ea02f4
treeceb826585d206e2f5c59ff7e968952ca42790e72
parent59154a1c51eae06c961b1ec9526901a93cdddf4b

ir: parse types


3 files changed, 42 insertions(+), 28 deletions(-)

src-self-hosted/ir.zig+36-22
......@@ -143,13 +143,8 @@ pub fn parseRoot(ctx: *ParseContext) !void {
143143 '@' => {
144144 const at_start = ctx.i;
145145 const ident = try skipToAndOver(ctx, ' ');
146 var ty: ?*Value = null;
147 if (eatByte(ctx, ':')) {
148 ty = try parseType(ctx);
149 skipSpace(ctx);
150 }
151 try requireEatBytes(ctx, "= ");
152 const inst = try parseInstruction(ctx);
146 const opt_type = try parseOptionalType(ctx);
147 const inst = try parseInstruction(ctx, opt_type);
153148 const ident_index = ctx.decls.items.len;
154149 if (try ctx.global_name_map.put(ident, ident_index)) |_| {
155150 return parseError(ctx, "redefinition of identifier '{}'", .{ident});
......@@ -202,11 +197,27 @@ fn parseError(ctx: *ParseContext, comptime format: []const u8, args: var) error{
202197 return error.ParseFailure;
203198}
204199
205fn parseType(ctx: *ParseContext) !*Value {
206 return parseError(ctx, "TODO parse type", .{});
200/// Regardless of whether a `Type` is returned, it skips past the '='.
201fn parseOptionalType(ctx: *ParseContext) !?Type {
202 skipSpace(ctx);
203 if (eatByte(ctx, ':')) {
204 const type_text_untrimmed = try skipToAndOver(ctx, '=');
205 skipSpace(ctx);
206 const type_text = mem.trim(u8, type_text_untrimmed, " \n");
207 if (mem.eql(u8, type_text, "usize")) {
208 return Type.initTag(.int_usize);
209 } else {
210 return parseError(ctx, "TODO parse type '{}'", .{type_text});
211 }
212 } else {
213 skipSpace(ctx);
214 try requireEatBytes(ctx, "=");
215 skipSpace(ctx);
216 return null;
217 }
207218}
208219
209fn parseInstruction(ctx: *ParseContext) error{ OutOfMemory, ParseFailure }!*Inst {
220fn parseInstruction(ctx: *ParseContext, opt_type: ?Type) error{ OutOfMemory, ParseFailure }!*Inst {
210221 switch (ctx.source[ctx.i]) {
211222 '"' => return parseStringLiteralConst(ctx),
212223 '0'...'9' => return parseIntegerLiteralConst(ctx),
......@@ -216,15 +227,26 @@ fn parseInstruction(ctx: *ParseContext) error{ OutOfMemory, ParseFailure }!*Inst
216227 inline for (Inst.all_types) |InstType| {
217228 const this_name = @tagName(std.meta.fieldInfo(InstType, "base").default_value.?.tag);
218229 if (mem.eql(u8, this_name, fn_name)) {
219 return parseInstructionGeneric(ctx, this_name, InstType);
230 return parseInstructionGeneric(ctx, this_name, InstType, opt_type);
220231 }
221232 }
222233 return parseError(ctx, "unknown instruction '{}'", .{fn_name});
223234}
224235
225fn parseInstructionGeneric(ctx: *ParseContext, comptime fn_name: []const u8, comptime InstType: type) !*Inst {
236fn parseInstructionGeneric(
237 ctx: *ParseContext,
238 comptime fn_name: []const u8,
239 comptime InstType: type,
240 opt_type: ?Type,
241) !*Inst {
226242 const inst_specific = try ctx.allocator.create(InstType);
227243
244 if (@hasField(InstType, "ty")) {
245 inst_specific.ty = opt_type orelse {
246 return parseError(ctx, "instruction '" ++ fn_name ++ "' requires type", .{});
247 };
248 }
249
228250 const Positionals = @TypeOf(inst_specific.positionals);
229251 inline for (@typeInfo(Positionals).Struct.fields) |arg_field| {
230252 @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 {
287309 '%' => {
288310 const at_start = ctx.i;
289311 const ident = try skipToAndOver(ctx, ' ');
290 var ty: ?*Value = null;
291 if (eatByte(ctx, ':')) {
292 skipSpace(ctx);
293 ty = try parseType(ctx);
294 skipSpace(ctx);
295 }
296 skipSpace(ctx);
297 try requireEatBytes(ctx, "=");
298 skipSpace(ctx);
299 const inst = try parseInstruction(ctx);
312 const opt_type = try parseOptionalType(ctx);
313 const inst = try parseInstruction(ctx, opt_type);
300314 const ident_index = instructions.items.len;
301315 if (try name_map.put(ident, ident_index)) |_| {
302316 return parseError(ctx, "redefinition of identifier '{}'", .{ident});
src-self-hosted/type.zig+3-3
......@@ -24,9 +24,9 @@ pub const Type = extern union {
2424 }
2525 }
2626
27 pub fn initTag(comptime tag: Tag) Type {
28 comptime assert(@enumToInt(tag) < Tag.no_payload_count);
29 return .{ .tag_if_small_enough = @enumToInt(tag) };
27 pub fn initTag(comptime small_tag: Tag) Type {
28 comptime assert(@enumToInt(small_tag) < Tag.no_payload_count);
29 return .{ .tag_if_small_enough = @enumToInt(small_tag) };
3030 }
3131
3232 pub fn initPayload(payload: *Payload) Type {
src-self-hosted/value.zig+3-3
......@@ -37,9 +37,9 @@ pub const Value = extern union {
3737 bytes,
3838 };
3939
40 pub fn initTag(comptime tag: Tag) Value {
41 comptime assert(@enumToInt(tag) < Tag.no_payload_count);
42 return .{ .tag_if_small_enough = @enumToInt(tag) };
40 pub fn initTag(comptime small_tag: Tag) Value {
41 comptime assert(@enumToInt(small_tag) < Tag.no_payload_count);
42 return .{ .tag_if_small_enough = @enumToInt(small_tag) };
4343 }
4444
4545 pub fn initPayload(payload: *Payload) Value {