about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBaitinq <[email protected]>2025-07-13 10:06:44 +0200
committerBaitinq <[email protected]>2025-07-13 10:06:44 +0200
commitb74dc51d07ca6f928127223165ed84e5a5b33e78 (patch)
tree6b3554c30aac27ad31f8858af26c9a83bded1901 /src
parentBoostrap: Support calling function ptr (diff)
downloadpry-lang-b74dc51d07ca6f928127223165ed84e5a5b33e78.tar.gz
pry-lang-b74dc51d07ca6f928127223165ed84e5a5b33e78.tar.bz2
pry-lang-b74dc51d07ca6f928127223165ed84e5a5b33e78.zip
Boostrap: Fuction def call and multiplicative expr
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/codegen.pry93
-rw-r--r--src/bootstrap/llvm.pry4
-rw-r--r--src/bootstrap/parser.pry28
3 files changed, 86 insertions, 39 deletions
diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry
index 2846378..934b532 100644
--- a/src/bootstrap/codegen.pry
+++ b/src/bootstrap/codegen.pry
@@ -355,10 +355,7 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 	};
 	
 	if ((*expression).type == NODE_FUNCTION_DEFINITION) {
-		printf("THIS2\n");
-	/* TODO: IMPLEMENT */
-		printf("ASS %d\n", (*expression).type);
-
+                /* Functions should be declared "globally" */
 		let builder_pos = LLVMGetInsertBlock((*c).builder);
 
 		let llvm_param_types = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef) * 20));
@@ -393,8 +390,12 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 		let retur_type = codegen_get_llvm_type(c, function_definition.retur_type);
 		assert(retur_type != cast(*LLVMTypeRef, null));
 
-		let function_type = LLVMFunctionType(*retur_type, llvm_param_types, i, 0);
-		let function = LLVMAddFunction((*c).llvm_module, name, function_type);
+		let function_type = LLVMFunctionType(*retur_type, llvm_param_types, i, is_varargs);
+		let n_name = name;
+		if name == cast(*i8, null) {
+			n_name = "unnamed_func";
+		};
+		let function = LLVMAddFunction((*c).llvm_module, n_name, function_type);
                 let function_entry = LLVMAppendBasicBlock(function, "entrypoint");
                 LLVMPositionBuilderAtEnd((*c).builder, function_entry);
 
@@ -416,12 +417,11 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 		(*node_type).type = NODE_TYPE_FUNCTION_TYPE;
 		(*node_type).data = cast(*void, d);
 
-		/* TODO: Recurisve functions */
+                /* TODO: Needed for recursive functions */
 
 		let params = cast(*LLVMValueRef, arena_alloc((*c).arena, sizeof(LLVMValueRef) * function_definition.parameters_len));
 		LLVMGetParams(function, params);
 
-		/* TODO */
 		let parameters_index = 0;
 		while parameters_index < function_definition.parameters_len {
 			let p = (*(params + cast(*LLVMValueRef, parameters_index)));
@@ -561,6 +561,31 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 		return codegen_generate_literal(c, result, name, expression, pnode_type);
 	};
 	
+	if ((*expression).type == NODE_MULTIPLICATIVE_EXPRESSION) {
+		let exp = (*(cast(*NODE_MULTIPLICATIVE_EXPRESSION_DATA, (*expression).data)));
+		let lhs_value = codegen_generate_expression_value(c, exp.lhs, cast(*i8, null));
+		assert(lhs_value != cast(*Variable, null));
+		let rhs_value = codegen_generate_expression_value(c, exp.rhs, cast(*i8, null));
+		assert(rhs_value != cast(*Variable, null));
+
+		/* TODO: Compare types */
+
+		let result = cast(LLVMValueRef, null);
+
+		if exp.typ == MULTIPLICATIVE_EXPRESSION_TYPE_MUL {
+			result = LLVMBuildMul((*c).builder, (*lhs_value).value, (*rhs_value).value, "");
+		};
+		if exp.typ == MULTIPLICATIVE_EXPRESSION_TYPE_DIV {
+			result = LLVMBuildSDiv((*c).builder, (*lhs_value).value, (*rhs_value).value, "");
+		};
+		if exp.typ == MULTIPLICATIVE_EXPRESSION_TYPE_MOD {
+			result = LLVMBuildSRem((*c).builder, (*lhs_value).value, (*rhs_value).value, "");
+		};
+		assert(result != cast(LLVMValueRef, null));
+
+		return codegen_generate_literal(c, result, name, expression, (*lhs_value).node_type);
+	};
+	
 	if ((*expression).type == NODE_UNARY_EXPRESSION) {
 		let exp = (*(cast(*NODE_UNARY_EXPRESSION_DATA, (*expression).data)));
 		let k = codegen_generate_expression_value(c, exp.expression, cast(*i8, null));
@@ -570,7 +595,9 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 		let typ = (*k).node_type;
 
 		if exp.typ == UNARY_EXPRESSION_TYPE_NOT {
-			/* TODO: assert bool */
+			assert((*typ).type == NODE_TYPE_SIMPLE_TYPE);
+			let simple_type = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*typ).data);
+			assert(strcmp(simple_type.name, "bool"));
                         r = LLVMBuildICmp((*c).builder, cast(LLVMIntPredicate, LLVMIntEQ), (*k).value, LLVMConstInt(LLVMInt1Type(), 0, 0), "");
 			let node_type = Node{};
 			node_type.type = NODE_TYPE_SIMPLE_TYPE;
@@ -595,7 +622,7 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 		};
 		
 		if exp.typ == UNARY_EXPRESSION_TYPE_STAR {
-			/* TODO: assert ptr */
+			assert((*typ).type == NODE_TYPE_POINTER_TYPE);
 			let n = (*k).node_type;
 			typ = (*cast(*NODE_TYPE_POINTER_TYPE_DATA, (*n).data)).type;
 			let ptr_type = codegen_get_llvm_type(c, typ);
@@ -608,11 +635,12 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 	
 	if ((*expression).type == NODE_TYPE_FUNCTION_TYPE) {
 		let e = *((*c).environment);
-		printf("LLEL\n");
 		assert(e.scope_stack_len == 1);
-		printf("THIS3\n");
 
-		/* TODO: Check if already exists */
+		let existing = environment_get_variable((*c).environment, name);
+		if (existing != cast(*Variable, null)) {
+			return existing;
+		};
 
 		let function_type = codegen_get_llvm_type(c, expression);
 		assert(function_type != cast(*LLVMTypeRef, null));
@@ -767,30 +795,37 @@ let get_function_return_type = (ic: *codegen, fun: *Node) => *Node {
 let codegen_generate_function_call_statement = (c: *codegen, statement: *Node) => *Variable {
 	assert((*statement).type == NODE_FUNCTION_CALL_STATEMENT);
 	let stmt = cast(*NODE_FUNCTION_CALL_STATEMENT_DATA, (*statement).data);
-	let expression = (*(*stmt).expression);
-	assert(expression.type == NODE_PRIMARY_EXPRESSION_IDENTIFIER); /* TODO: Function definition support */
+	let expression = (*stmt).expression;
 
-	let ident = (*cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, expression.data));
-	let function = environment_get_variable((*c).environment, ident.name);
-	if function == cast(*Variable, null) {
-		printf("NO variable: %s\n", ident.name);
-		assert(false);
-	};
 	let node = statement;
-	if LLVMGetValueKind((*function).value) != LLVMFunctionValueKind {
-		let lt = codegen_get_llvm_type(c, (*function).node_type);
-		assert(lt != cast(*LLVMTypeRef, null));
-		(*function).value = LLVMBuildLoad2((*c).builder, LLVMPointerType(*lt, 0), (*function).value, "");
-		node = (*function).node;
+	let function = cast(*Variable, null);
+
+	if (*expression).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER {
+		let ident = (*cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*expression).data));
+		function = environment_get_variable((*c).environment, ident.name);
+		if function == cast(*Variable, null) {
+			printf("NO variable: %s\n", ident.name);
+			assert(false);
+		};
+
+		if LLVMGetValueKind((*function).value) != LLVMFunctionValueKind {
+			let lt = codegen_get_llvm_type(c, (*function).node_type);
+			assert(lt != cast(*LLVMTypeRef, null));
+			(*function).value = LLVMBuildLoad2((*c).builder, LLVMPointerType(*lt, 0), (*function).value, "");
+			node = (*function).node;
+		};
 	};
+	if (*expression).type == NODE_FUNCTION_DEFINITION {
+		function = codegen_generate_expression_value(c, expression, cast(*i8, null));
+	};
+
+	assert(function != cast(*Variable, null));
 
 	let arguments = cast(*LLVMValueRef, arena_alloc((*c).arena, sizeof(LLVMValueRef) * (*stmt).arguments_len));
 
 	let i = 0;
-	printf("arguments_len: %d\n", (*stmt).arguments_len);
-
 	while i < (*stmt).arguments_len {
-		let argument = (*((*stmt).arguments + cast(**Node, i))); /* TODO */
+		let argument = (*((*stmt).arguments + cast(**Node, i)));
 		let arg = codegen_generate_expression_value(c, argument, cast(*i8, null));
 		assert(arg != cast(*Variable, null));
 		/* TODO: Typecheck */
diff --git a/src/bootstrap/llvm.pry b/src/bootstrap/llvm.pry
index 2ddcd2c..3f794e3 100644
--- a/src/bootstrap/llvm.pry
+++ b/src/bootstrap/llvm.pry
@@ -321,6 +321,10 @@ extern LLVMBuildICmp = (LLVMBuilderRef, LLVMIntPredicate, LLVMValueRef, LLVMValu
 extern LLVMBuildNeg = (LLVMBuilderRef, LLVMValueRef, *i8) => LLVMValueRef;
 extern LLVMBuildSub = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
 extern LLVMBuildAdd = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
+extern LLVMBuildMul = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
+extern LLVMBuildSDiv = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
+extern LLVMBuildSRem = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
+
 extern LLVMBuildGEP2 = (LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, *LLVMValueRef, i64, *i8) => LLVMValueRef;
 extern LLVMAddGlobal = (LLVMModuleRef, LLVMTypeRef, *i8) => LLVMValueRef;
 extern LLVMSetInitializer = (LLVMValueRef, LLVMValueRef) => void;
diff --git a/src/bootstrap/parser.pry b/src/bootstrap/parser.pry
index bc36a41..5c34edb 100644
--- a/src/bootstrap/parser.pry
+++ b/src/bootstrap/parser.pry
@@ -1084,12 +1084,14 @@ let parser_parse_function_arguments = (p: *parser) => *slice {
 /* FunctionCallStatement ::= (IDENTIFIER | FunctionDefinition) LPAREN FunctionArguments? RPAREN */
 let parse_function_call_statement = (p: *parser) => *Node {
 	let ident = parser_accept_token(p, TOKEN_IDENTIFIER);
+	let fn_def = parser_accept_parse(p, parser_parse_function_definition);
+
 	if ident == cast(*token, null) {
-		return cast(*Node, null);
+		if fn_def == cast(*Node, null) {
+			return cast(*Node, null);
+		};
 	};
 
-	/* TODO: Function definition call */
-		
 	if parser_accept_token(p, TOKEN_LPAREN) == cast(*token, null) {
 	    return cast(*Node, null);
 	};
@@ -1103,16 +1105,22 @@ let parse_function_call_statement = (p: *parser) => *Node {
 	    return cast(*Node, null);
 	};
 
-	let expression_data = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA)));
-	(*expression_data).name = cast(*i8, (*ident).data);
-	let expression = cast(*Node, arena_alloc((*p).arena, sizeof(Node)));
-	(*expression).type = NODE_PRIMARY_EXPRESSION_IDENTIFIER;
-	(*expression).data = cast(*void, expression_data);
-
 	let d = cast(*NODE_FUNCTION_CALL_STATEMENT_DATA , arena_alloc((*p).arena, sizeof(NODE_FUNCTION_CALL_STATEMENT_DATA)));
-	(*d).expression = expression;
 	(*d).arguments = cast(**Node, (*arguments).data);
 	(*d).arguments_len = (*arguments).data_len;
+
+	if fn_def != cast(*Node, null) {
+		(*d).expression = fn_def;
+	};
+	if fn_def == cast(*Node, null) {
+		let expression_data = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA)));
+		(*expression_data).name = cast(*i8, (*ident).data);
+		let expression = cast(*Node, arena_alloc((*p).arena, sizeof(Node)));
+		(*expression).type = NODE_PRIMARY_EXPRESSION_IDENTIFIER;
+		(*expression).data = cast(*void, expression_data);
+		(*d).expression = expression;
+	};
+
 	let n = Node{};
 	n.type = NODE_FUNCTION_CALL_STATEMENT;
 	n.data = cast(*void, d);