From 4cb203db9242cb477027b92d866c4dccece64d38 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 19 Apr 2020 00:02:03 -0400 Subject: [PATCH] ir: parsing integer literals --- src-self-hosted/ir.zig | 47 +++++++++++++++++++++++++++++++--------- src-self-hosted/type.zig | 1 + 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index 57087e9bc..1be63e0a7 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -219,8 +219,8 @@ fn parseOptionalType(ctx: *ParseContext) !?Type { fn parseInstruction(ctx: *ParseContext, opt_type: ?Type) error{ OutOfMemory, ParseFailure }!*Inst { switch (ctx.source[ctx.i]) { - '"' => return parseStringLiteralConst(ctx), - '0'...'9' => return parseIntegerLiteralConst(ctx), + '"' => return parseStringLiteralConst(ctx, opt_type), + '0'...'9' => return parseIntegerLiteralConst(ctx, opt_type), else => {}, } const fn_name = try skipToAndOver(ctx, '('); @@ -327,7 +327,7 @@ fn parseBody(ctx: *ParseContext) !Inst.Fn.Body { }; } -fn parseStringLiteralConst(ctx: *ParseContext) !*Inst { +fn parseStringLiteralConst(ctx: *ParseContext, opt_type: ?Type) !*Inst { const start = ctx.i; ctx.i += 1; // skip over '"' @@ -344,17 +344,21 @@ fn parseStringLiteralConst(ctx: *ParseContext) !*Inst { }, else => |e| return e, }; + const const_inst = try ctx.allocator.create(Inst.Constant); + errdefer ctx.allocator.destroy(const_inst); + const bytes_payload = try ctx.allocator.create(Value.Payload.Bytes); errdefer ctx.allocator.destroy(bytes_payload); bytes_payload.* = .{ .data = parsed }; - const ty_payload = try ctx.allocator.create(Type.Payload.Array_u8_Sentinel0); - errdefer ctx.allocator.destroy(ty_payload); - ty_payload.* = .{ .len = parsed.len }; + const ty = opt_type orelse blk: { + const ty_payload = try ctx.allocator.create(Type.Payload.Array_u8_Sentinel0); + ty_payload.* = .{ .len = parsed.len }; + break :blk Type.initPayload(&ty_payload.base); + }; - const const_inst = try ctx.allocator.create(Inst.Constant); const_inst.* = .{ - .ty = Type.initPayload(&ty_payload.base), + .ty = ty, .positionals = .{ .value = Value.initPayload(&bytes_payload.base) }, .kw_args = .{}, }; @@ -370,8 +374,31 @@ fn parseStringLiteralConst(ctx: *ParseContext) !*Inst { return parseError(ctx, "unexpected EOF in string literal", .{}); } -fn parseIntegerLiteralConst(ctx: *ParseContext) !*Inst { - return parseError(ctx, "TODO parse integer literal", .{}); +fn parseIntegerLiteralConst(ctx: *ParseContext, opt_type: ?Type) !*Inst { + const start = ctx.i; + while (ctx.i < ctx.source.len) : (ctx.i += 1) switch (ctx.source[ctx.i]) { + '0'...'9' => continue, + else => break, + }; + const number_text = ctx.source[start..ctx.i]; + const number = std.fmt.parseInt(u64, number_text, 10) catch |err| switch (err) { + error.Overflow => return parseError(ctx, "TODO handle big integers", .{}), + error.InvalidCharacter => return parseError(ctx, "invalid integer literal", .{}), + }; + + const int_payload = try ctx.allocator.create(Value.Payload.Int_u64); + errdefer ctx.allocator.destroy(int_payload); + int_payload.* = .{ .int = number }; + + const const_inst = try ctx.allocator.create(Inst.Constant); + errdefer ctx.allocator.destroy(const_inst); + + const_inst.* = .{ + .ty = opt_type orelse Type.initTag(.int_comptime), + .positionals = .{ .value = Value.initPayload(&int_payload.base) }, + .kw_args = .{}, + }; + return &const_inst.base; } pub fn main() anyerror!void { diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig index a111b61b5..d3e561a0d 100644 --- a/src-self-hosted/type.zig +++ b/src-self-hosted/type.zig @@ -75,6 +75,7 @@ pub const Type = extern union { /// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`. pub const Tag = enum { // The first section of this enum are tags that require no payload. + int_comptime, int_u8, int_usize, // Bump this when adding items above.