about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/codegen.pry204
-rw-r--r--src/bootstrap/llvm.pry13
-rw-r--r--src/bootstrap/parser.pry30
-rw-r--r--src/codegen.zig11
4 files changed, 224 insertions, 34 deletions
diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry
index 7293c09..7d83a3b 100644
--- a/src/bootstrap/codegen.pry
+++ b/src/bootstrap/codegen.pry
@@ -1,10 +1,60 @@
+import "!hashmap.pry";
+
 import "llvm.pry";
 
+let Variable = struct {
+	value: LLVMValueRef,
+	type: LLVMTypeRef,
+	node: *Node,
+	node_type: *Node,
+	stack_level: *i64,
+};
+
+let Scope = struct {
+	variables: *HashMap,
+};
+
+let Environment = struct {
+	scope_stack: **Scope,
+	scope_stack_len: i64,
+	arena: *arena,
+};
+
+let environment_create_scope = (e: *Environment) => void {
+	let scope = cast(*Scope, arena_alloc((*e).arena, sizeof(Scope)));
+	(*scope).variables = hashmap_init(16, (*e).arena);
+	(*((*e).scope_stack + cast(**Scope, (*e).scope_stack_len))) = scope;
+	(*e).scope_stack_len = (*e).scope_stack_len + 1;
+
+	return;
+};
+
+let environment_drop_scope = (e: *Environment) => void {
+	(*e).scope_stack_len = (*e).scope_stack_len - 1;
+
+	return;
+};
+
+let environment_init = (alloc: *arena) => *Environment {
+	let e = cast(*Environment, arena_alloc(alloc, sizeof(Environment)));
+	(*e).scope_stack = cast(**Scope, arena_alloc(alloc, sizeof(*Scope) * 20));
+	(*e).scope_stack_len = 0;
+	(*e).arena = alloc;
+
+	environment_create_scope(e);
+
+	return e;
+};
+
 let codegen = struct {
 	llvm_module: LLVMModuleRef,
 	llvm_context: LLVMContextRef,
 	builder: LLVMBuilderRef,
 	arena: *arena,
+	environment: *Environment,
+
+	current_function: LLVMValueRef,
+	current_function_retur_type: *Node,
 };
 
 let codegen_init = (alloc: *arena) => *codegen {
@@ -24,6 +74,7 @@ let codegen_init = (alloc: *arena) => *codegen {
 	(*c).llvm_context = context;
 	(*c).builder = builder;
 	(*c).arena = alloc;
+	(*c).environment = environment_init(alloc);
 
 	return c;
 };
@@ -34,20 +85,33 @@ let create_node = (c: *codegen, n: Node) => *Node {
 	return res;
 };
 
-let Variable = struct {
-	value: LLVMValueRef,
-	type: LLVMTypeRef,
-	node: *Node,
-	node_type: *Node,
-	stack_level: *i64,
-};
-
 let codegen_create_variable = (c: *codegen, variable: Variable) => *Variable {
 	let v = cast(*Variable, arena_alloc((*c).arena, sizeof(Variable)));
 	*v = variable;
 	return v;
 };
 
+let codegen_get_llvm_type = (c: *codegen, node: *Node) => *LLVMTypeRef {
+	printf("LLVM TYPE: %d\n", (*node).type);
+	assert((*node).type >= NODE_TYPE_SIMPLE_TYPE);
+	assert((*node).type <= NODE_TYPE_STRUCT_TYPE);
+	
+	assert((*node).type == NODE_TYPE_SIMPLE_TYPE); /* TODO */
+
+	let simple_type = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*node).data);
+	
+	if strcmp(simple_type.name, "i64") {
+		let r = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef)));
+		*r = LLVMInt64Type();
+		return r;
+	};
+
+	printf("NO TYPE!\n");
+	assert(false);
+
+	return cast(*LLVMTypeRef, null);
+};
+
 let codegen_generate_literal = (c: *codegen, literal_val: LLVMValueRef, name: *i8, node: *Node, node_type: *Node) => *Variable {
 	/* TODO: Global */
 	let v = Variable{};
@@ -59,6 +123,8 @@ let codegen_generate_literal = (c: *codegen, literal_val: LLVMValueRef, name: *i
 	return codegen_create_variable(c, v);
 };
 
+extern codegen_generate_statement = (*codegen, *Node) => i64;
+
 let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *i8) => *Variable {
 	if ((*expression).type == NODE_PRIMARY_EXPRESSION_NUMBER) {
 		let n = (*cast(*NODE_PRIMARY_EXPRESSION_NUMBER_DATA, (*expression).data)).value;
@@ -77,11 +143,89 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 	};
 	
 	if ((*expression).type == NODE_FUNCTION_DEFINITION) {
+	/* TODO: IMPLEMENT */
 		printf("ASS %d\n", (*expression).type);
-		assert(false); /* TODO */
-		printf("ERT\n");
+
+		let builder_pos = LLVMGetInsertBlock((*c).builder);
+
+		let llvm_param_types = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef) * 20));
+		let param_types = cast(**Node, arena_alloc((*c).arena, sizeof(*Node) * 20));
+		/* TODO: VARARGS */
+
+		
+		let function_definition = *cast(*NODE_FUNCTION_DEFINITION_DATA, (*expression).data);
+
+		let i = 0;
+		/* TODO */
+		while i < function_definition.parameters_len {
+			i = i + 1;
+		};
+
+		let retur_type = codegen_get_llvm_type(c, function_definition.retur_type);
+		if retur_type == cast(*LLVMTypeRef, null) {
+			printf("LEL\n");
+			return cast(*Variable, null);
+		};
+
+		let function_type = LLVMFunctionType(*retur_type, llvm_param_types, i, 0);
+		let function = LLVMAddFunction((*c).llvm_module, name, function_type);
+                let function_entry = LLVMAppendBasicBlock(function, "entrypoint");
+                LLVMPositionBuilderAtEnd((*c).builder, function_entry);
+
+		/* TODO: SCOPE */
+		environment_create_scope((*c).environment);
+		let last_function = (*c).current_function;
+		(*c).current_function = function;
+		let last_function_retur_type = (*c).current_function_retur_type;
+		(*c).current_function_retur_type = function_definition.retur_type;
+
+		/* TODO: Defer */
+
+		let d = cast(*NODE_TYPE_FUNCTION_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_FUNCTION_TYPE_DATA)));
+		(*d).parameters = param_types;
+		(*d).parameters_len = i;
+		(*d).retur_type = function_definition.retur_type;
+		let n = Node{};
+		let node_type = create_node(c, n);
+		(*node_type).type = NODE_TYPE_FUNCTION_TYPE;
+		(*node_type).data = cast(*void, d);
+
+		/* TODO: Recurisve 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 {
+			parameters_index = parameters_index + 1;
+		};
+
+		i = 0;
+		while i < function_definition.statements_len {
+			let stmt = *(function_definition.statements + cast(**Node, i));
+
+			let res = codegen_generate_statement(c, stmt);
+			if res != 0 {
+				return cast(*Variable, null);
+			};
+
+			i = i + 1;
+		};
+
+		LLVMPositionBuilderAtEnd((*c).builder, builder_pos);
+	
+		let v = Variable{};
+		v.value = function;
+		v.type = cast(LLVMTypeRef, null);
+		v.stack_level = cast(*i64, null);
+		v.node = expression;
+		v.node_type = node_type;
+		return codegen_create_variable(c, v);
 	};
 
+	printf("ASSERT 1\n");
 	assert(false);
 
 	return cast(*Variable, null);
@@ -99,19 +243,49 @@ let codegen_generate_assignment_statement = (c: *codegen, stmt: *NODE_ASSIGNMENT
 		return 0;
 	};
 
+	printf("ASSERT 2 %d\n", lhs.type);
 	assert(false);
 	return 0;
 };
 
+let codegen_generate_return_statement = (c: *codegen, stmt: *NODE_RETURN_STATEMENT_DATA) => i64 {
+	printf("HELLO!\n");
+	let expression = (*stmt).expression;
+
+	if expression == cast(*Node, null) {
+		printf("RETURN VOID!\n");
+		LLVMBuildRetVoid((*c).builder);
+		return 0;
+	};
+
+	let val = codegen_generate_expression_value(c, expression, cast(*i8, null));
+	if val == cast(*Variable, null) {
+		return 1;
+	};
+
+	/* TODO: Check type */
+
+	LLVMBuildRet((*c).builder, (*val).value);
+
+	printf("BYE!\n");
+
+	return 0;
+};
+
 let codegen_generate_statement = (c: *codegen, statement: *Node) => i64 {
 	let stmt = *statement;
-	assert(stmt.type == NODE_ASSIGNMENT_STATEMENT); /* TODO: generate other node types */
 
-	let res = codegen_generate_assignment_statement(c, cast(*NODE_ASSIGNMENT_STATEMENT_DATA, stmt.data));
-	if res != 0 {
-		return 1;
+	if stmt.type == NODE_ASSIGNMENT_STATEMENT {
+		return codegen_generate_assignment_statement(c, cast(*NODE_ASSIGNMENT_STATEMENT_DATA, stmt.data));
 	};
-	printf("STMT: %d\n", stmt.type);
+
+	if stmt.type == NODE_RETURN_STATEMENT {
+		return codegen_generate_return_statement(c, cast(*NODE_RETURN_STATEMENT_DATA, stmt.data));
+	};
+
+	printf("ASSERT 3 %d\n", stmt.type);
+	assert(false);
+
 	return 0;
 };
 
diff --git a/src/bootstrap/llvm.pry b/src/bootstrap/llvm.pry
index 8cd600f..f958286 100644
--- a/src/bootstrap/llvm.pry
+++ b/src/bootstrap/llvm.pry
@@ -258,6 +258,7 @@ let LLVMTargetRef = newtype *void;
 
 let LLVMValueRef = newtype *void;
 let LLVMTypeRef = newtype *void;
+let LLVMBasicBlockRef = newtype *void;
 
 extern LLVMConstInt = (LLVMTypeRef, i64, i64) => LLVMValueRef;
 extern LLVMInt64Type = () => LLVMTypeRef;
@@ -269,6 +270,8 @@ extern LLVMDisposeModule = (LLVMModuleRef) => void;
 extern LLVMShutdown = () => void;
 extern LLVMDisposeBuilder = (LLVMBuilderRef) => void;
 
+extern LLVMGetInsertBlock = (LLVMBuilderRef) => LLVMBasicBlockRef;
+
 extern LLVMDumpModule = (LLVMModuleRef) => void;
 extern LLVMGetDefaultTargetTriple = () => *i8;
 extern LLVMGetTargetFromTriple = (*i8, *LLVMTargetRef, **i8) => i64;
@@ -287,3 +290,13 @@ let LLVMAbortProcessAction = 0;
 extern LLVMTargetMachineEmitToFile = (LLVMTargetMachineRef, LLVMModuleRef, *i8, i64, **i8) => i64;
 
 let LLVMObjectFile = 1;
+
+extern LLVMFunctionType = (LLVMTypeRef, *LLVMTypeRef, i64, i64) => LLVMTypeRef;
+extern LLVMAddFunction = (LLVMModuleRef, *i8, LLVMTypeRef) => LLVMValueRef;
+extern LLVMAppendBasicBlock = (LLVMValueRef, *i8) => LLVMBasicBlockRef;
+extern LLVMPositionBuilderAtEnd = (LLVMBuilderRef, LLVMBasicBlockRef) => void;
+
+extern LLVMGetParams = (LLVMValueRef, *LLVMValueRef) => void;
+
+extern LLVMBuildRetVoid = (LLVMBuilderRef) => void;
+extern LLVMBuildRet = (LLVMBuilderRef, LLVMValueRef) => void;
diff --git a/src/bootstrap/parser.pry b/src/bootstrap/parser.pry
index daac296..0b6d5b6 100644
--- a/src/bootstrap/parser.pry
+++ b/src/bootstrap/parser.pry
@@ -160,7 +160,7 @@ let NODE_TYPE_SIMPLE_TYPE_DATA = struct {
 };
 
 let NODE_TYPE_FUNCTION_TYPE_DATA = struct {
-    parameters: *Node,
+    parameters: **Node,
     parameters_len: i64,
     retur_type: *Node,
 };
@@ -294,8 +294,6 @@ let parser_parse_type = (p: *parser) => *Node {
 
 /* FunctionParameters ::= IDENTIFIER ":" Type ("," IDENTIFIER ":" Type)* */
 let parser_parse_function_parameters = (p: *parser) => *slice {
-	/* TODO: Params */
-
 	let node_list = cast(**Node, arena_alloc((*p).arena, sizeof(**Node) * 20));
 	let i = 0;
 	while true {
@@ -306,12 +304,28 @@ let parser_parse_function_parameters = (p: *parser) => *slice {
 		if ident == cast(*token, null) {
 			break;
 		};
-		/* TODO: Rest */
+		if parser_accept_token(p, TOKEN_COLON) == cast(*token, null) {
+			return cast(*slice, null);
+		};
+		let type_annotation = parser_parse_type(p);
+		if type_annotation == cast(*Node, null) {
+			return cast(*slice, null);
+		};
+
+		let d = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA)));
+		(*d).name = cast(*i8, ident.data);
+		(*d).type = type_annotation;
+		let n = Node{};
+		n.type = NODE_PRIMARY_EXPRESSION_IDENTIFIER;
+		n.data = cast(*void, d);
+		(*(node_list + cast(**Node, i))) = create_node(p, n);
+
+		i = i + 1;
 	};
 
 	let s = cast(*slice, arena_alloc((*p).arena, sizeof(slice)));
 	(*s).data = cast(*void, node_list);
-	(*s).data_len = 0;
+	(*s).data_len = i;
 	return s;
 };
 
@@ -359,9 +373,9 @@ let parser_parse_function_definition = (p: *parser) => *Node {
 	let d = cast(*NODE_FUNCTION_DEFINITION_DATA, arena_alloc((*p).arena, sizeof(NODE_FUNCTION_DEFINITION_DATA)));
 	(*d).statements = statements;
 	(*d).statements_len = i;
-	(*d).parameters = cast(**Node, params.data);
-	(*d).parameters_len = params.data_len;
-	(*d).retur_type = cast(*Node, null);
+	(*d).parameters = cast(**Node, (*params).data);
+	(*d).parameters_len = (*params).data_len;
+	(*d).retur_type = retur_type;
 
 	let n = Node{};
 	n.type = NODE_FUNCTION_DEFINITION;
diff --git a/src/codegen.zig b/src/codegen.zig
index 019110c..1123db8 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -499,17 +499,6 @@ pub const CodeGen = struct {
                 // TODO: This should be done with a defer when `builder_pos` is declared, but for some reason it doesn't work
                 llvm.LLVMPositionBuilderAtEnd(self.builder, builder_pos);
 
-                // Global functions
-                if (name == null or self.environment.scope_stack.items.len == 2) {
-                    return try self.create_variable(.{
-                        .value = function,
-                        .type = null,
-                        .stack_level = null,
-                        .node = expression,
-                        .node_type = node_type,
-                    });
-                }
-
                 return try self.create_variable(.{
                     .value = function,
                     .type = null,