pub const lang = @import("./lang.zig"); pub const env = @import("./env.zig"); pub const corelib = @import("./corelib.zig"); pub const util = @import("./util.zig"); const lexer = @import("./lexer.zig"); const parser = @import("./parser.zig"); const std = @import("std"); const Allocator = std.mem.Allocator; pub const State = struct { const Self = @This(); const Frontend = struct { allocator: Allocator, tokenizer: lexer.Tokenizer, env: *env.Environment, pub fn init(allocator: Allocator, environ: *env.Environment, buf: []const u8) !Frontend { const t = try lexer.Tokenizer.init(allocator, buf); return .{ .allocator = allocator, .tokenizer = t, .env = environ, }; } pub fn createParser(self: *Frontend) !parser.Parser { return parser.Parser.init(self.allocator, &self.tokenizer, self.env); } pub fn deinit(self: *Frontend) void { self.tokenizer.deinit(); } }; allocator: Allocator, env: env.Environment, frontend: ?Frontend = null, /// Initialize a Zexa `State` pub fn init(allocator: Allocator) !Self { var e = try env.Environment.init(allocator); try corelib.loadCoreLibrary(&e.primary_scope); return .{ .allocator = allocator, .env = e, }; } /// Deinitialize the state pub fn deinit(self: *Self) void { if (self.frontend) |*f| { f.deinit(); } self.env.deinit(); } /// Returns the primary scope pub fn getScope(self: *Self) *lang.Scope { return &self.env.primary_scope; } /// Load `buf` into a frontend for execution pub fn loadString(self: *Self, buf: []const u8) !void { self.frontend = try Frontend.init(self.allocator, &self.env, buf); } /// Load the contents of `reader` into a frontend for execution pub fn loadFile(self: *Self, reader: *std.Io.Reader) !void { const contents = try reader.allocRemaining(self.allocator, .unlimited); defer self.allocator.free(contents); try self.loadString(contents); } /// Load the library `lib` pub fn loadLibrary(self: *Self, lib: lang.Library) lang.RuntimeError!void { try self.getScope().loadLibrary(lib); } /// Tokenize, parse and evaluate the code in the frontend pub fn exec(self: *Self) !?*lang.Value { if (self.frontend) |*f| { defer { f.deinit(); self.frontend = null; } try f.tokenizer.lex(); var p = try f.createParser(); defer p.deinit(); try p.parse(); return try self.getScope().evalAst(p.ast.items); } else { return null; } } }; test { _ = lang; _ = env; _ = corelib; _ = lexer; _ = parser; }