about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <[email protected]>2025-07-12 09:49:27 +0200
committerBaitinq <[email protected]>2025-07-12 17:43:28 +0200
commit954f79db55ed4bd0349907d7b580ec5205e5e295 (patch)
treee9e464dff0ee72a27519b087d80690c0c9dfe893
parentBoostrap: Support cast statement (diff)
downloadpry-lang-954f79db55ed4bd0349907d7b580ec5205e5e295.tar.gz
pry-lang-954f79db55ed4bd0349907d7b580ec5205e5e295.tar.bz2
pry-lang-954f79db55ed4bd0349907d7b580ec5205e5e295.zip
Boostrap: Implement import
-rw-r--r--examples/0.pry74
-rw-r--r--src/bootstrap/codegen.pry32
-rw-r--r--src/bootstrap/main.pry10
-rw-r--r--src/bootstrap/parser.pry101
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) {