Embedded programming language for Zig
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move `evalExpr` to `Scope`

IamPyu b5ce0773 1166fd89

+51 -48
+4 -48
src/env.zig
··· 7 7 const Scope = zexa.types.Scope; 8 8 const Value = zexa.types.Value; 9 9 10 - pub const RuntimeError = error{InvalidFunction}; 11 - 12 10 pub const Environment = struct { 13 11 const Self = @This(); 14 12 ··· 26 24 self.primary_scope.deinit(); 27 25 } 28 26 29 - pub fn evalExpr(self: *Self, scope: *Scope, expr: *Value) !*Value { 30 - const val = switch (expr.*) { 31 - .atom => |atom| switch (atom) { 32 - .nil => Value{ .atom = .nil }, 33 - .bool => |b| Value{ .atom = .{ .bool = b } }, 34 - .num => |n| Value{ .atom = .{ .num = n } }, 35 - .str => |s| return try Value.initString(scope, s), 36 - .sym => |s| return scope.get(s) orelse try Value.initNil(scope), 37 - .quote => |v| return v, 38 - .native_func => return expr, 39 - }, 40 - .cons => { 41 - const slice = try expr.toSlice(scope); 42 - 43 - if (slice.len == 0) { 44 - return Value.initNil(scope); 45 - } 46 - 47 - const car = try self.evalExpr(scope, slice[0]); 48 - const cdr = slice[1..]; 49 - 50 - switch (car.*) { 51 - .atom => |atom| switch (atom) { 52 - .native_func => |f| { 53 - for (cdr) |*v| { 54 - v.* = try self.evalExpr(scope, v.*); 55 - } 56 - 57 - return f(scope, cdr); 58 - }, 59 - else => return RuntimeError.InvalidFunction, 60 - }, 61 - else => return RuntimeError.InvalidFunction, 62 - } 63 - 64 - return Value.initNil(scope); 65 - }, 66 - }; 67 - 68 - return Value.initFrom(scope, val); 69 - } 70 - 71 27 pub fn evalAst(self: *Self, ast: []const *Value) !*Value { 72 28 var iter = SliceIterator(*Value).init(ast); 73 29 var value: ?*Value = null; ··· 77 33 return value orelse try Value.initNil(&self.primary_scope); 78 34 } 79 35 80 - value = try self.evalExpr(&self.primary_scope, iter.next().?); 36 + value = try self.primary_scope.evalExpr(iter.next().?); 81 37 } 82 38 } 83 39 }; ··· 87 43 defer env.deinit(); 88 44 89 45 const v = try Value.initFrom(&env.primary_scope, .{ .atom = .{ .num = 34 } }); 90 - const val = try env.evalExpr(&env.primary_scope, v); 46 + const val = try env.primary_scope.evalExpr(v); 91 47 92 48 try std.testing.expectEqual(Value{ .atom = .{ .num = 34 } }, val.*); 93 49 } ··· 105 61 .atom = .{ .sym = key }, 106 62 }); 107 63 108 - const fetched = try env.evalExpr(&env.primary_scope, sym); 64 + const fetched = try env.primary_scope.evalExpr(sym); 109 65 try std.testing.expectEqualStrings("hello world!", fetched.*.atom.str); 110 66 } 111 67 ··· 167 123 try Value.initFromAny(scope, 435), 168 124 }); 169 125 170 - _ = try env.evalExpr(scope, list); 126 + _ = try scope.evalExpr(list); 171 127 }
+47
src/types.zig
··· 3 3 const Allocator = std.mem.Allocator; 4 4 const Arena = std.heap.ArenaAllocator; 5 5 6 + pub const RuntimeError = error{InvalidFunction}; 7 + 6 8 pub const Scope = struct { 7 9 const Self = @This(); 8 10 ··· 59 61 60 62 return null; 61 63 } 64 + 65 + pub fn evalExpr(self: *Self, expr: *Value) !*Value { 66 + const val = switch (expr.*) { 67 + .atom => |atom| switch (atom) { 68 + .nil => Value{ .atom = .nil }, 69 + .bool => |b| Value{ .atom = .{ .bool = b } }, 70 + .num => |n| Value{ .atom = .{ .num = n } }, 71 + .str => |s| return try Value.initString(self, s), 72 + .sym => |s| return self.get(s) orelse try Value.initNil(self), 73 + .quote => |v| return v, 74 + .native_func => return expr, 75 + }, 76 + .cons => { 77 + const slice = try expr.toSlice(self); 78 + 79 + if (slice.len == 0) { 80 + return Value.initNil(self); 81 + } 82 + 83 + const car = try self.evalExpr(slice[0]); 84 + const cdr = slice[1..]; 85 + 86 + switch (car.*) { 87 + .atom => |atom| switch (atom) { 88 + .native_func => |f| { 89 + for (cdr) |*v| { 90 + v.* = try self.evalExpr(v.*); 91 + } 92 + 93 + return f(self, cdr); 94 + }, 95 + else => return RuntimeError.InvalidFunction, 96 + }, 97 + else => return RuntimeError.InvalidFunction, 98 + } 99 + 100 + return Value.initNil(self); 101 + }, 102 + }; 103 + 104 + return Value.initFrom(self, val); 105 + } 62 106 }; 63 107 64 108 pub const Symbol = []const u8; ··· 77 121 Cons, 78 122 }; 79 123 124 + /// A value that lives in a `Scope` 125 + /// 126 + /// The lifetime of any value is bounded to the scope by an arena allocator. 80 127 pub const Value = union(enum) { 81 128 const Self = @This(); 82 129