about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <[email protected]>2025-03-21 20:22:45 +0100
committerBaitinq <[email protected]>2025-03-22 20:30:56 +0100
commit95999cb6a286871e245e8b9e20d79bc6cd22252c (patch)
treeb9ae565e1284fc58c255725fb78ee877a3bd960f
parentMisc: Improve error handling (diff)
downloadinterpreter-95999cb6a286871e245e8b9e20d79bc6cd22252c.tar.gz
interpreter-95999cb6a286871e245e8b9e20d79bc6cd22252c.tar.bz2
interpreter-95999cb6a286871e245e8b9e20d79bc6cd22252c.zip
Feature: Add initial support for linking external symbols
-rw-r--r--examples/15.src12
-rw-r--r--grammar.ebnf2
-rw-r--r--src/codegen.zig24
-rw-r--r--src/parser.zig12
4 files changed, 44 insertions, 6 deletions
diff --git a/examples/15.src b/examples/15.src
index 7bd73d2..fd68961 100644
--- a/examples/15.src
+++ b/examples/15.src
@@ -1,7 +1,11 @@
-let putc = (i64) => i64;
-
-let main = () => i64 {
-	putc(52);
+let putchar = (i64) => i64;
 
+let main = (_: void) => i64 {
+	putchar(72);
+	putchar(101);
+	putchar(108);
+	putchar(108);
+	putchar(111);
+	putchar(10);
 	return 0;
 };
diff --git a/grammar.ebnf b/grammar.ebnf
index bbfe488..562f2f8 100644
--- a/grammar.ebnf
+++ b/grammar.ebnf
@@ -2,7 +2,7 @@ Program      ::= Statement+
 
 Statement    ::= (AssignmentStatement | FunctionCallStatement | IfStatement | WhileStatement | ReturnStatement) SEMICOLON
 
-AssignmentStatement ::= "let" IDENTIFIER EQUALS Expression
+AssignmentStatement ::= "let" IDENTIFIER EQUALS (Type | Expression)
 
 FunctionCallStatement ::= (IDENTIFIER | FunctionDefinition) LPAREN FunctionArguments? RPAREN
 
diff --git a/src/codegen.zig b/src/codegen.zig
index c16fa34..4e2d897 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -196,6 +196,7 @@ pub const CodeGen = struct {
         const function_return_type = switch (function.node.?.*) {
             .FUNCTION_DEFINITION => |x| x.return_type,
             .PRIMARY_EXPRESSION => |x| x.IDENTIFIER.type.?,
+            .TYPE => |x| x.FUNCTION_TYPE.return_type,
             else => unreachable,
         };
 
@@ -458,6 +459,28 @@ pub const CodeGen = struct {
 
                 return self.generate_literal(cmp, llvm.LLVMInt1Type(), name);
             },
+            .TYPE => |typ| {
+                std.debug.assert(typ == .FUNCTION_TYPE);
+                const function_type = try self.get_llvm_type(expression);
+                const function = llvm.LLVMAddFunction(self.llvm_module, try std.fmt.allocPrintZ(self.arena, "{s}", .{name.?}), function_type);
+
+                // Global functions
+                if (self.environment.scope_stack.items.len == 1) {
+                    return try self.create_variable(.{
+                        .value = function,
+                        .type = function_type,
+                        .stack_level = null,
+                        .node = expression,
+                    });
+                }
+
+                const ptr = self.environment.get_variable(name.?);
+                _ = llvm.LLVMBuildStore(self.builder, function, ptr.?.value) orelse return CodeGenError.CompilationError;
+                ptr.?.type = function_type;
+                ptr.?.node = expression;
+
+                return ptr.?;
+            },
             else => unreachable,
         };
     }
@@ -496,6 +519,7 @@ pub const CodeGen = struct {
             .SIMPLE_TYPE => |t| {
                 if (std.mem.eql(u8, t.name, "i64")) return llvm.LLVMInt64Type();
                 if (std.mem.eql(u8, t.name, "bool")) return llvm.LLVMInt1Type();
+                if (std.mem.eql(u8, t.name, "void")) return llvm.LLVMInt1Type(); //TODO:
                 unreachable;
             },
             // TODO: Properly handle this vv
diff --git a/src/parser.zig b/src/parser.zig
index b0a469c..d2067a1 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -142,7 +142,7 @@ pub const Parser = struct {
         });
     }
 
-    // AssignmentStatement ::= "let" IDENTIFIER EQUALS Expression
+    // AssignmentStatement ::= "let" IDENTIFIER EQUALS (Type | Expression)
     fn parse_assignment_statement(self: *Parser) ParserError!*Node {
         errdefer if (!self.try_context) std.debug.print("Error parsing assignment statement {any}\n", .{self.peek_token()});
 
@@ -155,6 +155,16 @@ pub const Parser = struct {
 
         _ = try self.parse_token(tokenizer.TokenType.EQUALS);
 
+        if (self.accept_parse(parse_type)) |typ| {
+            return self.create_node(.{
+                .ASSIGNMENT_STATEMENT = .{
+                    .is_declaration = is_declaration,
+                    .name = try self.arena.dupe(u8, identifier.type.IDENTIFIER),
+                    .expression = @constCast(typ),
+                },
+            });
+        }
+
         const expression = try self.parse_expression();
 
         return self.create_node(.{