about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/codegen.pry75
-rw-r--r--src/bootstrap/llvm.pry2
-rw-r--r--src/bootstrap/parser.pry4
3 files changed, 74 insertions, 7 deletions
diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry
index fefc17d..eea8c58 100644
--- a/src/bootstrap/codegen.pry
+++ b/src/bootstrap/codegen.pry
@@ -418,17 +418,81 @@ let codegen_generate_return_statement = (c: *codegen, stmt: *NODE_RETURN_STATEME
 	return 0;
 };
 
-let codegen_generate_function_call_statement = (c: *codegen, stmt: *NODE_FUNCTION_CALL_STATEMENT_DATA) => i64 {
+let get_function_return_type = (ic: *codegen, fun: *Node) => *Node {
+	if (*fun).type == NODE_FUNCTION_DEFINITION {
+		let d = cast(*NODE_FUNCTION_DEFINITION_DATA, (*fun).data);
+		return (*d).retur_type;
+	};
+	if (*fun).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER {
+		let d = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*fun).data);
+		let f = environment_get_variable((*ic).environment, (*d).name);
+		if f == cast(*Variable, null) {
+			return cast(*Node, null);
+		};
+		let f_type = (*f).node_type;
+		assert((*f_type).type == NODE_TYPE_FUNCTION_TYPE);
+		return get_function_return_type(ic, f_type);
+	};
+	if (*fun).type == NODE_TYPE_FUNCTION_TYPE  {
+		let d = cast(*NODE_TYPE_FUNCTION_TYPE_DATA, (*fun).data);
+		return (*d).retur_type;
+	};
+	printf("HMM %d\n", (*fun).type);
+	assert(false);
+	return cast(*Node, null);
+};
+
+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 ident = (*cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, expression.data));
 	let function = environment_get_variable((*c).environment, ident.name);
+	if function == cast(*Variable, null) {
+		return cast(*Variable, null);
+	};
+	/* TODO: Support function ptr */
 
-	printf("LELELEL\n");
-	assert(false);
+	let arguments = cast(*LLVMValueRef, arena_alloc((*c).arena, sizeof(LLVMValueRef) * (*stmt).arguments_len));
 
-	return 0;
+	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 arg = codegen_generate_expression_value(c, argument, cast(*i8, null));
+		if arg == cast(*Variable, null) {
+			printf("BAD");
+			assert(false);
+		};
+		/* TODO: Typecheck */
+
+		(*(arguments + cast(*LLVMValueRef, i))) = arg;
+
+		i = i + 1;
+	};
+
+	let function_type = codegen_get_llvm_type(c, (*function).node_type);
+	if function_type == cast(*LLVMTypeRef, null) {
+		printf("FN Type\n");
+		assert(false);
+	};
+
+	let res = LLVMBuildCall2((*c).builder, *function_type, (*function).value, arguments, i, "");
+
+	let function_return_type = get_function_return_type(c, (*function).node_type);
+
+	let v = Variable{};
+
+	v.value = res;
+	v.type = cast(LLVMTypeRef, null);
+	v.stack_level = cast(*i64, null);
+	v.node = statement;
+	v.node_type = function_return_type;
+
+	return codegen_create_variable(c, v);
 };
 
 let codegen_generate_statement = (c: *codegen, statement: *Node) => i64 {
@@ -443,7 +507,8 @@ let codegen_generate_statement = (c: *codegen, statement: *Node) => i64 {
 	};
 	
 	if stmt.type == NODE_FUNCTION_CALL_STATEMENT {
-		return codegen_generate_function_call_statement(c, cast(*NODE_FUNCTION_CALL_STATEMENT_DATA, stmt.data));
+		codegen_generate_function_call_statement(c, statement);
+		return 0;
 	};
 
 	printf("ASSERT 3 %d\n", stmt.type);
diff --git a/src/bootstrap/llvm.pry b/src/bootstrap/llvm.pry
index 85b3c2b..71dce09 100644
--- a/src/bootstrap/llvm.pry
+++ b/src/bootstrap/llvm.pry
@@ -303,3 +303,5 @@ extern LLVMGetParams = (LLVMValueRef, *LLVMValueRef) => void;
 extern LLVMBuildRetVoid = (LLVMBuilderRef) => void;
 extern LLVMBuildRet = (LLVMBuilderRef, LLVMValueRef) => void;
 extern LLVMPointerType = (LLVMTypeRef, i64) => LLVMTypeRef;
+
+extern LLVMBuildCall2 = (LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, *LLVMValueRef, i64, *i8) => LLVMValueRef;
diff --git a/src/bootstrap/parser.pry b/src/bootstrap/parser.pry
index 6ad7a39..40ed001 100644
--- a/src/bootstrap/parser.pry
+++ b/src/bootstrap/parser.pry
@@ -649,8 +649,8 @@ let parse_function_call_statement = (p: *parser) => *Node {
 
 	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;
+	(*d).arguments = cast(**Node, (*arguments).data);
+	(*d).arguments_len = (*arguments).data_len;
 	let n = Node{};
 	n.type = NODE_FUNCTION_CALL_STATEMENT;
 	n.data = cast(*void, d);