diff options
| author | Baitinq <[email protected]> | 2025-07-13 10:06:44 +0200 |
|---|---|---|
| committer | Baitinq <[email protected]> | 2025-07-13 10:06:44 +0200 |
| commit | b74dc51d07ca6f928127223165ed84e5a5b33e78 (patch) | |
| tree | 6b3554c30aac27ad31f8858af26c9a83bded1901 | |
| parent | Boostrap: Support calling function ptr (diff) | |
| download | pry-lang-b74dc51d07ca6f928127223165ed84e5a5b33e78.tar.gz pry-lang-b74dc51d07ca6f928127223165ed84e5a5b33e78.tar.bz2 pry-lang-b74dc51d07ca6f928127223165ed84e5a5b33e78.zip | |
Boostrap: Fuction def call and multiplicative expr
| -rw-r--r-- | src/bootstrap/codegen.pry | 93 | ||||
| -rw-r--r-- | src/bootstrap/llvm.pry | 4 | ||||
| -rw-r--r-- | src/bootstrap/parser.pry | 28 |
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); |