about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBaitinq <[email protected]>2025-05-20 23:19:46 +0200
committerBaitinq <[email protected]>2025-05-20 23:19:46 +0200
commitb736233822765222c3963d03749b8f6200000dd3 (patch)
tree868202dd7161897cbc2b0f745791b57d3608e140 /src
parentFeature: Add support for casting types (diff)
downloadpry-lang-b736233822765222c3963d03749b8f6200000dd3.tar.gz
pry-lang-b736233822765222c3963d03749b8f6200000dd3.tar.bz2
pry-lang-b736233822765222c3963d03749b8f6200000dd3.zip
Feature: Add more type checks
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/main.src10
-rw-r--r--src/bootstrap/tokenizer.src28
-rw-r--r--src/codegen.zig38
3 files changed, 40 insertions, 36 deletions
diff --git a/src/bootstrap/main.src b/src/bootstrap/main.src
index aa916d9..7917e04 100644
--- a/src/bootstrap/main.src
+++ b/src/bootstrap/main.src
@@ -1,13 +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;
-extern malloc = (i64) => *i8;
-extern free = (*i8) => void;
-
 import "!stdlib.src";
 
 import "tokenizer.src";
diff --git a/src/bootstrap/tokenizer.src b/src/bootstrap/tokenizer.src
index cb09e3f..051050c 100644
--- a/src/bootstrap/tokenizer.src
+++ b/src/bootstrap/tokenizer.src
@@ -1,5 +1,5 @@
 extern strlen = (*i8) => i64;
-extern memcpy = (*i8, *i8, i64) => void;
+extern memcpy = (*void, *void, i64) => void;
 extern sprintf = (*i8, *i8, varargs) => void;
 extern atoi = (*i8) => i64;
 extern fopen = (*i8, *i8) => *i8;
@@ -9,6 +9,8 @@ extern fseek = (*i8, i64, i64) => i64;
 extern ftell = (*i8) => i64;
 extern fread = (*i8, i64, i64, *i8) => i64;
 extern fclose = (*i8) => *i8;
+extern malloc = (i64) => *void;
+extern free = (*void) => void;
 
 import "!stdlib.src";
 
@@ -27,7 +29,7 @@ let read_file = (filename: *i8) => *i8 {
 	file_size = ftell(file);
 	fseek(file, 0, 0);
 
-	buf = malloc(file_size + 1);
+	buf = cast(*i8, malloc(file_size + 1));
 
 	let bytes_read = fread(buf, 1, file_size, file);
 	(*(buf + bytes_read)) = '\0';
@@ -89,8 +91,8 @@ let tokenizer_accept_string = (str: *i8) => bool {
 	let str_len = strlen(str);
 	if offset + str_len > file_size { return false; };
 
-	let s = malloc(1000);
-	memcpy(s, buf + offset, str_len);
+	let s = cast(*i8, malloc(1000));
+	memcpy(cast(*void, s), cast(*void, buf + offset), str_len);
 
 	if strcmp(s, str) {
 		offset = offset + str_len;
@@ -102,7 +104,7 @@ let tokenizer_accept_string = (str: *i8) => bool {
 
 let tokenizer_consume_until_condition = (condition: (i8) => bool) => *i8 {
 	let start = offset;
-	let res = malloc(1000);
+	let res = cast(*i8, malloc(1000));
 
 	while true {
 		if offset >= file_size {
@@ -168,7 +170,7 @@ let tokenizer_accept_int_type = () => *i64 {
 	if strlen(string) == 0 {
 		return null;
 	};
-	let x = malloc(8);
+	let x = cast(*i64, malloc(8));
 	*x = atoi(string);
 	return x;
 };
@@ -312,7 +314,7 @@ let tokenizer_next = () => *i8 {
 	
 	let maybe_int = tokenizer_accept_int_type();
 	if maybe_int != null {
-		let t = malloc(1000);
+		let t = cast(*i8, malloc(1000));
 		sprintf(t, "int:%d", *maybe_int);
 
 		return t;
@@ -320,7 +322,7 @@ let tokenizer_next = () => *i8 {
 
 	let maybe_char = tokenizer_accept_char_type();
 	if maybe_char != null {
-		let t = malloc(1000);
+		let t = cast(*i8, malloc(1000));
 		sprintf(t, "char:%d", *maybe_char);
 
 		return t;
@@ -328,7 +330,7 @@ let tokenizer_next = () => *i8 {
 
 	let maybe_string = tokenizer_accept_string_type();
 	if maybe_string != null {
-		let t = malloc(1000);
+		let t = cast(*i8, malloc(1000));
 		sprintf(t, "string:%s", maybe_string);
 
 		return t;
@@ -347,7 +349,7 @@ let tokenizer_next = () => *i8 {
 		return null;
 	};
 
-	let t = malloc(100);
+	let t = cast(*i8, malloc(100));
 	sprintf(t, "identifier:%s", string);
 	
 	return t;
@@ -360,7 +362,7 @@ let tokenizer_init = (filename: *i8) => i64 {
 
 	println("%s", buf);
 
-	tokens = malloc(100000);
+	tokens = cast(*i8, malloc(100000));
 
 	while true {
 		let t = tokenizer_next();
@@ -382,8 +384,8 @@ let tokenizer_init = (filename: *i8) => i64 {
 };
 
 let tokenizer_deinit = () => i64 {
-	free(tokens);
-	free(buf);
+	free(cast(*void, tokens));
+	free(cast(*void, buf));
 
 	return 0;
 };
diff --git a/src/codegen.zig b/src/codegen.zig
index d6415cf..c9e39ea 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -161,16 +161,15 @@ pub const CodeGen = struct {
             } else {
                 ptr = self.environment.get_variable(identifier.name).?.value;
                 typ = self.environment.get_variable(identifier.name).?.node_type;
+                // TODO: Do this in more places! (everywhere get_llvm_type?)  Also check types in return and cmp
+                const expected_type = typ;
+                std.debug.print("TYP {s}: {any} vs {any} -- {any}\n", .{ identifier.name, expected_type.TYPE, variable.node_type.TYPE, variable.node });
+                std.debug.assert(self.compare_types(expected_type, variable.node_type, assignment_statement.is_dereference));
             }
 
             if (assignment_statement.is_dereference) {
                 ptr = llvm.LLVMBuildLoad2(self.builder, try self.get_llvm_type(typ), ptr, "");
-            } else {
-                // TODO: we should still do this with dereferences, but differently
-                // TODO: Do this in more places! (everywhere get_llvm_type?)
-                std.debug.assert(self.compare_types(typ, variable.node_type));
             }
-
             _ = llvm.LLVMBuildStore(self.builder, variable.value, ptr);
 
             if (assignment_statement.is_dereference) {
@@ -187,7 +186,6 @@ pub const CodeGen = struct {
             if (assignment_statement.is_declaration) {
                 try self.environment.add_variable(identifier.name, new_variable);
             } else {
-                // TODO: Dont allow changing types of variables if its not declaration
                 try self.environment.set_variable(identifier.name, new_variable);
             }
         } else {
@@ -223,8 +221,11 @@ pub const CodeGen = struct {
 
         var arguments = std.ArrayList(llvm.LLVMValueRef).init(self.arena);
 
-        for (function_call_statement.arguments) |argument| {
+        for (0.., function_call_statement.arguments) |i, argument| {
             const arg = try self.generate_expression_value(argument, null);
+            const expected_type = function.node_type.TYPE.FUNCTION_TYPE.parameters[i];
+            std.debug.print("TYP {s}: {any} vs {any}\n", .{ function_call_statement.expression.PRIMARY_EXPRESSION.IDENTIFIER.name, expected_type.TYPE, arg.node_type.TYPE });
+            std.debug.assert(self.compare_types(expected_type, arg.node_type, false));
             try arguments.append(arg.value);
         }
 
@@ -458,6 +459,7 @@ pub const CodeGen = struct {
             },
             .PRIMARY_EXPRESSION => |primary_expression| switch (primary_expression) {
                 .NULL => {
+                    //TODO: This should likely be *void.
                     return try self.generate_literal(llvm.LLVMConstNull(llvm.LLVMPointerType(llvm.LLVMInt8Type(), 0)), name, expression, try self.create_node(.{
                         .TYPE = .{
                             .POINTER_TYPE = .{
@@ -729,15 +731,24 @@ pub const CodeGen = struct {
         }
     }
 
-    fn compare_types(self: *CodeGen, a: *parser.Node, b: *parser.Node) bool {
+    fn compare_types(self: *CodeGen, a: *parser.Node, b: *parser.Node, is_dereference: bool) bool {
         std.debug.assert(a.* == parser.Node.TYPE);
         std.debug.assert(b.* == parser.Node.TYPE);
 
-        const a_type = a.TYPE;
+        var a_type = a.TYPE;
         const b_type = b.TYPE;
 
+        if (a_type == .SIMPLE_TYPE and std.mem.eql(u8, "varargs", a_type.SIMPLE_TYPE.name)) {
+            return true;
+        }
+
+        if (is_dereference) {
+            a_type = a_type.POINTER_TYPE.type.TYPE;
+        }
+
         if (!std.mem.eql(u8, @tagName(a_type), @tagName(b_type))) {
-            std.debug.print("Tagname mismatch: {s} vs {s}\n", .{ @tagName(a_type), @tagName(b_type) });
+            std.debug.print("Tagname mismatch: {any} vs {any}\n", .{ a_type, b_type });
+            return false;
         }
 
         switch (a_type) {
@@ -752,7 +763,7 @@ pub const CodeGen = struct {
             .FUNCTION_TYPE => |a_func| {
                 const b_func = b_type.FUNCTION_TYPE;
 
-                if (!self.compare_types(a_func.return_type, b_func.return_type)) {
+                if (!self.compare_types(a_func.return_type, b_func.return_type, false)) {
                     std.debug.print("Function return type mismatch\n", .{});
                     return false;
                 }
@@ -763,7 +774,7 @@ pub const CodeGen = struct {
                 }
 
                 for (a_func.parameters, b_func.parameters) |a_param, b_param| {
-                    if (!self.compare_types(a_param, b_param)) {
+                    if (!self.compare_types(a_param, b_param, false)) {
                         std.debug.print("Parameter  type mismatch\n", .{});
                         return false;
                     }
@@ -773,7 +784,8 @@ pub const CodeGen = struct {
             },
             .POINTER_TYPE => |a_ptr| {
                 const b_ptr = b_type.POINTER_TYPE;
-                const res = self.compare_types(a_ptr.type, b_ptr.type);
+
+                const res = self.compare_types(a_ptr.type, b_ptr.type, false);
                 if (!res) {
                     std.debug.print("Pointer base type mismatch\n", .{});
                 }