| ... | ... | @@ -219,8 +219,8 @@ fn parseOptionalType(ctx: *ParseContext) !?Type { |
| 219 | 219 | |
| 220 | 220 | fn parseInstruction(ctx: *ParseContext, opt_type: ?Type) error{ OutOfMemory, ParseFailure }!*Inst { |
| 221 | 221 | switch (ctx.source[ctx.i]) { |
| 222 | | '"' => return parseStringLiteralConst(ctx), |
| 223 | | '0'...'9' => return parseIntegerLiteralConst(ctx), |
| 222 | '"' => return parseStringLiteralConst(ctx, opt_type), |
| 223 | '0'...'9' => return parseIntegerLiteralConst(ctx, opt_type), |
| 224 | 224 | else => {}, |
| 225 | 225 | } |
| 226 | 226 | const fn_name = try skipToAndOver(ctx, '('); |
| ... | ... | @@ -327,7 +327,7 @@ fn parseBody(ctx: *ParseContext) !Inst.Fn.Body { |
| 327 | 327 | }; |
| 328 | 328 | } |
| 329 | 329 | |
| 330 | | fn parseStringLiteralConst(ctx: *ParseContext) !*Inst { |
| 330 | fn parseStringLiteralConst(ctx: *ParseContext, opt_type: ?Type) !*Inst { |
| 331 | 331 | const start = ctx.i; |
| 332 | 332 | ctx.i += 1; // skip over '"' |
| 333 | 333 | |
| ... | ... | @@ -344,17 +344,21 @@ fn parseStringLiteralConst(ctx: *ParseContext) !*Inst { |
| 344 | 344 | }, |
| 345 | 345 | else => |e| return e, |
| 346 | 346 | }; |
| 347 | const const_inst = try ctx.allocator.create(Inst.Constant); |
| 348 | errdefer ctx.allocator.destroy(const_inst); |
| 349 | |
| 347 | 350 | const bytes_payload = try ctx.allocator.create(Value.Payload.Bytes); |
| 348 | 351 | errdefer ctx.allocator.destroy(bytes_payload); |
| 349 | 352 | bytes_payload.* = .{ .data = parsed }; |
| 350 | 353 | |
| 351 | | const ty_payload = try ctx.allocator.create(Type.Payload.Array_u8_Sentinel0); |
| 352 | | errdefer ctx.allocator.destroy(ty_payload); |
| 353 | | ty_payload.* = .{ .len = parsed.len }; |
| 354 | const ty = opt_type orelse blk: { |
| 355 | const ty_payload = try ctx.allocator.create(Type.Payload.Array_u8_Sentinel0); |
| 356 | ty_payload.* = .{ .len = parsed.len }; |
| 357 | break :blk Type.initPayload(&ty_payload.base); |
| 358 | }; |
| 354 | 359 | |
| 355 | | const const_inst = try ctx.allocator.create(Inst.Constant); |
| 356 | 360 | const_inst.* = .{ |
| 357 | | .ty = Type.initPayload(&ty_payload.base), |
| 361 | .ty = ty, |
| 358 | 362 | .positionals = .{ .value = Value.initPayload(&bytes_payload.base) }, |
| 359 | 363 | .kw_args = .{}, |
| 360 | 364 | }; |
| ... | ... | @@ -370,8 +374,31 @@ fn parseStringLiteralConst(ctx: *ParseContext) !*Inst { |
| 370 | 374 | return parseError(ctx, "unexpected EOF in string literal", .{}); |
| 371 | 375 | } |
| 372 | 376 | |
| 373 | | fn parseIntegerLiteralConst(ctx: *ParseContext) !*Inst { |
| 374 | | return parseError(ctx, "TODO parse integer literal", .{}); |
| 377 | fn parseIntegerLiteralConst(ctx: *ParseContext, opt_type: ?Type) !*Inst { |
| 378 | const start = ctx.i; |
| 379 | while (ctx.i < ctx.source.len) : (ctx.i += 1) switch (ctx.source[ctx.i]) { |
| 380 | '0'...'9' => continue, |
| 381 | else => break, |
| 382 | }; |
| 383 | const number_text = ctx.source[start..ctx.i]; |
| 384 | const number = std.fmt.parseInt(u64, number_text, 10) catch |err| switch (err) { |
| 385 | error.Overflow => return parseError(ctx, "TODO handle big integers", .{}), |
| 386 | error.InvalidCharacter => return parseError(ctx, "invalid integer literal", .{}), |
| 387 | }; |
| 388 | |
| 389 | const int_payload = try ctx.allocator.create(Value.Payload.Int_u64); |
| 390 | errdefer ctx.allocator.destroy(int_payload); |
| 391 | int_payload.* = .{ .int = number }; |
| 392 | |
| 393 | const const_inst = try ctx.allocator.create(Inst.Constant); |
| 394 | errdefer ctx.allocator.destroy(const_inst); |
| 395 | |
| 396 | const_inst.* = .{ |
| 397 | .ty = opt_type orelse Type.initTag(.int_comptime), |
| 398 | .positionals = .{ .value = Value.initPayload(&int_payload.base) }, |
| 399 | .kw_args = .{}, |
| 400 | }; |
| 401 | return &const_inst.base; |
| 375 | 402 | } |
| 376 | 403 | |
| 377 | 404 | pub fn main() anyerror!void { |