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.zig57
1 files changed, 32 insertions, 25 deletions
diff --git a/src/evaluator.zig b/src/evaluator.zig
index 95aecd1..f4a56d8 100644
--- a/src/evaluator.zig
+++ b/src/evaluator.zig
@@ -41,7 +41,7 @@ pub const Evaluator = struct {
         }
 
         const main = self.environment.get_variable("main") orelse return EvaluatorError.EvaluationError;
-        return try self.evaluate_function_definition(main.FUNCTION_DEFINITION);
+        return try self.evaluate_function_definition(main.FUNCTION_DEFINITION, &[_]*parser.Node{});
     }
 
     fn evaluate_statement(self: *Evaluator, statement: *parser.Node) EvaluatorError!void {
@@ -71,21 +71,11 @@ pub const Evaluator = struct {
             return EvaluatorError.EvaluationError;
         }
 
-        var variable: *Variable = undefined;
-        if (assignment_statement.expression.* == parser.Node.FUNCTION_DEFINITION) {
-            variable = try self.create_variable(.{
-                .FUNCTION_DEFINITION = assignment_statement.expression,
-            });
-        } else {
-            const val = try self.get_expression_value(assignment_statement.expression);
-            variable = try self.create_variable(.{
-                .NUMBER = val,
-            });
-        }
+        const variable = try self.create_variable(assignment_statement.expression);
         try self.environment.add_variable(assignment_statement.name, variable);
     }
 
-    fn evaluate_function_call_statement(self: *Evaluator, node: *parser.Node) !i64 {
+    fn evaluate_function_call_statement(self: *Evaluator, node: *parser.Node) EvaluatorError!i64 {
         errdefer std.debug.print("Error evaluating function call statement\n", .{});
         std.debug.assert(node.* == parser.Node.FUNCTION_CALL_STATEMENT);
 
@@ -98,9 +88,9 @@ pub const Evaluator = struct {
             return 0;
         }
 
-        const val = self.environment.get_variable(function_call_statement.name) orelse return EvaluatorError.EvaluationError;
+        const function_definition = self.environment.get_variable(function_call_statement.name) orelse return EvaluatorError.EvaluationError;
 
-        return self.evaluate_function_definition(val.FUNCTION_DEFINITION); //TODO: Pass arguments to this
+        return self.evaluate_function_definition(function_definition.FUNCTION_DEFINITION, function_call_statement.arguments);
     }
 
     fn evaluate_return_statement(self: *Evaluator, return_statement: *parser.Node) !i64 {
@@ -136,17 +126,13 @@ pub const Evaluator = struct {
                 }
             },
             // I don't like having 2 places where we evaluate functions
-            .FUNCTION_CALL_STATEMENT => |x| {
-                const func = self.environment.get_variable(x.name) orelse return EvaluatorError.EvaluationError;
-
-                return try self.evaluate_function_definition(func.FUNCTION_DEFINITION);
-            },
+            .FUNCTION_CALL_STATEMENT => return try self.evaluate_function_call_statement(node),
 
             else => unreachable,
         }
     }
 
-    fn evaluate_function_definition(self: *Evaluator, node: *parser.Node) EvaluatorError!i64 {
+    fn evaluate_function_definition(self: *Evaluator, node: *parser.Node, arguments: []*parser.Node) EvaluatorError!i64 {
         errdefer std.debug.print("Error evaluating function definition\n", .{});
         std.debug.assert(node.* == parser.Node.FUNCTION_DEFINITION);
 
@@ -155,7 +141,17 @@ pub const Evaluator = struct {
         try self.environment.create_scope();
         defer self.environment.drop_scope();
 
+        std.debug.assert(function_definition.parameters.len == arguments.len);
+
         var i: usize = 0;
+        while (i < arguments.len) : (i += 1) {
+            const parameter = function_definition.parameters[i];
+            const argument = arguments[i];
+
+            try self.environment.add_variable(parameter.PRIMARY_EXPRESSION.IDENTIFIER.name, try self.create_variable(argument));
+        }
+
+        i = 0;
         while (i < function_definition.statements.len - 1) {
             const stmt = function_definition.statements[i];
             try self.evaluate_statement(stmt);
@@ -166,9 +162,19 @@ pub const Evaluator = struct {
         return try self.evaluate_return_statement(return_stmt);
     }
 
-    fn create_variable(self: *Evaluator, variable_value: Variable) !*Variable {
+    fn create_variable(self: *Evaluator, node: *parser.Node) !*Variable {
         const variable = try self.allocator.create(Variable);
-        variable.* = variable_value;
+        if (node.* == parser.Node.FUNCTION_DEFINITION) {
+            variable.* = .{
+                .FUNCTION_DEFINITION = node,
+            };
+        } else {
+            const val = try self.get_expression_value(node);
+            variable.* = .{
+                .NUMBER = val,
+            };
+        }
+
         return variable;
     }
 };
@@ -215,8 +221,9 @@ const Environment = struct {
     }
 
     fn get_variable(self: *Environment, name: []const u8) ?*Variable {
-        var i = self.scope_stack.items.len - 1;
-        while (i >= 0) : (i -= 1) {
+        var i = self.scope_stack.items.len;
+        while (i > 0) {
+            i -= 1;
             const scope = self.scope_stack.items[i];
             if (scope.variables.get(name)) |v| return v;
         }