tiny.pluck.toplevel.forms
Defined in toplevel.
API (7)
Actions
Public operations.
processDefineprocessDefineFunctionprocessDefineTypeprocessExprQueryprocessFormprocessFormSexprprocessQuery
Source
Source: lib/pluck/src/toplevel/forms.zig
zig
const std = @import("std");const pluck = @import("../root.zig");const pexpr = pluck.pexpr;const PExpr = pexpr.PExpr;const Symbol = pexpr.Symbol;const context_owner = @import("context.zig");const ToplevelContext = context_owner.ToplevelContext;const top_types = @import("types.zig");const ToplevelError = top_types.ToplevelError;const result_owner = @import("result.zig");const QueryResult = result_owner.QueryResult;const definitions_owner = @import("definitions.zig");const query_owner = @import("query.zig");const source_owner = @import("source.zig");pub fn processForm(self: *ToplevelContext, source: []const u8) ToplevelError!?QueryResult { return processFormSexpr(self, source);}pub fn processFormSexpr(self: *ToplevelContext, source: []const u8) ToplevelError!?QueryResult { const arena_alloc = self.arena.allocator(); self.last_query_constructor_typo = null; const source_copy = arena_alloc.dupe(u8, source) catch return ToplevelError.OutOfMemory; self.current_source = source_copy; const tokens = pexpr.tokenize(arena_alloc, source) catch return failParse(self); defer pexpr.freeTokens(arena_alloc, tokens); if (tokens.len == 0) { return null; } if (tokens.len >= 2 and std.mem.eql(u8, tokens[0], "(")) { if (std.mem.eql(u8, tokens[1], "define")) { try processDefine(self, tokens); return null; } if (std.mem.eql(u8, tokens[1], "define-type")) { try processDefineType(self, tokens); return null; } if (std.mem.eql(u8, tokens[1], "query")) { return try processQuery(self, tokens); } } return try processExprQuery(self, tokens);}pub fn processDefine(self: *ToplevelContext, tokens: []const pexpr.Token) ToplevelError!void { const arena_alloc = self.arena.allocator(); if (tokens.len < 4) { return ToplevelError.InvalidDefineForm; } var pos: usize = 2; if (std.mem.eql(u8, tokens[pos], "(")) { return processDefineFunction(self, tokens); } const name = tokens[pos]; pos += 1; if (!source_owner.isIdentifier(name)) { return ToplevelError.InvalidDefineForm; } const duped_name = arena_alloc.dupe(u8, name) catch return ToplevelError.OutOfMemory; const prev_def = self.definitions.remove(duped_name); const dummy = PExpr.init(arena_alloc, .{ .construct = .{ .constructor = "Unit" } }) catch return ToplevelError.OutOfMemory; self.definitions.define(duped_name, dummy) catch return ToplevelError.OutOfMemory; errdefer { _ = self.definitions.remove(duped_name); if (prev_def) |expr| { self.definitions.define(duped_name, expr) catch {}; } } const remaining_tokens = tokens[pos..]; if (remaining_tokens.len < 2) { return ToplevelError.InvalidDefineForm; } var parser = pexpr.Parser.init(arena_alloc, remaining_tokens, &self.types, &self.definitions); defer parser.deinit(); const expr = parser.parseExpr() catch return failParse(self); if (parser.peek()) |tok| { if (!std.mem.eql(u8, tok, ")")) { return ToplevelError.InvalidDefineForm; } } _ = definitions_owner.defineWithDocTrackChange(self, duped_name, expr, null) catch return ToplevelError.OutOfMemory;}pub fn processDefineFunction(self: *ToplevelContext, tokens: []const pexpr.Token) ToplevelError!void { const arena_alloc = self.arena.allocator(); var pos: usize = 3; if (pos >= tokens.len) return ToplevelError.InvalidDefineForm; const name = tokens[pos]; pos += 1; if (!source_owner.isIdentifier(name)) { return ToplevelError.InvalidDefineForm; } const duped_name = arena_alloc.dupe(u8, name) catch return ToplevelError.OutOfMemory; const prev_def = self.definitions.remove(duped_name); const dummy = PExpr.init(arena_alloc, .{ .construct = .{ .constructor = "Unit" } }) catch return ToplevelError.OutOfMemory; self.definitions.define(duped_name, dummy) catch return ToplevelError.OutOfMemory; errdefer { _ = self.definitions.remove(duped_name); if (prev_def) |expr| { self.definitions.define(duped_name, expr) catch {}; } } var args: std.ArrayList(Symbol) = .empty; defer args.deinit(arena_alloc); while (pos < tokens.len) { const tok = tokens[pos]; if (std.mem.eql(u8, tok, ")")) { pos += 1; break; } if (!source_owner.isIdentifier(tok)) { return ToplevelError.InvalidDefineForm; } args.append(arena_alloc, tok) catch return ToplevelError.OutOfMemory; pos += 1; } const body_tokens = tokens[pos..]; if (body_tokens.len < 2) { return ToplevelError.InvalidDefineForm; } var parser = pexpr.Parser.init(arena_alloc, body_tokens, &self.types, &self.definitions); defer parser.deinit(); for (args.items) |arg| { parser.pushEnv(arg) catch return ToplevelError.OutOfMemory; } const body = parser.parseExpr() catch return failParse(self); for (args.items) |_| { parser.popEnv(); } var result = body; var i = args.items.len; while (i > 0) { i -= 1; const arg_name = arena_alloc.dupe(u8, args.items[i]) catch return ToplevelError.OutOfMemory; result = PExpr.initWithArgs(arena_alloc, .{ .abs = .{ .var_name = arg_name } }, &.{result}) catch return ToplevelError.OutOfMemory; } if (args.items.len == 0) { result = PExpr.initWithArgs(arena_alloc, .{ .abs = .{ .var_name = "_" } }, &.{result}) catch return ToplevelError.OutOfMemory; } _ = definitions_owner.defineWithDocTrackChange(self, duped_name, result, null) catch return ToplevelError.OutOfMemory;}pub fn processDefineType(self: *ToplevelContext, tokens: []const pexpr.Token) ToplevelError!void { const arena_alloc = self.arena.allocator(); if (tokens.len < 5) { return ToplevelError.InvalidDefineTypeForm; } var pos: usize = 2; const type_name = tokens[pos]; pos += 1; if (!source_owner.isIdentifier(type_name)) { return ToplevelError.InvalidDefineTypeForm; } const CtorNameArgs = struct { name: Symbol, args: []const Symbol }; var parsed_ctors: std.ArrayList(CtorNameArgs) = .empty; defer parsed_ctors.deinit(arena_alloc); while (pos < tokens.len) { const tok = tokens[pos]; if (std.mem.eql(u8, tok, ")")) { break; } if (!std.mem.eql(u8, tok, "(")) { return ToplevelError.InvalidDefineTypeForm; } pos += 1; if (pos >= tokens.len) return ToplevelError.InvalidDefineTypeForm; const ctor_name = tokens[pos]; pos += 1; if (!source_owner.isConstructorName(ctor_name)) { return ToplevelError.InvalidDefineTypeForm; } var ctor_args: std.ArrayList(Symbol) = .empty; defer ctor_args.deinit(arena_alloc); while (pos < tokens.len) { const arg_tok = tokens[pos]; if (std.mem.eql(u8, arg_tok, ")")) { pos += 1; break; } ctor_args.append(arena_alloc, arg_tok) catch return ToplevelError.OutOfMemory; pos += 1; } const args_slice = ctor_args.toOwnedSlice(arena_alloc) catch return ToplevelError.OutOfMemory; parsed_ctors.append(arena_alloc, .{ .name = ctor_name, .args = args_slice }) catch return ToplevelError.OutOfMemory; } if (parsed_ctors.items.len == 0) { return ToplevelError.InvalidDefineTypeForm; } const type_name_duped = arena_alloc.dupe(u8, type_name) catch return ToplevelError.OutOfMemory; for (parsed_ctors.items) |ctor| { const ctor_name_duped = arena_alloc.dupe(u8, ctor.name) catch return ToplevelError.OutOfMemory; try self.types.type_of_constructor.put(ctor_name_duped, type_name_duped); const args_copy = arena_alloc.alloc(Symbol, ctor.args.len) catch return ToplevelError.OutOfMemory; for (ctor.args, 0..) |arg, i| { args_copy[i] = arena_alloc.dupe(u8, arg) catch return ToplevelError.OutOfMemory; } try self.types.args_of_constructor.put(ctor_name_duped, args_copy); } const ctor_names = arena_alloc.alloc(Symbol, parsed_ctors.items.len) catch return ToplevelError.OutOfMemory; for (parsed_ctors.items, 0..) |ctor, i| { ctor_names[i] = arena_alloc.dupe(u8, ctor.name) catch return ToplevelError.OutOfMemory; } try self.types.constructors_of_type.put(type_name_duped, ctor_names);}pub fn processQuery(self: *ToplevelContext, tokens: []const pexpr.Token) ToplevelError!QueryResult { const arena_alloc = self.arena.allocator(); if (tokens.len < 4) { return ToplevelError.InvalidQueryForm; } var expr_start: usize = 2; if (tokens.len > 4) { const maybe_name = tokens[2]; const next_token = tokens[3]; if (source_owner.isIdentifier(maybe_name) and !std.mem.eql(u8, next_token, ")")) { expr_start = 3; } } const expr_tokens = tokens[expr_start..]; var parser = pexpr.Parser.init(arena_alloc, expr_tokens, &self.types, &self.definitions); defer parser.deinit(); const expr = parser.parseExpr() catch return failParse(self); return query_owner.runQuery(self, expr);}pub fn processExprQuery(self: *ToplevelContext, tokens: []const pexpr.Token) ToplevelError!QueryResult { const arena_alloc = self.arena.allocator(); var parser = pexpr.Parser.init(arena_alloc, tokens, &self.types, &self.definitions); defer parser.deinit(); const expr = parser.parseExpr() catch return failParse(self); return query_owner.runQuery(self, expr);}fn failParse(self: *ToplevelContext) ToplevelError { if (self.current_source) |source| { self.last_error_span = source_owner.spanFromOffsets(source, 0, source.len); } return ToplevelError.ParseError;}Source: lib/pluck/src/toplevel/root.zig:13
zig
pub const forms = @import("forms.zig");Complete call list for toplevel.forms.processDefineFunction
8 direct calls.
tiny.choir.backends.artifact.Symbol.deinit[method] atlib/choir/src/backends/artifact/model/linkage/symbol.zig:35tiny.pluck.pexpr.PExpr.init[function] atlib/pluck/src/pexpr.zig:155tiny.pluck.pexpr.PExpr.initWithArgs[function] atlib/pluck/src/pexpr.zig:159tiny.pluck.pexpr.Parser.deinit[method] atlib/pluck/src/pexpr.zig:671tiny.pluck.pexpr.Parser.init[function] atlib/pluck/src/pexpr.zig:655tiny.pluck.pexpr.Parser.parseExpr[method] atlib/pluck/src/pexpr.zig:717tiny.pluck.pexpr.Parser.popEnv[method] atlib/pluck/src/pexpr.zig:706tiny.pluck.pexpr.Parser.pushEnv[method] atlib/pluck/src/pexpr.zig:698
Audit
| Definitions | 8 |
|---|---|
| Public names | 8 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |