From 954f79db55ed4bd0349907d7b580ec5205e5e295 Mon Sep 17 00:00:00 2001 From: Baitinq Date: Sat, 12 Jul 2025 09:49:27 +0200 Subject: Boostrap: Implement import --- examples/0.pry | 74 ++------------------------------- src/bootstrap/codegen.pry | 32 ++++++++++----- src/bootstrap/main.pry | 10 +---- src/bootstrap/parser.pry | 101 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 122 insertions(+), 95 deletions(-) diff --git a/examples/0.pry b/examples/0.pry index a31ab63..9559973 100644 --- a/examples/0.pry +++ b/examples/0.pry @@ -1,80 +1,12 @@ /* HELLO! Welcome to the unnamed language */ -extern printf = (*i8, varargs) => void; -extern exit = (i64) => void; - -let strcmp = (stra: *i8, strb: *i8) => bool { - let i = 0; - while i < 10 { - printf("I: %d\n", i); /* CONTINUE */ - let ca = (*(stra + cast(*i8, i))); - i = i + 1; - }; - - return true; -}; - -let isdigit = (c: i8) => bool { - if c >= '0' { - if c <= '9' { - return true; - }; - }; - return false; -}; - -let isalpha = (c: i8) => bool { - if c >= 'a' { - if c <= 'z' { - return true; - }; - }; - if c >= 'A' { - if c <= 'Z' { - return true; - }; - }; - return false; -}; - -let isalphanum = (c: i8) => bool { - if isalpha(c) { - return true; - }; - if isdigit(c) { - return true; - }; - - return false; -}; - -let iswhitespace = (c: i8) => bool { - if c == ' ' { - return true; - }; - - if c >= '\t' { - if c <= '\r' { - return true; - }; - }; - - return false; -}; - -let assert = (cond: bool) => void { - if !cond { - printf("ASSERTION FAILED\n"); - exit(1); - }; - - return; -}; +import "!stdlib.pry"; let main = (argc: i64, argv: *i64) => i64 { printf("%d\n", argc); isdigit('a'); - strcmp("a", "b"); + let x = strcmp("a", "a"); + printf("%d\n", x); return 2; }; diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry index 50836cc..6d5b1c8 100644 --- a/src/bootstrap/codegen.pry +++ b/src/bootstrap/codegen.pry @@ -21,15 +21,18 @@ let Environment = struct { }; let environment_create_scope = (e: *Environment) => void { + printf("CREATE SCOPE!!!!!!!!!!!: %d\n", (*e).scope_stack_len); 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; + printf("AFTER SCOPE!!!!!!!!!!!: %d\n", (*e).scope_stack_len); return; }; let environment_drop_scope = (e: *Environment) => void { + printf("DROP SCOPE!!!!!!!!!!!\n"); (*e).scope_stack_len = (*e).scope_stack_len - 1; return; @@ -57,8 +60,11 @@ let environment_get_variable = (e: *Environment, name: *i8) => *Variable { }; let environment_add_variable = (e: *Environment, name: *i8, variable: *Variable) => void { + printf("B4 XXXX %d\n", (*e).scope_stack_len); let top_scope = *(((*e).scope_stack + cast(**Scope, (*e).scope_stack_len - 1))); + printf("XXXX %d\n", (*e).scope_stack_len); hashmap_put((*top_scope).variables, name, cast(*void, variable)); + printf("XXXXY\n"); return; }; @@ -417,7 +423,6 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: * 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 { @@ -427,10 +432,7 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: * let param = *cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*param_node).data); let param_type = param.type; let llvm_param_type = codegen_get_llvm_type(c, param_type); - if llvm_param_type == cast(*LLVMTypeRef, null) { - printf("LEL3\n"); - return cast(*Variable, null); - }; + assert(llvm_param_type != cast(*LLVMTypeRef, null)); if (*param_type).type == NODE_TYPE_FUNCTION_TYPE { (*llvm_param_type) = LLVMPointerType(*llvm_param_type, 0); }; @@ -443,7 +445,10 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: * v.stack_level = cast(*i64, null); v.node = param_node; v.node_type = param_type; - environment_add_variable((*c).environment, param.name, codegen_create_variable(c, v)); +let xx =codegen_create_variable(c, v); + printf("THERE %s\n", param.name); + environment_add_variable((*c).environment, param.name, xx); + printf("HERE\n"); parameters_index = parameters_index + 1; }; @@ -452,10 +457,7 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: * let stmt = *(function_definition.statements + cast(**Node, i)); let res = codegen_generate_statement(c, stmt); - if res != 0 { - printf("LEL\n"); - return cast(*Variable, null); - }; + assert(res == 0); i = i + 1; }; @@ -905,6 +907,12 @@ let codegen_generate_while_statement = (c: *codegen, statement: *NODE_WHILE_STAT return null; }; +extern codegen_generate = (*codegen, *Node) => i64; + +let codegen_generate_import_declaration = (c: *codegen, statement: *NODE_IMPORT_DECLARATION_DATA) => i64 { + return codegen_generate(c, (*statement).program); +}; + let codegen_generate_statement = (c: *codegen, statement: *Node) => i64 { let stmt = *statement; @@ -930,6 +938,10 @@ let codegen_generate_statement = (c: *codegen, statement: *Node) => i64 { codegen_generate_while_statement(c, cast(*NODE_WHILE_STATEMENT_DATA, stmt.data)); return 0; }; + + if stmt.type == NODE_IMPORT_DECLARATION { + return codegen_generate_import_declaration(c, cast(*NODE_IMPORT_DECLARATION_DATA, stmt.data)); + }; printf("ASSERT 3 %d\n", stmt.type); assert(false); diff --git a/src/bootstrap/main.pry b/src/bootstrap/main.pry index 29e41ff..84824fd 100644 --- a/src/bootstrap/main.pry +++ b/src/bootstrap/main.pry @@ -1,11 +1,3 @@ -extern fopen = (*i8, *i8) => *i8; -extern fgets = (*i8, i64, *i8) => void; -extern feof = (*i8) => bool; -extern fseek = (*i8, i64, i64) => i64; -extern ftell = (*i8) => i64; -extern fread = (*i8, i64, i64, *i8) => i64; -extern fclose = (*i8) => *i8; - import "!stdlib.pry"; import "!mem.pry"; @@ -55,7 +47,7 @@ let main = (argc: i64, argv: **i8) => i64 { let t = tokenizer_init(alloc, file); let ts = tokenizer_tokenize(t); - let p = parser_init(cast(*token, ts.data), ts.data_len, alloc); + let p = parser_init(cast(*token, ts.data), ts.data_len, alloc, filename); let ast = parse(p); let c = codegen_init(alloc); diff --git a/src/bootstrap/parser.pry b/src/bootstrap/parser.pry index 29aba73..444a033 100644 --- a/src/bootstrap/parser.pry +++ b/src/bootstrap/parser.pry @@ -1,3 +1,24 @@ +import "tokenizer.pry"; + +extern fopen = (*i8, *i8) => *i8; +extern fgets = (*i8, i64, *i8) => void; +extern feof = (*i8) => bool; +extern fseek = (*i8, i64, i64) => i64; +extern lseek = (i64, i64, i64) => i64; +extern ftell = (*i8) => i64; +extern fread = (*i8, i64, i64, *i8) => i64; +extern fclose = (*i8) => *i8; + +extern strcpy = (*i8, *i8) => *i8; +extern dirname = (*i8) => *i8; +extern open = (*i8, i64) => i64; +extern openat = (i64, *i8, i64) => i64; +extern read = (i64, *i8, i64) => i64; +extern realpath = (*i8, *i8) => *i8; +extern snprintf = (*i8, i64, *i8, *i8, *i8) => i64; +extern strcpy = (*i8, *i8) => *i8; +extern strlen = (*i8) => i64; + let Node = struct { type: i64, data: *void, @@ -195,6 +216,7 @@ let parser = struct { offset: i64, arena: *arena, + filename: *i8, }; extern parser_parse_statement = (*parser) => *Node; @@ -202,13 +224,14 @@ extern parser_parse_expression = (*parser) => *Node; extern parse_function_call_statement = (*parser) => *Node; extern parser_parse_additive_expression = (*parser) => *Node; -let parser_init = (ts: *token, ts_len: i64, ar: *arena) => *parser { +let parser_init = (ts: *token, ts_len: i64, ar: *arena, filename: *i8) => *parser { let p = cast(*parser, arena_alloc(ar, sizeof(parser))); (*p).tokens = ts; (*p).tokens_len = ts_len; (*p).offset = 0; (*p).arena = ar; + (*p).filename = filename; return p; }; @@ -690,8 +713,6 @@ let parser_parse_primary_expression = (p: *parser) => *Node { return create_node(p, n); }; - printf("DIFF TYPE: %d\n", (*tok).type); - return cast(*Node, null); }; @@ -927,7 +948,6 @@ let parse_assignment_statement = (p: *parser) => *Node { let lhs = parser_parse_expression(p); /* TODO */ if lhs == cast(*Node, null) { - printf("ANOTHER BNLL\n"); return cast(*Node, null); }; @@ -937,7 +957,6 @@ let parse_assignment_statement = (p: *parser) => *Node { let rhs = parser_parse_expression(p); /* TODO */ if rhs == cast(*Node, null) { - printf("NUL EXP\n"); return cast(*Node, null); }; @@ -952,6 +971,70 @@ let parse_assignment_statement = (p: *parser) => *Node { return create_node(p, n); }; +extern parse = (*parser) => *Node; + +let parser_parse_import_declaration = (p: *parser) => *Node { + if parser_accept_token(p, TOKEN_IMPORT) == cast(*token, null) { + return cast(*Node, null); + }; + + let expr = parser_parse_primary_expression(p); + if expr == cast(*Node, null) { + return cast(*Node, null); + }; + + assert((*expr).type == NODE_PRIMARY_EXPRESSION_STRING); + + let impor_filename = (*cast(*NODE_PRIMARY_EXPRESSION_STRING_DATA, (*expr).data)).value; + let current_file = cast(*i8, arena_alloc((*p).arena, sizeof(i8) * 70)); + strcpy(current_file, (*p).filename); + + /* stdlib. TODO: this is very hacky and won't work if running the compiler binary by itself */ + if (*impor_filename) == '!' { + let buf = cast(*i8, arena_alloc((*p).arena, sizeof(i8) * 70)); + sprintf(buf, "./std/%s", (impor_filename + cast(*i8, 1))); + impor_filename = buf; + current_file = "."; + }; + + let dirpath = dirname(current_file); + let dir = open(dirpath, 0); + assert(dir != -1); + + let file = openat(dir, impor_filename, 0); + assert(file != -1); + + let file_size = lseek(file, 0, 2); + lseek(file, 0, 0); + let file_contents = cast(*i8, arena_alloc((*p).arena, file_size + 1)); + + let bytes_read = read(file, file_contents, file_size); + (*(file_contents + cast(*i8, bytes_read))) = '\0'; + + let todo = slice{}; + todo.data = cast(*void, file_contents); + todo.data_len = file_size; + let inner_tokenizer = tokenizer_init((*p).arena, todo); + let tokens = tokenizer_tokenize(inner_tokenizer); + + let buf2 = cast(*i8, arena_alloc((*p).arena, 90)); + strcpy(buf2, dirpath); + (*(buf2 + cast(*i8, strlen(dirpath)))) = '/'; + strcpy(buf2 + cast(*i8, strlen(dirpath) + 1), impor_filename); + let full_path = realpath(buf2, cast(*i8, null)); + + let inner_parser = parser_init(cast(*token, tokens.data), tokens.data_len, (*p).arena, full_path); + let ast = parse(inner_parser); + + let d = cast(*NODE_IMPORT_DECLARATION_DATA , arena_alloc((*p).arena, sizeof(NODE_IMPORT_DECLARATION_DATA))); + (*d).filename = impor_filename; + (*d).program = ast; + let n = Node{}; + n.type = NODE_IMPORT_DECLARATION; + n.data = cast(*void, d); + return create_node(p, n); +}; + /* FunctionArguments ::= Expression ("," Expression)* */ let parser_parse_function_arguments = (p: *parser) => *slice { let node_list = cast(**Node, arena_alloc((*p).arena, sizeof(*Node) * 20)); @@ -1052,6 +1135,14 @@ let parser_parse_statement = (p: *parser) => *Node { }; return retu; }; + + let retu = parser_accept_parse(p, parser_parse_import_declaration); + if retu != cast(*Node, null) { + if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { + return cast(*Node, null); + }; + return retu; + }; let retu = parser_accept_parse(p, parser_parse_extern_declaration); if retu != cast(*Node, null) { -- cgit 1.4.1