about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <[email protected]>2025-04-01 23:46:55 +0200
committerBaitinq <[email protected]>2025-04-01 23:47:14 +0200
commitd4ec81f8453ecc5ded0d2c2843c952ab27d19642 (patch)
tree89af68c5f2b9c5552e95c70d6f2fba44b3d1d7a2
parentEvaluator: Remove evaluator (diff)
downloadpry-lang-d4ec81f8453ecc5ded0d2c2843c952ab27d19642.tar.gz
pry-lang-d4ec81f8453ecc5ded0d2c2843c952ab27d19642.tar.bz2
pry-lang-d4ec81f8453ecc5ded0d2c2843c952ab27d19642.zip
Feature: Start adding support for assigning to pointers with arithmetic
-rw-r--r--examples/18.src10
-rw-r--r--grammar.ebnf2
-rw-r--r--src/codegen.zig64
-rw-r--r--src/parser.zig25
4 files changed, 58 insertions, 43 deletions
diff --git a/examples/18.src b/examples/18.src
index 90234c4..6d75e30 100644
--- a/examples/18.src
+++ b/examples/18.src
@@ -4,13 +4,13 @@ extern free = (*i64) => void;
 
 let main = () => i64 {
 	let x = malloc(128);
-	/*
-	*(x+0) = 10;
-	*(x+8) = 20;
-	*/
+	(*(x+0)) = 10;
+	(*(x+1)) = 20;
+	(*(x+2)) = 40;
 	printf("%p\n", x);
-	printf("%d\n", *x);
+	printf("%d\n", *(x+0));
 	printf("%d\n", *(x+1));
+	printf("%d\n", *(x+2));
 	free(x);
 	return 0;
 };
diff --git a/grammar.ebnf b/grammar.ebnf
index 85d824d..f421d28 100644
--- a/grammar.ebnf
+++ b/grammar.ebnf
@@ -2,7 +2,7 @@ Program      ::= Statement+
 
 Statement    ::= (AssignmentStatement | ExternDeclaration | FunctionCallStatement | IfStatement | WhileStatement | ReturnStatement) SEMICOLON
 
-AssignmentStatement ::= ("let")? ("*")? IDENTIFIER EQUALS Expression
+AssignmentStatement ::= ("let")? ("*")? Expression EQUALS Expression
 
 ExternDeclaration ::= "extern" IDENTIFIER EQUALS Type
 
diff --git a/src/codegen.zig b/src/codegen.zig
index 553de77..d6b3e98 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -123,40 +123,48 @@ pub const CodeGen = struct {
     fn generate_assignment_statement(self: *CodeGen, statement: *parser.Node) CodeGenError!void {
         errdefer std.debug.print("Error generating assignment statement\n", .{});
         std.debug.assert(statement.* == parser.Node.ASSIGNMENT_STATEMENT);
-
         const assignment_statement = statement.ASSIGNMENT_STATEMENT;
 
-        if (assignment_statement.is_declaration and self.environment.scope_stack.items.len > 1) {
-            std.debug.assert(assignment_statement.is_dereference == false);
-            // TODO: vv Int64Type is a problem
-            const alloca = llvm.LLVMBuildAlloca(self.builder, llvm.LLVMInt64Type(), try std.fmt.allocPrintZ(self.arena, "{s}", .{assignment_statement.name})); //TODO: Correct type
-            try self.environment.add_variable(assignment_statement.name, try self.create_variable(.{
-                .value = alloca,
-                .type = llvm.LLVMVoidType(), // This gets set to the correct type during the expression type resolution. ALTERNATIVE: Pass the alloca
-                .stack_level = null,
-                .node = statement,
-            }));
-        }
+        if (assignment_statement.lhs.* == .PRIMARY_EXPRESSION) {
+            const identifier = assignment_statement.lhs.PRIMARY_EXPRESSION.IDENTIFIER;
 
-        var undereferenced_variable: ?*Variable = null;
-        if (assignment_statement.is_dereference) {
-            const ptr = self.environment.get_variable(assignment_statement.name) orelse unreachable;
-            undereferenced_variable = ptr;
-            const x = llvm.LLVMBuildLoad2(self.builder, ptr.type, ptr.value, "") orelse return CodeGenError.CompilationError;
-            try self.environment.add_variable(assignment_statement.name, try self.create_variable(.{
-                .value = x,
-                .type = ptr.type,
-                .stack_level = null,
-                .node = statement,
-            }));
-        }
+            if (assignment_statement.is_declaration and self.environment.scope_stack.items.len > 1) {
+                std.debug.assert(assignment_statement.is_dereference == false);
+                // TODO: vv Int64Type is a problem
+                const alloca = llvm.LLVMBuildAlloca(self.builder, llvm.LLVMInt64Type(), try std.fmt.allocPrintZ(self.arena, "{s}", .{identifier.name})); //TODO: Correct type
+                try self.environment.add_variable(identifier.name, try self.create_variable(.{
+                    .value = alloca,
+                    .type = llvm.LLVMVoidType(), // This gets set to the correct type during the expression type resolution. ALTERNATIVE: Pass the alloca
+                    .stack_level = null,
+                    .node = statement,
+                }));
+            }
 
-        const variable = try self.generate_expression_value(assignment_statement.expression, assignment_statement.name);
+            var undereferenced_variable: ?*Variable = null;
+            if (assignment_statement.is_dereference) {
+                const ptr = self.environment.get_variable(identifier.name) orelse unreachable;
+                undereferenced_variable = ptr;
+                const x = llvm.LLVMBuildLoad2(self.builder, ptr.type, ptr.value, "") orelse return CodeGenError.CompilationError;
+                try self.environment.add_variable(identifier.name, try self.create_variable(.{
+                    .value = x,
+                    .type = ptr.type,
+                    .stack_level = null,
+                    .node = statement,
+                }));
+            }
 
-        if (!assignment_statement.is_dereference) {
-            try self.environment.add_variable(assignment_statement.name, variable);
+            const variable = try self.generate_expression_value(assignment_statement.rhs, identifier.name);
+
+            if (!assignment_statement.is_dereference) {
+                try self.environment.add_variable(identifier.name, variable);
+            } else {
+                try self.environment.add_variable(identifier.name, undereferenced_variable.?);
+            }
         } else {
-            try self.environment.add_variable(assignment_statement.name, undereferenced_variable.?);
+            const xd = assignment_statement.lhs.UNARY_EXPRESSION.expression;
+            const a = try self.generate_expression_value(xd, null);
+            const variable = try self.generate_expression_value(assignment_statement.rhs, null);
+            _ = llvm.LLVMBuildStore(self.builder, variable.value, a.value);
         }
     }
 
diff --git a/src/parser.zig b/src/parser.zig
index a40c811..4f607be 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -16,8 +16,8 @@ pub const Node = union(enum) {
     ASSIGNMENT_STATEMENT: struct {
         is_declaration: bool,
         is_dereference: bool,
-        name: []const u8,
-        expression: *Node,
+        lhs: *Node,
+        rhs: *Node,
     },
     FUNCTION_CALL_STATEMENT: struct {
         expression: *Node,
@@ -154,7 +154,7 @@ pub const Parser = struct {
         });
     }
 
-    // AssignmentStatement ::= ("let")? ("*")? IDENTIFIER EQUALS Expression
+    // AssignmentStatement ::= ("let")? ("*")? Expression EQUALS 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()});
 
@@ -168,18 +168,18 @@ pub const Parser = struct {
             is_dereference = true;
         }
 
-        const identifier = try self.parse_token(tokenizer.TokenType.IDENTIFIER);
+        const lhs = try self.parse_expression();
 
         _ = try self.parse_token(tokenizer.TokenType.EQUALS);
 
-        const expression = try self.parse_expression();
+        const rhs = try self.parse_expression();
 
         return self.create_node(.{
             .ASSIGNMENT_STATEMENT = .{
                 .is_declaration = is_declaration,
                 .is_dereference = is_dereference,
-                .name = try self.arena.dupe(u8, identifier.type.IDENTIFIER),
-                .expression = @constCast(expression),
+                .lhs = lhs,
+                .rhs = rhs,
             },
         });
     }
@@ -200,8 +200,15 @@ pub const Parser = struct {
             .ASSIGNMENT_STATEMENT = .{
                 .is_declaration = true,
                 .is_dereference = false,
-                .name = try self.arena.dupe(u8, identifier.type.IDENTIFIER),
-                .expression = @constCast(typ),
+                .lhs = try self.create_node(.{
+                    .PRIMARY_EXPRESSION = .{
+                        .IDENTIFIER = .{
+                            .name = try self.arena.dupe(u8, identifier.type.IDENTIFIER),
+                            .type = null,
+                        },
+                    },
+                }),
+                .rhs = @constCast(typ),
             },
         });
     }