about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <[email protected]>2025-07-09 22:15:36 +0200
committerBaitinq <[email protected]>2025-07-09 22:15:36 +0200
commite17c3c2e297168aa3268b70cbd3a3d692bdde951 (patch)
tree6641768f70486c5387d7cf1614e6aaf6d9a9f4b8
parentBootstrap: Support if statement (diff)
downloadpry-lang-e17c3c2e297168aa3268b70cbd3a3d692bdde951.tar.gz
pry-lang-e17c3c2e297168aa3268b70cbd3a3d692bdde951.tar.bz2
pry-lang-e17c3c2e297168aa3268b70cbd3a3d692bdde951.zip
Bootstrap: Support equality expressions
-rw-r--r--src/bootstrap/codegen.pry49
-rw-r--r--src/bootstrap/llvm.pry13
-rw-r--r--src/bootstrap/parser.pry114
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);