a lisp-like language, loosely based on John N. Shutt's "Kernel" language
1const std = @import("std");
2
3/// An object, which is either a pair or and atom. Objects are stored in a big
4/// contiguous arraylist.
5const Object = union(enum) {
6 /// A pair or list. A list `(1 2 3)` is equivalent to `(1 . (2 . (3 . ())))`
7 pair: Pair,
8 /// An integer number. TODO: Other kinds of numbers.
9 number: i64,
10 /// A symbol, such as `+`, `foo`, or `the-word-recursion-has-many-meanings`.
11 /// TODO: Interning.
12 symbol: []const u8,
13 /// Represented as `()`.
14 nil,
15
16 /// An index with which to refer to an Object in the storage array.
17 const Handle = enum(u32) { _ };
18};
19
20/// Represented as `(car . cdr)`.
21const Pair = struct {
22 car: Object.Handle,
23 cdr: Object.Handle,
24};
25
26/// A scope or environment in which bindings may be looked up.
27const Environment = struct {
28 bindings: std.StringHashMap(Object.Handle),
29 parent: ?*Environment = null,
30};
31
32/// The overall interpreter that holds all objects.
33const Machine = struct {
34 objects: std.ArrayList(Object),
35 root_env: Environment,
36
37 fn init(allocator: std.mem.Allocator) Machine {
38 const result: Machine = .{
39 .objects = .{},
40 .root_env = .{ .bindings = .init(allocator) },
41 };
42
43 // TODO: add basic math fns to root environment.
44
45 return result;
46 }
47};