| ... | @@ -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 | } |
| 204 | | 199 | |
| 205 | fn parseType(ctx: *ParseContext) !*Value { | 200 | /// Regardless of whether a `Type` is returned, it skips past the '='. |
| 206 | return parseError(ctx, "TODO parse type", .{}); | 201 | fn 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 | } |
| 208 | | 219 | |
| 209 | fn parseInstruction(ctx: *ParseContext) error{ OutOfMemory, ParseFailure }!*Inst { | 220 | fn 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 | } |
| 224 | | 235 | |
| 225 | fn parseInstructionGeneric(ctx: *ParseContext, comptime fn_name: []const u8, comptime InstType: type) !*Inst { | 236 | fn 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); |
| 227 | | 243 | |
| | 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}); |