summary refs log tree commit diff
path: root/src/evaluator.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/evaluator.zig')
-rw-r--r--src/evaluator.zig109
1 files changed, 71 insertions, 38 deletions
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;
     }
 };