summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <manuelpalenzuelamerino@gmail.com>2025-01-16 00:36:57 +0100
committerBaitinq <manuelpalenzuelamerino@gmail.com>2025-01-16 00:36:57 +0100
commitddb118b488da257bb4b4db5e79881aedd62d5b8a (patch)
treec0e21c5abdc65187c234fb12a38a1644865d33ff
parentParser: clean (diff)
downloadinterpreter-ddb118b488da257bb4b4db5e79881aedd62d5b8a.tar.gz
interpreter-ddb118b488da257bb4b4db5e79881aedd62d5b8a.tar.bz2
interpreter-ddb118b488da257bb4b4db5e79881aedd62d5b8a.zip
Evaluator: Start working on new function-capable evaluator
-rw-r--r--examples/4.src9
-rw-r--r--src/evaluator.zig109
-rw-r--r--src/main.zig14
-rw-r--r--src/parser.zig2
4 files changed, 86 insertions, 48 deletions
diff --git a/examples/4.src b/examples/4.src
index ddbc5d4..6e639a8 100644
--- a/examples/4.src
+++ b/examples/4.src
@@ -3,6 +3,11 @@ let print_one = () => {
 	return 0;
 };
 
-let y = print_one();
 
-print(y);
+let main = () => {
+	let y = print_one();
+
+	print(y);
+
+	return y;
+};
diff --git a/src/evaluator.zig b/src/evaluator.zig
index fd0c8e5..13c7639 100644
--- a/src/evaluator.zig
+++ b/src/evaluator.zig
@@ -7,17 +7,15 @@ const EvaluatorError = error{
 };
 
 pub const Evaluator = struct {
-    variables: std.StringHashMap(?i64),
-    return_value: i64,
+    variables: std.StringHashMap(?*parser.Node), //TODO: Reference vs value
 
     allocator: std.mem.Allocator,
 
     pub fn init(allocator: std.mem.Allocator) !*Evaluator {
         const evaluator = try allocator.create(Evaluator);
         evaluator.* = .{
-            .variables = std.StringHashMap(?i64).init(allocator),
+            .variables = std.StringHashMap(?*parser.Node).init(allocator),
             .allocator = allocator,
-            .return_value = 0,
         };
         return evaluator;
     }
@@ -30,47 +28,44 @@ pub const Evaluator = struct {
     pub fn evaluate_ast(self: *Evaluator, ast: *parser.Node) !i64 {
         std.debug.assert(ast.* == parser.Node.PROGRAM);
 
-        const program = ast.*.PROGRAM;
+        const main = find_main(ast) orelse return EvaluatorError.EvaluationError;
 
-        for (program.statements) |statement| {
+        for (main.*.FUNCTION_DEFINITION.statements) |statement| {
             try self.evaluate_statement(statement);
         }
 
-        return self.return_value;
+        return 0; //TODO: Return value
     }
 
-    fn evaluate_statement(self: *Evaluator, statement: *parser.Node) !void {
+    fn evaluate_statement(self: *Evaluator, statement: *parser.Node) EvaluatorError!void {
         errdefer std.debug.print("Error evaluating statement\n", .{});
         std.debug.assert(statement.* == parser.Node.STATEMENT);
 
         return switch (statement.STATEMENT.statement.*) {
-            .VARIABLE_STATEMENT => |*variable_statement| try self.evaluate_variable_statement(@ptrCast(variable_statement)),
+            .ASSIGNMENT_STATEMENT => |*assignment_statement| try self.evaluate_assignment_statement(@ptrCast(assignment_statement)),
             .PRINT_STATEMENT => |*print_statement| try self.evaluate_print_statement(@ptrCast(print_statement)),
-            .RETURN_STATEMENT => |*return_statement| try self.evaluate_return_statement(@ptrCast(return_statement)),
+            .FUNCTION_CALL_STATEMENT => |*function_call_statement| try self.evaluate_function_call_statement(@ptrCast(function_call_statement)),
             else => unreachable,
         };
     }
 
-    fn evaluate_variable_statement(self: *Evaluator, node: *parser.Node) !void {
-        errdefer std.debug.print("Error evaluating variable statement\n", .{});
-        std.debug.assert(node.* == parser.Node.VARIABLE_STATEMENT);
+    fn evaluate_assignment_statement(self: *Evaluator, node: *parser.Node) !void {
+        errdefer std.debug.print("Error evaluating assignment statement\n", .{});
+        std.debug.assert(node.* == parser.Node.ASSIGNMENT_STATEMENT);
 
-        const variable_statement = node.VARIABLE_STATEMENT;
+        const assignment_statement = node.ASSIGNMENT_STATEMENT;
 
         //TODO: We should lowercase keys no?
-        if (variable_statement.is_declaration) {
-            try self.variables.put(variable_statement.name, null);
+        if (assignment_statement.is_declaration) {
+            try self.variables.put(assignment_statement.name, null);
         }
 
-        // Make sure identifier exists
-        const val = try self.get_expression_value(node.VARIABLE_STATEMENT.expression);
-
-        if (!self.variables.contains(variable_statement.name)) {
-            std.debug.print("Variable not found: {s}\n", .{variable_statement.name});
+        if (!self.variables.contains(assignment_statement.name)) {
+            std.debug.print("Variable not found: {s}\n", .{assignment_statement.name});
             return EvaluatorError.EvaluationError;
         }
 
-        try self.variables.put(variable_statement.name, val);
+        try self.variables.put(assignment_statement.name, assignment_statement.expression);
     }
 
     fn evaluate_print_statement(self: *Evaluator, print_statement: *parser.Node) !void {
@@ -82,6 +77,19 @@ pub const Evaluator = struct {
         std.debug.print("PRINT: {d}\n", .{print_value});
     }
 
+    fn evaluate_function_call_statement(self: *Evaluator, function_call_statement: *parser.Node) !void {
+        errdefer std.debug.print("Error evaluating function call statement\n", .{});
+        std.debug.assert(function_call_statement.* == parser.Node.FUNCTION_CALL_STATEMENT);
+
+        const node = self.variables.get(function_call_statement.FUNCTION_CALL_STATEMENT.name) orelse return EvaluatorError.EvaluationError;
+
+        const x = node.?.FUNCTION_DEFINITION;
+
+        for (x.statements) |stmt| {
+            try self.evaluate_statement(stmt); //TODO: Return stmt?
+        }
+    }
+
     // TODO: This is a functionless implementation of return, we should not do this
     fn evaluate_return_statement(self: *Evaluator, return_statement: *parser.Node) !void {
         errdefer std.debug.print("Error evaluating return statement\n", .{});
@@ -96,23 +104,48 @@ pub const Evaluator = struct {
         errdefer std.debug.print("Error getting statement value\n", .{});
         std.debug.assert(node.* == parser.Node.EXPRESSION);
 
-        return switch (node.EXPRESSION) {
-            .NUMBER => |number| number.value,
-            .IDENTIFIER => |identifier| {
-                const val = self.variables.get(identifier.name) orelse {
-                    std.debug.print("Identifier {any} not found\n", .{identifier.name});
-                    return EvaluatorError.EvaluationError;
-                };
-
-                return val.?;
-            },
-            .BINARY => |operation| {
-                //TODO: For now, this just represents sum
-                const lhs = try self.get_expression_value(operation.lhs);
-                const rhs = try self.get_expression_value(operation.rhs);
-                return lhs + rhs;
+        switch (node.EXPRESSION) {
+            .ADDITIVE_EXPRESSION => |additive_expression| {
+                switch (additive_expression.expression.*) {
+                    .ADDITIVE_EXPRESSION => |x| {
+                        const lhs = try self.get_expression_value(x.lhs);
+                        const rhs = try self.get_expression_value(x.rhs);
+                        return lhs + rhs;
+                    },
+                    .PRIMARY_EXPRESSION => |x| {
+                        switch (x) {
+                            .NUMBER => |number| return number.value,
+                            .IDENTIFIER => |identifier| {
+                                const val = self.variables.get(identifier.name) orelse {
+                                    std.debug.print("Identifier {any} not found\n", .{identifier.name});
+                                    return EvaluatorError.EvaluationError;
+                                };
+
+                                return self.get_expression_value(val.?);
+                            },
+                            else => unreachable,
+                        }
+                    },
+                    else => unreachable,
+                }
             },
-        };
+            else => unreachable,
+        }
+    }
+
+    fn find_main(ast: *parser.Node) ?*parser.Node {
+        std.debug.assert(ast.* == parser.Node.PROGRAM);
+
+        for (ast.PROGRAM.statements) |*statement| {
+            const x = statement.*.STATEMENT.statement;
+            if (x.* != parser.Node.ASSIGNMENT_STATEMENT) continue;
+            const y = x.*.ASSIGNMENT_STATEMENT;
+            if (y.is_declaration and std.mem.eql(u8, y.name, "main")) {
+                return y.expression;
+            }
+        }
+
+        return null;
     }
 };
 
diff --git a/src/main.zig b/src/main.zig
index da72d72..d9f6a13 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -17,8 +17,8 @@ pub fn main() !void {
         if (deinit_status == .leak) @panic("Memory leak detected!");
     }
 
-    // const source_evaluator = try evaluator.Evaluator.init(allocator);
-    // defer source_evaluator.deinit();
+    const source_evaluator = try evaluator.Evaluator.init(allocator);
+    defer source_evaluator.deinit();
 
     var arena = std.heap.ArenaAllocator.init(allocator);
     defer arena.deinit();
@@ -30,7 +30,7 @@ pub fn main() !void {
             const buf = try stdin.readUntilDelimiterAlloc(allocator, '\n', 1024);
             defer allocator.free(buf);
 
-            process_buf(buf, allocator, &arena) catch |err| {
+            process_buf(buf, allocator, &arena, source_evaluator) catch |err| {
                 try stdout.print("Error processing line: {any}\n", .{err});
             };
         }
@@ -39,11 +39,11 @@ pub fn main() !void {
         const file = try std.fs.cwd().openFile(path, .{});
         const buf = try file.readToEndAlloc(allocator, 1 * 1024 * 1024);
         defer allocator.free(buf);
-        try process_buf(buf, allocator, &arena);
+        try process_buf(buf, allocator, &arena, source_evaluator);
     }
 }
 
-fn process_buf(buf: []u8, allocator: std.mem.Allocator, arena: *std.heap.ArenaAllocator) !void {
+fn process_buf(buf: []u8, allocator: std.mem.Allocator, arena: *std.heap.ArenaAllocator, source_evaluator: *evaluator.Evaluator) !void {
     std.debug.print("Buf:\n{s}\n", .{buf});
 
     var token_list = std.ArrayList(tokenizer.Token).init(allocator);
@@ -59,8 +59,8 @@ fn process_buf(buf: []u8, allocator: std.mem.Allocator, arena: *std.heap.ArenaAl
     const ast = try source_parser.parse();
     std.debug.print("AST: {any}\n", .{ast});
 
-    // const result = try source_evaluator.evaluate_ast(ast);
-    // std.debug.print("Evaluation result: {any}\n", .{result});
+    const result = try source_evaluator.evaluate_ast(ast);
+    std.debug.print("Evaluation result: {any}\n", .{result});
 }
 
 test {
diff --git a/src/parser.zig b/src/parser.zig
index 3732b2b..f7f90ba 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -37,7 +37,7 @@ pub const Node = union(NodeType) {
     FUNCTION_CALL_STATEMENT: struct {
         name: []const u8,
     },
-    EXPRESSION: struct {
+    EXPRESSION: union(enum) {
         ADDITIVE_EXPRESSION: struct {
             expression: *Node,
         },