fix boolean operators
- remove Logical expressions - add basic token return type to LLVMTypeRef converter - add codegen for Bool literals - fix "and" and "or" being identified as identifiers
This commit is contained in:
parent
f08d613198
commit
e25621350a
|
@ -1,7 +1,11 @@
|
||||||
// import std;
|
// import std;
|
||||||
|
|
||||||
fn add() i32 {
|
fn add() i32 {
|
||||||
return 1 + 1;
|
return 69 + 69;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn and_fn() bool {
|
||||||
|
return true and false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// type is void by default
|
// type is void by default
|
||||||
|
|
|
@ -80,13 +80,6 @@ pub const UnaryExpr = struct {
|
||||||
right: *Expr,
|
right: *Expr,
|
||||||
};
|
};
|
||||||
|
|
||||||
// looks like a BinaryExpr, but is not a BinaryExpr
|
|
||||||
pub const LogicalExpr = struct {
|
|
||||||
left: *Expr,
|
|
||||||
op: Token,
|
|
||||||
right: *Expr,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const LiteralExpr = union(enum) {
|
pub const LiteralExpr = union(enum) {
|
||||||
Bool: bool,
|
Bool: bool,
|
||||||
Integer: []const u8,
|
Integer: []const u8,
|
||||||
|
@ -108,7 +101,6 @@ pub const ExprType = enum {
|
||||||
|
|
||||||
Binary,
|
Binary,
|
||||||
Unary,
|
Unary,
|
||||||
Logical,
|
|
||||||
Literal,
|
Literal,
|
||||||
Variable,
|
Variable,
|
||||||
Call,
|
Call,
|
||||||
|
@ -159,7 +151,6 @@ pub const Expr = union(ExprType) {
|
||||||
|
|
||||||
Binary: BinaryExpr,
|
Binary: BinaryExpr,
|
||||||
Unary: UnaryExpr,
|
Unary: UnaryExpr,
|
||||||
Logical: LogicalExpr,
|
|
||||||
Literal: LiteralExpr,
|
Literal: LiteralExpr,
|
||||||
Struct: StructExpr,
|
Struct: StructExpr,
|
||||||
|
|
||||||
|
|
|
@ -184,12 +184,8 @@ fn binOpToStr(op: BinaryOperator) ?[]const u8 {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printBinOp(inner: var, comptime is_binop: bool) void {
|
fn printBinOp(inner: var) void {
|
||||||
if (is_binop) {
|
std.debug.warn("({}", binOpToStr(inner.op));
|
||||||
std.debug.warn("({}", binOpToStr(inner.op));
|
|
||||||
} else {
|
|
||||||
std.debug.warn("({}", inner.op.lexeme);
|
|
||||||
}
|
|
||||||
printTwoExprs(inner.left, inner.right);
|
printTwoExprs(inner.left, inner.right);
|
||||||
std.debug.warn(")");
|
std.debug.warn(")");
|
||||||
}
|
}
|
||||||
|
@ -202,8 +198,7 @@ fn printSingleOp(tok: []const u8, applied: *const Expr) void {
|
||||||
|
|
||||||
pub fn printExpr(expr: *const Expr) void {
|
pub fn printExpr(expr: *const Expr) void {
|
||||||
switch (expr.*) {
|
switch (expr.*) {
|
||||||
.Binary => |binary| printBinOp(binary, true),
|
.Binary => |binary| printBinOp(binary),
|
||||||
.Logical => |logical| printBinOp(logical, false),
|
|
||||||
|
|
||||||
.Unary => |unary| printSingleOp(unary.op.lexeme, unary.right),
|
.Unary => |unary| printSingleOp(unary.op.lexeme, unary.right),
|
||||||
.Grouping => |expr_ptr| printSingleOp("group", expr_ptr),
|
.Grouping => |expr_ptr| printSingleOp("group", expr_ptr),
|
||||||
|
|
|
@ -10,8 +10,20 @@ fn sliceify(non_slice: ?[*]const u8) []const u8 {
|
||||||
pub const CompileError = error{
|
pub const CompileError = error{
|
||||||
LLVMError,
|
LLVMError,
|
||||||
EmitError,
|
EmitError,
|
||||||
|
TypeError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn retTypeToLLVM(ret_type: []const u8) !llvm.LLVMTypeRef {
|
||||||
|
if (std.mem.eql(u8, ret_type, "i32")) {
|
||||||
|
return llvm.LLVMInt32Type();
|
||||||
|
} else if (std.mem.eql(u8, ret_type, "bool")) {
|
||||||
|
return llvm.LLVMInt1Type();
|
||||||
|
} else {
|
||||||
|
std.debug.warn("Invalid return type: {}\n", ret_type);
|
||||||
|
return CompileError.TypeError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub const Codegen = struct {
|
pub const Codegen = struct {
|
||||||
allocator: *std.mem.Allocator,
|
allocator: *std.mem.Allocator,
|
||||||
|
|
||||||
|
@ -41,9 +53,17 @@ pub const Codegen = struct {
|
||||||
var val_cstr = try std.cstr.addNullByte(self.allocator, val);
|
var val_cstr = try std.cstr.addNullByte(self.allocator, val);
|
||||||
break :blk2 llvm.LLVMConstRealOfString(llvm.LLVMDoubleType(), val_cstr.ptr);
|
break :blk2 llvm.LLVMConstRealOfString(llvm.LLVMDoubleType(), val_cstr.ptr);
|
||||||
},
|
},
|
||||||
|
.Bool => |val| blk2: {
|
||||||
|
if (val) {
|
||||||
|
break :blk2 llvm.LLVMConstInt(llvm.LLVMInt1Type(), 1, 1);
|
||||||
|
} else {
|
||||||
|
break :blk2 llvm.LLVMConstInt(llvm.LLVMInt1Type(), 0, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
.Binary => |binary| {
|
.Binary => |binary| {
|
||||||
var left = try self.emitExpr(builder, binary.left);
|
var left = try self.emitExpr(builder, binary.left);
|
||||||
var right = try self.emitExpr(builder, binary.right);
|
var right = try self.emitExpr(builder, binary.right);
|
||||||
|
@ -54,6 +74,8 @@ pub const Codegen = struct {
|
||||||
.Mul => llvm.LLVMBuildMul(builder, left, right, c"multmp"),
|
.Mul => llvm.LLVMBuildMul(builder, left, right, c"multmp"),
|
||||||
|
|
||||||
//.Div => llvm.LLVMBuildDiv(builder, left, right, c"divtmp"),
|
//.Div => llvm.LLVMBuildDiv(builder, left, right, c"divtmp"),
|
||||||
|
.And => llvm.LLVMBuildAnd(builder, left, right, c"andtmp"),
|
||||||
|
.Or => llvm.LLVMBuildOr(builder, left, right, c"ortmp"),
|
||||||
|
|
||||||
else => {
|
else => {
|
||||||
std.debug.warn("Unexpected binary operator: '{}'\n", binary.op);
|
std.debug.warn("Unexpected binary operator: '{}'\n", binary.op);
|
||||||
|
@ -96,23 +118,24 @@ pub const Codegen = struct {
|
||||||
const name_cstr = try std.cstr.addNullByte(self.allocator, name);
|
const name_cstr = try std.cstr.addNullByte(self.allocator, name);
|
||||||
errdefer self.allocator.free(name_cstr);
|
errdefer self.allocator.free(name_cstr);
|
||||||
|
|
||||||
//const ret_type = decl.return_type.lexeme;
|
const fn_ret_type = decl.return_type.lexeme;
|
||||||
|
|
||||||
var param_types = llvm.LLVMTypeList.init(self.allocator);
|
var param_types = llvm.LLVMTypeList.init(self.allocator);
|
||||||
errdefer param_types.deinit();
|
errdefer param_types.deinit();
|
||||||
|
|
||||||
for (decl.params.toSlice()) |param| {
|
for (decl.params.toSlice()) |param| {
|
||||||
|
// TODO solve type with cute enums etc
|
||||||
try param_types.append(llvm.LLVMInt32Type());
|
try param_types.append(llvm.LLVMInt32Type());
|
||||||
}
|
}
|
||||||
|
|
||||||
var ret_type = llvm.LLVMFunctionType(
|
var llvm_ret_type = llvm.LLVMFunctionType(
|
||||||
llvm.LLVMInt32Type(),
|
try retTypeToLLVM(fn_ret_type),
|
||||||
param_types.toSlice().ptr,
|
param_types.toSlice().ptr,
|
||||||
@intCast(c_uint, param_types.len),
|
@intCast(c_uint, param_types.len),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
var func = llvm.LLVMAddFunction(mod, name_cstr.ptr, ret_type);
|
var func = llvm.LLVMAddFunction(mod, name_cstr.ptr, llvm_ret_type);
|
||||||
var entry = llvm.LLVMAppendBasicBlock(func, c"entry");
|
var entry = llvm.LLVMAppendBasicBlock(func, c"entry");
|
||||||
|
|
||||||
var builder = llvm.LLVMCreateBuilder();
|
var builder = llvm.LLVMCreateBuilder();
|
||||||
|
|
|
@ -267,19 +267,6 @@ pub const Parser = struct {
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mkLogical(self: *Parser, left: *Expr, op: Token, right: *Expr) !*Expr {
|
|
||||||
var expr = try self.allocator.create(Expr);
|
|
||||||
expr.* = Expr{
|
|
||||||
.Logical = ast.LogicalExpr{
|
|
||||||
.left = left,
|
|
||||||
.op = op,
|
|
||||||
.right = right,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mkAssign(self: *Parser, name: Token, value: *Expr) !*Expr {
|
fn mkAssign(self: *Parser, name: Token, value: *Expr) !*Expr {
|
||||||
var expr = try self.allocator.create(Expr);
|
var expr = try self.allocator.create(Expr);
|
||||||
expr.* = Expr{
|
expr.* = Expr{
|
||||||
|
@ -934,7 +921,7 @@ pub const Parser = struct {
|
||||||
_ = try self.nextToken();
|
_ = try self.nextToken();
|
||||||
|
|
||||||
var right = try self.parseAnd();
|
var right = try self.parseAnd();
|
||||||
expr = try self.mkLogical(expr, op, right);
|
expr = try self.mkBinary(expr, try toBinaryOperator(op), right);
|
||||||
}
|
}
|
||||||
|
|
||||||
return expr;
|
return expr;
|
||||||
|
@ -948,7 +935,7 @@ pub const Parser = struct {
|
||||||
_ = try self.nextToken();
|
_ = try self.nextToken();
|
||||||
|
|
||||||
var right = try self.parseEquality();
|
var right = try self.parseEquality();
|
||||||
expr = try self.mkLogical(expr, op, right);
|
expr = try self.mkBinary(expr, try toBinaryOperator(op), right);
|
||||||
}
|
}
|
||||||
|
|
||||||
return expr;
|
return expr;
|
||||||
|
|
|
@ -52,6 +52,8 @@ const keywords = [_][]const u8{
|
||||||
"println",
|
"println",
|
||||||
"loop",
|
"loop",
|
||||||
"pub",
|
"pub",
|
||||||
|
"and",
|
||||||
|
"or",
|
||||||
};
|
};
|
||||||
|
|
||||||
const keyword_ttypes = [_]TokenType{
|
const keyword_ttypes = [_]TokenType{
|
||||||
|
@ -82,6 +84,8 @@ const keyword_ttypes = [_]TokenType{
|
||||||
.Println,
|
.Println,
|
||||||
.Loop,
|
.Loop,
|
||||||
.Pub,
|
.Pub,
|
||||||
|
.And,
|
||||||
|
.Or,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn getKeyword(keyword: []const u8) ?TokenType {
|
fn getKeyword(keyword: []const u8) ?TokenType {
|
||||||
|
|
Loading…
Reference in New Issue