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 {...@@ -143,13 +143,8 @@ pub fn parseRoot(ctx: *ParseContext) !void {
143 '@' => {143 '@' => {
144 const at_start = ctx.i;144 const at_start = ctx.i;
145 const ident = try skipToAndOver(ctx, ' ');145 const ident = try skipToAndOver(ctx, ' ');
146 var ty: ?*Value = null;146 const opt_type = try parseOptionalType(ctx);
147 if (eatByte(ctx, ':')) {147 const inst = try parseInstruction(ctx, opt_type);
148 ty = try parseType(ctx);
149 skipSpace(ctx);
150 }
151 try requireEatBytes(ctx, "= ");
152 const inst = try parseInstruction(ctx);
153 const ident_index = ctx.decls.items.len;148 const ident_index = ctx.decls.items.len;
154 if (try ctx.global_name_map.put(ident, ident_index)) |_| {149 if (try ctx.global_name_map.put(ident, ident_index)) |_| {
155 return parseError(ctx, "redefinition of identifier '{}'", .{ident});150 return parseError(ctx, "redefinition of identifier '{}'", .{ident});
...@@ -202,11 +197,27 @@ fn parseError(ctx: *ParseContext, comptime format: []const u8, args: var) error{...@@ -202,11 +197,27 @@ fn parseError(ctx: *ParseContext, comptime format: []const u8, args: var) error{
202 return error.ParseFailure;197 return error.ParseFailure;
203}198}
204199
205fn parseType(ctx: *ParseContext) !*Value {200/// Regardless of whether a `Type` is returned, it skips past the '='.
206 return parseError(ctx, "TODO parse type", .{});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 }
207}218}
208219
209fn parseInstruction(ctx: *ParseContext) error{ OutOfMemory, ParseFailure }!*Inst {220fn parseInstruction(ctx: *ParseContext, opt_type: ?Type) error{ OutOfMemory, ParseFailure }!*Inst {
210 switch (ctx.source[ctx.i]) {221 switch (ctx.source[ctx.i]) {
211 '"' => return parseStringLiteralConst(ctx),222 '"' => return parseStringLiteralConst(ctx),
212 '0'...'9' => return parseIntegerLiteralConst(ctx),223 '0'...'9' => return parseIntegerLiteralConst(ctx),
...@@ -216,15 +227,26 @@ fn parseInstruction(ctx: *ParseContext) error{ OutOfMemory, ParseFailure }!*Inst...@@ -216,15 +227,26 @@ fn parseInstruction(ctx: *ParseContext) error{ OutOfMemory, ParseFailure }!*Inst
216 inline for (Inst.all_types) |InstType| {227 inline for (Inst.all_types) |InstType| {
217 const this_name = @tagName(std.meta.fieldInfo(InstType, "base").default_value.?.tag);228 const this_name = @tagName(std.meta.fieldInfo(InstType, "base").default_value.?.tag);
218 if (mem.eql(u8, this_name, fn_name)) {229 if (mem.eql(u8, this_name, fn_name)) {
219 return parseInstructionGeneric(ctx, this_name, InstType);230 return parseInstructionGeneric(ctx, this_name, InstType, opt_type);
220 }231 }
221 }232 }
222 return parseError(ctx, "unknown instruction '{}'", .{fn_name});233 return parseError(ctx, "unknown instruction '{}'", .{fn_name});
223}234}
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 {
226 const inst_specific = try ctx.allocator.create(InstType);242 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
228 const Positionals = @TypeOf(inst_specific.positionals);250 const Positionals = @TypeOf(inst_specific.positionals);
229 inline for (@typeInfo(Positionals).Struct.fields) |arg_field| {251 inline for (@typeInfo(Positionals).Struct.fields) |arg_field| {
230 @field(inst_specific.positionals, arg_field.name) = try parseParameterGeneric(ctx, arg_field.field_type);252 @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 {...@@ -287,16 +309,8 @@ fn parseBody(ctx: *ParseContext) !Inst.Fn.Body {
287 '%' => {309 '%' => {
288 const at_start = ctx.i;310 const at_start = ctx.i;
289 const ident = try skipToAndOver(ctx, ' ');311 const ident = try skipToAndOver(ctx, ' ');
290 var ty: ?*Value = null;312 const opt_type = try parseOptionalType(ctx);
291 if (eatByte(ctx, ':')) {313 const inst = try parseInstruction(ctx, opt_type);
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);
300 const ident_index = instructions.items.len;314 const ident_index = instructions.items.len;
301 if (try name_map.put(ident, ident_index)) |_| {315 if (try name_map.put(ident, ident_index)) |_| {
302 return parseError(ctx, "redefinition of identifier '{}'", .{ident});316 return parseError(ctx, "redefinition of identifier '{}'", .{ident});
src-self-hosted/type.zig+3-3
...@@ -24,9 +24,9 @@ pub const Type = extern union {...@@ -24,9 +24,9 @@ pub const Type = extern union {
24 }24 }
25 }25 }
2626
27 pub fn initTag(comptime tag: Tag) Type {27 pub fn initTag(comptime small_tag: Tag) Type {
28 comptime assert(@enumToInt(tag) < Tag.no_payload_count);28 comptime assert(@enumToInt(small_tag) < Tag.no_payload_count);
29 return .{ .tag_if_small_enough = @enumToInt(tag) };29 return .{ .tag_if_small_enough = @enumToInt(small_tag) };
30 }30 }
3131
32 pub fn initPayload(payload: *Payload) Type {32 pub fn initPayload(payload: *Payload) Type {
src-self-hosted/value.zig+3-3
...@@ -37,9 +37,9 @@ pub const Value = extern union {...@@ -37,9 +37,9 @@ pub const Value = extern union {
37 bytes,37 bytes,
38 };38 };
3939
40 pub fn initTag(comptime tag: Tag) Value {40 pub fn initTag(comptime small_tag: Tag) Value {
41 comptime assert(@enumToInt(tag) < Tag.no_payload_count);41 comptime assert(@enumToInt(small_tag) < Tag.no_payload_count);
42 return .{ .tag_if_small_enough = @enumToInt(tag) };42 return .{ .tag_if_small_enough = @enumToInt(small_tag) };
43 }43 }
4444
45 pub fn initPayload(payload: *Payload) Value {45 pub fn initPayload(payload: *Payload) Value {