add proper Integer32 and Integer64 literals
This commit is contained in:
parent
76d888bde8
commit
7e41d03eb9
7 changed files with 90 additions and 12 deletions
|
@ -7,8 +7,8 @@ fn f() i32 {
|
|||
return 2;
|
||||
}
|
||||
|
||||
fn f2() i32 {
|
||||
return f.awoo;
|
||||
fn f2() i64 {
|
||||
return 1301;
|
||||
}
|
||||
|
||||
enum B {
|
||||
|
|
|
@ -209,7 +209,9 @@ pub const TypeSolver = struct {
|
|||
.Bool => SymbolUnderlyingType{ .Bool = {} },
|
||||
|
||||
// TODO determine its i64 depending of parseInt results
|
||||
.Integer => SymbolUnderlyingType{ .Integer32 = {} },
|
||||
.Integer32 => SymbolUnderlyingType{ .Integer32 = {} },
|
||||
.Integer64 => SymbolUnderlyingType{ .Integer64 = {} },
|
||||
.Float => SymbolUnderlyingType{ .Double = {} },
|
||||
|
||||
else => unreachable,
|
||||
};
|
||||
|
|
|
@ -83,7 +83,10 @@ pub const UnaryExpr = struct {
|
|||
|
||||
pub const LiteralExpr = union(enum) {
|
||||
Bool: bool,
|
||||
Integer: []const u8,
|
||||
|
||||
Integer32: i32,
|
||||
Integer64: i64,
|
||||
|
||||
Float: []const u8,
|
||||
String: []const u8,
|
||||
Array: ExprList,
|
||||
|
|
|
@ -227,7 +227,8 @@ pub fn printExpr(expr: *const Expr) void {
|
|||
.Literal => |literal| {
|
||||
switch (literal) {
|
||||
.Bool => |val| std.debug.warn("{}", val),
|
||||
.Integer => |val| std.debug.warn("{}", val),
|
||||
.Integer32 => |val| std.debug.warn("{}", val),
|
||||
.Integer64 => |val| std.debug.warn("{}", val),
|
||||
.Float => |val| std.debug.warn("{}", val),
|
||||
.String => |val| std.debug.warn("'{}'", val),
|
||||
.Array => |exprs| {
|
||||
|
@ -362,6 +363,7 @@ fn prettyType(typ: SymbolUnderlyingType) []const u8 {
|
|||
.Integer32 => "i32",
|
||||
.Integer64 => "i64",
|
||||
.Bool => "bool",
|
||||
.Double => "double",
|
||||
|
||||
.OpaqueType => |ident| retWithName("opaque", ident),
|
||||
.Struct => |ident| retWithName("struct", ident),
|
||||
|
|
|
@ -85,10 +85,17 @@ pub const Codegen = struct {
|
|||
.Literal => |literal| blk: {
|
||||
break :blk switch (literal) {
|
||||
// TODO other literals
|
||||
.Integer => |val| blk2: {
|
||||
var val_cstr = try std.cstr.addNullByte(self.allocator, val);
|
||||
break :blk2 llvm.LLVMConstIntOfString(llvm.LLVMInt32Type(), val_cstr.ptr, 10);
|
||||
},
|
||||
.Integer32 => |val| llvm.LLVMConstInt(
|
||||
llvm.LLVMInt32Type(),
|
||||
@intCast(c_ulonglong, val),
|
||||
10,
|
||||
),
|
||||
.Integer64 => |val| llvm.LLVMConstInt(
|
||||
llvm.LLVMInt64Type(),
|
||||
@intCast(c_ulonglong, val),
|
||||
10,
|
||||
),
|
||||
|
||||
.Float => |val| blk2: {
|
||||
var val_cstr = try std.cstr.addNullByte(self.allocator, val);
|
||||
break :blk2 llvm.LLVMConstRealOfString(llvm.LLVMDoubleType(), val_cstr.ptr);
|
||||
|
|
|
@ -9,6 +9,7 @@ pub const TypeList = std.ArrayList(SymbolUnderlyingType);
|
|||
pub const SymbolUnderlyingTypeEnum = enum {
|
||||
Integer32,
|
||||
Integer64,
|
||||
Double,
|
||||
Bool,
|
||||
|
||||
// opaque unsolved identifier
|
||||
|
@ -19,9 +20,28 @@ pub const SymbolUnderlyingTypeEnum = enum {
|
|||
Enum,
|
||||
};
|
||||
|
||||
pub fn isSymUnTypeEnumSubset(
|
||||
maybe_member: SymbolUnderlyingTypeEnum,
|
||||
superset: SymbolUnderlyingTypeEnum,
|
||||
) bool {
|
||||
// return false for supersets that aren't supersets
|
||||
switch (superset) {
|
||||
.Integer32, .Double, .Bool, .OpaqueType, .Struct, .Enum => return false,
|
||||
|
||||
// for now, only integer64 is a superset (containing integer32)
|
||||
.Integer64 => {
|
||||
return switch (maybe_member) {
|
||||
.Integer32 => true,
|
||||
else => false,
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub const SymbolUnderlyingType = union(SymbolUnderlyingTypeEnum) {
|
||||
Integer32: void,
|
||||
Integer64: void,
|
||||
Double: void,
|
||||
Bool: void,
|
||||
OpaqueType: []const u8,
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ const TokenType = tokens.TokenType;
|
|||
pub const ParseError = error{
|
||||
CompileError,
|
||||
UnknownOperator,
|
||||
InvalidInteger,
|
||||
};
|
||||
|
||||
const Node = ast.Node;
|
||||
|
@ -356,11 +357,22 @@ pub const Parser = struct {
|
|||
return expr;
|
||||
}
|
||||
|
||||
fn mkInteger(self: *Parser, val: []const u8) !*ast.Expr {
|
||||
fn mkInt32(self: *Parser, val: i32) !*ast.Expr {
|
||||
var expr = try self.allocator.create(Expr);
|
||||
expr.* = Expr{
|
||||
.Literal = ast.LiteralExpr{
|
||||
.Integer = val,
|
||||
.Integer32 = val,
|
||||
},
|
||||
};
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
fn mkInt64(self: *Parser, val: i64) !*ast.Expr {
|
||||
var expr = try self.allocator.create(Expr);
|
||||
expr.* = Expr{
|
||||
.Literal = ast.LiteralExpr{
|
||||
.Integer64 = val,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1124,8 +1136,40 @@ pub const Parser = struct {
|
|||
.False => try self.mkBool(false),
|
||||
.True => try self.mkBool(true),
|
||||
|
||||
.Integer => try self.mkInteger(lexeme),
|
||||
.Integer => blk: {
|
||||
// hacky, but it works. the old approach was doing
|
||||
// parseInt(i64) on the catch block of parseInt(i32)
|
||||
var i32_num_opt: ?i32 = std.fmt.parseInt(i32, lexeme, 10) catch null;
|
||||
var i64_num: i64 = std.fmt.parseInt(i64, lexeme, 10) catch |err| {
|
||||
return self.doError(
|
||||
"Invalid integer (not 32bit or 64bit) '{}': {}",
|
||||
lexeme,
|
||||
err,
|
||||
);
|
||||
};
|
||||
|
||||
if (i32_num_opt) |i32_num| {
|
||||
break :blk try self.mkInt32(i32_num);
|
||||
} else {
|
||||
break :blk try self.mkInt64(i64_num);
|
||||
}
|
||||
|
||||
// old one
|
||||
|
||||
//break :blk try self.mkInt32(std.fmt.parseInt(i32, lexeme, 10) catch |err32| {
|
||||
// break :blk try self.mkInt64(std.fmt.parseInt(i64, lexeme, 10) catch |err64| {
|
||||
// return self.doError(
|
||||
// "Invalid integer (not 32bit or 64bit) '{}': {}",
|
||||
// lexeme,
|
||||
// err64,
|
||||
// );
|
||||
// });
|
||||
//});
|
||||
},
|
||||
|
||||
// TODO std.fmt.parseFloat
|
||||
.Float => try self.mkFloat(lexeme),
|
||||
|
||||
.String => try self.mkString(lexeme),
|
||||
.Identifier => try self.mkVariable(self.peek()),
|
||||
|
||||
|
|
Loading…
Reference in a new issue