From e17c3c2e297168aa3268b70cbd3a3d692bdde951 Mon Sep 17 00:00:00 2001 From: Baitinq Date: Wed, 9 Jul 2025 22:15:36 +0200 Subject: Bootstrap: Support equality expressions --- src/bootstrap/codegen.pry | 49 ++++++++++++++++++++ src/bootstrap/llvm.pry | 13 ++++++ src/bootstrap/parser.pry | 114 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 170 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry index 8b95451..c115da9 100644 --- a/src/bootstrap/codegen.pry +++ b/src/bootstrap/codegen.pry @@ -474,6 +474,55 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: * return codegen_create_variable(c, v); }; + if ((*expression).type == NODE_EQUALITY_EXPRESSION) { + let exp = (*(cast(*NODE_EQUALITY_EXPRESSION_DATA, (*expression).data))); + let lhs_value = codegen_generate_expression_value(c, exp.lhs, cast(*i8, null)); + if lhs_value == cast(*Variable, null) { + return cast(*Variable, null); + }; + let rhs_value = codegen_generate_expression_value(c, exp.rhs, cast(*i8, null)); + if rhs_value == cast(*Variable, null) { + return cast(*Variable, null); + }; + + /* TODO: compare types */ + let op = -1; + + if exp.typ == EQUALITY_EXPRESSION_TYPE_EQ { + op = LLVMIntEQ; + }; + if exp.typ == EQUALITY_EXPRESSION_TYPE_NE { + op = LLVMIntNE; + }; + if exp.typ == EQUALITY_EXPRESSION_TYPE_GE { + op = LLVMIntSGE; + }; + if exp.typ == EQUALITY_EXPRESSION_TYPE_LE { + op = LLVMIntSLE; + }; + if exp.typ == EQUALITY_EXPRESSION_TYPE_LT { + op = LLVMIntSLT; + }; + if exp.typ == EQUALITY_EXPRESSION_TYPE_GT { + op = LLVMIntSGT; + }; + + assert(op != -1); + + let cmp = LLVMBuildICmp((*c).builder, cast(LLVMIntPredicate, op), (*lhs_value).value, (*rhs_value).value, ""); + + + let node_type = Node{}; + node_type.type = NODE_TYPE_SIMPLE_TYPE; + + let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); + (*d).name = "bool"; + (*d).underlying_type = cast(*Node, null); + node_type.data = cast(*void, d); + + return codegen_generate_literal(c, cmp, name, expression, create_node(c, node_type)); + }; + if ((*expression).type == NODE_TYPE_FUNCTION_TYPE) { let e = *((*c).environment); printf("LLEL\n"); diff --git a/src/bootstrap/llvm.pry b/src/bootstrap/llvm.pry index 51ab978..bc68d86 100644 --- a/src/bootstrap/llvm.pry +++ b/src/bootstrap/llvm.pry @@ -255,6 +255,7 @@ let LLVMModuleRef = newtype *void; let LLVMTargetMachineRef = newtype *void; let LLVMContextRef = newtype *void; let LLVMTargetRef = newtype *void; +let LLVMIntPredicate = newtype i64; let LLVMValueRef = newtype *void; let LLVMTypeRef = newtype *void; @@ -315,3 +316,15 @@ extern LLVMGetLastInstruction = (LLVMBasicBlockRef) => LLVMValueRef; extern LLVMBuildBr = (LLVMBuilderRef, LLVMBasicBlockRef) => LLVMValueRef; extern LLVMIsATerminatorInst = (LLVMValueRef) => LLVMValueRef; extern LLVMBuildCondBr = (LLVMBuilderRef, LLVMValueRef, LLVMBasicBlockRef, LLVMBasicBlockRef) => LLVMValueRef; +extern LLVMBuildICmp = (LLVMBuilderRef, LLVMIntPredicate, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef; + +let LLVMIntEQ = 32; +let LLVMIntNE = 33; +let LLVMIntUGT = 34; +let LLVMIntUGE = 35; +let LLVMIntULT = 36; +let LLVMIntULE = 37; +let LLVMIntSGT = 38; +let LLVMIntSGE = 39; +let LLVMIntSLT = 40; +let LLVMIntSLE = 41; diff --git a/src/bootstrap/parser.pry b/src/bootstrap/parser.pry index 95f847b..cb8c269 100644 --- a/src/bootstrap/parser.pry +++ b/src/bootstrap/parser.pry @@ -200,6 +200,7 @@ let parser = struct { extern parser_parse_statement = (*parser) => *Node; extern parser_parse_expression = (*parser) => *Node; extern parse_function_call_statement = (*parser) => *Node; +extern parser_parse_additive_expression = (*parser) => *Node; let parser_init = (ts: *token, ts_len: i64, ar: *arena) => *parser { let p = cast(*parser, arena_alloc(ar, sizeof(parser))); @@ -599,8 +600,105 @@ let parser_parse_primary_expression = (p: *parser) => *Node { /* EqualityExpression ::= AdditiveExpression ("==" | "!=" | "<=" | ">=" | "<" | ">") AdditiveExpression */ let parser_parse_equality_expression = (p: *parser) => *Node { - /* TODO */ - return cast(*Node, null); + let lhs = parser_parse_additive_expression(p); + if lhs == cast(*Node, null) { + return cast(*Node, null); + }; + + let typ = -1; + let ex = parser_accept_parse(p, (ip: *parser) => *Node { + if parser_accept_token(ip, TOKEN_BANG) == cast(*token, null) { + return cast(*Node, null); + }; + if parser_accept_token(ip, TOKEN_BANG) == cast(*token, null) { + return cast(*Node, null); + }; + let n = Node{}; + return create_node(ip, n); + }); + if ex != cast(*Node, null) { + typ = EQUALITY_EXPRESSION_TYPE_EQ; + }; + + if (typ == -1) { + ex = parser_accept_parse(p, (ip: *parser) => *Node { + if (parser_accept_token(ip, TOKEN_BANG) == cast(*token, null)) { + return cast(*Node, null); + }; + if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) { + return cast(*Node, null); + }; + let n = Node{}; + return create_node(ip, n); + }); + if (ex != cast(*Node, null)) { + typ = EQUALITY_EXPRESSION_TYPE_NE; + }; + }; + + if (typ == -1) { + ex = parser_accept_parse(p, (ip: *parser) => *Node { + if (parser_accept_token(ip, TOKEN_LESS) == cast(*token, null)) { + return cast(*Node, null); + }; + if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) { + return cast(*Node, null); + }; + let n = Node{}; + return create_node(ip, n); + }); + if (ex != cast(*Node, null)) { + typ = EQUALITY_EXPRESSION_TYPE_LE; + }; + }; + + if (typ == -1) { + ex = parser_accept_parse(p, (ip: *parser) => *Node { + if (parser_accept_token(ip, TOKEN_GREATER) == cast(*token, null)) { + return cast(*Node, null); + }; + if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) { + return cast(*Node, null); + }; + let n = Node{}; + return create_node(ip, n); + }); + if (ex != cast(*Node, null)) { + typ = EQUALITY_EXPRESSION_TYPE_GE; + }; + }; + + if (typ == -1) { + if (parser_accept_token(p, TOKEN_LESS) != cast(*token, null)) { + typ = EQUALITY_EXPRESSION_TYPE_LT; + }; + }; + + if (typ == -1) { + if (parser_accept_token(p, TOKEN_GREATER) != cast(*token, null)) { + typ = EQUALITY_EXPRESSION_TYPE_GT; + }; + }; + + if typ == -1 { + return cast(*Node, null); + }; + + let rhs = parser_parse_additive_expression(p); + if rhs == cast(*Node, null) { + return cast(*Node, null); + }; + + let d = cast(*NODE_EQUALITY_EXPRESSION_DATA, arena_alloc((*p).arena, sizeof(NODE_EQUALITY_EXPRESSION_DATA))); + (*d).lhs = lhs; + (*d).rhs = rhs; + (*d).typ = typ; + + let n = Node{}; + n.type = NODE_EQUALITY_EXPRESSION ; + n.data = cast(*void, d); + + return create_node(p, n); }; /* PostfixExpression ::= PrimaryExpression (CastStatement | SizeOfStatement | FunctionCallStatement | FieldAccess )* */ @@ -618,11 +716,15 @@ let parser_parse_unary_expression = (p: *parser) => *Node { if parser_accept_token(p, TOKEN_BANG) != cast(*token, null) { typ = UNARY_EXPRESSION_TYPE_NOT; }; - if parser_accept_token(p, TOKEN_MINUS) != cast(*token, null) { - typ = UNARY_EXPRESSION_TYPE_MINUS; + if typ == -1 { + if parser_accept_token(p, TOKEN_MINUS) != cast(*token, null) { + typ = UNARY_EXPRESSION_TYPE_MINUS; + }; }; - if parser_accept_token(p, TOKEN_MUL) != cast(*token, null) { - typ = UNARY_EXPRESSION_TYPE_STAR; + if typ == -1 { + if parser_accept_token(p, TOKEN_MUL) != cast(*token, null) { + typ = UNARY_EXPRESSION_TYPE_STAR; + }; }; if typ == -1 { return parser_parse_postfix_expression(p); -- cgit 1.4.1