X-Git-Url: https://git.ayoreis.com/zlox.git/blobdiff_plain/6ae8b98923f9b393fbfa25db8af61a9bd6f1b0f6..f1f777199093f609b87f8e334589e9f0283249da:/src/Environment.zig?ds=inline diff --git a/src/Environment.zig b/src/Environment.zig index 25744a7..40a396a 100644 --- a/src/Environment.zig +++ b/src/Environment.zig @@ -6,17 +6,28 @@ const Literal = Token.Literal; const Environment = @This(); const ErrorPayload = @import("Interpreter.zig").ErrorPayload; +enclosing: ?*Environment, values: StringHashMapUnmanaged(Literal) = .empty, +pub fn init(enclosing: ?*Environment) Environment { + return .{ + .enclosing = enclosing, + }; +} + pub fn define(self: *Environment, allocator: Allocator, name: []const u8, value: Literal) !void { try self.values.put(allocator, name, value); } pub fn get(self: *Environment, allocator: Allocator, name: Token, err_payload: *ErrorPayload) !Literal { - return self.values.get(name.lexeme) orelse { - err_payload.* = .{ .token = name, .message = try std.fmt.allocPrint(allocator, "Undefined variable '{s}'.", .{name.lexeme}) }; - return error.RuntimeError; - }; + if (self.values.contains(name.lexeme)) { + return self.values.get(name.lexeme).?; + } + + if (self.enclosing) |enclosing| return enclosing.get(allocator, name, err_payload); + + err_payload.* = .{ .token = name, .message = try std.fmt.allocPrint(allocator, "Undefined variable '{s}'.", .{name.lexeme}) }; + return error.RuntimeError; } pub fn assign(self: *Environment, allocator: Allocator, name: Token, value: Literal, err_payload: *ErrorPayload) !void { @@ -25,6 +36,11 @@ pub fn assign(self: *Environment, allocator: Allocator, name: Token, value: Lite return; } + if (self.enclosing) |enclosing| { + try enclosing.assign(allocator, name, value, err_payload); + return; + } + err_payload.* = .{ .token = name, .message = try std.fmt.allocPrint(allocator, "Undefined variable '{s}'.", .{name.lexeme}) }; return error.RuntimeError; }