| ... | ... | @@ -143,13 +143,8 @@ pub fn parseRoot(ctx: *ParseContext) !void { |
| 143 | 143 | '@' => { |
| 144 | 144 | const at_start = ctx.i; |
| 145 | 145 | 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); |
| 153 | 148 | const ident_index = ctx.decls.items.len; |
| 154 | 149 | if (try ctx.global_name_map.put(ident, ident_index)) |_| { |
| 155 | 150 | return parseError(ctx, "redefinition of identifier '{}'", .{ident}); |
| ... | ... | @@ -202,11 +197,27 @@ fn parseError(ctx: *ParseContext, comptime format: []const u8, args: var) error{ |
| 202 | 197 | return error.ParseFailure; |
| 203 | 198 | } |
| 204 | 199 | |
| 205 | | fn parseType(ctx: *ParseContext) !*Value { |
| 206 | | return parseError(ctx, "TODO parse type", .{}); |
| 200 | /// Regardless of whether a `Type` is returned, it skips past the '='. |
| 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 | 221 | switch (ctx.source[ctx.i]) { |
| 211 | 222 | '"' => return parseStringLiteralConst(ctx), |
| 212 | 223 | '0'...'9' => return parseIntegerLiteralConst(ctx), |
| ... | ... | @@ -216,15 +227,26 @@ fn parseInstruction(ctx: *ParseContext) error{ OutOfMemory, ParseFailure }!*Inst |
| 216 | 227 | inline for (Inst.all_types) |InstType| { |
| 217 | 228 | const this_name = @tagName(std.meta.fieldInfo(InstType, "base").default_value.?.tag); |
| 218 | 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 | 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 | 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 | 250 | const Positionals = @TypeOf(inst_specific.positionals); |
| 229 | 251 | inline for (@typeInfo(Positionals).Struct.fields) |arg_field| { |
| 230 | 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 | 309 | '%' => { |
| 288 | 310 | const at_start = ctx.i; |
| 289 | 311 | 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); |
| 300 | 314 | const ident_index = instructions.items.len; |
| 301 | 315 | if (try name_map.put(ident, ident_index)) |_| { |
| 302 | 316 | return parseError(ctx, "redefinition of identifier '{}'", .{ident}); |