about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBaitinq <[email protected]>2025-07-13 17:33:36 +0200
committerBaitinq <[email protected]>2025-07-13 17:33:36 +0200
commit78d208bb568cc983a0546f6a53ae3b67104683ee (patch)
tree1726b737e0d01910154132ebd0faa46509a6f5c6 /src
parentBoostrap: Support sizeof builtin (diff)
downloadpry-lang-78d208bb568cc983a0546f6a53ae3b67104683ee.tar.gz
pry-lang-78d208bb568cc983a0546f6a53ae3b67104683ee.tar.bz2
pry-lang-78d208bb568cc983a0546f6a53ae3b67104683ee.zip
Boostrap: Support struct definition
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/codegen.pry45
-rw-r--r--src/bootstrap/llvm.pry2
-rw-r--r--src/bootstrap/parser.pry64
3 files changed, 109 insertions, 2 deletions
diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry
index be2ee5c..9363265 100644
--- a/src/bootstrap/codegen.pry
+++ b/src/bootstrap/codegen.pry
@@ -739,6 +739,51 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 		return codegen_create_variable(c, v);
 	};
 
+	if ((*expression).type == NODE_TYPE_STRUCT_TYPE) {
+		let struc_data = *cast(*NODE_TYPE_STRUCT_TYPE_DATA, (*expression).data);
+		let dd = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA)));
+		(*dd).name = name;
+		(*dd).underlying_type = expression;
+		let n = Node{};
+		n.type = NODE_TYPE_SIMPLE_TYPE;
+		n.data = cast(*void, dd);
+		let simple_type_node = create_node(c, n);
+
+		let struc_type = LLVMStructCreateNamed((*c).llvm_context, name);
+
+		if name != cast(*i8, null) {
+			let v = Variable{};
+			v.value = cast(LLVMValueRef, null);
+			v.type = struc_type;
+			v.stack_level = cast(*i64, null);
+			v.node = expression;
+			v.node_type = simple_type_node;
+			environment_add_variable((*c).environment, name, codegen_create_variable(c, v));
+		};
+
+		let llvm_types = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef) * 20));
+		let i = 0;
+		while i < struc_data.fields_len {
+			let field = *(struc_data.fields + cast(**Node, i));
+			assert((*field).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER);
+			let t = (*cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*field).data)).type;
+			let lt = codegen_get_llvm_type(c, t);
+			assert(lt != cast(*LLVMTypeRef, null));
+			(*(llvm_types + cast(*LLVMTypeRef, i))) = *lt;
+			i = i + 1;
+		};
+
+		LLVMStructSetBody(struc_type, llvm_types, i, 0);
+
+		let v = Variable{};
+		v.value = cast(LLVMValueRef, null);
+		v.type = struc_type;
+		v.stack_level = cast(*i64, null);
+		v.node = expression;
+		v.node_type = simple_type_node;
+		return codegen_create_variable(c, v);
+	};
+
 	printf("ASSERT 1: %d\n", (*expression).type);
 	assert(false);
 
diff --git a/src/bootstrap/llvm.pry b/src/bootstrap/llvm.pry
index 1771908..84ce88c 100644
--- a/src/bootstrap/llvm.pry
+++ b/src/bootstrap/llvm.pry
@@ -345,4 +345,6 @@ let LLVMIntSLT = 40;
 let LLVMIntSLE = 41;
 
 extern LLVMStoreSizeOfType = (LLVMTargetDataRef, LLVMTypeRef) => i64;
+extern LLVMStructCreateNamed = (LLVMContextRef, *i8) => LLVMTypeRef;
+extern LLVMStructSetBody = (LLVMTypeRef, *LLVMTypeRef, i64, i64) => void;
 
diff --git a/src/bootstrap/parser.pry b/src/bootstrap/parser.pry
index 355b54d..8cefefd 100644
--- a/src/bootstrap/parser.pry
+++ b/src/bootstrap/parser.pry
@@ -191,7 +191,7 @@ let NODE_TYPE_POINTER_TYPE_DATA = struct {
 };
 
 let NODE_TYPE_STRUCT_TYPE_DATA = struct {
-    fields: *Node,
+    fields: **Node,
     fields_len: i64,
 };
 
@@ -606,7 +606,7 @@ let parser_parse_function_parameters = (p: *parser) => *slice {
 		};
 
 		let d = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA)));
-		(*d).name = cast(*i8, (*ident).data); /* TODO: Typecheck struct access */
+		(*d).name = cast(*i8, (*ident).data);
 		(*d).type = type_annotation;
 		let n = Node{};
 		n.type = NODE_PRIMARY_EXPRESSION_IDENTIFIER;
@@ -622,6 +622,62 @@ let parser_parse_function_parameters = (p: *parser) => *slice {
 	return s;
 };
 
+/* StructDefinition ::= "struct" LBRACE StructFields? RBRACE */
+let parser_parse_struct_definition = (p: *parser) => *Node {
+	if parser_accept_token(p, TOKEN_STRUCT) == cast(*token, null) {
+		return cast(*Node, null);
+	};
+	if parser_accept_token(p, TOKEN_LBRACE) == cast(*token, null) {
+		return cast(*Node, null);
+	};
+
+	let fields = cast(**Node, arena_alloc((*p).arena, sizeof(*Node) * 20));
+	let i = 0;
+	while true {
+		let field = parser_accept_parse(p, (ip: *parser) => *Node {
+			let ident = parser_accept_token(ip, TOKEN_IDENTIFIER);
+			if ident == cast(*token, null) {
+				return cast(*Node, null);
+			};
+			if parser_accept_token(ip, TOKEN_COLON) == cast(*token, null) {
+				return cast(*Node, null);
+			};
+			let typ_annotation = parser_parse_type(ip);
+			if typ_annotation == cast(*Node, null) {
+				return cast(*Node, null);
+			};
+			printf("STRUCT TYP: %d\n" (*typ_annotation).type);
+			let d = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, arena_alloc((*ip).arena, sizeof(NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA)));
+			(*d).name = cast(*i8, (*ident).data);
+			(*d).type = typ_annotation;
+			let n = Node{};
+			n.type = NODE_PRIMARY_EXPRESSION_IDENTIFIER;
+			n.data = cast(*void, d);
+			return create_node(ip, n);
+		});
+		if field == cast(*Node, null) {
+			break;
+		};
+
+		parser_accept_token(p, TOKEN_COMMA);
+
+		(*(fields + cast(**Node, i))) = field;
+		i = i + 1;
+	};
+
+	if parser_accept_token(p, TOKEN_RBRACE) == cast(*token, null) {
+		return cast(*Node, null);
+	};
+
+	let d = cast(*NODE_TYPE_STRUCT_TYPE_DATA, arena_alloc((*p).arena, sizeof(NODE_TYPE_STRUCT_TYPE_DATA)));
+	(*d).fields = fields;
+	(*d).fields_len = i;
+	let n = Node{};
+	n.type = NODE_TYPE_STRUCT_TYPE;
+	n.data = cast(*void, d);
+	return create_node(p, n);
+};
+
 /* FunctionDefinition ::= LPAREN FunctionParameters? RPAREN ARROW IDENTIFIER LBRACE Statement* ReturnStatement SEMICOLON RBRACE */
 let parser_parse_function_definition = (p: *parser) => *Node {
 	if parser_accept_token(p, TOKEN_LPAREN) == cast(*token, null) {
@@ -682,6 +738,10 @@ let parser_parse_primary_expression = (p: *parser) => *Node {
 	if stmt != cast(*Node, null) {
 		return stmt;
 	};
+	let stmt = parser_accept_parse(p, parser_parse_struct_definition);
+	if stmt != cast(*Node, null) {
+		return stmt;
+	};
 
 	if parser_accept_token(p, TOKEN_LPAREN) != cast(*token, null) {
 		let expr = parser_parse_expression(p);