diff options
| author | Baitinq <[email protected]> | 2025-07-13 17:33:36 +0200 |
|---|---|---|
| committer | Baitinq <[email protected]> | 2025-07-13 17:33:36 +0200 |
| commit | 78d208bb568cc983a0546f6a53ae3b67104683ee (patch) | |
| tree | 1726b737e0d01910154132ebd0faa46509a6f5c6 /src | |
| parent | Boostrap: Support sizeof builtin (diff) | |
| download | pry-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.pry | 45 | ||||
| -rw-r--r-- | src/bootstrap/llvm.pry | 2 | ||||
| -rw-r--r-- | src/bootstrap/parser.pry | 64 |
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); |