summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <manuelpalenzuelamerino@gmail.com>2025-01-18 12:33:03 +0100
committerBaitinq <manuelpalenzuelamerino@gmail.com>2025-01-18 12:36:04 +0100
commit4bd00f3138e8a460366d2d764afd382903b09f0b (patch)
tree294c1f5be7d2f0e5eeaa3ab1e26801a770f77c1a
parentExamples: Add variable scopes example (diff)
downloadinterpreter-4bd00f3138e8a460366d2d764afd382903b09f0b.tar.gz
interpreter-4bd00f3138e8a460366d2d764afd382903b09f0b.tar.bz2
interpreter-4bd00f3138e8a460366d2d764afd382903b09f0b.zip
Misc: Start working on scopes
-rw-r--r--src/evaluator.zig21
1 files changed, 13 insertions, 8 deletions
diff --git a/src/evaluator.zig b/src/evaluator.zig
index 4570851..1c38161 100644
--- a/src/evaluator.zig
+++ b/src/evaluator.zig
@@ -6,16 +6,20 @@ const EvaluatorError = error{
     OutOfMemory,
 };
 
-const VariableType = enum { NUMBER, FUNCTION };
+const VariableType = enum { NUMBER, FUNCTION_DEFINITION };
 
 const Variable = union(VariableType) {
     NUMBER: i64,
-    FUNCTION: *parser.Node,
+    FUNCTION_DEFINITION: *parser.Node,
+};
+
+const Scope = struct {
+    variables: std.StringHashMap(?*Variable),
 };
 
 pub const Evaluator = struct {
     ast: ?*parser.Node,
-    variables: std.StringHashMap(?*Variable),
+    scope_stack: std.ArrayList(*Scope),
     //TODO: CREATE STACK WITH SCOPES AND WE CAN SEARCH UP SCOPES
 
     allocator: std.mem.Allocator,
@@ -25,7 +29,7 @@ pub const Evaluator = struct {
         const evaluator = try allocator.create(Evaluator);
         evaluator.* = .{
             .ast = null,
-            .variables = std.StringHashMap(?*Variable).init(allocator),
+            .scope_stack = std.ArrayList(*Scope).init(allocator),
             .allocator = allocator,
         };
         return evaluator;
@@ -42,7 +46,7 @@ pub const Evaluator = struct {
         }
 
         const main = self.variables.get("main") orelse return EvaluatorError.EvaluationError;
-        return try self.evaluate_function_definition(main.?.FUNCTION);
+        return try self.evaluate_function_definition(main.?.FUNCTION_DEFINITION);
     }
 
     fn evaluate_statement(self: *Evaluator, statement: *parser.Node) EvaluatorError!void {
@@ -74,7 +78,7 @@ pub const Evaluator = struct {
 
         if (assignment_statement.expression.* == parser.Node.FUNCTION_DEFINITION) {
             try self.variables.put(assignment_statement.name, try self.create_variable(.{
-                .FUNCTION = assignment_statement.expression,
+                .FUNCTION_DEFINITION = assignment_statement.expression,
             }));
         } else {
             const val = try self.get_expression_value(assignment_statement.expression);
@@ -99,7 +103,7 @@ pub const Evaluator = struct {
 
         const val = self.variables.get(function_call_statement.name) orelse return EvaluatorError.EvaluationError;
 
-        return self.evaluate_function_definition(val.?.FUNCTION); //TODO: Pass arguments to this
+        return self.evaluate_function_definition(val.?.FUNCTION_DEFINITION); //TODO: Pass arguments to this
     }
 
     fn evaluate_return_statement(self: *Evaluator, return_statement: *parser.Node) !i64 {
@@ -134,10 +138,11 @@ pub const Evaluator = struct {
                     else => unreachable,
                 }
             },
+            // I don't like having 2 places where we evaluate functions
             .FUNCTION_CALL_STATEMENT => |x| {
                 const func = self.variables.get(x.name) orelse return EvaluatorError.EvaluationError;
 
-                return try self.evaluate_function_definition(func.?.FUNCTION);
+                return try self.evaluate_function_definition(func.?.FUNCTION_DEFINITION);
             },
 
             else => unreachable,