@ai-matrx/records 0.82.1 → 0.83.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -53,8 +53,12 @@ type AggregateOutcome = {
53
53
  * is not a number is a refusal; no values at all is NULL, not 0); filled/empty/unique by
54
54
  * `nullif(text,'')`; percent_empty/percent_filled as 100 x share of the rows (NULL over none). Exact: an average that does not terminate is reported as inexact.
55
55
  */
56
- /** custom.formula_node_kinds(), the functions a formula may call (read on the clone 2026-10-03). */
57
- declare const FORMULA_FUNCTIONS: Set<string>;
56
+ /**
57
+ * The functions a formula may call — THE one list, `@ai-matrx/kit/formula` (mirrors the store's
58
+ * custom.formula_node_kinds(); architecture D6). The gate parses with kit's parser too, and keeps
59
+ * only its own EXACT evaluator below: numbers are read from the digits as typed into fractions.
60
+ */
61
+ declare const FORMULA_FUNCTION_NAMES: ReadonlySet<string>;
58
62
  type FxNode = {
59
63
  k: "num";
60
64
  v: Q;
@@ -77,8 +81,8 @@ type FxNode = {
77
81
  f: string;
78
82
  args: FxNode[];
79
83
  };
80
- /** Parse a formula text, or say what is wrong with it. */
81
- declare function parseFormula(text: string): FxNode | string;
84
+ /** Parse a formula text with the one parser, or say what is wrong with it. */
85
+ declare function parseGateFormula(text: string): FxNode | string;
82
86
  /** Every `{Label}` a formula reads. */
83
87
  declare function formulaRefs(n: FxNode): string[];
84
88
  /**
@@ -944,4 +948,4 @@ interface SafeReusesResult {
944
948
  }
945
949
  declare function safeReuses(spec: TemplateSpec, reuses: Reuse[], existingTables: ExistingTable[]): SafeReusesResult;
946
950
 
947
- export { AgentSnapshotRow, type AggregateOutcome, type ApplyResult, type AutofixResult, BAD_OUTCOME, BOOKING_AVAILABILITY_FACTS, type CapabilityStatus, CapabilityWord, DESIGNATED_REAL_NUMBERS, type DerivedUseCase, type DescribeCheckResult, type DescribeCtx, type DescribePlan, type DescribePlanDoor, type DescribePlanTable, type DescribeProblem, type DescribeResult, type DoorsPart, type ExistingTable, FORMULA_FUNCTIONS, type FieldRequest, GALLERY_ONLY, GOOD_OUTCOME, INSTALL_PLAN_VERSION, IndustryGroup, MAIN_TABLE_ROWS_MAX, MAIN_TABLE_ROWS_MIN, PUBLIC_MAIL_DOMAINS, RECORDS_UI_CALENDAR_MODES, RECORDS_UI_FIELD_SURFACES, RECORDS_UI_VIEW_LAYOUTS, type RepairAnswer, type RepairPatch, type RepairSlice, SERVER_DATE_GRAMMAR, type SafeReusesResult, type SeedRow, SharedBlockId, TABLES_MAX, TABLES_MIN, TEMPLATE_PLAN_DOORS, TIME_BOUND_STAGE, TITLE_DISTINCT_SHARE, type TablesPart, TeachesFeature, TemplateAgent, type TemplateAgentBinding, type TemplateAgentCopyRequest, type TemplateAssetRow, type TemplateAttachment, TemplateAutomation, TemplateBooking, TemplateBookingWindow, type TemplateCard, TemplateChecklist, TemplateDashboard, type TemplateDeclaration, TemplateDigest, TemplateDimensions, TemplateDocument, type TemplateDoorAnswer, type TemplateDoorRun, TemplateDrillDown, type TemplateFamilyDoor, TemplateField, TemplateFootprint, TemplateForm, type TemplateHostExtras, type TemplateInstallPlan, TemplateJob, type TemplateMadeKind, TemplateMergeBinding, TemplateNotification, type TemplatePlanAgent, type TemplatePlanBinding, type TemplatePlanDoor, type TemplatePlanExtraAgent, type TemplatePlanStep, TemplatePortal, TemplateRowAction, TemplateSpec, type TemplateSpecWithAttachments, TemplateStageRules, type TemplateStatus, TemplateTable, TemplateTryIt, type TemplateUpgradeAnswer, type TemplateUpgradeHint, type TemplateUpgradeRun, type TemplateVerdict, TemplateView, TemplateViewKind, TemplateWorkflow, type TrimResult, VIEW_SHAPE_FACTS, type ValidateOptions, type ViewsPart, agentCopyRequest, allTables, anyOfWhere, applyRepairPatches, assertTemplate, attachmentProblems, autofixDescribeSpec, automationHeld, blockTable, bookingArgs, bookingColumnsProblem, capabilitiesUsed, capabilityStatus, checklistSpec, choiceDisplayFormat, compileHostExtras, compileInstallPlan, dashboardBlocks, deferredRelationFields, deferredRelations, derivedFieldSpec, describeCheck, describeSpec, describeVocabulary, digestSpec, documentBody, domainsIn, drillDownDashboard, evalFormula, extrasProblems, fallbackView, foreignTextProblems, formArgs, formulaFieldSpec, formulaOrder, formulaRefs, foundationTokens, isSelfDeclaredField, isTimedField, lastResortTrim, meaningWords, mergeDescribeParts, normalizeForPhones, notificationParts, numberText, numberedStreet, packageDescribeResult, parseAt, parseFormula, parseNumeric, pathOfAt, peopleOf, phonesOutsideFictionalRange, planTables, portalArgs, relationFieldSpec, relationPatches, relativeHasTime, repairSlices, requiredCircleProblem, resolveDateToken, resolvePath, resolveRelativeDates, reusesOf, rowActionList, rowLevels, rowsFor, ruleBreak, runTemplateDoor, safeReuses, sameMeaning, selfDeclaredFieldSpec, sensitivityFloorOf, shellsPayload, stageFieldOf, stageRulesSpec, storeAggregate, storeFilterMatches, storeText, tableShellPayload, templateCard, templateDeclaration, templateText, templateUpgradeHint, timedFieldSpec, toUseCase, unwrap, upgradeTemplateInstall, useCaseProblemsOf, validateTemplate, viewMatches, viewSpec, zoneOffset };
951
+ export { AgentSnapshotRow, type AggregateOutcome, type ApplyResult, type AutofixResult, BAD_OUTCOME, BOOKING_AVAILABILITY_FACTS, type CapabilityStatus, CapabilityWord, DESIGNATED_REAL_NUMBERS, type DerivedUseCase, type DescribeCheckResult, type DescribeCtx, type DescribePlan, type DescribePlanDoor, type DescribePlanTable, type DescribeProblem, type DescribeResult, type DoorsPart, type ExistingTable, FORMULA_FUNCTION_NAMES, type FieldRequest, GALLERY_ONLY, GOOD_OUTCOME, INSTALL_PLAN_VERSION, IndustryGroup, MAIN_TABLE_ROWS_MAX, MAIN_TABLE_ROWS_MIN, PUBLIC_MAIL_DOMAINS, RECORDS_UI_CALENDAR_MODES, RECORDS_UI_FIELD_SURFACES, RECORDS_UI_VIEW_LAYOUTS, type RepairAnswer, type RepairPatch, type RepairSlice, SERVER_DATE_GRAMMAR, type SafeReusesResult, type SeedRow, SharedBlockId, TABLES_MAX, TABLES_MIN, TEMPLATE_PLAN_DOORS, TIME_BOUND_STAGE, TITLE_DISTINCT_SHARE, type TablesPart, TeachesFeature, TemplateAgent, type TemplateAgentBinding, type TemplateAgentCopyRequest, type TemplateAssetRow, type TemplateAttachment, TemplateAutomation, TemplateBooking, TemplateBookingWindow, type TemplateCard, TemplateChecklist, TemplateDashboard, type TemplateDeclaration, TemplateDigest, TemplateDimensions, TemplateDocument, type TemplateDoorAnswer, type TemplateDoorRun, TemplateDrillDown, type TemplateFamilyDoor, TemplateField, TemplateFootprint, TemplateForm, type TemplateHostExtras, type TemplateInstallPlan, TemplateJob, type TemplateMadeKind, TemplateMergeBinding, TemplateNotification, type TemplatePlanAgent, type TemplatePlanBinding, type TemplatePlanDoor, type TemplatePlanExtraAgent, type TemplatePlanStep, TemplatePortal, TemplateRowAction, TemplateSpec, type TemplateSpecWithAttachments, TemplateStageRules, type TemplateStatus, TemplateTable, TemplateTryIt, type TemplateUpgradeAnswer, type TemplateUpgradeHint, type TemplateUpgradeRun, type TemplateVerdict, TemplateView, TemplateViewKind, TemplateWorkflow, type TrimResult, VIEW_SHAPE_FACTS, type ValidateOptions, type ViewsPart, agentCopyRequest, allTables, anyOfWhere, applyRepairPatches, assertTemplate, attachmentProblems, autofixDescribeSpec, automationHeld, blockTable, bookingArgs, bookingColumnsProblem, capabilitiesUsed, capabilityStatus, checklistSpec, choiceDisplayFormat, compileHostExtras, compileInstallPlan, dashboardBlocks, deferredRelationFields, deferredRelations, derivedFieldSpec, describeCheck, describeSpec, describeVocabulary, digestSpec, documentBody, domainsIn, drillDownDashboard, evalFormula, extrasProblems, fallbackView, foreignTextProblems, formArgs, formulaFieldSpec, formulaOrder, formulaRefs, foundationTokens, isSelfDeclaredField, isTimedField, lastResortTrim, meaningWords, mergeDescribeParts, normalizeForPhones, notificationParts, numberText, numberedStreet, packageDescribeResult, parseAt, parseGateFormula, parseNumeric, pathOfAt, peopleOf, phonesOutsideFictionalRange, planTables, portalArgs, relationFieldSpec, relationPatches, relativeHasTime, repairSlices, requiredCircleProblem, resolveDateToken, resolvePath, resolveRelativeDates, reusesOf, rowActionList, rowLevels, rowsFor, ruleBreak, runTemplateDoor, safeReuses, sameMeaning, selfDeclaredFieldSpec, sensitivityFloorOf, shellsPayload, stageFieldOf, stageRulesSpec, storeAggregate, storeFilterMatches, storeText, tableShellPayload, templateCard, templateDeclaration, templateText, templateUpgradeHint, timedFieldSpec, toUseCase, unwrap, upgradeTemplateInstall, useCaseProblemsOf, validateTemplate, viewMatches, viewSpec, zoneOffset };
@@ -53,8 +53,12 @@ type AggregateOutcome = {
53
53
  * is not a number is a refusal; no values at all is NULL, not 0); filled/empty/unique by
54
54
  * `nullif(text,'')`; percent_empty/percent_filled as 100 x share of the rows (NULL over none). Exact: an average that does not terminate is reported as inexact.
55
55
  */
56
- /** custom.formula_node_kinds(), the functions a formula may call (read on the clone 2026-10-03). */
57
- declare const FORMULA_FUNCTIONS: Set<string>;
56
+ /**
57
+ * The functions a formula may call — THE one list, `@ai-matrx/kit/formula` (mirrors the store's
58
+ * custom.formula_node_kinds(); architecture D6). The gate parses with kit's parser too, and keeps
59
+ * only its own EXACT evaluator below: numbers are read from the digits as typed into fractions.
60
+ */
61
+ declare const FORMULA_FUNCTION_NAMES: ReadonlySet<string>;
58
62
  type FxNode = {
59
63
  k: "num";
60
64
  v: Q;
@@ -77,8 +81,8 @@ type FxNode = {
77
81
  f: string;
78
82
  args: FxNode[];
79
83
  };
80
- /** Parse a formula text, or say what is wrong with it. */
81
- declare function parseFormula(text: string): FxNode | string;
84
+ /** Parse a formula text with the one parser, or say what is wrong with it. */
85
+ declare function parseGateFormula(text: string): FxNode | string;
82
86
  /** Every `{Label}` a formula reads. */
83
87
  declare function formulaRefs(n: FxNode): string[];
84
88
  /**
@@ -944,4 +948,4 @@ interface SafeReusesResult {
944
948
  }
945
949
  declare function safeReuses(spec: TemplateSpec, reuses: Reuse[], existingTables: ExistingTable[]): SafeReusesResult;
946
950
 
947
- export { AgentSnapshotRow, type AggregateOutcome, type ApplyResult, type AutofixResult, BAD_OUTCOME, BOOKING_AVAILABILITY_FACTS, type CapabilityStatus, CapabilityWord, DESIGNATED_REAL_NUMBERS, type DerivedUseCase, type DescribeCheckResult, type DescribeCtx, type DescribePlan, type DescribePlanDoor, type DescribePlanTable, type DescribeProblem, type DescribeResult, type DoorsPart, type ExistingTable, FORMULA_FUNCTIONS, type FieldRequest, GALLERY_ONLY, GOOD_OUTCOME, INSTALL_PLAN_VERSION, IndustryGroup, MAIN_TABLE_ROWS_MAX, MAIN_TABLE_ROWS_MIN, PUBLIC_MAIL_DOMAINS, RECORDS_UI_CALENDAR_MODES, RECORDS_UI_FIELD_SURFACES, RECORDS_UI_VIEW_LAYOUTS, type RepairAnswer, type RepairPatch, type RepairSlice, SERVER_DATE_GRAMMAR, type SafeReusesResult, type SeedRow, SharedBlockId, TABLES_MAX, TABLES_MIN, TEMPLATE_PLAN_DOORS, TIME_BOUND_STAGE, TITLE_DISTINCT_SHARE, type TablesPart, TeachesFeature, TemplateAgent, type TemplateAgentBinding, type TemplateAgentCopyRequest, type TemplateAssetRow, type TemplateAttachment, TemplateAutomation, TemplateBooking, TemplateBookingWindow, type TemplateCard, TemplateChecklist, TemplateDashboard, type TemplateDeclaration, TemplateDigest, TemplateDimensions, TemplateDocument, type TemplateDoorAnswer, type TemplateDoorRun, TemplateDrillDown, type TemplateFamilyDoor, TemplateField, TemplateFootprint, TemplateForm, type TemplateHostExtras, type TemplateInstallPlan, TemplateJob, type TemplateMadeKind, TemplateMergeBinding, TemplateNotification, type TemplatePlanAgent, type TemplatePlanBinding, type TemplatePlanDoor, type TemplatePlanExtraAgent, type TemplatePlanStep, TemplatePortal, TemplateRowAction, TemplateSpec, type TemplateSpecWithAttachments, TemplateStageRules, type TemplateStatus, TemplateTable, TemplateTryIt, type TemplateUpgradeAnswer, type TemplateUpgradeHint, type TemplateUpgradeRun, type TemplateVerdict, TemplateView, TemplateViewKind, TemplateWorkflow, type TrimResult, VIEW_SHAPE_FACTS, type ValidateOptions, type ViewsPart, agentCopyRequest, allTables, anyOfWhere, applyRepairPatches, assertTemplate, attachmentProblems, autofixDescribeSpec, automationHeld, blockTable, bookingArgs, bookingColumnsProblem, capabilitiesUsed, capabilityStatus, checklistSpec, choiceDisplayFormat, compileHostExtras, compileInstallPlan, dashboardBlocks, deferredRelationFields, deferredRelations, derivedFieldSpec, describeCheck, describeSpec, describeVocabulary, digestSpec, documentBody, domainsIn, drillDownDashboard, evalFormula, extrasProblems, fallbackView, foreignTextProblems, formArgs, formulaFieldSpec, formulaOrder, formulaRefs, foundationTokens, isSelfDeclaredField, isTimedField, lastResortTrim, meaningWords, mergeDescribeParts, normalizeForPhones, notificationParts, numberText, numberedStreet, packageDescribeResult, parseAt, parseFormula, parseNumeric, pathOfAt, peopleOf, phonesOutsideFictionalRange, planTables, portalArgs, relationFieldSpec, relationPatches, relativeHasTime, repairSlices, requiredCircleProblem, resolveDateToken, resolvePath, resolveRelativeDates, reusesOf, rowActionList, rowLevels, rowsFor, ruleBreak, runTemplateDoor, safeReuses, sameMeaning, selfDeclaredFieldSpec, sensitivityFloorOf, shellsPayload, stageFieldOf, stageRulesSpec, storeAggregate, storeFilterMatches, storeText, tableShellPayload, templateCard, templateDeclaration, templateText, templateUpgradeHint, timedFieldSpec, toUseCase, unwrap, upgradeTemplateInstall, useCaseProblemsOf, validateTemplate, viewMatches, viewSpec, zoneOffset };
951
+ export { AgentSnapshotRow, type AggregateOutcome, type ApplyResult, type AutofixResult, BAD_OUTCOME, BOOKING_AVAILABILITY_FACTS, type CapabilityStatus, CapabilityWord, DESIGNATED_REAL_NUMBERS, type DerivedUseCase, type DescribeCheckResult, type DescribeCtx, type DescribePlan, type DescribePlanDoor, type DescribePlanTable, type DescribeProblem, type DescribeResult, type DoorsPart, type ExistingTable, FORMULA_FUNCTION_NAMES, type FieldRequest, GALLERY_ONLY, GOOD_OUTCOME, INSTALL_PLAN_VERSION, IndustryGroup, MAIN_TABLE_ROWS_MAX, MAIN_TABLE_ROWS_MIN, PUBLIC_MAIL_DOMAINS, RECORDS_UI_CALENDAR_MODES, RECORDS_UI_FIELD_SURFACES, RECORDS_UI_VIEW_LAYOUTS, type RepairAnswer, type RepairPatch, type RepairSlice, SERVER_DATE_GRAMMAR, type SafeReusesResult, type SeedRow, SharedBlockId, TABLES_MAX, TABLES_MIN, TEMPLATE_PLAN_DOORS, TIME_BOUND_STAGE, TITLE_DISTINCT_SHARE, type TablesPart, TeachesFeature, TemplateAgent, type TemplateAgentBinding, type TemplateAgentCopyRequest, type TemplateAssetRow, type TemplateAttachment, TemplateAutomation, TemplateBooking, TemplateBookingWindow, type TemplateCard, TemplateChecklist, TemplateDashboard, type TemplateDeclaration, TemplateDigest, TemplateDimensions, TemplateDocument, type TemplateDoorAnswer, type TemplateDoorRun, TemplateDrillDown, type TemplateFamilyDoor, TemplateField, TemplateFootprint, TemplateForm, type TemplateHostExtras, type TemplateInstallPlan, TemplateJob, type TemplateMadeKind, TemplateMergeBinding, TemplateNotification, type TemplatePlanAgent, type TemplatePlanBinding, type TemplatePlanDoor, type TemplatePlanExtraAgent, type TemplatePlanStep, TemplatePortal, TemplateRowAction, TemplateSpec, type TemplateSpecWithAttachments, TemplateStageRules, type TemplateStatus, TemplateTable, TemplateTryIt, type TemplateUpgradeAnswer, type TemplateUpgradeHint, type TemplateUpgradeRun, type TemplateVerdict, TemplateView, TemplateViewKind, TemplateWorkflow, type TrimResult, VIEW_SHAPE_FACTS, type ValidateOptions, type ViewsPart, agentCopyRequest, allTables, anyOfWhere, applyRepairPatches, assertTemplate, attachmentProblems, autofixDescribeSpec, automationHeld, blockTable, bookingArgs, bookingColumnsProblem, capabilitiesUsed, capabilityStatus, checklistSpec, choiceDisplayFormat, compileHostExtras, compileInstallPlan, dashboardBlocks, deferredRelationFields, deferredRelations, derivedFieldSpec, describeCheck, describeSpec, describeVocabulary, digestSpec, documentBody, domainsIn, drillDownDashboard, evalFormula, extrasProblems, fallbackView, foreignTextProblems, formArgs, formulaFieldSpec, formulaOrder, formulaRefs, foundationTokens, isSelfDeclaredField, isTimedField, lastResortTrim, meaningWords, mergeDescribeParts, normalizeForPhones, notificationParts, numberText, numberedStreet, packageDescribeResult, parseAt, parseGateFormula, parseNumeric, pathOfAt, peopleOf, phonesOutsideFictionalRange, planTables, portalArgs, relationFieldSpec, relationPatches, relativeHasTime, repairSlices, requiredCircleProblem, resolveDateToken, resolvePath, resolveRelativeDates, reusesOf, rowActionList, rowLevels, rowsFor, ruleBreak, runTemplateDoor, safeReuses, sameMeaning, selfDeclaredFieldSpec, sensitivityFloorOf, shellsPayload, stageFieldOf, stageRulesSpec, storeAggregate, storeFilterMatches, storeText, tableShellPayload, templateCard, templateDeclaration, templateText, templateUpgradeHint, timedFieldSpec, toUseCase, unwrap, upgradeTemplateInstall, useCaseProblemsOf, validateTemplate, viewMatches, viewSpec, zoneOffset };
@@ -327,6 +327,7 @@ var CATALOGUE_STATUSES = ["planned", "authoring", "checking", "waiting_on_lane_1
327
327
 
328
328
  // src/templates/validate.ts
329
329
  import { isUuidShape } from "@ai-matrx/kit/uuid";
330
+ import { FORMULA_FUNCTIONS as KIT_FORMULA_FUNCTIONS, parseFormula as parseFormulaText } from "@ai-matrx/kit/formula";
330
331
 
331
332
  // src/templates/confidential.ts
332
333
  var TABLE_KERNEL_ID = "11111111-0000-4000-8000-000000000001";
@@ -2738,134 +2739,28 @@ function storeFilterMatches(row, filter, _timeZone) {
2738
2739
  return have === String(want);
2739
2740
  });
2740
2741
  }
2741
- var FORMULA_FUNCTIONS = /* @__PURE__ */ new Set([
2742
- "ABS",
2743
- "AND",
2744
- "ARRAYCOMPACT",
2745
- "ARRAYJOIN",
2746
- "AVERAGE",
2747
- "BLANK",
2748
- "CONCATENATE",
2749
- "CONTAINS",
2750
- "DATEADD",
2751
- "DATEDIFF",
2752
- "DATETIME_FORMAT",
2753
- "DAY",
2754
- "FIND",
2755
- "IF",
2756
- "ISBLANK",
2757
- "LEFT",
2758
- "LEN",
2759
- "LOWER",
2760
- "MAX",
2761
- "MIN",
2762
- "MONTH",
2763
- "NOT",
2764
- "OR",
2765
- "REGEX_MATCH",
2766
- "RIGHT",
2767
- "ROUND",
2768
- "SUBSTITUTE",
2769
- "SUM",
2770
- "SWITCH",
2771
- "TODAY",
2772
- "NOW",
2773
- "TRIM",
2774
- "UPPER",
2775
- "WORKDAY",
2776
- "YEAR"
2777
- ]);
2778
- function fxTokens(text) {
2779
- const out = [];
2780
- let i = 0;
2781
- while (i < text.length) {
2782
- const c = text[i];
2783
- if (/\s/.test(c)) i += 1;
2784
- else if (c === "{") {
2785
- const j = text.indexOf("}", i);
2786
- if (j < 0) return "a { has no closing }";
2787
- out.push({ t: "ref", v: text.slice(i + 1, j).trim() });
2788
- i = j + 1;
2789
- } else if (c === "'" || c === '"') {
2790
- const j = text.indexOf(c, i + 1);
2791
- if (j < 0) return "a quoted word has no closing quote";
2792
- out.push({ t: "str", v: text.slice(i + 1, j) });
2793
- i = j + 1;
2794
- } else if (/[0-9.]/.test(c)) {
2795
- const m = /^[0-9]*\.?[0-9]+/.exec(text.slice(i));
2796
- out.push({ t: "num", v: m[0] });
2797
- i += m[0].length;
2798
- } else if (/[A-Za-z_]/.test(c)) {
2799
- const m = /^[A-Za-z_][A-Za-z_0-9]*/.exec(text.slice(i));
2800
- out.push({ t: "name", v: m[0] });
2801
- i += m[0].length;
2802
- } else if ("+-*/(),%".includes(c)) {
2803
- out.push({ t: "op", v: c });
2804
- i += 1;
2805
- } else return `"${c}" is not part of a formula`;
2806
- }
2807
- return out;
2808
- }
2809
- function parseFormula(text) {
2810
- const toks = fxTokens(text);
2811
- if (typeof toks === "string") return toks;
2812
- let p = 0;
2813
- const peek = () => toks[p];
2814
- const fail = (why) => {
2815
- throw new Error(why);
2816
- };
2817
- const expr = () => {
2818
- let a = term();
2819
- while (peek()?.t === "op" && (peek().v === "+" || peek().v === "-")) {
2820
- const op = toks[p++].v;
2821
- a = { k: "bin", op, a, b: term() };
2822
- }
2823
- return a;
2824
- };
2825
- const term = () => {
2826
- let a = factor();
2827
- while (peek()?.t === "op" && (peek().v === "*" || peek().v === "/" || peek().v === "%")) {
2828
- const op = toks[p++].v;
2829
- a = { k: "bin", op, a, b: factor() };
2830
- }
2831
- return a;
2832
- };
2833
- const factor = () => {
2834
- const tk = toks[p++];
2835
- if (!tk) return fail("the formula ends too early");
2836
- if (tk.t === "num") return { k: "num", v: parseNumeric(tk.v) };
2837
- if (tk.t === "str") return { k: "str", v: tk.v };
2838
- if (tk.t === "ref") return { k: "ref", v: tk.v };
2839
- if (tk.t === "op" && tk.v === "-") return { k: "neg", a: factor() };
2840
- if (tk.t === "op" && tk.v === "(") {
2841
- const e = expr();
2842
- if (toks[p++]?.v !== ")") fail("a ( has no closing )");
2843
- return e;
2844
- }
2845
- if (tk.t === "name") {
2846
- const f = tk.v.toUpperCase();
2847
- if (!FORMULA_FUNCTIONS.has(f)) fail(`${tk.v} is not a formula function the store knows`);
2848
- if (toks[p++]?.v !== "(") fail(`${f} is followed by its arguments in ( )`);
2849
- const args = [];
2850
- if (peek()?.v !== ")") {
2851
- args.push(expr());
2852
- while (peek()?.v === ",") {
2853
- p += 1;
2854
- args.push(expr());
2855
- }
2856
- }
2857
- if (toks[p++]?.v !== ")") fail(`${f}( has no closing )`);
2858
- return { k: "call", f, args };
2859
- }
2860
- return fail(`"${tk.v}" is out of place`);
2861
- };
2862
- try {
2863
- const e = expr();
2864
- if (p !== toks.length) return `"${toks[p].v}" is out of place`;
2865
- return e;
2866
- } catch (err) {
2867
- return err.message;
2868
- }
2742
+ var FORMULA_FUNCTION_NAMES = new Set(KIT_FORMULA_FUNCTIONS.map((f) => f.name));
2743
+ function toFx(n) {
2744
+ switch (n.kind) {
2745
+ case "number":
2746
+ return { k: "num", v: parseNumeric(n.raw) };
2747
+ case "string":
2748
+ return { k: "str", v: n.value };
2749
+ case "boolean":
2750
+ return { k: "call", f: n.value ? "TRUE" : "FALSE", args: [] };
2751
+ case "reference":
2752
+ return { k: "ref", v: n.name };
2753
+ case "unary":
2754
+ return { k: "neg", a: toFx(n.operand) };
2755
+ case "binary":
2756
+ return { k: "bin", op: n.operator, a: toFx(n.left), b: toFx(n.right) };
2757
+ case "call":
2758
+ return { k: "call", f: n.name, args: n.args.map(toFx) };
2759
+ }
2760
+ }
2761
+ function parseGateFormula(text) {
2762
+ const parsed = parseFormulaText(text);
2763
+ return parsed.ok ? toFx(parsed.ast) : parsed.error;
2869
2764
  }
2870
2765
  function formulaRefs(n) {
2871
2766
  if (n.k === "ref") return [n.v];
@@ -2905,7 +2800,7 @@ function evalFormula(n, valueOf) {
2905
2800
  if (n.op === "*") return { ok: true, v: q(a.n * b.n, a.d * b.d) };
2906
2801
  if (b.n === 0n) return { ok: false, why: "it divides by zero on a row" };
2907
2802
  if (n.op === "/") return { ok: true, v: q(a.n * b.d, a.d * b.n) };
2908
- return { ok: false, why: "% is not mirrored" };
2803
+ return { ok: false, why: `${n.op} is not mirrored` };
2909
2804
  }
2910
2805
  case "call": {
2911
2806
  if (n.f === "ABS" && n.args.length === 1) {
@@ -3648,7 +3543,7 @@ function validateTemplate(raw, options = {}) {
3648
3543
  return isComputed(pf) ? computedOf(target, pf, { key: far.key, values: far.values }, depth + 1) : { ok: true, v: far.values?.[f.pick] ?? null };
3649
3544
  }
3650
3545
  if (f.parityType === "formula" && f.formula) {
3651
- const ast = parseFormula(f.formula);
3546
+ const ast = parseGateFormula(f.formula);
3652
3547
  if (typeof ast === "string") return { ok: false, why: ast };
3653
3548
  let why = null;
3654
3549
  const r2 = evalFormula(ast, (label2) => {
@@ -3678,7 +3573,7 @@ function validateTemplate(raw, options = {}) {
3678
3573
  if (!f) return false;
3679
3574
  if (isNumber(f)) return true;
3680
3575
  if (f.parityType !== "formula" || !f.formula) return false;
3681
- const ast = parseFormula(f.formula);
3576
+ const ast = parseGateFormula(f.formula);
3682
3577
  if (typeof ast === "string") return false;
3683
3578
  const refsStored = formulaRefs(ast).every((l) => {
3684
3579
  const rf = byToken.get(table)?.fields.find((x) => x.label === l);
@@ -4985,7 +4880,7 @@ function validateTemplate(raw, options = {}) {
4985
4880
  say(fat, `"${f.label}" is a formula; write it in formula, naming fields in braces: {Total} - {Paid}.`);
4986
4881
  continue;
4987
4882
  }
4988
- const ast = parseFormula(f.formula);
4883
+ const ast = parseGateFormula(f.formula);
4989
4884
  if (typeof ast === "string") {
4990
4885
  say(fat, `The formula "${f.formula}" cannot be read: ${ast}.`);
4991
4886
  continue;
@@ -7830,7 +7725,7 @@ export {
7830
7725
  DEFAULT_TEMPLATE_AGENT,
7831
7726
  DESIGNATED_REAL_NUMBERS,
7832
7727
  ENTITY_REFERENCE_KINDS,
7833
- FORMULA_FUNCTIONS,
7728
+ FORMULA_FUNCTION_NAMES,
7834
7729
  GALLERY_ONLY,
7835
7730
  GOOD_OUTCOME,
7836
7731
  INDUSTRY_GROUPS,
@@ -7913,7 +7808,7 @@ export {
7913
7808
  numberedStreet,
7914
7809
  packageDescribeResult,
7915
7810
  parseAt,
7916
- parseFormula,
7811
+ parseGateFormula,
7917
7812
  parseNumeric,
7918
7813
  pathOfAt,
7919
7814
  peopleOf,