@metta-ts/core 1.0.1 → 1.0.2
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.
- package/dist/index.d.ts +147 -38
- package/dist/index.js +2602 -331
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -75,6 +75,10 @@ function groundEq(a, b) {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
var SYM_INTERN = /* @__PURE__ */ new Map();
|
|
78
|
+
var MIN_EXPR_INTERN_ARITY = 64;
|
|
79
|
+
function canInternExprItems(items) {
|
|
80
|
+
return items.length >= MIN_EXPR_INTERN_ARITY;
|
|
81
|
+
}
|
|
78
82
|
function sym(name) {
|
|
79
83
|
let s = SYM_INTERN.get(name);
|
|
80
84
|
if (s === void 0) {
|
|
@@ -122,6 +126,112 @@ function expr(items) {
|
|
|
122
126
|
ground
|
|
123
127
|
};
|
|
124
128
|
}
|
|
129
|
+
function createInternTable() {
|
|
130
|
+
return {
|
|
131
|
+
buckets: /* @__PURE__ */ new Map(),
|
|
132
|
+
variables: /* @__PURE__ */ new Map(),
|
|
133
|
+
expressions: /* @__PURE__ */ new WeakSet(),
|
|
134
|
+
hasUnsafeGrounded: /* @__PURE__ */ new WeakMap()
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function bucketIntern(table, a) {
|
|
138
|
+
const h = hashOf(a);
|
|
139
|
+
const entry = table.buckets.get(h);
|
|
140
|
+
if (entry === void 0) {
|
|
141
|
+
table.buckets.set(h, a);
|
|
142
|
+
if (a.kind === "expr") table.expressions.add(a);
|
|
143
|
+
return a;
|
|
144
|
+
}
|
|
145
|
+
if (!Array.isArray(entry)) {
|
|
146
|
+
if (atomEq(entry, a)) return entry;
|
|
147
|
+
table.buckets.set(h, [entry, a]);
|
|
148
|
+
if (a.kind === "expr") table.expressions.add(a);
|
|
149
|
+
return a;
|
|
150
|
+
}
|
|
151
|
+
for (const existing of entry) {
|
|
152
|
+
if (atomEq(existing, a)) return existing;
|
|
153
|
+
}
|
|
154
|
+
entry.push(a);
|
|
155
|
+
if (a.kind === "expr") table.expressions.add(a);
|
|
156
|
+
return a;
|
|
157
|
+
}
|
|
158
|
+
function isStateExpression(a) {
|
|
159
|
+
const head = a.items[0];
|
|
160
|
+
return head?.kind === "sym" && (head.name === "State" || head.name === "StateValue");
|
|
161
|
+
}
|
|
162
|
+
function hasUnsafeGrounded(table, a) {
|
|
163
|
+
if (a.kind === "gnd") return true;
|
|
164
|
+
if (a.kind !== "expr") return false;
|
|
165
|
+
if (isStateExpression(a)) return true;
|
|
166
|
+
const cached = table.hasUnsafeGrounded.get(a);
|
|
167
|
+
if (cached !== void 0) return cached;
|
|
168
|
+
for (const it of a.items) {
|
|
169
|
+
if (hasUnsafeGrounded(table, it)) {
|
|
170
|
+
table.hasUnsafeGrounded.set(a, true);
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
table.hasUnsafeGrounded.set(a, false);
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
function internVariable(table, a) {
|
|
178
|
+
let v = table.variables.get(a.name);
|
|
179
|
+
if (v === void 0) {
|
|
180
|
+
v = a;
|
|
181
|
+
table.variables.set(a.name, v);
|
|
182
|
+
}
|
|
183
|
+
return v;
|
|
184
|
+
}
|
|
185
|
+
function internAtom(table, a) {
|
|
186
|
+
if (table === void 0) return a;
|
|
187
|
+
switch (a.kind) {
|
|
188
|
+
case "sym":
|
|
189
|
+
return sym(a.name);
|
|
190
|
+
case "var":
|
|
191
|
+
return internVariable(table, a);
|
|
192
|
+
case "expr":
|
|
193
|
+
return internExpr(table, a);
|
|
194
|
+
case "gnd":
|
|
195
|
+
return a;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function internExpr(table, a) {
|
|
199
|
+
if (table === void 0 || table.expressions.has(a) || !a.ground || !canInternExprItems(a.items) || hasUnsafeGrounded(table, a)) {
|
|
200
|
+
return a;
|
|
201
|
+
}
|
|
202
|
+
const its = a.items;
|
|
203
|
+
let items = null;
|
|
204
|
+
let ground = true;
|
|
205
|
+
for (let i = 0; i < its.length; i++) {
|
|
206
|
+
const it = its[i];
|
|
207
|
+
const r = internAtom(table, it);
|
|
208
|
+
if (!r.ground) ground = false;
|
|
209
|
+
if (items !== null) items.push(r);
|
|
210
|
+
else if (r !== it) {
|
|
211
|
+
items = its.slice(0, i);
|
|
212
|
+
items.push(r);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const candidate = items === null && ground === a.ground ? a : expr(items ?? its);
|
|
216
|
+
return bucketIntern(table, candidate);
|
|
217
|
+
}
|
|
218
|
+
function internBuiltExpr(table, a) {
|
|
219
|
+
if (table === void 0 || table.expressions.has(a) || !a.ground || !canInternExprItems(a.items) || hasUnsafeGrounded(table, a)) {
|
|
220
|
+
return a;
|
|
221
|
+
}
|
|
222
|
+
const its = a.items;
|
|
223
|
+
let items = null;
|
|
224
|
+
for (let i = 0; i < its.length; i++) {
|
|
225
|
+
const it = its[i];
|
|
226
|
+
const r = it.kind === "var" ? internVariable(table, it) : it.kind === "sym" ? sym(it.name) : it;
|
|
227
|
+
if (items !== null) items.push(r);
|
|
228
|
+
else if (r !== it) {
|
|
229
|
+
items = its.slice(0, i);
|
|
230
|
+
items.push(r);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return bucketIntern(table, items === null ? a : expr(items));
|
|
234
|
+
}
|
|
125
235
|
function groundType(v) {
|
|
126
236
|
switch (v.g) {
|
|
127
237
|
case "int":
|
|
@@ -425,12 +535,32 @@ function format(a) {
|
|
|
425
535
|
var emptyBindings = [];
|
|
426
536
|
var valRel = (x, a) => ({ tag: "val", x, a, y: void 0 });
|
|
427
537
|
var eqRel = (x, y) => ({ tag: "eq", x, a: void 0, y });
|
|
538
|
+
function isValFor(r, x) {
|
|
539
|
+
return r.tag === "val" && r.x === x;
|
|
540
|
+
}
|
|
541
|
+
function firstValIndex(b, x) {
|
|
542
|
+
for (let i = 0; i < b.length; i++) if (isValFor(b[i], x)) return i;
|
|
543
|
+
return -1;
|
|
544
|
+
}
|
|
545
|
+
function copyWithoutVal(b, x, first, out = []) {
|
|
546
|
+
for (let i = 0; i < first; i++) out.push(b[i]);
|
|
547
|
+
for (let i = first + 1; i < b.length; i++) {
|
|
548
|
+
const r = b[i];
|
|
549
|
+
if (!isValFor(r, x)) out.push(r);
|
|
550
|
+
}
|
|
551
|
+
return out;
|
|
552
|
+
}
|
|
428
553
|
function lookupVal(b, x) {
|
|
429
|
-
for (
|
|
554
|
+
for (let i = 0; i < b.length; i++) {
|
|
555
|
+
const r = b[i];
|
|
556
|
+
if (isValFor(r, x)) return r.a;
|
|
557
|
+
}
|
|
430
558
|
return void 0;
|
|
431
559
|
}
|
|
432
560
|
function removeVal(b, x) {
|
|
433
|
-
|
|
561
|
+
const first = firstValIndex(b, x);
|
|
562
|
+
if (first < 0) return b;
|
|
563
|
+
return copyWithoutVal(b, x, first);
|
|
434
564
|
}
|
|
435
565
|
function hasLoop(b) {
|
|
436
566
|
for (const r of b) {
|
|
@@ -440,10 +570,48 @@ function hasLoop(b) {
|
|
|
440
570
|
return false;
|
|
441
571
|
}
|
|
442
572
|
function addValRaw(b, x, a) {
|
|
443
|
-
|
|
573
|
+
const first = firstValIndex(b, x);
|
|
574
|
+
if (first < 0) {
|
|
575
|
+
return prependValRaw(b, x, a);
|
|
576
|
+
}
|
|
577
|
+
return copyWithoutVal(b, x, first, [valRel(x, a)]);
|
|
578
|
+
}
|
|
579
|
+
function prependValRaw(b, x, a) {
|
|
580
|
+
const rel = valRel(x, a);
|
|
581
|
+
return b.length === 0 ? [rel] : [rel, ...b];
|
|
444
582
|
}
|
|
445
583
|
function addEqRaw(b, x, y) {
|
|
446
|
-
|
|
584
|
+
if (x === y) return b;
|
|
585
|
+
return [eqRel(x, y), ...b];
|
|
586
|
+
}
|
|
587
|
+
function makeValRel(x, a) {
|
|
588
|
+
return valRel(x, a);
|
|
589
|
+
}
|
|
590
|
+
function fromRelations(rels) {
|
|
591
|
+
return rels;
|
|
592
|
+
}
|
|
593
|
+
function size(b) {
|
|
594
|
+
return b.length;
|
|
595
|
+
}
|
|
596
|
+
function isEmpty(b) {
|
|
597
|
+
return b.length === 0;
|
|
598
|
+
}
|
|
599
|
+
function relations(b) {
|
|
600
|
+
return b;
|
|
601
|
+
}
|
|
602
|
+
function* valEntries(b) {
|
|
603
|
+
for (const r of b) if (r.tag === "val") yield [r.x, r.a];
|
|
604
|
+
}
|
|
605
|
+
function someVal(b, pred) {
|
|
606
|
+
for (const r of b) if (r.tag === "val" && pred(r.x, r.a)) return true;
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
609
|
+
function hasEq(b) {
|
|
610
|
+
for (const r of b) if (r.tag === "eq") return true;
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
function* eqRelations(b) {
|
|
614
|
+
for (const r of b) if (r.tag === "eq") yield r;
|
|
447
615
|
}
|
|
448
616
|
|
|
449
617
|
// src/match.ts
|
|
@@ -480,25 +648,26 @@ function occursThrough(target, a, rels, b, seen) {
|
|
|
480
648
|
function reconcile(b, l, r) {
|
|
481
649
|
const out = [];
|
|
482
650
|
for (const mb of matchAtoms(l, r)) {
|
|
483
|
-
if (mb
|
|
484
|
-
continue;
|
|
651
|
+
if (someVal(mb, (x, a) => occursThrough(x, a, mb, b, /* @__PURE__ */ new Set()))) continue;
|
|
485
652
|
for (const m of merge(b, mb)) out.push(m);
|
|
486
653
|
}
|
|
487
654
|
return out;
|
|
488
655
|
}
|
|
489
656
|
function addVarBinding(b, x, v) {
|
|
490
657
|
const prev = lookupVal(b, x);
|
|
491
|
-
if (prev === void 0) return [
|
|
658
|
+
if (prev === void 0) return [prependValRaw(b, x, v)];
|
|
492
659
|
if (atomEq(prev, v)) return [b];
|
|
493
660
|
return reconcile(b, prev, v);
|
|
494
661
|
}
|
|
495
662
|
function addVarEquality(b, x, y) {
|
|
663
|
+
if (x === y) return [b];
|
|
496
664
|
const vx = lookupVal(b, x);
|
|
497
665
|
const vy = lookupVal(b, y);
|
|
498
666
|
if (vx === void 0 || vy === void 0 || atomEq(vx, vy)) return [addEqRaw(b, x, y)];
|
|
499
667
|
return reconcile(b, vx, vy);
|
|
500
668
|
}
|
|
501
669
|
function mergeOne(bs, r) {
|
|
670
|
+
if (r.tag === "eq" && r.x === r.y) return bs;
|
|
502
671
|
const out = [];
|
|
503
672
|
for (const b of bs) {
|
|
504
673
|
const ext = r.tag === "val" ? addVarBinding(b, r.x, r.a) : addVarEquality(b, r.x, r.y);
|
|
@@ -508,37 +677,30 @@ function mergeOne(bs, r) {
|
|
|
508
677
|
}
|
|
509
678
|
function merge(a, b) {
|
|
510
679
|
let acc = [a];
|
|
511
|
-
for (const r of b) acc = mergeOne(acc, r);
|
|
680
|
+
for (const r of relations(b)) acc = mergeOne(acc, r);
|
|
512
681
|
return acc;
|
|
513
682
|
}
|
|
514
683
|
function matchAtomsWith(custom, l, r, leftSuffix = "") {
|
|
515
|
-
if (l.kind === "sym" && r.kind === "sym") return l.name === r.name ? [
|
|
684
|
+
if (l.kind === "sym" && r.kind === "sym") return l.name === r.name ? [emptyBindings] : [];
|
|
516
685
|
if (l.kind === "var" && r.kind === "var") {
|
|
517
686
|
const lx = l.name + leftSuffix;
|
|
518
|
-
return lx === r.name ? [
|
|
687
|
+
return lx === r.name ? [emptyBindings] : [prependValRaw(emptyBindings, lx, r)];
|
|
519
688
|
}
|
|
520
|
-
if (l.kind === "var") return [
|
|
689
|
+
if (l.kind === "var") return [prependValRaw(emptyBindings, l.name + leftSuffix, r)];
|
|
521
690
|
if (r.kind === "var")
|
|
522
691
|
return [
|
|
523
|
-
|
|
524
|
-
{
|
|
525
|
-
tag: "val",
|
|
526
|
-
x: r.name,
|
|
527
|
-
a: leftSuffix === "" ? l : suffixVars(l, leftSuffix),
|
|
528
|
-
y: void 0
|
|
529
|
-
}
|
|
530
|
-
]
|
|
692
|
+
prependValRaw(emptyBindings, r.name, leftSuffix === "" ? l : suffixVars(l, leftSuffix))
|
|
531
693
|
];
|
|
532
694
|
if (l.kind === "expr" && r.kind === "expr")
|
|
533
|
-
return matchAll(custom, [
|
|
695
|
+
return matchAll(custom, [emptyBindings], l.items, r.items, leftSuffix);
|
|
534
696
|
if (l.kind === "gnd") return matchGrounded(custom, l, r);
|
|
535
697
|
if (r.kind === "gnd") return matchGrounded(custom, r, l);
|
|
536
|
-
return atomEq(l, r) ? [
|
|
698
|
+
return atomEq(l, r) ? [emptyBindings] : [];
|
|
537
699
|
}
|
|
538
700
|
function matchGrounded(custom, g, other) {
|
|
539
701
|
if (g.kind === "gnd" && g.match !== void 0) return g.match(other);
|
|
540
702
|
if (custom !== void 0) return custom(g, other);
|
|
541
|
-
return atomEq(g, other) ? [
|
|
703
|
+
return atomEq(g, other) ? [emptyBindings] : [];
|
|
542
704
|
}
|
|
543
705
|
function matchAll(custom, acc, xs, ys, leftSuffix = "") {
|
|
544
706
|
if (xs.length !== ys.length) return [];
|
|
@@ -559,6 +721,81 @@ function matchAtomsScoped(l, r, suffix) {
|
|
|
559
721
|
return matchAtomsWith(void 0, l, r, suffix);
|
|
560
722
|
}
|
|
561
723
|
|
|
724
|
+
// src/trail.ts
|
|
725
|
+
var Trail = class {
|
|
726
|
+
binds = /* @__PURE__ */ new Map();
|
|
727
|
+
trail = [];
|
|
728
|
+
/** A restore point: the current trail length. */
|
|
729
|
+
mark() {
|
|
730
|
+
return this.trail.length;
|
|
731
|
+
}
|
|
732
|
+
/** Undo every binding made since `m`. */
|
|
733
|
+
undo(m) {
|
|
734
|
+
const t = this.trail;
|
|
735
|
+
while (t.length > m) this.binds.delete(t.pop());
|
|
736
|
+
}
|
|
737
|
+
/** Bind `$name` to `a` and record it on the trail. The caller guarantees `$name` is currently unbound. */
|
|
738
|
+
bind(name, a) {
|
|
739
|
+
this.binds.set(name, a);
|
|
740
|
+
this.trail.push(name);
|
|
741
|
+
}
|
|
742
|
+
/** Follow variable bindings to the representative: a non-variable, or an unbound variable. */
|
|
743
|
+
deref(a) {
|
|
744
|
+
let cur = a;
|
|
745
|
+
while (cur.kind === "var") {
|
|
746
|
+
const v = this.binds.get(cur.name);
|
|
747
|
+
if (v === void 0) return cur;
|
|
748
|
+
cur = v;
|
|
749
|
+
}
|
|
750
|
+
return cur;
|
|
751
|
+
}
|
|
752
|
+
/** The atom currently bound to `$name`, if any (the direct binding, not dereferenced). */
|
|
753
|
+
get(name) {
|
|
754
|
+
return this.binds.get(name);
|
|
755
|
+
}
|
|
756
|
+
/** Resolve `a` against the current bindings, one pass (the same discipline as the immutable
|
|
757
|
+
* `instantiate`/`applySubst`): a variable becomes its bound value as-is; the value's own variables are
|
|
758
|
+
* not re-resolved, and an expression's children are resolved. This matches the evaluator exactly,
|
|
759
|
+
* including that a cyclic binding (`$y = (.. $y ..)`, which `matchAtoms` produces and `hasLoop` does not
|
|
760
|
+
* reject) terminates instead of looping. A new term is built only where a child changed. */
|
|
761
|
+
resolve(a) {
|
|
762
|
+
if (a.kind === "var") return this.deref(a);
|
|
763
|
+
if (a.kind !== "expr" || a.ground) return a;
|
|
764
|
+
const its = a.items;
|
|
765
|
+
let items = null;
|
|
766
|
+
for (let i = 0; i < its.length; i++) {
|
|
767
|
+
const it = its[i];
|
|
768
|
+
const r = this.resolve(it);
|
|
769
|
+
if (items !== null) items.push(r);
|
|
770
|
+
else if (r !== it) {
|
|
771
|
+
items = its.slice(0, i);
|
|
772
|
+
items.push(r);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
return items === null ? a : { ...a, items };
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
function unifyTrail(tr, l0, r0) {
|
|
779
|
+
const l = tr.deref(l0);
|
|
780
|
+
const r = tr.deref(r0);
|
|
781
|
+
if (l === r) return true;
|
|
782
|
+
if (l.kind === "var") {
|
|
783
|
+
if (r.kind === "var" && l.name === r.name) return true;
|
|
784
|
+
tr.bind(l.name, r);
|
|
785
|
+
return true;
|
|
786
|
+
}
|
|
787
|
+
if (r.kind === "var") {
|
|
788
|
+
tr.bind(r.name, l);
|
|
789
|
+
return true;
|
|
790
|
+
}
|
|
791
|
+
if (l.kind === "sym") return r.kind === "sym" && l.name === r.name;
|
|
792
|
+
if (l.kind === "gnd") return r.kind === "gnd" && atomEq(l, r);
|
|
793
|
+
if (r.kind !== "expr" || l.items.length !== r.items.length) return false;
|
|
794
|
+
for (let i = 0; i < l.items.length; i++)
|
|
795
|
+
if (!unifyTrail(tr, l.items[i], r.items[i])) return false;
|
|
796
|
+
return true;
|
|
797
|
+
}
|
|
798
|
+
|
|
562
799
|
// src/substitution.ts
|
|
563
800
|
var emptySubst = [];
|
|
564
801
|
function lookupSubst(s, x) {
|
|
@@ -610,29 +847,31 @@ function occurs(x, a) {
|
|
|
610
847
|
// src/instantiate.ts
|
|
611
848
|
function bindingsToSubst(b) {
|
|
612
849
|
const out = [];
|
|
613
|
-
for (const
|
|
850
|
+
for (const e of valEntries(b)) out.push(e);
|
|
614
851
|
return out;
|
|
615
852
|
}
|
|
616
|
-
function instantiate(b, a, suffix = "") {
|
|
853
|
+
function instantiate(b, a, suffix = "", intern) {
|
|
617
854
|
if (a.kind === "var") {
|
|
618
|
-
if (suffix === "") return b
|
|
855
|
+
if (suffix === "") return isEmpty(b) ? a : lookupVal(b, a.name) ?? a;
|
|
619
856
|
const name = a.name + suffix;
|
|
620
857
|
return lookupVal(b, name) ?? variable(name);
|
|
621
858
|
}
|
|
622
859
|
if (a.ground || a.kind !== "expr") return a;
|
|
623
|
-
if (b
|
|
860
|
+
if (isEmpty(b) && suffix === "") return a;
|
|
624
861
|
const its = a.items;
|
|
625
862
|
let items = null;
|
|
626
863
|
for (let i = 0; i < its.length; i++) {
|
|
627
864
|
const it = its[i];
|
|
628
|
-
const r = instantiate(b, it, suffix);
|
|
865
|
+
const r = instantiate(b, it, suffix, intern);
|
|
629
866
|
if (items !== null) items.push(r);
|
|
630
867
|
else if (r !== it) {
|
|
631
868
|
items = its.slice(0, i);
|
|
632
869
|
items.push(r);
|
|
633
870
|
}
|
|
634
871
|
}
|
|
635
|
-
|
|
872
|
+
if (items === null) return a;
|
|
873
|
+
if (intern === void 0 || !canInternExprItems(items)) return expr(items);
|
|
874
|
+
return internBuiltExpr(intern, expr(items));
|
|
636
875
|
}
|
|
637
876
|
|
|
638
877
|
// src/pmap.ts
|
|
@@ -711,13 +950,30 @@ var idxCount = (idx, atom) => {
|
|
|
711
950
|
};
|
|
712
951
|
var emptyLog = null;
|
|
713
952
|
var logSize = (log) => log === null ? 0 : log.size;
|
|
714
|
-
var
|
|
953
|
+
var idxCache = /* @__PURE__ */ new WeakMap();
|
|
954
|
+
var logGroundIdx = (log) => {
|
|
955
|
+
if (log === null) return emptyPMap;
|
|
956
|
+
const hit = idxCache.get(log);
|
|
957
|
+
if (hit !== void 0) return hit;
|
|
958
|
+
const chain = [];
|
|
959
|
+
let node = log;
|
|
960
|
+
while (node !== null && !idxCache.has(node)) {
|
|
961
|
+
chain.push(node);
|
|
962
|
+
node = node.prev;
|
|
963
|
+
}
|
|
964
|
+
let idx = node === null ? emptyPMap : idxCache.get(node);
|
|
965
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
966
|
+
const n = chain[i];
|
|
967
|
+
if (n.atom.ground) idx = idxAdd(idx, n.atom);
|
|
968
|
+
idxCache.set(n, idx);
|
|
969
|
+
}
|
|
970
|
+
return idx;
|
|
971
|
+
};
|
|
715
972
|
var logNonGround = (log) => log === null ? 0 : log.nonGround;
|
|
716
973
|
var logAppend = (log, atom) => ({
|
|
717
974
|
atom,
|
|
718
975
|
prev: log,
|
|
719
976
|
size: (log === null ? 0 : log.size) + 1,
|
|
720
|
-
groundIdx: atom.ground ? idxAdd(logGroundIdx(log), atom) : logGroundIdx(log),
|
|
721
977
|
nonGround: (log === null ? 0 : log.nonGround) + (atom.ground ? 0 : 1)
|
|
722
978
|
});
|
|
723
979
|
function logAppendAll(log, atoms) {
|
|
@@ -734,6 +990,374 @@ function logToArray(log) {
|
|
|
734
990
|
}
|
|
735
991
|
var logFromArray = (atoms) => logAppendAll(emptyLog, atoms);
|
|
736
992
|
|
|
993
|
+
// src/flat-atomspace.ts
|
|
994
|
+
var TERM_SYM = 1;
|
|
995
|
+
var TERM_GND = 2;
|
|
996
|
+
var TERM_VAR = 3;
|
|
997
|
+
var TERM_EXPR = 4;
|
|
998
|
+
var CHUNK_SIZE = 16384;
|
|
999
|
+
var ABSENT = -1;
|
|
1000
|
+
var Int32Chunks = class {
|
|
1001
|
+
chunks = [];
|
|
1002
|
+
tail = new Int32Array(CHUNK_SIZE);
|
|
1003
|
+
length = 0;
|
|
1004
|
+
push(value) {
|
|
1005
|
+
const index = this.length;
|
|
1006
|
+
const offset = index % CHUNK_SIZE;
|
|
1007
|
+
if (offset === 0) {
|
|
1008
|
+
if (index > 0) this.chunks.push(this.tail);
|
|
1009
|
+
this.tail = new Int32Array(CHUNK_SIZE);
|
|
1010
|
+
}
|
|
1011
|
+
this.tail[offset] = value | 0;
|
|
1012
|
+
this.length = index + 1;
|
|
1013
|
+
return index;
|
|
1014
|
+
}
|
|
1015
|
+
get(index) {
|
|
1016
|
+
return index < this.chunks.length * CHUNK_SIZE ? this.chunks[Math.floor(index / CHUNK_SIZE)][index % CHUNK_SIZE] : this.tail[index % CHUNK_SIZE];
|
|
1017
|
+
}
|
|
1018
|
+
};
|
|
1019
|
+
function groundKey(v) {
|
|
1020
|
+
switch (v.g) {
|
|
1021
|
+
case "int":
|
|
1022
|
+
return "i\0" + typeof v.n + "\0" + String(v.n);
|
|
1023
|
+
case "float":
|
|
1024
|
+
return "f\0" + String(v.n);
|
|
1025
|
+
case "str":
|
|
1026
|
+
return "s\0" + v.s;
|
|
1027
|
+
case "bool":
|
|
1028
|
+
return v.b ? "b\x001" : "b\x000";
|
|
1029
|
+
case "unit":
|
|
1030
|
+
return "u";
|
|
1031
|
+
case "error":
|
|
1032
|
+
return "e\0" + v.msg;
|
|
1033
|
+
case "ext":
|
|
1034
|
+
return "x\0" + v.kind + "\0" + v.id;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
function groundHash2(v) {
|
|
1038
|
+
return strHash(groundKey(v));
|
|
1039
|
+
}
|
|
1040
|
+
function canCompactAtom(a) {
|
|
1041
|
+
switch (a.kind) {
|
|
1042
|
+
case "sym":
|
|
1043
|
+
case "var":
|
|
1044
|
+
return true;
|
|
1045
|
+
case "gnd":
|
|
1046
|
+
return a.exec === void 0 && a.match === void 0;
|
|
1047
|
+
case "expr":
|
|
1048
|
+
return a.items.every(canCompactAtom);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
var FlatAtomSpaceTable = class {
|
|
1052
|
+
termKind = new Int32Chunks();
|
|
1053
|
+
termStart = new Int32Chunks();
|
|
1054
|
+
termLen = new Int32Chunks();
|
|
1055
|
+
termHash = new Int32Chunks();
|
|
1056
|
+
termGround = new Int32Chunks();
|
|
1057
|
+
termData = new Int32Chunks();
|
|
1058
|
+
factRoot = new Int32Chunks();
|
|
1059
|
+
factHeadSym = new Int32Chunks();
|
|
1060
|
+
hashBuckets = /* @__PURE__ */ new Map();
|
|
1061
|
+
symByName = /* @__PURE__ */ new Map();
|
|
1062
|
+
groundByKey = /* @__PURE__ */ new Map();
|
|
1063
|
+
varByName = /* @__PURE__ */ new Map();
|
|
1064
|
+
termFacts = /* @__PURE__ */ new Map();
|
|
1065
|
+
symbols = [];
|
|
1066
|
+
grounds = [];
|
|
1067
|
+
vars = [];
|
|
1068
|
+
get factCount() {
|
|
1069
|
+
return this.factRoot.length;
|
|
1070
|
+
}
|
|
1071
|
+
insertFact(atom) {
|
|
1072
|
+
const root = this.insertAtom(atom);
|
|
1073
|
+
const id = this.factRoot.push(root);
|
|
1074
|
+
this.factHeadSym.push(this.headSymOf(root));
|
|
1075
|
+
const facts = this.termFacts.get(root);
|
|
1076
|
+
if (facts === void 0) this.termFacts.set(root, [id]);
|
|
1077
|
+
else facts.push(id);
|
|
1078
|
+
return id;
|
|
1079
|
+
}
|
|
1080
|
+
factsForTerm(term) {
|
|
1081
|
+
return this.termFacts.get(term) ?? [];
|
|
1082
|
+
}
|
|
1083
|
+
insertAtom(atom) {
|
|
1084
|
+
switch (atom.kind) {
|
|
1085
|
+
case "sym":
|
|
1086
|
+
return this.internLeaf(
|
|
1087
|
+
TERM_SYM,
|
|
1088
|
+
this.internSym(atom.name),
|
|
1089
|
+
strHash("s\0" + atom.name),
|
|
1090
|
+
true
|
|
1091
|
+
);
|
|
1092
|
+
case "gnd": {
|
|
1093
|
+
const key = groundKey(atom.value);
|
|
1094
|
+
return this.internLeaf(
|
|
1095
|
+
TERM_GND,
|
|
1096
|
+
this.internGround(key, atom.value),
|
|
1097
|
+
groundHash2(atom.value),
|
|
1098
|
+
true
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1101
|
+
case "var":
|
|
1102
|
+
return this.internLeaf(
|
|
1103
|
+
TERM_VAR,
|
|
1104
|
+
this.internVar(atom.name),
|
|
1105
|
+
strHash("v\0" + atom.name),
|
|
1106
|
+
false
|
|
1107
|
+
);
|
|
1108
|
+
case "expr": {
|
|
1109
|
+
const children = atom.items.map((child) => this.insertAtom(child));
|
|
1110
|
+
return this.internExpr(children);
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
lookupAtom(atom) {
|
|
1115
|
+
switch (atom.kind) {
|
|
1116
|
+
case "sym": {
|
|
1117
|
+
const leaf = this.symByName.get(atom.name);
|
|
1118
|
+
return leaf === void 0 ? void 0 : this.lookupLeaf(TERM_SYM, leaf, strHash("s\0" + atom.name));
|
|
1119
|
+
}
|
|
1120
|
+
case "gnd": {
|
|
1121
|
+
if (!canCompactAtom(atom)) return void 0;
|
|
1122
|
+
const key = groundKey(atom.value);
|
|
1123
|
+
const leaf = this.groundByKey.get(key);
|
|
1124
|
+
return leaf === void 0 ? void 0 : this.lookupLeaf(TERM_GND, leaf, groundHash2(atom.value));
|
|
1125
|
+
}
|
|
1126
|
+
case "var": {
|
|
1127
|
+
const leaf = this.varByName.get(atom.name);
|
|
1128
|
+
return leaf === void 0 ? void 0 : this.lookupLeaf(TERM_VAR, leaf, strHash("v\0" + atom.name));
|
|
1129
|
+
}
|
|
1130
|
+
case "expr": {
|
|
1131
|
+
const children = [];
|
|
1132
|
+
for (const child of atom.items) {
|
|
1133
|
+
const term = this.lookupAtom(child);
|
|
1134
|
+
if (term === void 0) return void 0;
|
|
1135
|
+
children.push(term);
|
|
1136
|
+
}
|
|
1137
|
+
return this.lookupExpr(children);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
decodeTerm(term) {
|
|
1142
|
+
const kind = this.termKind.get(term);
|
|
1143
|
+
const start = this.termStart.get(term);
|
|
1144
|
+
switch (kind) {
|
|
1145
|
+
case TERM_SYM:
|
|
1146
|
+
return sym(this.symbols[start]);
|
|
1147
|
+
case TERM_GND: {
|
|
1148
|
+
const ground = this.grounds[start];
|
|
1149
|
+
return gnd(ground, groundType(ground));
|
|
1150
|
+
}
|
|
1151
|
+
case TERM_VAR:
|
|
1152
|
+
return variable(this.vars[start]);
|
|
1153
|
+
case TERM_EXPR: {
|
|
1154
|
+
const len = this.termLen.get(term);
|
|
1155
|
+
const items = [];
|
|
1156
|
+
for (let i = 0; i < len; i++) items.push(this.decodeTerm(this.termData.get(start + i)));
|
|
1157
|
+
return expr(items);
|
|
1158
|
+
}
|
|
1159
|
+
default:
|
|
1160
|
+
throw new Error(`flat-atomspace: bad term kind ${kind}`);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
isTermGround(term) {
|
|
1164
|
+
return this.termGround.get(term) === 1;
|
|
1165
|
+
}
|
|
1166
|
+
headSymOf(term) {
|
|
1167
|
+
const kind = this.termKind.get(term);
|
|
1168
|
+
if (kind === TERM_SYM) return this.termStart.get(term);
|
|
1169
|
+
if (kind !== TERM_EXPR || this.termLen.get(term) === 0) return ABSENT;
|
|
1170
|
+
const head = this.termData.get(this.termStart.get(term));
|
|
1171
|
+
return this.termKind.get(head) === TERM_SYM ? this.termStart.get(head) : ABSENT;
|
|
1172
|
+
}
|
|
1173
|
+
lookupHeadSym(name) {
|
|
1174
|
+
return this.symByName.get(name);
|
|
1175
|
+
}
|
|
1176
|
+
internSym(name) {
|
|
1177
|
+
const existing = this.symByName.get(name);
|
|
1178
|
+
if (existing !== void 0) return existing;
|
|
1179
|
+
const id = this.symbols.length;
|
|
1180
|
+
this.symbols.push(name);
|
|
1181
|
+
this.symByName.set(name, id);
|
|
1182
|
+
return id;
|
|
1183
|
+
}
|
|
1184
|
+
internGround(key, value) {
|
|
1185
|
+
const existing = this.groundByKey.get(key);
|
|
1186
|
+
if (existing !== void 0) return existing;
|
|
1187
|
+
const id = this.grounds.length;
|
|
1188
|
+
this.grounds.push(value);
|
|
1189
|
+
this.groundByKey.set(key, id);
|
|
1190
|
+
return id;
|
|
1191
|
+
}
|
|
1192
|
+
internVar(name) {
|
|
1193
|
+
const existing = this.varByName.get(name);
|
|
1194
|
+
if (existing !== void 0) return existing;
|
|
1195
|
+
const id = this.vars.length;
|
|
1196
|
+
this.vars.push(name);
|
|
1197
|
+
this.varByName.set(name, id);
|
|
1198
|
+
return id;
|
|
1199
|
+
}
|
|
1200
|
+
internLeaf(kind, leaf, hash, ground) {
|
|
1201
|
+
const existing = this.lookupLeaf(kind, leaf, hash);
|
|
1202
|
+
if (existing !== void 0) return existing;
|
|
1203
|
+
return this.pushTerm(kind, leaf, 1, hash, ground);
|
|
1204
|
+
}
|
|
1205
|
+
lookupLeaf(kind, leaf, hash) {
|
|
1206
|
+
const bucket = this.hashBuckets.get(hash);
|
|
1207
|
+
if (bucket === void 0) return void 0;
|
|
1208
|
+
for (const term of bucket)
|
|
1209
|
+
if (this.termKind.get(term) === kind && this.termStart.get(term) === leaf) return term;
|
|
1210
|
+
return void 0;
|
|
1211
|
+
}
|
|
1212
|
+
internExpr(children) {
|
|
1213
|
+
const existing = this.lookupExpr(children);
|
|
1214
|
+
if (existing !== void 0) return existing;
|
|
1215
|
+
let hash = mixHash(1163415634, children.length);
|
|
1216
|
+
let ground = true;
|
|
1217
|
+
const start = this.termData.length;
|
|
1218
|
+
for (const child of children) {
|
|
1219
|
+
hash = mixHash(hash, child);
|
|
1220
|
+
if (!this.isTermGround(child)) ground = false;
|
|
1221
|
+
this.termData.push(child);
|
|
1222
|
+
}
|
|
1223
|
+
return this.pushTerm(TERM_EXPR, start, children.length, hash, ground);
|
|
1224
|
+
}
|
|
1225
|
+
lookupExpr(children) {
|
|
1226
|
+
let hash = mixHash(1163415634, children.length);
|
|
1227
|
+
for (const child of children) hash = mixHash(hash, child);
|
|
1228
|
+
const bucket = this.hashBuckets.get(hash);
|
|
1229
|
+
if (bucket === void 0) return void 0;
|
|
1230
|
+
termLoop: for (const term of bucket) {
|
|
1231
|
+
if (this.termKind.get(term) !== TERM_EXPR || this.termLen.get(term) !== children.length)
|
|
1232
|
+
continue;
|
|
1233
|
+
const start = this.termStart.get(term);
|
|
1234
|
+
for (let i = 0; i < children.length; i++)
|
|
1235
|
+
if (this.termData.get(start + i) !== children[i]) continue termLoop;
|
|
1236
|
+
return term;
|
|
1237
|
+
}
|
|
1238
|
+
return void 0;
|
|
1239
|
+
}
|
|
1240
|
+
pushTerm(kind, start, len, hash, ground) {
|
|
1241
|
+
const term = this.termKind.length;
|
|
1242
|
+
this.termKind.push(kind);
|
|
1243
|
+
this.termStart.push(start);
|
|
1244
|
+
this.termLen.push(len);
|
|
1245
|
+
this.termHash.push(hash);
|
|
1246
|
+
this.termGround.push(ground ? 1 : 0);
|
|
1247
|
+
const bucket = this.hashBuckets.get(hash);
|
|
1248
|
+
if (bucket === void 0) this.hashBuckets.set(hash, [term]);
|
|
1249
|
+
else bucket.push(term);
|
|
1250
|
+
return term;
|
|
1251
|
+
}
|
|
1252
|
+
};
|
|
1253
|
+
var FlatAtomSpace = class _FlatAtomSpace {
|
|
1254
|
+
constructor(table, ranges, dead, liveCount, nonGroundCount) {
|
|
1255
|
+
this.table = table;
|
|
1256
|
+
this.ranges = ranges;
|
|
1257
|
+
this.dead = dead;
|
|
1258
|
+
this.liveCount = liveCount;
|
|
1259
|
+
this.nonGroundCount = nonGroundCount;
|
|
1260
|
+
}
|
|
1261
|
+
table;
|
|
1262
|
+
ranges;
|
|
1263
|
+
dead;
|
|
1264
|
+
liveCount;
|
|
1265
|
+
nonGroundCount;
|
|
1266
|
+
static empty() {
|
|
1267
|
+
return new _FlatAtomSpace(new FlatAtomSpaceTable(), [], /* @__PURE__ */ new Set(), 0, 0);
|
|
1268
|
+
}
|
|
1269
|
+
static fromAtoms(atoms) {
|
|
1270
|
+
if (!atoms.every(canCompactAtom)) return void 0;
|
|
1271
|
+
return _FlatAtomSpace.empty().appendAll(atoms);
|
|
1272
|
+
}
|
|
1273
|
+
get size() {
|
|
1274
|
+
return this.liveCount;
|
|
1275
|
+
}
|
|
1276
|
+
appendAll(atoms) {
|
|
1277
|
+
if (atoms.length === 0) return this;
|
|
1278
|
+
const start = this.table.factCount;
|
|
1279
|
+
let nonGround = this.nonGroundCount;
|
|
1280
|
+
for (const atom of atoms) {
|
|
1281
|
+
const fact = this.table.insertFact(atom);
|
|
1282
|
+
if (!this.table.isTermGround(this.table.factRoot.get(fact))) nonGround += 1;
|
|
1283
|
+
}
|
|
1284
|
+
const end = this.table.factCount;
|
|
1285
|
+
return new _FlatAtomSpace(
|
|
1286
|
+
this.table,
|
|
1287
|
+
appendRange(this.ranges, start, end),
|
|
1288
|
+
this.dead,
|
|
1289
|
+
this.liveCount + atoms.length,
|
|
1290
|
+
nonGround
|
|
1291
|
+
);
|
|
1292
|
+
}
|
|
1293
|
+
removeOne(atom) {
|
|
1294
|
+
const term = this.table.lookupAtom(atom);
|
|
1295
|
+
if (term === void 0) return this;
|
|
1296
|
+
for (const fact of this.visibleFactIds()) {
|
|
1297
|
+
if (this.table.factRoot.get(fact) !== term) continue;
|
|
1298
|
+
const dead = new Set(this.dead);
|
|
1299
|
+
dead.add(fact);
|
|
1300
|
+
const nonGround = this.table.isTermGround(term) ? this.nonGroundCount : this.nonGroundCount - 1;
|
|
1301
|
+
return new _FlatAtomSpace(this.table, this.ranges, dead, this.liveCount - 1, nonGround);
|
|
1302
|
+
}
|
|
1303
|
+
return this;
|
|
1304
|
+
}
|
|
1305
|
+
exactCount(atom) {
|
|
1306
|
+
if (!atom.ground) return 0;
|
|
1307
|
+
const term = this.table.lookupAtom(atom);
|
|
1308
|
+
if (term === void 0) return 0;
|
|
1309
|
+
let count = 0;
|
|
1310
|
+
for (const fact of this.table.factsForTerm(term))
|
|
1311
|
+
if (this.factVisible(fact) && !this.dead.has(fact)) count += 1;
|
|
1312
|
+
return count;
|
|
1313
|
+
}
|
|
1314
|
+
*candidatesFor(patternHead) {
|
|
1315
|
+
if (patternHead === void 0) {
|
|
1316
|
+
for (const fact of this.visibleFactIds()) yield this.decodeFact(fact);
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1319
|
+
const head = this.table.lookupHeadSym(patternHead);
|
|
1320
|
+
if (head === void 0) {
|
|
1321
|
+
for (const fact of this.visibleFactIds())
|
|
1322
|
+
if (this.table.factHeadSym.get(fact) === ABSENT) yield this.decodeFact(fact);
|
|
1323
|
+
return;
|
|
1324
|
+
}
|
|
1325
|
+
for (const fact of this.visibleFactIds()) {
|
|
1326
|
+
const factHead = this.table.factHeadSym.get(fact);
|
|
1327
|
+
if (factHead === ABSENT || factHead === head) yield this.decodeFact(fact);
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
toArray() {
|
|
1331
|
+
const out = [];
|
|
1332
|
+
for (const fact of this.visibleFactIds()) out.push(this.decodeFact(fact));
|
|
1333
|
+
return out;
|
|
1334
|
+
}
|
|
1335
|
+
roundTrip(atom) {
|
|
1336
|
+
return this.table.decodeTerm(this.table.insertAtom(atom));
|
|
1337
|
+
}
|
|
1338
|
+
decodeFact(fact) {
|
|
1339
|
+
return this.table.decodeTerm(this.table.factRoot.get(fact));
|
|
1340
|
+
}
|
|
1341
|
+
*visibleFactIds() {
|
|
1342
|
+
for (const range of this.ranges)
|
|
1343
|
+
for (let fact = range.start; fact < range.end; fact++) if (!this.dead.has(fact)) yield fact;
|
|
1344
|
+
}
|
|
1345
|
+
factVisible(fact) {
|
|
1346
|
+
for (const range of this.ranges) {
|
|
1347
|
+
if (fact < range.start) return false;
|
|
1348
|
+
if (fact < range.end) return true;
|
|
1349
|
+
}
|
|
1350
|
+
return false;
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
function appendRange(ranges, start, end) {
|
|
1354
|
+
if (start === end) return ranges;
|
|
1355
|
+
const last = ranges[ranges.length - 1];
|
|
1356
|
+
if (last !== void 0 && last.end === start)
|
|
1357
|
+
return [...ranges.slice(0, -1), { start: last.start, end }];
|
|
1358
|
+
return [...ranges, { start, end }];
|
|
1359
|
+
}
|
|
1360
|
+
|
|
737
1361
|
// src/wcojoin.ts
|
|
738
1362
|
function allVars(rels) {
|
|
739
1363
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -746,7 +1370,7 @@ function allVars(rels) {
|
|
|
746
1370
|
}
|
|
747
1371
|
return out;
|
|
748
1372
|
}
|
|
749
|
-
function
|
|
1373
|
+
function wcoJoinFold(rels, key, hooks, varOrder) {
|
|
750
1374
|
const order = varOrder ?? allVars(rels);
|
|
751
1375
|
const relInfos = rels.map((r) => {
|
|
752
1376
|
const relVars = order.filter((v) => r.vars.includes(v));
|
|
@@ -770,12 +1394,10 @@ function wcoJoin(rels, key, varOrder) {
|
|
|
770
1394
|
const participants = order.map(
|
|
771
1395
|
(v) => relInfos.map((ri, r) => ri.relVars.includes(v) ? r : -1).filter((r) => r >= 0)
|
|
772
1396
|
);
|
|
773
|
-
const out = [];
|
|
774
|
-
const partial = /* @__PURE__ */ new Map();
|
|
775
1397
|
const cursors = relInfos.map((ri) => ri.root);
|
|
776
1398
|
const recurse = (i) => {
|
|
777
1399
|
if (i === order.length) {
|
|
778
|
-
|
|
1400
|
+
hooks.onLeaf();
|
|
779
1401
|
return;
|
|
780
1402
|
}
|
|
781
1403
|
const parts = participants[i];
|
|
@@ -797,13 +1419,27 @@ function wcoJoin(rels, key, varOrder) {
|
|
|
797
1419
|
if (!ok2) continue;
|
|
798
1420
|
const saved = advanced.map(([r]) => [r, cursors[r]]);
|
|
799
1421
|
for (const [r, child] of advanced) cursors[r] = child;
|
|
800
|
-
|
|
1422
|
+
hooks.onDescend(v, entry.val);
|
|
801
1423
|
recurse(i + 1);
|
|
1424
|
+
hooks.onAscend(v);
|
|
802
1425
|
for (const [r, c] of saved) cursors[r] = c;
|
|
803
1426
|
}
|
|
804
|
-
partial.delete(v);
|
|
805
1427
|
};
|
|
806
1428
|
recurse(0);
|
|
1429
|
+
}
|
|
1430
|
+
function wcoJoin(rels, key, varOrder) {
|
|
1431
|
+
const out = [];
|
|
1432
|
+
const partial = /* @__PURE__ */ new Map();
|
|
1433
|
+
wcoJoinFold(
|
|
1434
|
+
rels,
|
|
1435
|
+
key,
|
|
1436
|
+
{
|
|
1437
|
+
onDescend: (v, val) => partial.set(v, val),
|
|
1438
|
+
onAscend: (v) => partial.delete(v),
|
|
1439
|
+
onLeaf: () => out.push(new Map(partial))
|
|
1440
|
+
},
|
|
1441
|
+
varOrder
|
|
1442
|
+
);
|
|
807
1443
|
return out;
|
|
808
1444
|
}
|
|
809
1445
|
|
|
@@ -1818,16 +2454,607 @@ function inferType(a, varTypes, holders) {
|
|
|
1818
2454
|
if (op === "let" && a.items.length === 4) return inferType(a.items[3], varTypes, holders);
|
|
1819
2455
|
return holders.get(op)?.retType;
|
|
1820
2456
|
}
|
|
1821
|
-
function
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
2457
|
+
function compileRewriteCellPat(a, seen) {
|
|
2458
|
+
if (a.kind === "sym") return { tag: "sym", atom: a };
|
|
2459
|
+
if (a.kind !== "var" || seen.has(a.name)) return void 0;
|
|
2460
|
+
seen.add(a.name);
|
|
2461
|
+
return { tag: "var", name: a.name };
|
|
2462
|
+
}
|
|
2463
|
+
function compileRewriteArgPat(a, seen) {
|
|
2464
|
+
if (a.kind === "sym") return { tag: "sym", atom: a };
|
|
2465
|
+
if (a.kind !== "expr" || a.items.length === 0) return void 0;
|
|
2466
|
+
const items = a.items.map((it) => compileRewriteCellPat(it, seen));
|
|
2467
|
+
if (items.some((it) => it === void 0)) return void 0;
|
|
2468
|
+
return { tag: "tuple", items };
|
|
2469
|
+
}
|
|
2470
|
+
function compileRewriteOut(a, vars) {
|
|
2471
|
+
if (a.kind !== "expr" || a.items.length === 0) return void 0;
|
|
2472
|
+
const out = [];
|
|
2473
|
+
for (const it of a.items) {
|
|
2474
|
+
if (it.kind === "sym") out.push({ tag: "sym", atom: it });
|
|
2475
|
+
else if (it.kind === "var" && vars.has(it.name)) out.push({ tag: "var", name: it.name });
|
|
2476
|
+
else return void 0;
|
|
2477
|
+
}
|
|
2478
|
+
return out;
|
|
2479
|
+
}
|
|
2480
|
+
function capturePositions(args) {
|
|
2481
|
+
const vars = /* @__PURE__ */ new Map();
|
|
2482
|
+
args.forEach((arg, i) => {
|
|
2483
|
+
if (arg.tag === "tuple")
|
|
2484
|
+
arg.items.forEach((cell, j) => {
|
|
2485
|
+
if (cell.tag === "var") vars.set(cell.name, { arg: i, cell: j });
|
|
2486
|
+
});
|
|
2487
|
+
});
|
|
2488
|
+
return vars;
|
|
2489
|
+
}
|
|
2490
|
+
function rewriteParamTypes(args) {
|
|
2491
|
+
return args.map((arg) => arg.tag === "sym" ? "sym" : `symtuple${arg.items.length}`);
|
|
2492
|
+
}
|
|
2493
|
+
function sameRewriteParamType(arg, type) {
|
|
2494
|
+
if (type === "sym") return arg.tag === "sym";
|
|
2495
|
+
if (!type.startsWith("symtuple") || arg.tag !== "tuple") return false;
|
|
2496
|
+
return arg.items.length === Number(type.slice("symtuple".length));
|
|
2497
|
+
}
|
|
2498
|
+
function atomToRewriteArg(a, type) {
|
|
2499
|
+
if (type === "sym") {
|
|
2500
|
+
if (a.kind === "sym") return { tag: "sym", atom: a };
|
|
2501
|
+
if (a.kind === "var") return { tag: "qvar", name: a.name };
|
|
2502
|
+
return void 0;
|
|
2503
|
+
}
|
|
2504
|
+
if (!type.startsWith("symtuple") || a.kind !== "expr") return void 0;
|
|
2505
|
+
const width = Number(type.slice("symtuple".length));
|
|
2506
|
+
if (a.items.length !== width) return void 0;
|
|
2507
|
+
const items = [];
|
|
2508
|
+
for (const it of a.items) {
|
|
2509
|
+
if (it.kind !== "sym") return void 0;
|
|
2510
|
+
items.push(it);
|
|
2511
|
+
}
|
|
2512
|
+
return { tag: "tuple", items };
|
|
2513
|
+
}
|
|
2514
|
+
function bindQueryVar(b, name, atom) {
|
|
2515
|
+
for (const rel of b) {
|
|
2516
|
+
if (rel.tag === "val" && rel.x === name) return rel.a === atom ? b : void 0;
|
|
2517
|
+
}
|
|
2518
|
+
return prependValRaw(b, name, atom);
|
|
2519
|
+
}
|
|
2520
|
+
function runRewriteRule(rule, vals) {
|
|
2521
|
+
let b = emptyBindings;
|
|
2522
|
+
for (let i = 0; i < rule.args.length; i++) {
|
|
2523
|
+
const pat = rule.args[i];
|
|
2524
|
+
const actual = vals[i];
|
|
2525
|
+
if (pat.tag === "sym") {
|
|
2526
|
+
if (actual.tag === "sym") {
|
|
2527
|
+
if (actual.atom !== pat.atom) return void 0;
|
|
2528
|
+
} else if (actual.tag === "qvar") {
|
|
2529
|
+
const nb = bindQueryVar(b, actual.name, pat.atom);
|
|
2530
|
+
if (nb === void 0) return void 0;
|
|
2531
|
+
b = nb;
|
|
2532
|
+
} else return void 0;
|
|
2533
|
+
continue;
|
|
2534
|
+
}
|
|
2535
|
+
if (actual.tag !== "tuple" || actual.items.length !== pat.items.length) return void 0;
|
|
2536
|
+
for (let j = 0; j < pat.items.length; j++) {
|
|
2537
|
+
const cell = pat.items[j];
|
|
2538
|
+
if (cell.tag === "sym" && actual.items[j] !== cell.atom) return void 0;
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
const out = rule.out.map((part) => {
|
|
2542
|
+
if (part.tag === "sym") return part.atom;
|
|
2543
|
+
const pos = rule.vars.get(part.name);
|
|
2544
|
+
return vals[pos.arg].items[pos.cell];
|
|
2545
|
+
});
|
|
2546
|
+
return { atom: expr(out), bnd: b };
|
|
2547
|
+
}
|
|
2548
|
+
function compileRewrite(env, functor) {
|
|
2549
|
+
const eqs = env.ruleIndex.get(functor);
|
|
2550
|
+
if (eqs === void 0 || eqs.length === 0) return void 0;
|
|
2551
|
+
const rules = [];
|
|
2552
|
+
let arity;
|
|
2553
|
+
let retType;
|
|
2554
|
+
let paramTypes;
|
|
2555
|
+
for (const [lhs, rhs] of eqs) {
|
|
2556
|
+
if (lhs.kind !== "expr" || lhs.items.length === 0 || lhs.items[0].kind !== "sym")
|
|
2557
|
+
return void 0;
|
|
2558
|
+
if (lhs.items[0].name !== functor) return void 0;
|
|
2559
|
+
arity ??= lhs.items.length - 1;
|
|
2560
|
+
if (lhs.items.length - 1 !== arity) return void 0;
|
|
2561
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2562
|
+
const args = lhs.items.slice(1).map((arg) => compileRewriteArgPat(arg, seen));
|
|
2563
|
+
if (args.some((arg) => arg === void 0)) return void 0;
|
|
2564
|
+
const typedArgs = args;
|
|
2565
|
+
if (paramTypes === void 0) paramTypes = rewriteParamTypes(typedArgs);
|
|
2566
|
+
else if (typedArgs.length !== paramTypes.length || typedArgs.some((arg, i) => !sameRewriteParamType(arg, paramTypes[i])))
|
|
2567
|
+
return void 0;
|
|
2568
|
+
const vars = capturePositions(typedArgs);
|
|
2569
|
+
const out = compileRewriteOut(rhs, new Set(vars.keys()));
|
|
2570
|
+
if (out === void 0) return void 0;
|
|
2571
|
+
const rt = `symtuple${out.length}`;
|
|
2572
|
+
if (retType === void 0) retType = rt;
|
|
2573
|
+
else if (retType !== rt) return void 0;
|
|
2574
|
+
rules.push({ args: typedArgs, out, vars });
|
|
2575
|
+
}
|
|
2576
|
+
if (arity === void 0 || retType === void 0 || paramTypes === void 0) return void 0;
|
|
2577
|
+
const run = (partAtoms) => {
|
|
2578
|
+
const vals = [];
|
|
2579
|
+
const qvars = /* @__PURE__ */ new Set();
|
|
2580
|
+
for (let i = 0; i < partAtoms.length; i++) {
|
|
2581
|
+
const v = atomToRewriteArg(partAtoms[i], paramTypes[i]);
|
|
2582
|
+
if (v === void 0) return void 0;
|
|
2583
|
+
if (v.tag === "qvar") {
|
|
2584
|
+
if (qvars.has(v.name)) return void 0;
|
|
2585
|
+
qvars.add(v.name);
|
|
2586
|
+
}
|
|
2587
|
+
vals.push(v);
|
|
2588
|
+
}
|
|
2589
|
+
const results = [];
|
|
2590
|
+
for (const rule of rules) {
|
|
2591
|
+
const r = runRewriteRule(rule, vals);
|
|
2592
|
+
if (r !== void 0) results.push(r);
|
|
2593
|
+
}
|
|
2594
|
+
return results.length === 0 ? void 0 : { results, counterDelta: rules.length };
|
|
2595
|
+
};
|
|
2596
|
+
return { kind: "rewrite", arity, retType, paramTypes, ruleCount: rules.length, run };
|
|
2597
|
+
}
|
|
2598
|
+
function compileSymPat(a, slots) {
|
|
2599
|
+
if (a.kind === "sym") return { tag: "sym", name: a.name };
|
|
2600
|
+
if (a.kind === "var") {
|
|
2601
|
+
if (slots.has(a.name)) return void 0;
|
|
2602
|
+
const slot = slots.size;
|
|
2603
|
+
slots.set(a.name, slot);
|
|
2604
|
+
return { tag: "slot", slot };
|
|
2605
|
+
}
|
|
2606
|
+
if (a.kind === "gnd") return { tag: "lit", atom: a };
|
|
2607
|
+
const items = [];
|
|
2608
|
+
for (const it of a.items) {
|
|
2609
|
+
const p = compileSymPat(it, slots);
|
|
2610
|
+
if (p === void 0) return void 0;
|
|
2611
|
+
items.push(p);
|
|
2612
|
+
}
|
|
2613
|
+
return { tag: "expr", items };
|
|
2614
|
+
}
|
|
2615
|
+
function compileSymTpl(a, slots) {
|
|
2616
|
+
if (a.kind === "var") {
|
|
2617
|
+
const slot = slots.get(a.name);
|
|
2618
|
+
return slot === void 0 ? { tag: "fresh", name: a.name } : { tag: "slot", slot };
|
|
2619
|
+
}
|
|
2620
|
+
if (a.kind !== "expr") return { tag: "atom", atom: a };
|
|
2621
|
+
return { tag: "expr", items: a.items.map((it) => compileSymTpl(it, slots)) };
|
|
2622
|
+
}
|
|
2623
|
+
function matchSymPat(pat, arg, slots) {
|
|
2624
|
+
switch (pat.tag) {
|
|
2625
|
+
case "sym":
|
|
2626
|
+
return arg.kind === "sym" && arg.name === pat.name;
|
|
2627
|
+
case "slot":
|
|
2628
|
+
slots[pat.slot] = arg;
|
|
2629
|
+
return true;
|
|
2630
|
+
case "lit":
|
|
2631
|
+
return atomEq(arg, pat.atom);
|
|
2632
|
+
case "expr": {
|
|
2633
|
+
if (arg.kind !== "expr" || arg.items.length !== pat.items.length) return false;
|
|
2634
|
+
for (let i = 0; i < pat.items.length; i++)
|
|
2635
|
+
if (!matchSymPat(pat.items[i], arg.items[i], slots)) return false;
|
|
2636
|
+
return true;
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
function bindSymQueryVar(bs, name, value) {
|
|
2641
|
+
const out = [];
|
|
2642
|
+
for (const b of bs) for (const ext of addVarBinding(b, name, value)) out.push(ext);
|
|
2643
|
+
return out;
|
|
2644
|
+
}
|
|
2645
|
+
function matchSymPatQuery(pat, arg, slots, bs) {
|
|
2646
|
+
switch (pat.tag) {
|
|
2647
|
+
case "sym":
|
|
2648
|
+
if (arg.kind === "var") return bindSymQueryVar(bs, arg.name, sym(pat.name));
|
|
2649
|
+
return arg.kind === "sym" && arg.name === pat.name ? [...bs] : [];
|
|
2650
|
+
case "slot":
|
|
2651
|
+
slots[pat.slot] = arg;
|
|
2652
|
+
return [...bs];
|
|
2653
|
+
case "lit":
|
|
2654
|
+
if (arg.kind === "var") return bindSymQueryVar(bs, arg.name, pat.atom);
|
|
2655
|
+
return atomEq(arg, pat.atom) ? [...bs] : [];
|
|
2656
|
+
case "expr": {
|
|
2657
|
+
if (arg.kind === "var") return void 0;
|
|
2658
|
+
if (arg.kind !== "expr" || arg.items.length !== pat.items.length) return [];
|
|
2659
|
+
let cur = [...bs];
|
|
2660
|
+
for (let i = 0; i < pat.items.length; i++) {
|
|
2661
|
+
const next = matchSymPatQuery(pat.items[i], arg.items[i], slots, cur);
|
|
2662
|
+
if (next === void 0) return void 0;
|
|
2663
|
+
if (next.length === 0) return [];
|
|
2664
|
+
cur = next;
|
|
2665
|
+
}
|
|
2666
|
+
return cur;
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
function buildSymTpl(tpl, slots, suffix) {
|
|
2671
|
+
switch (tpl.tag) {
|
|
2672
|
+
case "atom":
|
|
2673
|
+
return tpl.atom;
|
|
2674
|
+
case "slot":
|
|
2675
|
+
return slots[tpl.slot];
|
|
2676
|
+
case "fresh":
|
|
2677
|
+
return variable(tpl.name + suffix);
|
|
2678
|
+
case "expr":
|
|
2679
|
+
return expr(tpl.items.map((t) => buildSymTpl(t, slots, suffix)));
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2682
|
+
function compileSymbolic(env, functor) {
|
|
2683
|
+
if (env.varRulesVar.length !== 0) return void 0;
|
|
2684
|
+
const eqs = env.ruleIndex.get(functor);
|
|
2685
|
+
if (eqs === void 0 || eqs.length === 0) return void 0;
|
|
2686
|
+
const clauses = [];
|
|
2687
|
+
let arity;
|
|
2688
|
+
for (const [lhs, rhs] of eqs) {
|
|
2689
|
+
if (lhs.kind !== "expr" || lhs.items.length === 0) return void 0;
|
|
2690
|
+
if (lhs.items[0].kind !== "sym" || lhs.items[0].name !== functor) return void 0;
|
|
2691
|
+
const a = lhs.items.length - 1;
|
|
2692
|
+
if (arity === void 0) arity = a;
|
|
2693
|
+
else if (a !== arity) return void 0;
|
|
2694
|
+
const slots = /* @__PURE__ */ new Map();
|
|
2695
|
+
const pats = [];
|
|
2696
|
+
for (let i = 1; i < lhs.items.length; i++) {
|
|
2697
|
+
const p = compileSymPat(lhs.items[i], slots);
|
|
2698
|
+
if (p === void 0) return void 0;
|
|
2699
|
+
pats.push(p);
|
|
2700
|
+
}
|
|
2701
|
+
clauses.push({ pats, tpl: compileSymTpl(rhs, slots), nslots: slots.size });
|
|
2702
|
+
}
|
|
2703
|
+
if (arity === void 0) return void 0;
|
|
2704
|
+
const clauseCount = clauses.length;
|
|
2705
|
+
const run = (partAtoms, counter) => {
|
|
2706
|
+
const results = [];
|
|
2707
|
+
for (let i = 0; i < clauseCount; i++) {
|
|
2708
|
+
const clause = clauses[i];
|
|
2709
|
+
const slots = new Array(clause.nslots);
|
|
2710
|
+
let bnds = [emptyBindings];
|
|
2711
|
+
for (let j = 0; j < clause.pats.length; j++) {
|
|
2712
|
+
if (partAtoms[j].ground) {
|
|
2713
|
+
if (!matchSymPat(clause.pats[j], partAtoms[j], slots)) {
|
|
2714
|
+
bnds = [];
|
|
2715
|
+
break;
|
|
2716
|
+
}
|
|
2717
|
+
continue;
|
|
2718
|
+
}
|
|
2719
|
+
const next = matchSymPatQuery(clause.pats[j], partAtoms[j], slots, bnds);
|
|
2720
|
+
if (next === void 0) return void 0;
|
|
2721
|
+
bnds = next;
|
|
2722
|
+
if (bnds.length === 0) break;
|
|
2723
|
+
}
|
|
2724
|
+
if (bnds.length > 0) {
|
|
2725
|
+
const atom = buildSymTpl(clause.tpl, slots, "#" + (counter + i));
|
|
2726
|
+
for (const bnd of bnds)
|
|
2727
|
+
results.push({
|
|
2728
|
+
atom,
|
|
2729
|
+
bnd
|
|
2730
|
+
});
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
return results.length === 0 ? void 0 : { results, counterDelta: clauseCount };
|
|
2734
|
+
};
|
|
2735
|
+
return { kind: "symbolic", arity, clauseCount, run };
|
|
2736
|
+
}
|
|
2737
|
+
var IMP_GROUNDED = /* @__PURE__ */ new Set(["==", "<", ">", "<=", ">=", "+", "-", "*", "%"]);
|
|
2738
|
+
var DATA_DENY = /* @__PURE__ */ new Set([...KNOWN_OPS, "let*", "add-atom"]);
|
|
2739
|
+
var addCounter = (st, n) => n === 0 ? st : { counter: st.counter + n, world: st.world };
|
|
2740
|
+
var impBail = () => BAIL;
|
|
2741
|
+
function impMeta(parts) {
|
|
2742
|
+
const callees = /* @__PURE__ */ new Set();
|
|
2743
|
+
let directEffect = false;
|
|
2744
|
+
for (const part of parts) {
|
|
2745
|
+
if (part.directEffect) directEffect = true;
|
|
2746
|
+
for (const c of part.callees) callees.add(c);
|
|
2747
|
+
}
|
|
2748
|
+
return { directEffect, callees };
|
|
2749
|
+
}
|
|
2750
|
+
function impConst(atom) {
|
|
2751
|
+
return { node: (_slots, st) => ({ value: atom, st }), directEffect: false, callees: /* @__PURE__ */ new Set() };
|
|
2752
|
+
}
|
|
2753
|
+
function isDataSymbol(env, name) {
|
|
2754
|
+
return !DATA_DENY.has(name) && !env.ruleIndex.has(name) && !env.gt.has(name);
|
|
2755
|
+
}
|
|
2756
|
+
function compileImpStaticAtom(env, a, scope) {
|
|
2757
|
+
if (a.kind === "var") {
|
|
2758
|
+
const slot = scope.vars.get(a.name);
|
|
2759
|
+
if (slot === void 0) return void 0;
|
|
2760
|
+
return {
|
|
2761
|
+
node: (slots, st) => ({ value: slots[slot], st }),
|
|
2762
|
+
directEffect: false,
|
|
2763
|
+
callees: /* @__PURE__ */ new Set()
|
|
2764
|
+
};
|
|
2765
|
+
}
|
|
2766
|
+
if (a.kind === "sym") return isDataSymbol(env, a.name) ? impConst(a) : void 0;
|
|
2767
|
+
if (a.kind === "gnd") return impConst(a);
|
|
2768
|
+
if (a.items.length === 0) return impConst(a);
|
|
2769
|
+
const head = a.items[0];
|
|
2770
|
+
if (head.kind === "var") return void 0;
|
|
2771
|
+
if (head.kind === "sym" && !isDataSymbol(env, head.name)) return void 0;
|
|
2772
|
+
const items = a.items.map((it) => compileImpStaticAtom(env, it, scope));
|
|
2773
|
+
if (items.some((it) => it === void 0)) return void 0;
|
|
2774
|
+
const parts = items;
|
|
2775
|
+
return {
|
|
2776
|
+
node: (slots, st, ops) => {
|
|
2777
|
+
const out = [];
|
|
2778
|
+
let cur = st;
|
|
2779
|
+
for (const part of parts) {
|
|
2780
|
+
const r = part.node(slots, cur, ops);
|
|
2781
|
+
if (r === BAIL) return BAIL;
|
|
2782
|
+
out.push(r.value);
|
|
2783
|
+
cur = r.st;
|
|
2784
|
+
}
|
|
2785
|
+
return { value: expr(out), st: cur };
|
|
2786
|
+
},
|
|
2787
|
+
...impMeta(parts)
|
|
2788
|
+
};
|
|
2789
|
+
}
|
|
2790
|
+
function compileImpGrounded(env, op, args, scope, holders) {
|
|
2791
|
+
if (env.ruleIndex.has(op)) return void 0;
|
|
2792
|
+
const parts = args.map((arg) => compileImpAtom(env, arg, scope, holders));
|
|
2793
|
+
if (parts.some((part) => part === void 0)) return void 0;
|
|
2794
|
+
const compiled = parts;
|
|
2795
|
+
return {
|
|
2796
|
+
node: (slots, st, ops) => {
|
|
2797
|
+
const vals = [];
|
|
2798
|
+
let cur = st;
|
|
2799
|
+
for (const part of compiled) {
|
|
2800
|
+
const r = part.node(slots, cur, ops);
|
|
2801
|
+
if (r === BAIL) return BAIL;
|
|
2802
|
+
vals.push(r.value);
|
|
2803
|
+
cur = r.st;
|
|
2804
|
+
}
|
|
2805
|
+
const gr = callGrounded(env.gt, op, vals);
|
|
2806
|
+
return gr.tag === "ok" && gr.results.length === 1 ? { value: gr.results[0], st: cur } : BAIL;
|
|
2807
|
+
},
|
|
2808
|
+
...impMeta(compiled)
|
|
2809
|
+
};
|
|
2810
|
+
}
|
|
2811
|
+
function compileImpIf(env, args, scope, holders) {
|
|
2812
|
+
if (args.length !== 3 || (env.ruleIndex.get("if")?.length ?? 0) !== 2) return void 0;
|
|
2813
|
+
const cond = compileImpAtom(env, args[0], scope, holders);
|
|
2814
|
+
const then_ = compileImpAtom(env, args[1], scope, holders);
|
|
2815
|
+
const els = compileImpAtom(env, args[2], scope, holders);
|
|
2816
|
+
if (cond === void 0 || then_ === void 0 || els === void 0) return void 0;
|
|
2817
|
+
return {
|
|
2818
|
+
node: (slots, st, ops, discard) => {
|
|
2819
|
+
const c = cond.node(slots, st, ops);
|
|
2820
|
+
if (c === BAIL) return BAIL;
|
|
2821
|
+
const stIf = addCounter(c.st, 2);
|
|
2822
|
+
if (c.value.kind !== "gnd" || c.value.value.g !== "bool") return BAIL;
|
|
2823
|
+
return (c.value.value.b ? then_ : els).node(slots, stIf, ops, discard);
|
|
2824
|
+
},
|
|
2825
|
+
...impMeta([cond, then_, els])
|
|
2826
|
+
};
|
|
2827
|
+
}
|
|
2828
|
+
function compileImpLet(env, args, scope, holders) {
|
|
2829
|
+
if (args.length !== 3 || args[0].kind !== "var" || (env.ruleIndex.get("let")?.length ?? 0) !== 1)
|
|
2830
|
+
return void 0;
|
|
2831
|
+
const value = compileImpAtom(env, args[1], scope, holders);
|
|
2832
|
+
if (value === void 0) return void 0;
|
|
2833
|
+
const slot = scope.len;
|
|
2834
|
+
const nextScope = {
|
|
2835
|
+
vars: new Map(scope.vars).set(args[0].name, slot),
|
|
2836
|
+
len: slot + 1
|
|
2837
|
+
};
|
|
2838
|
+
const body = compileImpAtom(env, args[2], nextScope, holders);
|
|
2839
|
+
if (body === void 0) return void 0;
|
|
2840
|
+
return {
|
|
2841
|
+
node: (slots, st, ops, discard) => {
|
|
2842
|
+
const v = value.node(slots, st, ops);
|
|
2843
|
+
if (v === BAIL) return BAIL;
|
|
2844
|
+
const local = slots.slice();
|
|
2845
|
+
local[slot] = v.value;
|
|
2846
|
+
return body.node(local, addCounter(v.st, 1), ops, discard);
|
|
2847
|
+
},
|
|
2848
|
+
...impMeta([value, body])
|
|
2849
|
+
};
|
|
2850
|
+
}
|
|
2851
|
+
function compileImpLetStar(env, args, scope, holders) {
|
|
2852
|
+
if (args.length !== 2 || args[0].kind !== "expr" || (env.ruleIndex.get("let*")?.length ?? 0) !== 1 || (env.ruleIndex.get("let")?.length ?? 0) !== 1)
|
|
2853
|
+
return void 0;
|
|
2854
|
+
let curScope = scope;
|
|
2855
|
+
const bindings = [];
|
|
2856
|
+
for (const pair of args[0].items) {
|
|
2857
|
+
if (pair.kind !== "expr" || pair.items.length !== 2 || pair.items[0].kind !== "var")
|
|
2858
|
+
return void 0;
|
|
2859
|
+
const value = compileImpAtom(env, pair.items[1], curScope, holders);
|
|
2860
|
+
if (value === void 0) return void 0;
|
|
2861
|
+
const slot = curScope.len;
|
|
2862
|
+
bindings.push({ slot, value });
|
|
2863
|
+
curScope = {
|
|
2864
|
+
vars: new Map(curScope.vars).set(pair.items[0].name, slot),
|
|
2865
|
+
len: slot + 1
|
|
2866
|
+
};
|
|
2867
|
+
}
|
|
2868
|
+
const body = compileImpAtom(env, args[1], curScope, holders);
|
|
2869
|
+
if (body === void 0) return void 0;
|
|
2870
|
+
const parts = [...bindings.map((b) => b.value), body];
|
|
2871
|
+
return {
|
|
2872
|
+
node: (slots, st, ops, discard) => {
|
|
2873
|
+
const local = slots.slice();
|
|
2874
|
+
let cur = addCounter(st, 1);
|
|
2875
|
+
for (const binding of bindings) {
|
|
2876
|
+
const v = binding.value.node(local, cur, ops);
|
|
2877
|
+
if (v === BAIL) return BAIL;
|
|
2878
|
+
local[binding.slot] = v.value;
|
|
2879
|
+
cur = addCounter(addCounter(v.st, 1), 1);
|
|
2880
|
+
}
|
|
2881
|
+
return body.node(local, cur, ops, discard);
|
|
2882
|
+
},
|
|
2883
|
+
...impMeta(parts)
|
|
2884
|
+
};
|
|
2885
|
+
}
|
|
2886
|
+
function compileImpAddAtom(env, args, scope) {
|
|
2887
|
+
if (args.length !== 2 || args[0].kind !== "sym") return void 0;
|
|
2888
|
+
const added = args[1];
|
|
2889
|
+
if (added.kind !== "expr" || added.items.length === 0 || added.items[0].kind !== "sym" || added.items[0].name === "=")
|
|
2890
|
+
return void 0;
|
|
2891
|
+
const space = compileImpStaticAtom(env, args[0], scope);
|
|
2892
|
+
const atom = compileImpStaticAtom(env, added, scope);
|
|
2893
|
+
if (space === void 0 || atom === void 0) return void 0;
|
|
2894
|
+
return {
|
|
2895
|
+
node: (slots, st, ops) => {
|
|
2896
|
+
const s = space.node(slots, st, ops);
|
|
2897
|
+
if (s === BAIL) return BAIL;
|
|
2898
|
+
const a = atom.node(slots, s.st, ops);
|
|
2899
|
+
if (a === BAIL) return BAIL;
|
|
2900
|
+
const st2 = ops.addAtom(env, a.st, s.value, a.value);
|
|
2901
|
+
return st2 === void 0 ? BAIL : { value: emptyExpr, st: st2 };
|
|
2902
|
+
},
|
|
2903
|
+
directEffect: true,
|
|
2904
|
+
callees: /* @__PURE__ */ new Set()
|
|
2905
|
+
};
|
|
2906
|
+
}
|
|
2907
|
+
function compileImpCall(env, op, args, scope, holders) {
|
|
2908
|
+
const h = holders.get(op);
|
|
2909
|
+
if (h === void 0 || args.length !== h.arity) return void 0;
|
|
2910
|
+
const compiledArgs = args.map((arg) => compileImpAtom(env, arg, scope, holders));
|
|
2911
|
+
if (compiledArgs.some((arg) => arg === void 0)) return void 0;
|
|
2912
|
+
const parts = compiledArgs;
|
|
2913
|
+
const meta = impMeta(parts);
|
|
2914
|
+
return {
|
|
2915
|
+
node: (slots, st, ops, discard) => {
|
|
2916
|
+
const vals = [];
|
|
2917
|
+
let cur = st;
|
|
2918
|
+
for (const part of parts) {
|
|
2919
|
+
const r = part.node(slots, cur, ops);
|
|
2920
|
+
if (r === BAIL) return BAIL;
|
|
2921
|
+
vals.push(r.value);
|
|
2922
|
+
cur = r.st;
|
|
2923
|
+
}
|
|
2924
|
+
return h.run(vals, cur, ops, discard);
|
|
2925
|
+
},
|
|
2926
|
+
directEffect: meta.directEffect,
|
|
2927
|
+
callees: /* @__PURE__ */ new Set([...meta.callees, op])
|
|
2928
|
+
};
|
|
2929
|
+
}
|
|
2930
|
+
function compileImpTuple(env, items, scope, holders) {
|
|
2931
|
+
const parts = items.map((it) => compileImpAtom(env, it, scope, holders));
|
|
2932
|
+
if (parts.some((part) => part === void 0)) return void 0;
|
|
2933
|
+
const compiled = parts;
|
|
2934
|
+
return {
|
|
2935
|
+
node: (slots, st, ops, discard) => {
|
|
2936
|
+
let cur = st;
|
|
2937
|
+
if (discard === true) {
|
|
2938
|
+
for (const part of compiled) {
|
|
2939
|
+
const r = part.node(slots, cur, ops, true);
|
|
2940
|
+
if (r === BAIL) return BAIL;
|
|
2941
|
+
cur = r.st;
|
|
2942
|
+
}
|
|
2943
|
+
return { value: emptyExpr, st: cur };
|
|
2944
|
+
}
|
|
2945
|
+
const out = [];
|
|
2946
|
+
for (const part of compiled) {
|
|
2947
|
+
const r = part.node(slots, cur, ops);
|
|
2948
|
+
if (r === BAIL) return BAIL;
|
|
2949
|
+
out.push(r.value);
|
|
2950
|
+
cur = r.st;
|
|
2951
|
+
}
|
|
2952
|
+
return { value: expr(out), st: cur };
|
|
2953
|
+
},
|
|
2954
|
+
...impMeta(compiled)
|
|
2955
|
+
};
|
|
2956
|
+
}
|
|
2957
|
+
function compileImpAtom(env, a, scope, holders) {
|
|
2958
|
+
if (a.kind !== "expr" || a.items.length === 0) return compileImpStaticAtom(env, a, scope);
|
|
2959
|
+
const head = a.items[0];
|
|
2960
|
+
if (head.kind !== "sym") {
|
|
2961
|
+
if (head.kind === "var") return void 0;
|
|
2962
|
+
return compileImpTuple(env, a.items, scope, holders);
|
|
2963
|
+
}
|
|
2964
|
+
const op = head.name;
|
|
2965
|
+
const args = a.items.slice(1);
|
|
2966
|
+
if (op === "if") return compileImpIf(env, args, scope, holders);
|
|
2967
|
+
if (op === "let") return compileImpLet(env, args, scope, holders);
|
|
2968
|
+
if (op === "let*") return compileImpLetStar(env, args, scope, holders);
|
|
2969
|
+
if (op === "add-atom") return compileImpAddAtom(env, args, scope);
|
|
2970
|
+
if (IMP_GROUNDED.has(op)) return compileImpGrounded(env, op, args, scope, holders);
|
|
2971
|
+
const call = compileImpCall(env, op, args, scope, holders);
|
|
2972
|
+
if (call !== void 0) return call;
|
|
2973
|
+
return compileImpStaticAtom(env, a, scope);
|
|
2974
|
+
}
|
|
2975
|
+
function buildImpScope(params) {
|
|
2976
|
+
const vars = /* @__PURE__ */ new Map();
|
|
2977
|
+
for (let i = 0; i < params.length; i++) {
|
|
2978
|
+
const p = params[i];
|
|
2979
|
+
if (typeof p !== "string") return void 0;
|
|
2980
|
+
vars.set(p, i);
|
|
2981
|
+
}
|
|
2982
|
+
return { vars, len: params.length };
|
|
2983
|
+
}
|
|
2984
|
+
function compileImperative(env, compiled) {
|
|
2985
|
+
if (env.varRulesVar.length !== 0) return;
|
|
2986
|
+
const cand = /* @__PURE__ */ new Map();
|
|
2987
|
+
for (const f of env.ruleIndex.keys()) {
|
|
2988
|
+
if (compiled.has(f)) continue;
|
|
2989
|
+
const h = singleClauseHead(env, f);
|
|
2990
|
+
if (h !== void 0 && h.params.every((p) => typeof p === "string")) cand.set(f, h);
|
|
2991
|
+
}
|
|
2992
|
+
const holders = /* @__PURE__ */ new Map();
|
|
2993
|
+
for (const [f, { params }] of cand)
|
|
2994
|
+
holders.set(f, { kind: "imperative", arity: params.length, clauseCount: 1, run: impBail });
|
|
2995
|
+
for (; ; ) {
|
|
2996
|
+
let removed = false;
|
|
2997
|
+
const bodies = /* @__PURE__ */ new Map();
|
|
2998
|
+
for (const [f, h] of [...holders]) {
|
|
2999
|
+
const cd = cand.get(f);
|
|
3000
|
+
const scope = buildImpScope(cd.params);
|
|
3001
|
+
const body = scope === void 0 ? void 0 : compileImpAtom(env, cd.body, scope, holders);
|
|
3002
|
+
if (body === void 0) {
|
|
3003
|
+
holders.delete(f);
|
|
3004
|
+
removed = true;
|
|
3005
|
+
} else {
|
|
3006
|
+
bodies.set(f, body);
|
|
3007
|
+
h.arity = cd.params.length;
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
if (removed) continue;
|
|
3011
|
+
const effectful = /* @__PURE__ */ new Set();
|
|
3012
|
+
for (const [f, body] of bodies) if (body.directEffect) effectful.add(f);
|
|
3013
|
+
for (let changed = true; changed; ) {
|
|
3014
|
+
changed = false;
|
|
3015
|
+
for (const [f, body] of bodies) {
|
|
3016
|
+
if (effectful.has(f)) continue;
|
|
3017
|
+
for (const callee of body.callees)
|
|
3018
|
+
if (effectful.has(callee)) {
|
|
3019
|
+
effectful.add(f);
|
|
3020
|
+
changed = true;
|
|
3021
|
+
break;
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
for (const f of [...holders.keys()])
|
|
3026
|
+
if (!effectful.has(f)) {
|
|
3027
|
+
holders.delete(f);
|
|
3028
|
+
removed = true;
|
|
3029
|
+
}
|
|
3030
|
+
if (removed) continue;
|
|
3031
|
+
for (const [f, body] of bodies) {
|
|
3032
|
+
const arity = cand.get(f).params.length;
|
|
3033
|
+
holders.get(f).run = (partAtoms, st, ops, discard) => {
|
|
3034
|
+
if (partAtoms.length !== arity || partAtoms.some((a) => !a.ground)) return BAIL;
|
|
3035
|
+
try {
|
|
3036
|
+
return body.node(partAtoms, addCounter(st, 1), ops, discard);
|
|
3037
|
+
} catch (e) {
|
|
3038
|
+
if (e === BAIL) return BAIL;
|
|
3039
|
+
throw e;
|
|
3040
|
+
}
|
|
3041
|
+
};
|
|
3042
|
+
}
|
|
3043
|
+
for (const [f, h] of holders) compiled.set(f, h);
|
|
3044
|
+
return;
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
function compileEnv(env) {
|
|
3048
|
+
const pure = env.pureFunctors ?? /* @__PURE__ */ new Set();
|
|
3049
|
+
const cand = /* @__PURE__ */ new Map();
|
|
3050
|
+
for (const f of pure) {
|
|
3051
|
+
const h = singleClauseHead(env, f);
|
|
3052
|
+
if (h !== void 0) cand.set(f, h);
|
|
3053
|
+
}
|
|
1828
3054
|
const holders = /* @__PURE__ */ new Map();
|
|
1829
3055
|
for (const [f, { params }] of cand)
|
|
1830
3056
|
holders.set(f, {
|
|
3057
|
+
kind: "functional",
|
|
1831
3058
|
arity: params.length,
|
|
1832
3059
|
retType: void 0,
|
|
1833
3060
|
paramTypes: paramTypesOf(params),
|
|
@@ -1873,13 +3100,32 @@ function compileEnv(env) {
|
|
|
1873
3100
|
if (!removed) {
|
|
1874
3101
|
for (const [f, { node, arity }] of result)
|
|
1875
3102
|
holders.get(f).run = makeRun(arity, node, selfCallCount(cand.get(f).body, f) >= 2);
|
|
1876
|
-
|
|
3103
|
+
const compiled = new Map(holders);
|
|
3104
|
+
for (const f of pure) {
|
|
3105
|
+
if (compiled.has(f)) continue;
|
|
3106
|
+
const rewrite = compileRewrite(env, f);
|
|
3107
|
+
if (rewrite !== void 0) {
|
|
3108
|
+
compiled.set(f, rewrite);
|
|
3109
|
+
continue;
|
|
3110
|
+
}
|
|
3111
|
+
const symbolic = compileSymbolic(env, f);
|
|
3112
|
+
if (symbolic !== void 0) compiled.set(f, symbolic);
|
|
3113
|
+
}
|
|
3114
|
+
compileImperative(env, compiled);
|
|
3115
|
+
return compiled;
|
|
1877
3116
|
}
|
|
1878
3117
|
}
|
|
1879
3118
|
}
|
|
1880
|
-
function runCompiled(env, op, partAtoms) {
|
|
3119
|
+
function runCompiled(env, op, partAtoms, st, ops, discard) {
|
|
1881
3120
|
const h = env.compiled?.get(op);
|
|
1882
3121
|
if (h === void 0 || partAtoms.length !== h.arity) return void 0;
|
|
3122
|
+
if (h.kind === "rewrite") return h.run(partAtoms);
|
|
3123
|
+
if (h.kind === "symbolic") return h.run(partAtoms, st.counter);
|
|
3124
|
+
if (h.kind === "imperative") {
|
|
3125
|
+
if (ops === void 0) return void 0;
|
|
3126
|
+
const r = h.run(partAtoms, st, ops, discard);
|
|
3127
|
+
return r === BAIL ? void 0 : { results: [{ atom: r.value, bnd: emptyBindings }], counterDelta: 0, state: r.st };
|
|
3128
|
+
}
|
|
1883
3129
|
const vals = [];
|
|
1884
3130
|
for (const a of partAtoms) {
|
|
1885
3131
|
if (a.kind === "gnd" && a.value.g === "int") vals.push(a.value.n);
|
|
@@ -1889,9 +3135,8 @@ function runCompiled(env, op, partAtoms) {
|
|
|
1889
3135
|
}
|
|
1890
3136
|
try {
|
|
1891
3137
|
const r = h.run(vals);
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
return gint(r);
|
|
3138
|
+
const atom = typeof r === "boolean" ? gbool(r) : r instanceof Tup ? expr(r.v.map((n) => gint(n))) : gint(r);
|
|
3139
|
+
return { results: [{ atom, bnd: emptyBindings }], counterDelta: 0 };
|
|
1895
3140
|
} catch (e) {
|
|
1896
3141
|
if (e === BAIL || e instanceof RangeError) return void 0;
|
|
1897
3142
|
throw e;
|
|
@@ -1899,6 +3144,18 @@ function runCompiled(env, op, partAtoms) {
|
|
|
1899
3144
|
}
|
|
1900
3145
|
|
|
1901
3146
|
// src/eval.ts
|
|
3147
|
+
var CTOR_SC = process.env.METTA_CTOR_SC !== "0";
|
|
3148
|
+
var STREAM_CASE = process.env.METTA_STREAM_CASE !== "0";
|
|
3149
|
+
function exactCandidateSource(atom, count, total) {
|
|
3150
|
+
return {
|
|
3151
|
+
counterPadding: total - count,
|
|
3152
|
+
*[Symbol.iterator]() {
|
|
3153
|
+
for (let i = 0; i < count; i++) yield atom;
|
|
3154
|
+
}
|
|
3155
|
+
};
|
|
3156
|
+
}
|
|
3157
|
+
var candidateCounterPadding = (source) => source.counterPadding ?? 0;
|
|
3158
|
+
var syntheticCandidateSource = (source) => Object.prototype.hasOwnProperty.call(source, "counterPadding");
|
|
1902
3159
|
var LAZY_ARGS_OPS = /* @__PURE__ */ new Set(["par", "race", "once", "with-mutex"]);
|
|
1903
3160
|
var AsyncInSyncError = class extends Error {
|
|
1904
3161
|
constructor(op) {
|
|
@@ -1933,6 +3190,9 @@ function* callGroundedG(env, op, args) {
|
|
|
1933
3190
|
return callGrounded(env.gt, op, args);
|
|
1934
3191
|
}
|
|
1935
3192
|
var cons = (head, tail) => ({ head, tail });
|
|
3193
|
+
function isItemSource(work) {
|
|
3194
|
+
return !Array.isArray(work);
|
|
3195
|
+
}
|
|
1936
3196
|
var frame = (atom, ret = "none", vars = [], fin = false) => ({
|
|
1937
3197
|
atom,
|
|
1938
3198
|
ret,
|
|
@@ -1943,13 +3203,15 @@ var notReducibleA = sym("NotReducible");
|
|
|
1943
3203
|
var emptyA = sym("Empty");
|
|
1944
3204
|
var unitA = emptyExpr;
|
|
1945
3205
|
var errAtom = (a, msg) => expr([sym("Error"), a, sym(msg)]);
|
|
3206
|
+
var makeExpr = (_env, items) => expr(items);
|
|
3207
|
+
var inst = (env, b, a, suffix = "") => instantiate(b, a, suffix, env.intern);
|
|
1946
3208
|
function opOf(a) {
|
|
1947
3209
|
return a.kind === "expr" && a.items.length > 0 && a.items[0].kind === "sym" ? a.items[0].name : void 0;
|
|
1948
3210
|
}
|
|
1949
3211
|
function tryParHyperpose(env, world, bnd, arg, firstOnly) {
|
|
1950
3212
|
if (env.parEval === void 0) return void 0;
|
|
1951
3213
|
if (world.selfRules.size > 0) return void 0;
|
|
1952
|
-
const a =
|
|
3214
|
+
const a = inst(env, bnd, arg);
|
|
1953
3215
|
if (a.kind !== "expr" || opOf(a) !== "hyperpose" || a.items.length !== 2) return void 0;
|
|
1954
3216
|
const tup = a.items[1];
|
|
1955
3217
|
if (tup.kind !== "expr" || tup.items.length === 0) return void 0;
|
|
@@ -2018,6 +3280,40 @@ function headKey(a) {
|
|
|
2018
3280
|
return a.items[0].name;
|
|
2019
3281
|
return void 0;
|
|
2020
3282
|
}
|
|
3283
|
+
function isDefinedHead(env, w, name) {
|
|
3284
|
+
return env.ruleIndex.has(name) || env.sigs.has(name) || w.selfRules.has(name) || env.gt.has(name) || IMPURE_OPS.has(name);
|
|
3285
|
+
}
|
|
3286
|
+
function isNormalForm(env, w, t) {
|
|
3287
|
+
switch (t.kind) {
|
|
3288
|
+
case "var":
|
|
3289
|
+
case "gnd":
|
|
3290
|
+
return true;
|
|
3291
|
+
case "sym":
|
|
3292
|
+
return !isDefinedHead(env, w, t.name);
|
|
3293
|
+
case "expr": {
|
|
3294
|
+
const its = t.items;
|
|
3295
|
+
if (its.length === 0) return true;
|
|
3296
|
+
const h = its[0];
|
|
3297
|
+
if (h.kind !== "sym" || isDefinedHead(env, w, h.name)) return false;
|
|
3298
|
+
for (let i = 1; i < its.length; i++) if (!isNormalForm(env, w, its[i])) return false;
|
|
3299
|
+
return true;
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3303
|
+
function isNormalFormAssumingVars(env, w, t) {
|
|
3304
|
+
switch (t.kind) {
|
|
3305
|
+
case "var":
|
|
3306
|
+
return true;
|
|
3307
|
+
case "sym":
|
|
3308
|
+
case "gnd":
|
|
3309
|
+
return isNormalForm(env, w, t);
|
|
3310
|
+
case "expr": {
|
|
3311
|
+
if (t.items.length === 0) return true;
|
|
3312
|
+
const h = t.items[0];
|
|
3313
|
+
return h.kind === "sym" && !isDefinedHead(env, w, h.name) && t.items.every((x) => isNormalFormAssumingVars(env, w, x));
|
|
3314
|
+
}
|
|
3315
|
+
}
|
|
3316
|
+
}
|
|
2021
3317
|
function atomToStack(a, prev) {
|
|
2022
3318
|
if (a.kind === "expr") {
|
|
2023
3319
|
const op = opOf(a);
|
|
@@ -2075,6 +3371,7 @@ function emptyEnv(gt) {
|
|
|
2075
3371
|
return {
|
|
2076
3372
|
ruleIndex: /* @__PURE__ */ new Map(),
|
|
2077
3373
|
varRules: [],
|
|
3374
|
+
varRulesVar: [],
|
|
2078
3375
|
sigs: /* @__PURE__ */ new Map(),
|
|
2079
3376
|
gt,
|
|
2080
3377
|
atoms: [],
|
|
@@ -2083,6 +3380,7 @@ function emptyEnv(gt) {
|
|
|
2083
3380
|
exprTypes: [],
|
|
2084
3381
|
agt: /* @__PURE__ */ new Map(),
|
|
2085
3382
|
mutexes: /* @__PURE__ */ new Map(),
|
|
3383
|
+
evaluatedAtoms: /* @__PURE__ */ new WeakSet(),
|
|
2086
3384
|
factIndex: /* @__PURE__ */ new Map(),
|
|
2087
3385
|
argIndex: /* @__PURE__ */ new Map(),
|
|
2088
3386
|
nonGroundAtPos: /* @__PURE__ */ new Map(),
|
|
@@ -2190,43 +3488,46 @@ function ensureCompiled(env) {
|
|
|
2190
3488
|
}
|
|
2191
3489
|
}
|
|
2192
3490
|
function disableTabling(env) {
|
|
3491
|
+
env.evaluatedAtoms = /* @__PURE__ */ new WeakSet();
|
|
3492
|
+
env.compiled = void 0;
|
|
3493
|
+
env.compileDirty = void 0;
|
|
2193
3494
|
if (env.table !== void 0) {
|
|
2194
3495
|
env.table.clear();
|
|
2195
3496
|
env.pureFunctors = /* @__PURE__ */ new Set();
|
|
2196
|
-
if (env.compiled !== void 0) {
|
|
2197
|
-
env.compiled = /* @__PURE__ */ new Map();
|
|
2198
|
-
env.compileDirty = false;
|
|
2199
|
-
}
|
|
2200
3497
|
}
|
|
2201
3498
|
}
|
|
2202
3499
|
function addAtomToEnv(env, x) {
|
|
2203
|
-
env.
|
|
2204
|
-
|
|
2205
|
-
|
|
3500
|
+
const atom = env.intern === void 0 ? x : internAtom(env.intern, x);
|
|
3501
|
+
env.atoms.push(atom);
|
|
3502
|
+
const fk = headKey(atom);
|
|
3503
|
+
if (fk === void 0) env.varHeadedFacts.push(atom);
|
|
2206
3504
|
else {
|
|
2207
|
-
pushTo(env.factIndex, fk,
|
|
2208
|
-
if (
|
|
2209
|
-
for (let i = 1; i <
|
|
2210
|
-
const ak = argKey(
|
|
2211
|
-
if (ak !== void 0) pushTo(env.argIndex, fk + KEY_SEP + i + KEY_SEP + ak,
|
|
2212
|
-
else pushTo(env.nonGroundAtPos, fk + KEY_SEP + i,
|
|
3505
|
+
pushTo(env.factIndex, fk, atom);
|
|
3506
|
+
if (atom.kind === "expr")
|
|
3507
|
+
for (let i = 1; i < atom.items.length; i++) {
|
|
3508
|
+
const ak = argKey(atom.items[i]);
|
|
3509
|
+
if (ak !== void 0) pushTo(env.argIndex, fk + KEY_SEP + i + KEY_SEP + ak, atom);
|
|
3510
|
+
else pushTo(env.nonGroundAtPos, fk + KEY_SEP + i, atom);
|
|
2213
3511
|
}
|
|
2214
3512
|
}
|
|
2215
|
-
if (opOf(
|
|
2216
|
-
|
|
2217
|
-
const
|
|
3513
|
+
if (opOf(atom) === "=" && atom.kind === "expr" && atom.items.length === 3) {
|
|
3514
|
+
env.evaluatedAtoms = /* @__PURE__ */ new WeakSet();
|
|
3515
|
+
const lhs = atom.items[1];
|
|
3516
|
+
const rhs = atom.items[2];
|
|
2218
3517
|
const k = headKey(lhs);
|
|
2219
|
-
if (k === void 0)
|
|
2220
|
-
|
|
3518
|
+
if (k === void 0) {
|
|
3519
|
+
env.varRules.push([lhs, rhs]);
|
|
3520
|
+
if (isVariableHeaded(lhs)) env.varRulesVar.push([lhs, rhs]);
|
|
3521
|
+
} else {
|
|
2221
3522
|
const cur = env.ruleIndex.get(k);
|
|
2222
3523
|
if (cur === void 0) env.ruleIndex.set(k, [[lhs, rhs]]);
|
|
2223
3524
|
else cur.push([lhs, rhs]);
|
|
2224
3525
|
}
|
|
2225
3526
|
invalidateTabling(env);
|
|
2226
3527
|
}
|
|
2227
|
-
if (
|
|
2228
|
-
const subj =
|
|
2229
|
-
const t =
|
|
3528
|
+
if (atom.kind === "expr" && opOf(atom) === ":" && atom.items.length === 3) {
|
|
3529
|
+
const subj = atom.items[1];
|
|
3530
|
+
const t = atom.items[2];
|
|
2230
3531
|
if (subj.kind === "sym") {
|
|
2231
3532
|
if (opOf(t) === "->" && t.kind === "expr") env.sigs.set(subj.name, t.items.slice(1));
|
|
2232
3533
|
env.types.set(subj.name, [...env.types.get(subj.name) ?? [], t]);
|
|
@@ -2259,12 +3560,36 @@ function registerImportedTypes(env, atoms) {
|
|
|
2259
3560
|
}
|
|
2260
3561
|
}
|
|
2261
3562
|
function selfAtoms(env, w) {
|
|
2262
|
-
|
|
3563
|
+
const runtime = runtimeAtoms(w);
|
|
3564
|
+
return runtime.length === 0 ? env.atoms : [...env.atoms, ...runtime];
|
|
3565
|
+
}
|
|
3566
|
+
function runtimeAtoms(w) {
|
|
3567
|
+
const flat = w.flatSelfExtra?.toArray() ?? [];
|
|
3568
|
+
const log = logToArray(w.selfExtra);
|
|
3569
|
+
if (flat.length === 0) return log;
|
|
3570
|
+
if (log.length === 0) return flat;
|
|
3571
|
+
return [...flat, ...log];
|
|
2263
3572
|
}
|
|
2264
3573
|
function candidates(env, toEval) {
|
|
2265
3574
|
const k = headKey(toEval);
|
|
3575
|
+
if (k === void 0 && toEval.kind === "expr" && toEval.items.length > 0)
|
|
3576
|
+
return [...env.varRules];
|
|
2266
3577
|
const keyed = k !== void 0 ? env.ruleIndex.get(k) ?? [] : [];
|
|
2267
|
-
return [...keyed, ...env.
|
|
3578
|
+
return env.varRulesVar.length === 0 ? keyed : [...keyed, ...env.varRulesVar];
|
|
3579
|
+
}
|
|
3580
|
+
function namedSpaceAtoms(space) {
|
|
3581
|
+
return logToArray(space ?? emptyLog);
|
|
3582
|
+
}
|
|
3583
|
+
function namedSpaceCandidateGetter(w, space) {
|
|
3584
|
+
let scan;
|
|
3585
|
+
return (pInst) => {
|
|
3586
|
+
const log = space ?? emptyLog;
|
|
3587
|
+
if (pInst.ground && logNonGround(log) === 0 && w.store.size === 0) {
|
|
3588
|
+
return exactCandidateSource(pInst, idxCount(logGroundIdx(log), pInst), logSize(log));
|
|
3589
|
+
}
|
|
3590
|
+
scan ??= namedSpaceAtoms(space).map((x) => resolveStates(w, x));
|
|
3591
|
+
return scan;
|
|
3592
|
+
};
|
|
2268
3593
|
}
|
|
2269
3594
|
var initSt = () => ({
|
|
2270
3595
|
counter: 0,
|
|
@@ -2273,6 +3598,7 @@ var initSt = () => ({
|
|
|
2273
3598
|
store: /* @__PURE__ */ new Map(),
|
|
2274
3599
|
tokens: /* @__PURE__ */ new Map(),
|
|
2275
3600
|
selfExtra: emptyLog,
|
|
3601
|
+
flatSelfExtra: void 0,
|
|
2276
3602
|
selfRules: /* @__PURE__ */ new Map(),
|
|
2277
3603
|
selfVarRules: [],
|
|
2278
3604
|
maxStackDepth: 0
|
|
@@ -2284,6 +3610,7 @@ function cloneWorld(w) {
|
|
|
2284
3610
|
store: new Map(w.store),
|
|
2285
3611
|
tokens: new Map(w.tokens),
|
|
2286
3612
|
selfExtra: w.selfExtra,
|
|
3613
|
+
flatSelfExtra: w.flatSelfExtra,
|
|
2287
3614
|
selfRules: new Map(w.selfRules),
|
|
2288
3615
|
selfVarRules: w.selfVarRules,
|
|
2289
3616
|
maxStackDepth: w.maxStackDepth
|
|
@@ -2309,27 +3636,32 @@ function applyAtomDelta(into, added, removed) {
|
|
|
2309
3636
|
return out;
|
|
2310
3637
|
}
|
|
2311
3638
|
function mergeWorlds(base, branches) {
|
|
2312
|
-
const baseSelf =
|
|
3639
|
+
const baseSelf = runtimeAtoms(base);
|
|
2313
3640
|
let selfExtra = baseSelf.slice();
|
|
2314
3641
|
const spaces = new Map(base.spaces);
|
|
2315
3642
|
const store = new Map(base.store);
|
|
2316
3643
|
const tokens = new Map(base.tokens);
|
|
2317
3644
|
for (const w of branches) {
|
|
2318
|
-
const d = multisetDelta(baseSelf,
|
|
3645
|
+
const d = multisetDelta(baseSelf, runtimeAtoms(w));
|
|
2319
3646
|
selfExtra = applyAtomDelta(selfExtra, d.added, d.removed);
|
|
2320
3647
|
for (const [k, v] of w.spaces) {
|
|
2321
|
-
const baseV = base.spaces.get(k)
|
|
2322
|
-
const sd = multisetDelta(baseV, v);
|
|
2323
|
-
spaces.set(
|
|
3648
|
+
const baseV = namedSpaceAtoms(base.spaces.get(k));
|
|
3649
|
+
const sd = multisetDelta(baseV, namedSpaceAtoms(v));
|
|
3650
|
+
spaces.set(
|
|
3651
|
+
k,
|
|
3652
|
+
logFromArray(applyAtomDelta(namedSpaceAtoms(spaces.get(k)), sd.added, sd.removed))
|
|
3653
|
+
);
|
|
2324
3654
|
}
|
|
2325
3655
|
for (const [k, v] of w.store) if (!Object.is(base.store.get(k), v)) store.set(k, v);
|
|
2326
3656
|
for (const [k, v] of w.tokens) if (!Object.is(base.tokens.get(k), v)) tokens.set(k, v);
|
|
2327
3657
|
}
|
|
3658
|
+
const flat = base.flatSelfExtra === void 0 ? void 0 : FlatAtomSpace.fromAtoms(selfExtra);
|
|
2328
3659
|
const merged = {
|
|
2329
3660
|
spaces,
|
|
2330
3661
|
store,
|
|
2331
3662
|
tokens,
|
|
2332
|
-
selfExtra: logFromArray(selfExtra),
|
|
3663
|
+
selfExtra: flat === void 0 ? logFromArray(selfExtra) : emptyLog,
|
|
3664
|
+
flatSelfExtra: flat,
|
|
2333
3665
|
selfRules: /* @__PURE__ */ new Map(),
|
|
2334
3666
|
selfVarRules: [],
|
|
2335
3667
|
maxStackDepth: base.maxStackDepth
|
|
@@ -2379,10 +3711,13 @@ function resolveStates(w, a) {
|
|
|
2379
3711
|
}
|
|
2380
3712
|
return a;
|
|
2381
3713
|
}
|
|
2382
|
-
function subTokens(w, a) {
|
|
3714
|
+
function subTokens(w, a, intern) {
|
|
2383
3715
|
if (w.tokens.size === 0) return a;
|
|
2384
3716
|
if (a.kind === "sym") return w.tokens.get(a.name) ?? a;
|
|
2385
|
-
if (a.kind === "expr")
|
|
3717
|
+
if (a.kind === "expr") {
|
|
3718
|
+
const out = expr(a.items.map((x) => subTokens(w, x, intern)));
|
|
3719
|
+
return intern === void 0 ? out : internBuiltExpr(intern, out);
|
|
3720
|
+
}
|
|
2386
3721
|
return a;
|
|
2387
3722
|
}
|
|
2388
3723
|
function wrapStates(w, a) {
|
|
@@ -2399,7 +3734,7 @@ function wrapStates(w, a) {
|
|
|
2399
3734
|
}
|
|
2400
3735
|
return a;
|
|
2401
3736
|
}
|
|
2402
|
-
var typePrep = (w, a) => wrapStates(w, subTokens(w, a));
|
|
3737
|
+
var typePrep = (env, w, a) => wrapStates(w, subTokens(w, a, env.intern));
|
|
2403
3738
|
function candidatesW(env, w, toEval) {
|
|
2404
3739
|
const k2 = headKey(toEval);
|
|
2405
3740
|
const headRules = k2 !== void 0 ? w.selfRules.get(k2) ?? [] : [];
|
|
@@ -2407,7 +3742,12 @@ function candidatesW(env, w, toEval) {
|
|
|
2407
3742
|
}
|
|
2408
3743
|
var ruleVarsCache = /* @__PURE__ */ new WeakMap();
|
|
2409
3744
|
function ruleVars(lhs, rhs) {
|
|
2410
|
-
let
|
|
3745
|
+
let rhsCache = ruleVarsCache.get(lhs);
|
|
3746
|
+
if (rhsCache === void 0) {
|
|
3747
|
+
rhsCache = /* @__PURE__ */ new WeakMap();
|
|
3748
|
+
ruleVarsCache.set(lhs, rhsCache);
|
|
3749
|
+
}
|
|
3750
|
+
let vs = rhsCache.get(rhs);
|
|
2411
3751
|
if (vs === void 0) {
|
|
2412
3752
|
vs = atomVars(lhs);
|
|
2413
3753
|
const seen = new Set(vs);
|
|
@@ -2416,11 +3756,12 @@ function ruleVars(lhs, rhs) {
|
|
|
2416
3756
|
seen.add(v);
|
|
2417
3757
|
vs.push(v);
|
|
2418
3758
|
}
|
|
2419
|
-
|
|
3759
|
+
rhsCache.set(rhs, vs);
|
|
2420
3760
|
}
|
|
2421
3761
|
return vs;
|
|
2422
3762
|
}
|
|
2423
3763
|
function freshenSub(counter, lhs, rhs) {
|
|
3764
|
+
if (lhs.ground && rhs.ground) return [];
|
|
2424
3765
|
const vs = ruleVars(lhs, rhs);
|
|
2425
3766
|
return vs.length === 0 ? [] : vs.map((v) => [v, variable(v + "#" + String(counter))]);
|
|
2426
3767
|
}
|
|
@@ -2449,7 +3790,7 @@ function queryOp(env, st, prev, toEval, b) {
|
|
|
2449
3790
|
counter += 1;
|
|
2450
3791
|
for (const mb of matchAtomsScoped(lhs0, toEval, suffix)) {
|
|
2451
3792
|
for (const m of merge(b, mb)) {
|
|
2452
|
-
if (!hasLoop(m)) out.push(evalResult(prev,
|
|
3793
|
+
if (!hasLoop(m)) out.push(evalResult(prev, inst(env, m, rhs0, suffix), m));
|
|
2453
3794
|
}
|
|
2454
3795
|
}
|
|
2455
3796
|
}
|
|
@@ -2465,11 +3806,28 @@ function hasRuleFor(env, w, counter, a) {
|
|
|
2465
3806
|
return false;
|
|
2466
3807
|
}
|
|
2467
3808
|
function* evalOpG(env, st, prev, x, b) {
|
|
2468
|
-
const x2 =
|
|
3809
|
+
const x2 = inst(env, b, x);
|
|
2469
3810
|
const op = opOf(x2);
|
|
3811
|
+
if (op === "collapse" && x2.kind === "expr" && x2.items.length === 2) {
|
|
3812
|
+
const match = matchInsideOnce(x2.items[1]);
|
|
3813
|
+
if (match !== void 0) {
|
|
3814
|
+
const namedMatch = tryFastNamedOnceMatch(env, st, match, b);
|
|
3815
|
+
if (namedMatch !== void 0) {
|
|
3816
|
+
const items = namedMatch.value === void 0 ? [] : [namedMatch.value];
|
|
3817
|
+
return [[evalResult(prev, expr(items), b)], namedMatch.state];
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
if (op === "if" && x2.kind === "expr" && x2.items.length === 4) {
|
|
3822
|
+
const added = tryFastNamedAddIfAbsent(env, st, x2, b);
|
|
3823
|
+
if (added !== void 0) {
|
|
3824
|
+
const out = added.added ? [finItem(prev, emptyExpr, b)] : [];
|
|
3825
|
+
return [out, added.state];
|
|
3826
|
+
}
|
|
3827
|
+
}
|
|
2470
3828
|
const useGrounded = op !== void 0 && x2.kind === "expr" && !(pettaOpNames.has(op) && hasRuleFor(env, st.world, st.counter, x2));
|
|
2471
3829
|
if (useGrounded) {
|
|
2472
|
-
const args = x2.items.slice(1).map((a) => resolveStates(st.world, subTokens(st.world, a)));
|
|
3830
|
+
const args = x2.items.slice(1).map((a) => resolveStates(st.world, subTokens(st.world, a, env.intern)));
|
|
2473
3831
|
const r = yield* callGroundedG(env, op, args);
|
|
2474
3832
|
if (r.tag === "ok") return [r.results.map((res) => evalResult(prev, res, b)), st];
|
|
2475
3833
|
if (r.tag === "runtimeError") return [[finItem(prev, errAtom(x2, r.msg), b)], st];
|
|
@@ -2478,7 +3836,7 @@ function* evalOpG(env, st, prev, x, b) {
|
|
|
2478
3836
|
if (x2.kind === "expr" && x2.items.length > 0) {
|
|
2479
3837
|
const head = x2.items[0];
|
|
2480
3838
|
if (head.kind === "gnd" && head.exec !== void 0) {
|
|
2481
|
-
const args = x2.items.slice(1).map((a) => resolveStates(st.world, subTokens(st.world, a)));
|
|
3839
|
+
const args = x2.items.slice(1).map((a) => resolveStates(st.world, subTokens(st.world, a, env.intern)));
|
|
2482
3840
|
try {
|
|
2483
3841
|
const results = head.exec(args);
|
|
2484
3842
|
return [results.map((res) => evalResult(prev, res, b)), st];
|
|
@@ -2491,55 +3849,65 @@ function* evalOpG(env, st, prev, x, b) {
|
|
|
2491
3849
|
if (isEmbeddedOp(x2)) return [[{ stack: atomToStack(x2, prev), bnd: b }], st];
|
|
2492
3850
|
return queryOp(env, st, prev, x2, b);
|
|
2493
3851
|
}
|
|
2494
|
-
function unifyOp(prev, a, p, t, e, b) {
|
|
3852
|
+
function unifyOp(env, prev, a, p, t, e, b) {
|
|
2495
3853
|
const ms = [];
|
|
2496
3854
|
for (const mb of matchAtoms(a, p))
|
|
2497
|
-
for (const m of merge(b, mb)) if (!hasLoop(m)) ms.push(finItem(prev,
|
|
3855
|
+
for (const m of merge(b, mb)) if (!hasLoop(m)) ms.push(finItem(prev, inst(env, m, t), m));
|
|
2498
3856
|
return ms.length === 0 ? [finItem(prev, e, b)] : ms;
|
|
2499
3857
|
}
|
|
2500
3858
|
var isFinal = (it) => it.stack !== null && it.stack.tail === null && it.stack.head.fin;
|
|
2501
|
-
function finalPair(it) {
|
|
3859
|
+
function finalPair(env, it) {
|
|
2502
3860
|
const f = it.stack;
|
|
2503
|
-
return f === null ? [emptyA, []] : [
|
|
3861
|
+
return f === null ? [emptyA, []] : [inst(env, it.bnd, f.head.atom), it.bnd];
|
|
2504
3862
|
}
|
|
2505
|
-
function exhaustedPair(it) {
|
|
3863
|
+
function exhaustedPair(env, it) {
|
|
2506
3864
|
const f = it.stack;
|
|
2507
|
-
return f === null ? [emptyA, it.bnd] : [
|
|
3865
|
+
return f === null ? [emptyA, it.bnd] : [makeExpr(env, [sym("Error"), inst(env, it.bnd, f.head.atom), sym("StackOverflow")]), it.bnd];
|
|
2508
3866
|
}
|
|
2509
|
-
function
|
|
2510
|
-
let cur =
|
|
2511
|
-
|
|
2512
|
-
|
|
3867
|
+
function resolveBoundVarFix(env, b, n, x) {
|
|
3868
|
+
let cur = lookupVal(b, x);
|
|
3869
|
+
if (cur === void 0 || cur.ground) return cur;
|
|
3870
|
+
for (let i = 1; i < n; i++) {
|
|
3871
|
+
const next = inst(env, b, cur);
|
|
2513
3872
|
if (atomEq(next, cur)) return cur;
|
|
2514
3873
|
cur = next;
|
|
2515
3874
|
}
|
|
2516
3875
|
return cur;
|
|
2517
3876
|
}
|
|
2518
|
-
function restrictBnd(vars, b) {
|
|
3877
|
+
function restrictBnd(env, vars, b) {
|
|
3878
|
+
if (vars.length === 0) return emptyBindings;
|
|
2519
3879
|
const solved = [];
|
|
2520
3880
|
for (const x of vars) {
|
|
2521
|
-
const v =
|
|
2522
|
-
if (!(v.kind === "var" && v.name === x)) solved.push(
|
|
3881
|
+
const v = resolveBoundVarFix(env, b, size(b) + 1, x);
|
|
3882
|
+
if (v !== void 0 && !(v.kind === "var" && v.name === x)) solved.push(makeValRel(x, v));
|
|
2523
3883
|
}
|
|
2524
|
-
if (!b
|
|
3884
|
+
if (!hasEq(b)) return fromRelations(solved);
|
|
2525
3885
|
const vset = new Set(vars);
|
|
2526
|
-
const eqs =
|
|
2527
|
-
|
|
3886
|
+
const eqs = [];
|
|
3887
|
+
for (const r of eqRelations(b)) if (vset.has(r.x) && vset.has(r.y)) eqs.push(r);
|
|
3888
|
+
return fromRelations(solved.length === 0 ? eqs : [...solved, ...eqs]);
|
|
2528
3889
|
}
|
|
2529
|
-
function mergeRestrict(vars, baseB, pb) {
|
|
3890
|
+
function mergeRestrict(env, vars, baseB, pb) {
|
|
3891
|
+
if (vars.length === 0) return emptyBindings;
|
|
2530
3892
|
const merged = merge(baseB, pb);
|
|
2531
|
-
return restrictBnd(vars, merged.length > 0 ? merged[0] : pb);
|
|
3893
|
+
return restrictBnd(env, vars, merged.length > 0 ? merged[0] : pb);
|
|
2532
3894
|
}
|
|
2533
|
-
function
|
|
3895
|
+
function queryVarsOf(args) {
|
|
3896
|
+
const out = [];
|
|
3897
|
+
for (const a of args) if (!a.ground) out.push(...atomVars(a));
|
|
3898
|
+
return out;
|
|
3899
|
+
}
|
|
3900
|
+
function scopeVars(env, b, prev) {
|
|
2534
3901
|
const out = [];
|
|
2535
3902
|
const seen = /* @__PURE__ */ new Set();
|
|
2536
|
-
for (let p = prev; p !== null; p = p.tail) collectVars(
|
|
3903
|
+
for (let p = prev; p !== null; p = p.tail) collectVars(inst(env, b, p.head.atom), out, seen);
|
|
2537
3904
|
return out;
|
|
2538
3905
|
}
|
|
2539
|
-
function
|
|
3906
|
+
function chainLiveVars(cont, prev) {
|
|
2540
3907
|
const out = [];
|
|
2541
3908
|
const seen = /* @__PURE__ */ new Set();
|
|
2542
3909
|
for (let p = prev; p !== null; p = p.tail) collectVars(p.head.atom, out, seen);
|
|
3910
|
+
collectVars(cont, out, seen);
|
|
2543
3911
|
return out;
|
|
2544
3912
|
}
|
|
2545
3913
|
function superposeItem(prev, b, pair) {
|
|
@@ -2620,13 +3988,13 @@ function getTypesUncached(env, a) {
|
|
|
2620
3988
|
const params = ts.slice(0, -1);
|
|
2621
3989
|
let tb = [];
|
|
2622
3990
|
for (let i = 0; i < params.length && i < argTs.length; i++) {
|
|
2623
|
-
const m = matchAtoms(
|
|
3991
|
+
const m = matchAtoms(inst(env, tb, params[i]), argTs[i]);
|
|
2624
3992
|
if (m.length > 0) {
|
|
2625
3993
|
const merged = merge(tb, m[0]);
|
|
2626
3994
|
if (merged.length > 0) tb = merged[0];
|
|
2627
3995
|
}
|
|
2628
3996
|
}
|
|
2629
|
-
out.push(
|
|
3997
|
+
out.push(inst(env, tb, ret));
|
|
2630
3998
|
}
|
|
2631
3999
|
}
|
|
2632
4000
|
return out.length > 0 ? out : UNDEF_T;
|
|
@@ -2645,7 +4013,7 @@ function getTypesForQuery(env, a) {
|
|
|
2645
4013
|
for (const combo of combos) for (const t of opts) next.push([...combo, t]);
|
|
2646
4014
|
combos = next;
|
|
2647
4015
|
}
|
|
2648
|
-
return combos.map((c) =>
|
|
4016
|
+
return combos.map((c) => makeExpr(env, c));
|
|
2649
4017
|
}
|
|
2650
4018
|
function matchReduced(tb, expected, actual) {
|
|
2651
4019
|
if (atomEq(expected, UNDEF) || atomEq(actual, UNDEF)) return tb;
|
|
@@ -2676,11 +4044,11 @@ function typeCheckArgs(env, w, argTypes, i, tb, argsLeft) {
|
|
|
2676
4044
|
if (argsLeft.length === 0) return void 0;
|
|
2677
4045
|
const ti0 = argTypes[i];
|
|
2678
4046
|
if (ti0 === void 0) return void 0;
|
|
2679
|
-
const ti =
|
|
4047
|
+
const ti = inst(env, tb, ti0);
|
|
2680
4048
|
if (ti.kind === "sym" && (ti.name === "Atom" || ti.name === "%Undefined%"))
|
|
2681
4049
|
return typeCheckArgs(env, w, argTypes, i + 1, tb, argsLeft.slice(1));
|
|
2682
4050
|
const ai = argsLeft[0];
|
|
2683
|
-
const prepped = typePrep(w, ai);
|
|
4051
|
+
const prepped = typePrep(env, w, ai);
|
|
2684
4052
|
if (ti.kind === "sym" && ti.name === metaType(prepped))
|
|
2685
4053
|
return typeCheckArgs(env, w, argTypes, i + 1, tb, argsLeft.slice(1));
|
|
2686
4054
|
const actuals = getTypes(env, prepped);
|
|
@@ -2694,12 +4062,12 @@ function typeMismatch(env, w, op, args, ts = env.sigs.get(op)) {
|
|
|
2694
4062
|
if (ts === void 0) return void 0;
|
|
2695
4063
|
return typeCheckArgs(env, w, ts.slice(0, -1), 0, [], args);
|
|
2696
4064
|
}
|
|
2697
|
-
function matchCandidates(env, w, pInst) {
|
|
4065
|
+
function* matchCandidates(env, w, pInst) {
|
|
2698
4066
|
const k = headKey(pInst);
|
|
2699
4067
|
if (k === void 0) {
|
|
2700
|
-
const
|
|
2701
|
-
|
|
2702
|
-
return
|
|
4068
|
+
for (const atom of resolveAll(w, env.atoms.slice())) yield atom;
|
|
4069
|
+
yield* runtimeCandidates(w, void 0);
|
|
4070
|
+
return;
|
|
2703
4071
|
}
|
|
2704
4072
|
let bestKey;
|
|
2705
4073
|
let bestPosKey;
|
|
@@ -2710,9 +4078,9 @@ function matchCandidates(env, w, pInst) {
|
|
|
2710
4078
|
if (ak === void 0) continue;
|
|
2711
4079
|
const ik = k + KEY_SEP + i + KEY_SEP + ak;
|
|
2712
4080
|
const posKey = k + KEY_SEP + i;
|
|
2713
|
-
const
|
|
2714
|
-
if (
|
|
2715
|
-
bestSize =
|
|
4081
|
+
const size2 = (env.argIndex.get(ik)?.length ?? 0) + (env.nonGroundAtPos.get(posKey)?.length ?? 0);
|
|
4082
|
+
if (size2 < bestSize) {
|
|
4083
|
+
bestSize = size2;
|
|
2716
4084
|
bestKey = ik;
|
|
2717
4085
|
bestPosKey = posKey;
|
|
2718
4086
|
}
|
|
@@ -2724,71 +4092,111 @@ function matchCandidates(env, w, pInst) {
|
|
|
2724
4092
|
cands = (env.factIndex.get(k) ?? []).slice();
|
|
2725
4093
|
}
|
|
2726
4094
|
cands.push(...env.varHeadedFacts);
|
|
2727
|
-
if (pInst.ground && logNonGround(w.selfExtra) === 0 && w.store.size === 0) {
|
|
4095
|
+
if (pInst.ground && logNonGround(w.selfExtra) === 0 && (w.flatSelfExtra?.nonGroundCount ?? 0) === 0 && w.store.size === 0) {
|
|
2728
4096
|
const c = idxCount(logGroundIdx(w.selfExtra), pInst);
|
|
2729
|
-
for (
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
for (const a of extra) {
|
|
2734
|
-
const akk = headKey(a);
|
|
2735
|
-
if (akk === void 0 || akk === k) cands.push(a);
|
|
4097
|
+
for (const atom of cands) yield atom;
|
|
4098
|
+
const flatCount = w.flatSelfExtra?.exactCount(pInst) ?? 0;
|
|
4099
|
+
for (let i = 0; i < c + flatCount; i++) yield pInst;
|
|
4100
|
+
return;
|
|
2736
4101
|
}
|
|
2737
|
-
|
|
4102
|
+
for (const atom of resolveAll(w, cands)) yield atom;
|
|
4103
|
+
yield* runtimeCandidates(w, k);
|
|
2738
4104
|
}
|
|
2739
4105
|
function resolveAll(w, atoms) {
|
|
2740
4106
|
return w.store.size === 0 ? atoms : atoms.map((x) => resolveStates(w, x));
|
|
2741
4107
|
}
|
|
2742
|
-
function
|
|
4108
|
+
function* runtimeCandidates(w, k) {
|
|
4109
|
+
if (w.flatSelfExtra !== void 0) {
|
|
4110
|
+
for (const a of w.flatSelfExtra.candidatesFor(k)) yield resolveStates(w, a);
|
|
4111
|
+
}
|
|
4112
|
+
for (const a of logToArray(w.selfExtra)) {
|
|
4113
|
+
if (k === void 0) yield resolveStates(w, a);
|
|
4114
|
+
else {
|
|
4115
|
+
const akk = headKey(a);
|
|
4116
|
+
if (akk === void 0 || akk === k) yield resolveStates(w, a);
|
|
4117
|
+
}
|
|
4118
|
+
}
|
|
4119
|
+
}
|
|
4120
|
+
function matchConj(env, getCandidates, patterns, st, sols) {
|
|
2743
4121
|
let cur = sols;
|
|
2744
4122
|
let counter = st.counter;
|
|
2745
4123
|
for (const p of patterns) {
|
|
2746
4124
|
const next = [];
|
|
2747
4125
|
for (const b of cur) {
|
|
2748
|
-
const pInst =
|
|
2749
|
-
|
|
4126
|
+
const pInst = inst(env, b, p);
|
|
4127
|
+
const source = getCandidates(pInst);
|
|
4128
|
+
for (const atom of source) {
|
|
2750
4129
|
const atom2 = freshenRule(counter, atom, atom)[0];
|
|
2751
4130
|
counter += 1;
|
|
2752
4131
|
for (const mb of matchAtoms(pInst, atom2))
|
|
2753
4132
|
for (const m of merge(b, mb)) if (!hasLoop(m)) next.push(m);
|
|
2754
4133
|
}
|
|
4134
|
+
counter += candidateCounterPadding(source);
|
|
2755
4135
|
}
|
|
2756
4136
|
cur = next;
|
|
2757
4137
|
}
|
|
2758
4138
|
return [cur, { counter, world: st.world }];
|
|
2759
4139
|
}
|
|
2760
|
-
function
|
|
4140
|
+
function splitConjGoals(env, getCandidates, patterns, st, b0, perPositionAdmit) {
|
|
2761
4141
|
let counter = st.counter;
|
|
4142
|
+
const insts = patterns.map((p) => inst(env, b0, p));
|
|
4143
|
+
const pvarsList = insts.map((pInst) => atomVars(pInst));
|
|
4144
|
+
let joinVars;
|
|
4145
|
+
if (perPositionAdmit) {
|
|
4146
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4147
|
+
const shared = /* @__PURE__ */ new Set();
|
|
4148
|
+
for (const pvars of pvarsList)
|
|
4149
|
+
for (const v of new Set(pvars)) (seen.has(v) ? shared : seen).add(v);
|
|
4150
|
+
joinVars = shared;
|
|
4151
|
+
}
|
|
2762
4152
|
const groundRels = [];
|
|
2763
4153
|
const otherPatterns = [];
|
|
2764
|
-
for (
|
|
2765
|
-
const
|
|
2766
|
-
const pvars =
|
|
4154
|
+
for (let i = 0; i < patterns.length; i++) {
|
|
4155
|
+
const p = patterns[i];
|
|
4156
|
+
const pvars = pvarsList[i];
|
|
2767
4157
|
if (pvars.length === 0) {
|
|
2768
4158
|
otherPatterns.push(p);
|
|
2769
4159
|
continue;
|
|
2770
4160
|
}
|
|
4161
|
+
const pInst = insts[i];
|
|
2771
4162
|
const tuples = [];
|
|
2772
|
-
let
|
|
2773
|
-
|
|
4163
|
+
let relational = true;
|
|
4164
|
+
const source = getCandidates(pInst);
|
|
4165
|
+
for (const atom of source) {
|
|
2774
4166
|
const fresh = freshenRule(counter, atom, atom)[0];
|
|
2775
4167
|
counter += 1;
|
|
2776
4168
|
for (const mb of matchAtoms(pInst, fresh)) {
|
|
2777
4169
|
const t = /* @__PURE__ */ new Map();
|
|
2778
4170
|
for (const v of pvars) {
|
|
2779
|
-
const val =
|
|
4171
|
+
const val = lookupVal(mb, v) ?? variable(v);
|
|
2780
4172
|
t.set(v, val);
|
|
2781
|
-
if (!val.ground)
|
|
4173
|
+
if (!val.ground && (joinVars === void 0 || joinVars.has(v))) relational = false;
|
|
2782
4174
|
}
|
|
2783
4175
|
tuples.push(t);
|
|
2784
4176
|
}
|
|
2785
4177
|
}
|
|
2786
|
-
|
|
4178
|
+
counter += candidateCounterPadding(source);
|
|
4179
|
+
if (relational) groundRels.push({ vars: pvars, tuples });
|
|
2787
4180
|
else otherPatterns.push(p);
|
|
2788
4181
|
}
|
|
2789
|
-
|
|
4182
|
+
return { groundRels, otherPatterns, counter };
|
|
4183
|
+
}
|
|
4184
|
+
function conjJoinPartials(env, getCandidates, patterns, st, b0) {
|
|
4185
|
+
const { groundRels, otherPatterns, counter } = splitConjGoals(
|
|
4186
|
+
env,
|
|
4187
|
+
getCandidates,
|
|
4188
|
+
patterns,
|
|
4189
|
+
st,
|
|
4190
|
+
b0,
|
|
4191
|
+
// Result path: admit schematic facts at non-join positions to the leapfrog only when the fast matcher is
|
|
4192
|
+
// on. The leapfrog reorders results and freshens differently, so an admitted schematic goal makes the
|
|
4193
|
+
// answer alpha-equivalent (not byte-identical) to the coupled path; the default (trail off) keeps the
|
|
4194
|
+
// conservative all-ground gate, so the byte-identical reference order holds and the oracle is unaffected.
|
|
4195
|
+
env.useTrail === true
|
|
4196
|
+
);
|
|
4197
|
+
let partials;
|
|
2790
4198
|
if (groundRels.length > 0) {
|
|
2791
|
-
|
|
4199
|
+
partials = [];
|
|
2792
4200
|
for (const sol of wcoJoin(groundRels, mutexKey)) {
|
|
2793
4201
|
let bs = [b0];
|
|
2794
4202
|
for (const [v, val] of sol) {
|
|
@@ -2796,31 +4204,88 @@ function matchConjJoin(getCandidates, patterns, st, b0) {
|
|
|
2796
4204
|
for (const b of bs) nb.push(...addVarBinding(b, v, val));
|
|
2797
4205
|
bs = nb;
|
|
2798
4206
|
}
|
|
2799
|
-
for (const b of bs) if (!hasLoop(b))
|
|
4207
|
+
for (const b of bs) if (!hasLoop(b)) partials.push(b);
|
|
2800
4208
|
}
|
|
2801
4209
|
} else {
|
|
2802
|
-
|
|
2803
|
-
}
|
|
4210
|
+
partials = [b0];
|
|
4211
|
+
}
|
|
4212
|
+
return { partials, otherPatterns, counter };
|
|
4213
|
+
}
|
|
4214
|
+
function matchConjJoin(env, getCandidates, patterns, st, b0) {
|
|
4215
|
+
const {
|
|
4216
|
+
partials,
|
|
4217
|
+
otherPatterns,
|
|
4218
|
+
counter: c0
|
|
4219
|
+
} = conjJoinPartials(env, getCandidates, patterns, st, b0);
|
|
4220
|
+
let cur = partials;
|
|
4221
|
+
let counter = c0;
|
|
2804
4222
|
for (const p of otherPatterns) {
|
|
2805
4223
|
const next = [];
|
|
2806
4224
|
const freshCache = /* @__PURE__ */ new Map();
|
|
2807
4225
|
for (const b of cur) {
|
|
2808
|
-
const pInst =
|
|
2809
|
-
|
|
2810
|
-
|
|
4226
|
+
const pInst = inst(env, b, p);
|
|
4227
|
+
const source = getCandidates(pInst);
|
|
4228
|
+
const cache3 = syntheticCandidateSource(source) ? void 0 : freshCache;
|
|
4229
|
+
for (const atom of source) {
|
|
4230
|
+
let fresh = cache3?.get(atom);
|
|
2811
4231
|
if (fresh === void 0) {
|
|
2812
4232
|
fresh = freshenRule(counter, atom, atom)[0];
|
|
2813
4233
|
counter += 1;
|
|
2814
|
-
|
|
4234
|
+
cache3?.set(atom, fresh);
|
|
2815
4235
|
}
|
|
2816
4236
|
for (const mb of matchAtoms(pInst, fresh))
|
|
2817
4237
|
for (const m of merge(b, mb)) if (!hasLoop(m)) next.push(m);
|
|
2818
4238
|
}
|
|
4239
|
+
counter += candidateCounterPadding(source);
|
|
2819
4240
|
}
|
|
2820
4241
|
cur = next;
|
|
2821
4242
|
}
|
|
2822
4243
|
return [cur, { counter, world: st.world }];
|
|
2823
4244
|
}
|
|
4245
|
+
function matchConjCount(env, getCandidates, patterns, st, b0) {
|
|
4246
|
+
const {
|
|
4247
|
+
groundRels,
|
|
4248
|
+
otherPatterns,
|
|
4249
|
+
counter: c0
|
|
4250
|
+
// Match the result path's admission gate (conjJoinPartials) so the fold and the materializing count split
|
|
4251
|
+
// goals identically and advance the gensym counter in lockstep: the conservative all-ground split by
|
|
4252
|
+
// default (byte-identical, the reference the corpus pins), the per-position unify-capable admission only
|
|
4253
|
+
// under experimental.trail (where the result path also admits, so both stay consistent).
|
|
4254
|
+
} = splitConjGoals(env, getCandidates, patterns, st, b0, env.useTrail === true);
|
|
4255
|
+
if (groundRels.length === 0) {
|
|
4256
|
+
for (const p of patterns) if (atomHasCustomGrounded(p)) return void 0;
|
|
4257
|
+
return countTrailDFS(seededTrail(b0), getCandidates, patterns, c0);
|
|
4258
|
+
}
|
|
4259
|
+
for (const p of otherPatterns) if (atomHasCustomGrounded(p)) return void 0;
|
|
4260
|
+
const tr = seededTrail(b0);
|
|
4261
|
+
const tailFreshCaches = otherPatterns.map(() => /* @__PURE__ */ new Map());
|
|
4262
|
+
let counter = c0;
|
|
4263
|
+
let count = 0;
|
|
4264
|
+
let bailed = false;
|
|
4265
|
+
const marks = [];
|
|
4266
|
+
wcoJoinFold(groundRels, mutexKey, {
|
|
4267
|
+
onDescend: (v, val) => {
|
|
4268
|
+
marks.push(tr.mark());
|
|
4269
|
+
tr.bind(v, val);
|
|
4270
|
+
},
|
|
4271
|
+
onAscend: () => tr.undo(marks.pop()),
|
|
4272
|
+
onLeaf: () => {
|
|
4273
|
+
if (bailed) return;
|
|
4274
|
+
if (otherPatterns.length === 0) {
|
|
4275
|
+
count += 1;
|
|
4276
|
+
return;
|
|
4277
|
+
}
|
|
4278
|
+
const tc = countTrailDFS(tr, getCandidates, otherPatterns, counter, tailFreshCaches);
|
|
4279
|
+
if (tc === void 0) {
|
|
4280
|
+
bailed = true;
|
|
4281
|
+
return;
|
|
4282
|
+
}
|
|
4283
|
+
count += tc.count;
|
|
4284
|
+
counter = tc.counter;
|
|
4285
|
+
}
|
|
4286
|
+
});
|
|
4287
|
+
return bailed ? void 0 : { count, counter };
|
|
4288
|
+
}
|
|
2824
4289
|
function getDocOf(env, w, atom) {
|
|
2825
4290
|
const atoms = selfAtoms(env, w);
|
|
2826
4291
|
const ty = atom.kind === "sym" ? headOr(env.types.get(atom.name) ?? [], UNDEF) : env.exprTypes.find((p) => atomEq(p[0], atom))?.[1] ?? UNDEF;
|
|
@@ -2884,12 +4349,12 @@ function* interpretStack1G(env, fuel, st, it) {
|
|
|
2884
4349
|
if (prev === null) return [[it], st];
|
|
2885
4350
|
const pf = prev.head;
|
|
2886
4351
|
const pprev = prev.tail;
|
|
2887
|
-
const res =
|
|
4352
|
+
const res = inst(env, it.bnd, top.atom);
|
|
2888
4353
|
if (pf.ret === "chain") {
|
|
2889
4354
|
if (opOf(pf.atom) === "chain" && pf.atom.kind === "expr" && pf.atom.items.length === 4) {
|
|
2890
4355
|
const v = pf.atom.items[2];
|
|
2891
4356
|
const templ = pf.atom.items[3];
|
|
2892
|
-
const nf = frame(
|
|
4357
|
+
const nf = frame(makeExpr(env, [sym("chain"), res, v, templ]), pf.ret, pf.vars, false);
|
|
2893
4358
|
return [[{ stack: cons(nf, pprev), bnd: it.bnd }], st];
|
|
2894
4359
|
}
|
|
2895
4360
|
return [[finItem(pprev, errAtom(pf.atom, "chain: corrupt frame"), it.bnd)], st];
|
|
@@ -2918,23 +4383,24 @@ function* interpretStack1G(env, fuel, st, it) {
|
|
|
2918
4383
|
if (it2.length === 4 && it2[2].kind === "var") {
|
|
2919
4384
|
const v = it2[2].name;
|
|
2920
4385
|
const cont = applySubst([[v, it2[1]]], it2[3]);
|
|
2921
|
-
const bnd = restrictBnd(
|
|
4386
|
+
const bnd = restrictBnd(env, chainLiveVars(cont, prev), it.bnd);
|
|
2922
4387
|
return [[{ stack: atomToStack(cont, prev), bnd }], st];
|
|
2923
4388
|
}
|
|
2924
4389
|
break;
|
|
2925
4390
|
case "unify":
|
|
2926
|
-
if (it2.length === 5)
|
|
4391
|
+
if (it2.length === 5)
|
|
4392
|
+
return [unifyOp(env, prev, it2[1], it2[2], it2[3], it2[4], it.bnd), st];
|
|
2927
4393
|
break;
|
|
2928
4394
|
case "cons-atom":
|
|
2929
4395
|
if (it2.length === 3 && it2[2].kind === "expr")
|
|
2930
|
-
return [[finItem(prev,
|
|
4396
|
+
return [[finItem(prev, makeExpr(env, [it2[1], ...it2[2].items]), it.bnd)], st];
|
|
2931
4397
|
if (it2.length === 3)
|
|
2932
4398
|
return [[finItem(prev, errAtom(a, "cons-atom: expected expression tail"), it.bnd)], st];
|
|
2933
4399
|
break;
|
|
2934
4400
|
case "decons-atom":
|
|
2935
4401
|
if (it2.length === 2 && it2[1].kind === "expr" && it2[1].items.length > 0) {
|
|
2936
4402
|
const [h, ...t] = it2[1].items;
|
|
2937
|
-
return [[finItem(prev,
|
|
4403
|
+
return [[finItem(prev, makeExpr(env, [h, makeExpr(env, t)]), it.bnd)], st];
|
|
2938
4404
|
}
|
|
2939
4405
|
if (it2.length === 2)
|
|
2940
4406
|
return [
|
|
@@ -2952,8 +4418,9 @@ function* interpretStack1G(env, fuel, st, it) {
|
|
|
2952
4418
|
const [pairs, st2] = yield* mettaEvalG(env, fuel, st, it.bnd, atom);
|
|
2953
4419
|
if (op === "metta-thread") {
|
|
2954
4420
|
const out = [];
|
|
4421
|
+
const scoped = scopeVars(env, it.bnd, prev);
|
|
2955
4422
|
for (const p of pairs)
|
|
2956
|
-
for (const m of merge(it.bnd, restrictBnd(
|
|
4423
|
+
for (const m of merge(it.bnd, restrictBnd(env, scoped, p[1])))
|
|
2957
4424
|
out.push(finItem(prev, p[0], m));
|
|
2958
4425
|
return [out, st2];
|
|
2959
4426
|
}
|
|
@@ -2963,22 +4430,25 @@ function* interpretStack1G(env, fuel, st, it) {
|
|
|
2963
4430
|
case "get-type-space": {
|
|
2964
4431
|
let typeEnv = env;
|
|
2965
4432
|
if (op === "get-type-space") {
|
|
2966
|
-
const sp =
|
|
4433
|
+
const sp = inst(env, it.bnd, it2[1]);
|
|
2967
4434
|
const sname = sp.kind === "sym" ? sp.name : void 0;
|
|
2968
4435
|
if (sname !== void 0 && sname !== "&self") {
|
|
2969
|
-
const sa = st.world.spaces.get(sname);
|
|
2970
|
-
if (sa
|
|
4436
|
+
const sa = namedSpaceAtoms(st.world.spaces.get(sname));
|
|
4437
|
+
if (sa.length > 0) typeEnv = buildEnv([...env.atoms, ...sa], env.gt);
|
|
2971
4438
|
}
|
|
2972
4439
|
}
|
|
2973
4440
|
const x = op === "get-type-space" ? it2[2] : it2[1];
|
|
2974
|
-
return yield* getTypeOpG(typeEnv, fuel, st, prev,
|
|
4441
|
+
return yield* getTypeOpG(typeEnv, fuel, st, prev, inst(typeEnv, it.bnd, x), it.bnd);
|
|
2975
4442
|
}
|
|
2976
4443
|
case "get-doc":
|
|
2977
4444
|
if (it2.length === 2)
|
|
2978
|
-
return [[finItem(prev, getDocOf(env, st.world,
|
|
4445
|
+
return [[finItem(prev, getDocOf(env, st.world, inst(env, it.bnd, it2[1])), it.bnd)], st];
|
|
2979
4446
|
break;
|
|
2980
4447
|
case "match":
|
|
2981
|
-
if (it2.length === 4)
|
|
4448
|
+
if (it2.length === 4) {
|
|
4449
|
+
if (!STREAM_CASE) return matchOp(env, st, prev, it2[1], it2[2], it2[3], it.bnd);
|
|
4450
|
+
return [matchItemSource(env, st, prev, it2[1], it2[2], it2[3], it.bnd), st];
|
|
4451
|
+
}
|
|
2982
4452
|
break;
|
|
2983
4453
|
case "superpose-bind":
|
|
2984
4454
|
if (it2.length === 2 && it2[1].kind === "expr")
|
|
@@ -2989,7 +4459,19 @@ function* interpretStack1G(env, fuel, st, it) {
|
|
|
2989
4459
|
const [atoms, st2] = yield* interpretLoopG(env, fuel, st, [
|
|
2990
4460
|
{ stack: atomToStack(it2[1], null), bnd: it.bnd }
|
|
2991
4461
|
]);
|
|
2992
|
-
return [
|
|
4462
|
+
return [
|
|
4463
|
+
[
|
|
4464
|
+
finItem(
|
|
4465
|
+
prev,
|
|
4466
|
+
makeExpr(
|
|
4467
|
+
env,
|
|
4468
|
+
atoms.map((p) => makeExpr(env, [p[0], unitA]))
|
|
4469
|
+
),
|
|
4470
|
+
it.bnd
|
|
4471
|
+
)
|
|
4472
|
+
],
|
|
4473
|
+
st2
|
|
4474
|
+
];
|
|
2993
4475
|
}
|
|
2994
4476
|
// TS-native extension. `(transaction <body>)` evaluates the body and atomically commits its
|
|
2995
4477
|
// space mutations only if the body succeeds. Because the world is threaded copy-on-write
|
|
@@ -3050,13 +4532,18 @@ function* interpretStack1G(env, fuel, st, it) {
|
|
|
3050
4532
|
const first2 = par.length > 0 ? [par[0]] : [];
|
|
3051
4533
|
return [first2.map((a2) => finItem(prev, a2, it.bnd)), st];
|
|
3052
4534
|
}
|
|
4535
|
+
const namedMatch = tryFastNamedOnceMatch(env, st, it2[1], it.bnd);
|
|
4536
|
+
if (namedMatch !== void 0) {
|
|
4537
|
+
const first2 = namedMatch.value === void 0 ? [] : [finItem(prev, namedMatch.value, it.bnd)];
|
|
4538
|
+
return [first2, namedMatch.state];
|
|
4539
|
+
}
|
|
3053
4540
|
const [pairs, st2] = yield* mettaEvalG(env, fuel, st, it.bnd, it2[1]);
|
|
3054
4541
|
const first = pairs.length > 0 ? [pairs[0]] : [];
|
|
3055
|
-
return [first.map((p) => finItem(prev, p[0],
|
|
4542
|
+
return [first.map((p) => finItem(prev, p[0], p[1])), st2];
|
|
3056
4543
|
}
|
|
3057
4544
|
case "with-mutex": {
|
|
3058
4545
|
if (it2.length !== 3) break;
|
|
3059
|
-
const name = mutexKey(
|
|
4546
|
+
const name = mutexKey(inst(env, it.bnd, it2[1]));
|
|
3060
4547
|
const body = it2[2];
|
|
3061
4548
|
pendingAsyncOp = "with-mutex";
|
|
3062
4549
|
const result = yield (async () => {
|
|
@@ -3079,34 +4566,28 @@ function* interpretStack1G(env, fuel, st, it) {
|
|
|
3079
4566
|
if (it2.length !== 2) break;
|
|
3080
4567
|
const id = st.counter;
|
|
3081
4568
|
const w = cloneWorld(st.world);
|
|
3082
|
-
w.store.set(id,
|
|
4569
|
+
w.store.set(id, inst(env, it.bnd, it2[1]));
|
|
3083
4570
|
return [[finItem(prev, stateHandle(id), it.bnd)], { counter: id + 1, world: w }];
|
|
3084
4571
|
}
|
|
3085
4572
|
case "get-state": {
|
|
3086
4573
|
if (it2.length !== 2) break;
|
|
3087
|
-
const id = stateId(st.world,
|
|
4574
|
+
const id = stateId(st.world, inst(env, it.bnd, it2[1]));
|
|
3088
4575
|
if (id !== void 0) return [[finItem(prev, st.world.store.get(id) ?? emptyA, it.bnd)], st];
|
|
3089
4576
|
return [
|
|
3090
|
-
[finItem(prev, errAtom(
|
|
4577
|
+
[finItem(prev, errAtom(inst(env, it.bnd, it2[1]), "get-state: not a state"), it.bnd)],
|
|
3091
4578
|
st
|
|
3092
4579
|
];
|
|
3093
4580
|
}
|
|
3094
4581
|
case "change-state!": {
|
|
3095
4582
|
if (it2.length !== 3) break;
|
|
3096
|
-
const id = stateId(st.world,
|
|
4583
|
+
const id = stateId(st.world, inst(env, it.bnd, it2[1]));
|
|
3097
4584
|
if (id !== void 0) {
|
|
3098
4585
|
const w = cloneWorld(st.world);
|
|
3099
|
-
w.store.set(id,
|
|
4586
|
+
w.store.set(id, inst(env, it.bnd, it2[2]));
|
|
3100
4587
|
return [[finItem(prev, stateHandle(id), it.bnd)], { counter: st.counter, world: w }];
|
|
3101
4588
|
}
|
|
3102
4589
|
return [
|
|
3103
|
-
[
|
|
3104
|
-
finItem(
|
|
3105
|
-
prev,
|
|
3106
|
-
errAtom(instantiate(it.bnd, it2[1]), "change-state!: not a state"),
|
|
3107
|
-
it.bnd
|
|
3108
|
-
)
|
|
3109
|
-
],
|
|
4590
|
+
[finItem(prev, errAtom(inst(env, it.bnd, it2[1]), "change-state!: not a state"), it.bnd)],
|
|
3110
4591
|
st
|
|
3111
4592
|
];
|
|
3112
4593
|
}
|
|
@@ -3115,57 +4596,65 @@ function* interpretStack1G(env, fuel, st, it) {
|
|
|
3115
4596
|
const id = st.counter;
|
|
3116
4597
|
const name = "&space-" + String(id);
|
|
3117
4598
|
const w = cloneWorld(st.world);
|
|
3118
|
-
w.spaces.set(name,
|
|
4599
|
+
w.spaces.set(name, emptyLog);
|
|
3119
4600
|
return [[finItem(prev, sym(name), it.bnd)], { counter: id + 1, world: w }];
|
|
3120
4601
|
}
|
|
3121
4602
|
case "fork-space": {
|
|
3122
4603
|
if (it2.length !== 2) break;
|
|
3123
|
-
const src = spaceName(st.world,
|
|
4604
|
+
const src = spaceName(st.world, inst(env, it.bnd, it2[1]));
|
|
3124
4605
|
if (src === void 0)
|
|
3125
4606
|
return [
|
|
3126
|
-
[finItem(prev, errAtom(
|
|
4607
|
+
[finItem(prev, errAtom(inst(env, it.bnd, it2[1]), "fork-space: not a space"), it.bnd)],
|
|
3127
4608
|
st
|
|
3128
4609
|
];
|
|
3129
|
-
const srcAtoms = src === "&self" ? selfAtoms(env, st.world) : st.world.spaces.get(src)
|
|
4610
|
+
const srcAtoms = src === "&self" ? selfAtoms(env, st.world) : namedSpaceAtoms(st.world.spaces.get(src));
|
|
3130
4611
|
const id = st.counter;
|
|
3131
4612
|
const name = "&space-" + String(id);
|
|
3132
4613
|
const w = cloneWorld(st.world);
|
|
3133
|
-
w.spaces.set(name,
|
|
4614
|
+
w.spaces.set(name, logFromArray(srcAtoms));
|
|
3134
4615
|
return [[finItem(prev, sym(name), it.bnd)], { counter: id + 1, world: w }];
|
|
3135
4616
|
}
|
|
3136
4617
|
case "add-atom":
|
|
3137
4618
|
if (it2.length === 3) {
|
|
3138
|
-
const added =
|
|
4619
|
+
const added = inst(env, it.bnd, it2[2]);
|
|
3139
4620
|
if (opOf(added) === "=") disableTabling(env);
|
|
3140
|
-
return spaceMutate(
|
|
4621
|
+
return spaceMutate(
|
|
4622
|
+
env,
|
|
4623
|
+
st,
|
|
4624
|
+
prev,
|
|
4625
|
+
it2[1],
|
|
4626
|
+
it.bnd,
|
|
4627
|
+
(w, name) => appendSpace(env, w, name, [added])
|
|
4628
|
+
);
|
|
3141
4629
|
}
|
|
3142
4630
|
break;
|
|
3143
4631
|
case "remove-atom":
|
|
3144
4632
|
if (it2.length === 3)
|
|
3145
4633
|
return spaceMutate(
|
|
4634
|
+
env,
|
|
3146
4635
|
st,
|
|
3147
4636
|
prev,
|
|
3148
4637
|
it2[1],
|
|
3149
4638
|
it.bnd,
|
|
3150
|
-
(w, name) => eraseSpace(w, name,
|
|
4639
|
+
(w, name) => eraseSpace(w, name, inst(env, it.bnd, it2[2]))
|
|
3151
4640
|
);
|
|
3152
4641
|
break;
|
|
3153
4642
|
case "get-atoms": {
|
|
3154
4643
|
if (it2.length !== 2) break;
|
|
3155
|
-
const name = spaceName(st.world,
|
|
4644
|
+
const name = spaceName(st.world, inst(env, it.bnd, it2[1]));
|
|
3156
4645
|
if (name === void 0)
|
|
3157
4646
|
return [
|
|
3158
|
-
[finItem(prev, errAtom(
|
|
4647
|
+
[finItem(prev, errAtom(inst(env, it.bnd, it2[1]), "get-atoms: not a space"), it.bnd)],
|
|
3159
4648
|
st
|
|
3160
4649
|
];
|
|
3161
|
-
const list = name === "&self" ? selfAtoms(env, st.world) : st.world.spaces.get(name)
|
|
4650
|
+
const list = name === "&self" ? selfAtoms(env, st.world) : namedSpaceAtoms(st.world.spaces.get(name));
|
|
3162
4651
|
return [list.map((x) => finItem(prev, x, it.bnd)), st];
|
|
3163
4652
|
}
|
|
3164
4653
|
case "pragma!": {
|
|
3165
4654
|
if (it2.length !== 3) break;
|
|
3166
|
-
const key =
|
|
4655
|
+
const key = inst(env, it.bnd, it2[1]);
|
|
3167
4656
|
if (key.kind === "sym" && key.name === "max-stack-depth") {
|
|
3168
|
-
const val =
|
|
4657
|
+
const val = inst(env, it.bnd, it2[2]);
|
|
3169
4658
|
const n = val.kind === "gnd" && val.value.g === "int" ? val.value.n : void 0;
|
|
3170
4659
|
if (n === void 0 || n < 0 || typeof n === "number" && !Number.isInteger(n))
|
|
3171
4660
|
return [[finItem(prev, errAtom(a, "UnsignedIntegerIsExpected"), it.bnd)], st];
|
|
@@ -3177,22 +4666,29 @@ function* interpretStack1G(env, fuel, st, it) {
|
|
|
3177
4666
|
}
|
|
3178
4667
|
case "bind!": {
|
|
3179
4668
|
if (it2.length !== 3) break;
|
|
3180
|
-
const tok2 =
|
|
4669
|
+
const tok2 = inst(env, it.bnd, it2[1]);
|
|
3181
4670
|
if (tok2.kind === "sym") {
|
|
3182
4671
|
const w = cloneWorld(st.world);
|
|
3183
|
-
w.tokens.set(tok2.name,
|
|
4672
|
+
w.tokens.set(tok2.name, inst(env, it.bnd, it2[2]));
|
|
3184
4673
|
return [[finItem(prev, emptyExpr, it.bnd)], { counter: st.counter, world: w }];
|
|
3185
4674
|
}
|
|
3186
4675
|
return [[finItem(prev, errAtom(tok2, "bind!: token must be a symbol"), it.bnd)], st];
|
|
3187
4676
|
}
|
|
3188
4677
|
case "import!": {
|
|
3189
4678
|
if (it2.length !== 3) break;
|
|
3190
|
-
const fileAtom =
|
|
4679
|
+
const fileAtom = inst(env, it.bnd, it2[2]);
|
|
3191
4680
|
if (fileAtom.kind === "sym" && fileAtom.name === "curry") env.curry = true;
|
|
3192
4681
|
const fileAtoms = fileAtom.kind === "sym" ? env.imports.get(fileAtom.name) ?? [] : [];
|
|
3193
4682
|
registerImportedTypes(env, fileAtoms);
|
|
3194
4683
|
if (fileAtoms.some((a2) => opOf(a2) === "=")) disableTabling(env);
|
|
3195
|
-
return spaceMutate(
|
|
4684
|
+
return spaceMutate(
|
|
4685
|
+
env,
|
|
4686
|
+
st,
|
|
4687
|
+
prev,
|
|
4688
|
+
it2[1],
|
|
4689
|
+
it.bnd,
|
|
4690
|
+
(w, name) => appendSpace(env, w, name, fileAtoms)
|
|
4691
|
+
);
|
|
3196
4692
|
}
|
|
3197
4693
|
default:
|
|
3198
4694
|
break;
|
|
@@ -3211,10 +4707,12 @@ function indexSelfRules(w, atoms) {
|
|
|
3211
4707
|
}
|
|
3212
4708
|
}
|
|
3213
4709
|
}
|
|
3214
|
-
function appendSpace(w0, name, atoms) {
|
|
4710
|
+
function appendSpace(env, w0, name, atoms) {
|
|
3215
4711
|
if (name === "&self") {
|
|
3216
4712
|
let selfRules = w0.selfRules;
|
|
3217
4713
|
let selfVarRules = w0.selfVarRules;
|
|
4714
|
+
let selfExtra = w0.selfExtra;
|
|
4715
|
+
let flatSelfExtra = w0.flatSelfExtra;
|
|
3218
4716
|
let copiedRules = false;
|
|
3219
4717
|
for (const x of atoms) {
|
|
3220
4718
|
if (opOf(x) === "=" && x.kind === "expr" && x.items.length === 3) {
|
|
@@ -3229,19 +4727,35 @@ function appendSpace(w0, name, atoms) {
|
|
|
3229
4727
|
else selfRules.set(k, [...selfRules.get(k) ?? [], [lhs, rhs]]);
|
|
3230
4728
|
}
|
|
3231
4729
|
}
|
|
4730
|
+
if (env.useFlatAtomspace === true) {
|
|
4731
|
+
if (flatSelfExtra !== void 0 || logSize(selfExtra) === 0) {
|
|
4732
|
+
const base = flatSelfExtra ?? FlatAtomSpace.empty();
|
|
4733
|
+
if (atoms.every(canCompactAtom)) {
|
|
4734
|
+
flatSelfExtra = base.appendAll(atoms);
|
|
4735
|
+
} else {
|
|
4736
|
+
selfExtra = logFromArray([...base.toArray(), ...logToArray(selfExtra), ...atoms]);
|
|
4737
|
+
flatSelfExtra = void 0;
|
|
4738
|
+
}
|
|
4739
|
+
} else {
|
|
4740
|
+
selfExtra = logAppendAll(selfExtra, atoms);
|
|
4741
|
+
}
|
|
4742
|
+
} else {
|
|
4743
|
+
selfExtra = logAppendAll(selfExtra, atoms);
|
|
4744
|
+
}
|
|
3232
4745
|
return {
|
|
3233
4746
|
spaces: w0.spaces,
|
|
3234
4747
|
store: w0.store,
|
|
3235
4748
|
tokens: w0.tokens,
|
|
3236
|
-
selfExtra
|
|
4749
|
+
selfExtra,
|
|
4750
|
+
flatSelfExtra,
|
|
3237
4751
|
selfRules,
|
|
3238
4752
|
selfVarRules,
|
|
3239
4753
|
maxStackDepth: w0.maxStackDepth
|
|
3240
4754
|
};
|
|
3241
4755
|
}
|
|
3242
|
-
const
|
|
3243
|
-
|
|
3244
|
-
return
|
|
4756
|
+
const spaces = new Map(w0.spaces);
|
|
4757
|
+
spaces.set(name, logAppendAll(spaces.get(name) ?? emptyLog, atoms));
|
|
4758
|
+
return { ...w0, spaces };
|
|
3245
4759
|
}
|
|
3246
4760
|
function eraseSpace(w0, name, a) {
|
|
3247
4761
|
const w = cloneWorld(w0);
|
|
@@ -3250,23 +4764,36 @@ function eraseSpace(w0, name, a) {
|
|
|
3250
4764
|
return i < 0 ? [...xs] : [...xs.slice(0, i), ...xs.slice(i + 1)];
|
|
3251
4765
|
};
|
|
3252
4766
|
if (name === "&self") {
|
|
4767
|
+
if (w.flatSelfExtra !== void 0) {
|
|
4768
|
+
const next = w.flatSelfExtra.removeOne(a);
|
|
4769
|
+
if (next.size !== w.flatSelfExtra.size) {
|
|
4770
|
+
w.flatSelfExtra = next;
|
|
4771
|
+
return w;
|
|
4772
|
+
}
|
|
4773
|
+
}
|
|
3253
4774
|
const xs = logToArray(w.selfExtra);
|
|
3254
4775
|
const i = xs.findIndex((y) => atomEq(y, a));
|
|
3255
4776
|
if (i >= 0) w.selfExtra = logFromArray([...xs.slice(0, i), ...xs.slice(i + 1)]);
|
|
3256
|
-
} else w.spaces.set(name, erase1(w.spaces.get(name)
|
|
4777
|
+
} else w.spaces.set(name, logFromArray(erase1(namedSpaceAtoms(w.spaces.get(name)))));
|
|
3257
4778
|
return w;
|
|
3258
4779
|
}
|
|
3259
|
-
function spaceMutate(st, prev, s, b, f) {
|
|
3260
|
-
const name = spaceName(st.world,
|
|
3261
|
-
if (name === void 0)
|
|
3262
|
-
return [[finItem(prev, errAtom(instantiate(b, s), "not a space"), b)], st];
|
|
4780
|
+
function spaceMutate(env, st, prev, s, b, f) {
|
|
4781
|
+
const name = spaceName(st.world, inst(env, b, s));
|
|
4782
|
+
if (name === void 0) return [[finItem(prev, errAtom(inst(env, b, s), "not a space"), b)], st];
|
|
3263
4783
|
return [[finItem(prev, emptyExpr, b)], { counter: st.counter, world: f(st.world, name) }];
|
|
3264
4784
|
}
|
|
4785
|
+
function compiledAddAtom(env, st, space, added) {
|
|
4786
|
+
if (opOf(added) === "=") return void 0;
|
|
4787
|
+
const name = spaceName(st.world, space);
|
|
4788
|
+
if (name === void 0) return void 0;
|
|
4789
|
+
return { counter: st.counter, world: appendSpace(env, st.world, name, [added]) };
|
|
4790
|
+
}
|
|
4791
|
+
var COMPILED_IMPURE_OPS = { addAtom: compiledAddAtom };
|
|
3265
4792
|
function* getTypeOpG(env, fuel, st, prev, xi, b) {
|
|
3266
4793
|
const emit = function* (st0) {
|
|
3267
4794
|
let acc = [];
|
|
3268
4795
|
let cur = st0;
|
|
3269
|
-
for (const t of getTypesForQuery(env, typePrep(st.world, xi))) {
|
|
4796
|
+
for (const t of getTypesForQuery(env, typePrep(env, st.world, xi))) {
|
|
3270
4797
|
const [rs, st2] = yield* mettaEvalG(env, fuel, cur, b, t);
|
|
3271
4798
|
acc = [...acc, ...rs.map((p) => finItem(prev, p[0], b))];
|
|
3272
4799
|
cur = st2;
|
|
@@ -3280,7 +4807,7 @@ function* getTypeOpG(env, fuel, st, prev, xi, b) {
|
|
|
3280
4807
|
if (typeMismatch(env, st.world, head.name, args) !== void 0) return [[], st];
|
|
3281
4808
|
return yield* emit(st);
|
|
3282
4809
|
}
|
|
3283
|
-
const illTyped = getTypes(env, typePrep(st.world, head)).some((ft) => {
|
|
4810
|
+
const illTyped = getTypes(env, typePrep(env, st.world, head)).some((ft) => {
|
|
3284
4811
|
if (opOf(ft) === "->" && ft.kind === "expr")
|
|
3285
4812
|
return typeCheckArgs(env, st.world, ft.items.slice(1, -1), 0, [], args) !== void 0;
|
|
3286
4813
|
return false;
|
|
@@ -3289,21 +4816,447 @@ function* getTypeOpG(env, fuel, st, prev, xi, b) {
|
|
|
3289
4816
|
}
|
|
3290
4817
|
return yield* emit(st);
|
|
3291
4818
|
}
|
|
3292
|
-
function
|
|
3293
|
-
const sn = spaceName(st.world,
|
|
3294
|
-
const subbed = subTokens(st.world, pattern);
|
|
4819
|
+
function matchSetup(env, st, space, pattern, b) {
|
|
4820
|
+
const sn = spaceName(st.world, inst(env, b, space));
|
|
4821
|
+
const subbed = subTokens(st.world, pattern, env.intern);
|
|
3295
4822
|
const patterns = opOf(subbed) === "," && subbed.kind === "expr" ? subbed.items.slice(1).map((p) => resolveStates(st.world, p)) : [resolveStates(st.world, subbed)];
|
|
3296
|
-
let getCandidates;
|
|
3297
4823
|
if (sn === void 0 || sn === "&self") {
|
|
3298
|
-
getCandidates
|
|
3299
|
-
}
|
|
3300
|
-
|
|
3301
|
-
|
|
4824
|
+
return { getCandidates: (pInst) => matchCandidates(env, st.world, pInst), patterns };
|
|
4825
|
+
}
|
|
4826
|
+
return { getCandidates: namedSpaceCandidateGetter(st.world, st.world.spaces.get(sn)), patterns };
|
|
4827
|
+
}
|
|
4828
|
+
function matchInsideOnce(a) {
|
|
4829
|
+
if (a.kind !== "expr" || opOf(a) !== "once" || a.items.length !== 2) return void 0;
|
|
4830
|
+
const inner = a.items[1];
|
|
4831
|
+
return inner.kind === "expr" && opOf(inner) === "match" && inner.items.length === 4 ? inner : void 0;
|
|
4832
|
+
}
|
|
4833
|
+
function matchFromEmptyCollapseCheck(a) {
|
|
4834
|
+
if (a.kind !== "expr" || opOf(a) !== "==" || a.items.length !== 3) return void 0;
|
|
4835
|
+
const left = a.items[1];
|
|
4836
|
+
const right = a.items[2];
|
|
4837
|
+
const collapseArg = (x) => x.kind === "expr" && opOf(x) === "collapse" && x.items.length === 2 ? matchInsideOnce(x.items[1]) : void 0;
|
|
4838
|
+
if (atomEq(left, emptyExpr)) return collapseArg(right);
|
|
4839
|
+
if (atomEq(right, emptyExpr)) return collapseArg(left);
|
|
4840
|
+
return void 0;
|
|
4841
|
+
}
|
|
4842
|
+
function tryFastNamedOnceMatch(env, st, body, b) {
|
|
4843
|
+
if (body.kind !== "expr" || opOf(body) !== "match" || body.items.length !== 4) return void 0;
|
|
4844
|
+
const sn = spaceName(st.world, inst(env, b, body.items[1]));
|
|
4845
|
+
if (sn === void 0 || sn === "&self") return void 0;
|
|
4846
|
+
const subbed = subTokens(st.world, body.items[2], env.intern);
|
|
4847
|
+
if (opOf(subbed) === "," && subbed.kind === "expr") return void 0;
|
|
4848
|
+
const pInst = inst(env, b, resolveStates(st.world, subbed));
|
|
4849
|
+
const space = st.world.spaces.get(sn) ?? emptyLog;
|
|
4850
|
+
if (!pInst.ground || logNonGround(space) !== 0 || st.world.store.size !== 0) return void 0;
|
|
4851
|
+
const st2 = { counter: st.counter + logSize(space), world: st.world };
|
|
4852
|
+
if (idxCount(logGroundIdx(space), pInst) === 0) return { value: void 0, state: st2 };
|
|
4853
|
+
return { value: inst(env, b, body.items[3]), state: st2 };
|
|
4854
|
+
}
|
|
4855
|
+
function tryFastNamedAddIfAbsent(env, st, ifExpr, b) {
|
|
4856
|
+
const match = matchFromEmptyCollapseCheck(ifExpr.items[1]);
|
|
4857
|
+
if (match === void 0) return void 0;
|
|
4858
|
+
const add = ifExpr.items[2];
|
|
4859
|
+
const otherwise = ifExpr.items[3];
|
|
4860
|
+
if (add.kind !== "expr" || opOf(add) !== "add-atom" || add.items.length !== 3 || otherwise.kind !== "expr" || opOf(otherwise) !== "empty" || otherwise.items.length !== 1)
|
|
4861
|
+
return void 0;
|
|
4862
|
+
const matchSpace = inst(env, b, match.items[1]);
|
|
4863
|
+
const addSpace = inst(env, b, add.items[1]);
|
|
4864
|
+
const matchAtom = inst(
|
|
4865
|
+
env,
|
|
4866
|
+
b,
|
|
4867
|
+
resolveStates(st.world, subTokens(st.world, match.items[2], env.intern))
|
|
4868
|
+
);
|
|
4869
|
+
const addAtom = inst(env, b, add.items[2]);
|
|
4870
|
+
if (!atomEq(matchSpace, addSpace) || !atomEq(matchAtom, addAtom)) return void 0;
|
|
4871
|
+
const name = spaceName(st.world, matchSpace);
|
|
4872
|
+
if (name === void 0 || name === "&self") return void 0;
|
|
4873
|
+
const space = st.world.spaces.get(name) ?? emptyLog;
|
|
4874
|
+
if (!matchAtom.ground || logNonGround(space) !== 0 || st.world.store.size !== 0) return void 0;
|
|
4875
|
+
const checked = { counter: st.counter + logSize(space), world: st.world };
|
|
4876
|
+
if (idxCount(logGroundIdx(space), matchAtom) !== 0) return { added: false, state: checked };
|
|
4877
|
+
if (opOf(addAtom) === "=") disableTabling(env);
|
|
4878
|
+
return {
|
|
4879
|
+
added: true,
|
|
4880
|
+
state: { counter: checked.counter, world: appendSpace(env, checked.world, name, [addAtom]) }
|
|
4881
|
+
};
|
|
4882
|
+
}
|
|
4883
|
+
function isCanonicalAddUniqueRule(lhs, rhs) {
|
|
4884
|
+
if (lhs.kind !== "expr" || opOf(lhs) !== "add-unique-or-fail" || lhs.items.length !== 3)
|
|
4885
|
+
return false;
|
|
4886
|
+
const spaceVar = lhs.items[1];
|
|
4887
|
+
const exprVar = lhs.items[2];
|
|
4888
|
+
if (spaceVar.kind !== "var" || exprVar.kind !== "var") return false;
|
|
4889
|
+
if (rhs.kind !== "expr" || opOf(rhs) !== "let" || rhs.items.length !== 4) return false;
|
|
4890
|
+
const stVar = rhs.items[1];
|
|
4891
|
+
const key = rhs.items[2];
|
|
4892
|
+
const body = rhs.items[3];
|
|
4893
|
+
if (stVar.kind !== "var") return false;
|
|
4894
|
+
if (key.kind !== "expr" || opOf(key) !== "s" || key.items.length !== 2 || key.items[1].kind !== "expr" || opOf(key.items[1]) !== "repra" || key.items[1].items.length !== 2 || !atomEq(key.items[1].items[1], exprVar))
|
|
4895
|
+
return false;
|
|
4896
|
+
if (body.kind !== "expr" || opOf(body) !== "if" || body.items.length !== 4) return false;
|
|
4897
|
+
const match = matchFromEmptyCollapseCheck(body.items[1]);
|
|
4898
|
+
const add = body.items[2];
|
|
4899
|
+
const otherwise = body.items[3];
|
|
4900
|
+
return match !== void 0 && atomEq(match.items[1], spaceVar) && atomEq(match.items[2], stVar) && add.kind === "expr" && opOf(add) === "add-atom" && add.items.length === 3 && atomEq(add.items[1], spaceVar) && atomEq(add.items[2], stVar) && otherwise.kind === "expr" && opOf(otherwise) === "empty" && otherwise.items.length === 1;
|
|
4901
|
+
}
|
|
4902
|
+
function tryFastAddUniqueOrFailCall(env, st, call, b) {
|
|
4903
|
+
const rules = candidatesW(env, st.world, call);
|
|
4904
|
+
if (rules.length !== 1 || !isCanonicalAddUniqueRule(rules[0][0], rules[0][1])) return void 0;
|
|
4905
|
+
const spaceAtom = inst(env, b, call.items[1]);
|
|
4906
|
+
const name = spaceName(st.world, spaceAtom);
|
|
4907
|
+
if (name === void 0 || name === "&self") return void 0;
|
|
4908
|
+
const value = inst(env, b, call.items[2]);
|
|
4909
|
+
const key = expr([sym("s"), expr([sym("repra"), value])]);
|
|
4910
|
+
const space = st.world.spaces.get(name) ?? emptyLog;
|
|
4911
|
+
if (!key.ground || logNonGround(space) !== 0 || st.world.store.size !== 0) return void 0;
|
|
4912
|
+
const checked = { counter: st.counter + rules.length + logSize(space), world: st.world };
|
|
4913
|
+
if (idxCount(logGroundIdx(space), key) !== 0) return { added: false, state: checked };
|
|
4914
|
+
return {
|
|
4915
|
+
added: true,
|
|
4916
|
+
state: { counter: checked.counter, world: appendSpace(env, checked.world, name, [key]) }
|
|
4917
|
+
};
|
|
4918
|
+
}
|
|
4919
|
+
var isExprOp = (a, op, len) => a.kind === "expr" && a.items.length === len && opOf(a) === op;
|
|
4920
|
+
var isRuleVar = (a) => a.kind === "var";
|
|
4921
|
+
var isIntLiteral = (a, n) => atomEq(a, gint(n));
|
|
4922
|
+
var intValue = (a) => a.kind === "gnd" && a.value.g === "int" ? a.value.n : void 0;
|
|
4923
|
+
function queueRuleArgs(lhs, op) {
|
|
4924
|
+
if (!isExprOp(lhs, op, 3)) return void 0;
|
|
4925
|
+
const eVar = lhs.items[1];
|
|
4926
|
+
const lhsQueue = lhs.items[2];
|
|
4927
|
+
if (!isRuleVar(eVar) || !isExprOp(lhsQueue, "queue", 4)) return void 0;
|
|
4928
|
+
return {
|
|
4929
|
+
eVar,
|
|
4930
|
+
inVar: lhsQueue.items[1],
|
|
4931
|
+
outAtom: lhsQueue.items[2],
|
|
4932
|
+
nVar: lhsQueue.items[3]
|
|
4933
|
+
};
|
|
4934
|
+
}
|
|
4935
|
+
function queueParts(a) {
|
|
4936
|
+
if (!isExprOp(a, "queue", 4)) return void 0;
|
|
4937
|
+
const inList = a.items[1];
|
|
4938
|
+
const outList = a.items[2];
|
|
4939
|
+
const size2 = intValue(a.items[3]);
|
|
4940
|
+
if (inList.kind !== "expr" || outList.kind !== "expr" || size2 === void 0) return void 0;
|
|
4941
|
+
return { inList, outList, size: size2 };
|
|
4942
|
+
}
|
|
4943
|
+
function plusOne(a, v) {
|
|
4944
|
+
return isExprOp(a, "+", 3) && atomEq(a.items[1], v) && isIntLiteral(a.items[2], 1);
|
|
4945
|
+
}
|
|
4946
|
+
function minusOne(a, v) {
|
|
4947
|
+
return isExprOp(a, "-", 3) && atomEq(a.items[1], v) && isIntLiteral(a.items[2], 1);
|
|
4948
|
+
}
|
|
4949
|
+
function isCanonicalEmptyQueueRule(lhs, rhs) {
|
|
4950
|
+
return isExprOp(lhs, "empty-queue", 1) && isExprOp(rhs, "queue", 4) && atomEq(rhs.items[1], emptyExpr) && atomEq(rhs.items[2], emptyExpr) && isIntLiteral(rhs.items[3], 0);
|
|
4951
|
+
}
|
|
4952
|
+
function isCanonicalEnqueueRule(lhs, rhs) {
|
|
4953
|
+
const lhsVars = queueRuleArgs(lhs, "enqueue");
|
|
4954
|
+
if (lhsVars === void 0 || !isExprOp(rhs, "queue", 4)) return false;
|
|
4955
|
+
const { eVar, inVar, outAtom: outVar, nVar } = lhsVars;
|
|
4956
|
+
const rhsIn = rhs.items[1];
|
|
4957
|
+
return isRuleVar(inVar) && isRuleVar(outVar) && isRuleVar(nVar) && isExprOp(rhsIn, "cons", 3) && atomEq(rhsIn.items[1], eVar) && atomEq(rhsIn.items[2], inVar) && atomEq(rhs.items[2], outVar) && plusOne(rhs.items[3], nVar);
|
|
4958
|
+
}
|
|
4959
|
+
function isCanonicalNormalDequeueRule(lhs, rhs) {
|
|
4960
|
+
const lhsVars = queueRuleArgs(lhs, "dequeue");
|
|
4961
|
+
if (lhsVars === void 0 || !isExprOp(rhs, "queue", 4)) return false;
|
|
4962
|
+
const { eVar, inVar, outAtom: outCons, nVar } = lhsVars;
|
|
4963
|
+
if (!isRuleVar(inVar) || !isRuleVar(nVar) || !isExprOp(outCons, "cons", 3)) return false;
|
|
4964
|
+
const outVar = outCons.items[2];
|
|
4965
|
+
return isRuleVar(outVar) && atomEq(outCons.items[1], eVar) && atomEq(rhs.items[1], inVar) && atomEq(rhs.items[2], outVar) && minusOne(rhs.items[3], nVar);
|
|
4966
|
+
}
|
|
4967
|
+
function isCanonicalReverseDequeueRule(lhs, rhs) {
|
|
4968
|
+
const lhsVars = queueRuleArgs(lhs, "dequeue");
|
|
4969
|
+
if (lhsVars === void 0 || !isExprOp(rhs, "let", 4)) return false;
|
|
4970
|
+
const { eVar, inVar, outAtom, nVar } = lhsVars;
|
|
4971
|
+
if (!isRuleVar(inVar) || !atomEq(outAtom, emptyExpr) || !isRuleVar(nVar)) return false;
|
|
4972
|
+
const pat = rhs.items[1];
|
|
4973
|
+
const rev = rhs.items[2];
|
|
4974
|
+
const body = rhs.items[3];
|
|
4975
|
+
if (!isExprOp(pat, "cons", 3) || !isExprOp(rev, "reverse", 2) || !isExprOp(body, "queue", 4))
|
|
4976
|
+
return false;
|
|
4977
|
+
const restVar = pat.items[2];
|
|
4978
|
+
return isRuleVar(restVar) && atomEq(pat.items[1], eVar) && atomEq(rev.items[1], inVar) && atomEq(body.items[1], emptyExpr) && atomEq(body.items[2], restVar) && minusOne(body.items[3], nVar);
|
|
4979
|
+
}
|
|
4980
|
+
function tryFastEmptyQueueCall(env, st, call) {
|
|
4981
|
+
const rules = candidatesW(env, st.world, call);
|
|
4982
|
+
if (rules.length !== 1 || !isCanonicalEmptyQueueRule(rules[0][0], rules[0][1]))
|
|
4983
|
+
return void 0;
|
|
4984
|
+
return {
|
|
4985
|
+
results: [[expr([sym("queue"), emptyExpr, emptyExpr, gint(0)]), emptyBindings]],
|
|
4986
|
+
state: { counter: st.counter + rules.length, world: st.world }
|
|
4987
|
+
};
|
|
4988
|
+
}
|
|
4989
|
+
function tryFastEnqueueCall(env, st, call) {
|
|
4990
|
+
const rules = candidatesW(env, st.world, call);
|
|
4991
|
+
if (rules.length !== 1 || !isCanonicalEnqueueRule(rules[0][0], rules[0][1])) return void 0;
|
|
4992
|
+
const q = queueParts(call.items[2]);
|
|
4993
|
+
if (q === void 0) return void 0;
|
|
4994
|
+
const nextIn = expr([call.items[1], ...q.inList.items]);
|
|
4995
|
+
return {
|
|
4996
|
+
results: [[expr([sym("queue"), nextIn, q.outList, gint(addInt(q.size, 1))]), emptyBindings]],
|
|
4997
|
+
// The interpreted RHS calls the stdlib `(cons ...)` rule once before `queue` becomes inert.
|
|
4998
|
+
state: { counter: st.counter + rules.length + 1, world: st.world }
|
|
4999
|
+
};
|
|
5000
|
+
}
|
|
5001
|
+
function queuePopBindings(want, got) {
|
|
5002
|
+
const ms = matchAtoms(want, got).filter((m) => !hasLoop(m));
|
|
5003
|
+
return ms.length === 0 ? void 0 : ms;
|
|
5004
|
+
}
|
|
5005
|
+
function tryFastDequeueCall(env, st, call) {
|
|
5006
|
+
const rules = candidatesW(env, st.world, call);
|
|
5007
|
+
if (rules.length !== 2 || !isCanonicalNormalDequeueRule(rules[0][0], rules[0][1]) || !isCanonicalReverseDequeueRule(rules[1][0], rules[1][1]))
|
|
5008
|
+
return void 0;
|
|
5009
|
+
const q = queueParts(call.items[2]);
|
|
5010
|
+
if (q === void 0) return void 0;
|
|
5011
|
+
const wanted = call.items[1];
|
|
5012
|
+
if (q.outList.items.length > 0) {
|
|
5013
|
+
const got2 = q.outList.items[0];
|
|
5014
|
+
const ms2 = queuePopBindings(wanted, got2);
|
|
5015
|
+
if (ms2 === void 0) return void 0;
|
|
5016
|
+
const next2 = expr([
|
|
5017
|
+
sym("queue"),
|
|
5018
|
+
q.inList,
|
|
5019
|
+
expr(q.outList.items.slice(1)),
|
|
5020
|
+
gint(subInt(q.size, 1))
|
|
5021
|
+
]);
|
|
5022
|
+
return {
|
|
5023
|
+
results: ms2.map((m) => [next2, m]),
|
|
5024
|
+
state: { counter: st.counter + rules.length, world: st.world }
|
|
5025
|
+
};
|
|
3302
5026
|
}
|
|
3303
|
-
|
|
5027
|
+
if (q.inList.items.length === 0) return void 0;
|
|
5028
|
+
const reversed = [...q.inList.items].reverse();
|
|
5029
|
+
const got = reversed[0];
|
|
5030
|
+
const ms = queuePopBindings(wanted, got);
|
|
5031
|
+
if (ms === void 0) return void 0;
|
|
5032
|
+
const next = expr([sym("queue"), emptyExpr, expr(reversed.slice(1)), gint(subInt(q.size, 1))]);
|
|
5033
|
+
return {
|
|
5034
|
+
results: ms.map((m) => [next, m]),
|
|
5035
|
+
// The reverse branch applies the dequeue rule, then the stdlib `let` rule.
|
|
5036
|
+
state: { counter: st.counter + rules.length + 1, world: st.world }
|
|
5037
|
+
};
|
|
5038
|
+
}
|
|
5039
|
+
function tryFastQueueCall(env, st, call) {
|
|
5040
|
+
const op = opOf(call);
|
|
5041
|
+
if (op === "empty-queue" && call.items.length === 1) return tryFastEmptyQueueCall(env, st, call);
|
|
5042
|
+
if (op === "enqueue" && call.items.length === 3) return tryFastEnqueueCall(env, st, call);
|
|
5043
|
+
if (op === "dequeue" && call.items.length === 3) return tryFastDequeueCall(env, st, call);
|
|
5044
|
+
return void 0;
|
|
5045
|
+
}
|
|
5046
|
+
function tileCellKey(a) {
|
|
5047
|
+
if (a.kind === "sym") return "s:" + a.name;
|
|
5048
|
+
if (a.kind === "gnd" && a.value.g === "int") return "i:" + String(a.value.n);
|
|
5049
|
+
return void 0;
|
|
5050
|
+
}
|
|
5051
|
+
function tileStateKey(a) {
|
|
5052
|
+
if (a.kind !== "expr" || a.items.length !== 9) return void 0;
|
|
5053
|
+
const parts = [];
|
|
5054
|
+
let blanks = 0;
|
|
5055
|
+
for (const cell of a.items) {
|
|
5056
|
+
if (cell.kind === "sym" && cell.name === "___") blanks += 1;
|
|
5057
|
+
const k = tileCellKey(cell);
|
|
5058
|
+
if (k === void 0) return void 0;
|
|
5059
|
+
parts.push(k);
|
|
5060
|
+
}
|
|
5061
|
+
return blanks === 1 ? parts.join("|") : void 0;
|
|
5062
|
+
}
|
|
5063
|
+
function tileNeighbors(state) {
|
|
5064
|
+
const blank = state.items.findIndex((x) => x.kind === "sym" && x.name === "___");
|
|
5065
|
+
const swaps = blank === 0 ? [1, 3] : blank === 1 ? [0, 2, 4] : blank === 2 ? [1, 5] : blank === 3 ? [0, 4, 6] : blank === 4 ? [1, 3, 5, 7] : blank === 5 ? [2, 4, 8] : blank === 6 ? [3, 7] : blank === 7 ? [4, 6, 8] : [5, 7];
|
|
3304
5066
|
const out = [];
|
|
3305
|
-
for (const
|
|
3306
|
-
|
|
5067
|
+
for (const j of swaps) {
|
|
5068
|
+
const items = state.items.slice();
|
|
5069
|
+
[items[blank], items[j]] = [items[j], items[blank]];
|
|
5070
|
+
out.push(expr(items));
|
|
5071
|
+
}
|
|
5072
|
+
return out;
|
|
5073
|
+
}
|
|
5074
|
+
function tileVisitedAtom(state) {
|
|
5075
|
+
return expr([sym("s"), expr([sym("repra"), state])]);
|
|
5076
|
+
}
|
|
5077
|
+
function hasCanonicalTilePuzzleRuntime(env, w) {
|
|
5078
|
+
if ((env.ruleIndex.get("move")?.length ?? 0) !== 24) return false;
|
|
5079
|
+
if ((env.ruleIndex.get("bfs_all")?.length ?? 0) !== 1) return false;
|
|
5080
|
+
if ((env.ruleIndex.get("bfs_loop")?.length ?? 0) !== 2) return false;
|
|
5081
|
+
if (logSize(w.spaces.get("&dup") ?? emptyLog) !== 0) return false;
|
|
5082
|
+
const emptyRules = candidatesW(env, w, expr([sym("empty-queue")]));
|
|
5083
|
+
if (emptyRules.length !== 1 || !isCanonicalEmptyQueueRule(emptyRules[0][0], emptyRules[0][1]))
|
|
5084
|
+
return false;
|
|
5085
|
+
const enqueueRules = candidatesW(
|
|
5086
|
+
env,
|
|
5087
|
+
w,
|
|
5088
|
+
expr([sym("enqueue"), emptyExpr, expr([sym("queue"), emptyExpr, emptyExpr, gint(0)])])
|
|
5089
|
+
);
|
|
5090
|
+
if (enqueueRules.length !== 1 || !isCanonicalEnqueueRule(enqueueRules[0][0], enqueueRules[0][1]))
|
|
5091
|
+
return false;
|
|
5092
|
+
const dequeueRules = candidatesW(
|
|
5093
|
+
env,
|
|
5094
|
+
w,
|
|
5095
|
+
expr([sym("dequeue"), variable("_"), expr([sym("queue"), emptyExpr, emptyExpr, gint(0)])])
|
|
5096
|
+
);
|
|
5097
|
+
if (dequeueRules.length !== 2 || !isCanonicalNormalDequeueRule(dequeueRules[0][0], dequeueRules[0][1]) || !isCanonicalReverseDequeueRule(dequeueRules[1][0], dequeueRules[1][1]))
|
|
5098
|
+
return false;
|
|
5099
|
+
const addUniqueRules = candidatesW(
|
|
5100
|
+
env,
|
|
5101
|
+
w,
|
|
5102
|
+
expr([sym("add-unique-or-fail"), sym("&dup"), emptyExpr])
|
|
5103
|
+
);
|
|
5104
|
+
return addUniqueRules.length === 1 && isCanonicalAddUniqueRule(addUniqueRules[0][0], addUniqueRules[0][1]);
|
|
5105
|
+
}
|
|
5106
|
+
function tryFastTilePuzzleBfsAll(env, st, call) {
|
|
5107
|
+
if (opOf(call) !== "bfs_all" || call.items.length !== 2 || st.world.store.size !== 0)
|
|
5108
|
+
return void 0;
|
|
5109
|
+
const start = call.items[1];
|
|
5110
|
+
const startKey = tileStateKey(start);
|
|
5111
|
+
if (start.kind !== "expr" || startKey === void 0) return void 0;
|
|
5112
|
+
if (!hasCanonicalTilePuzzleRuntime(env, st.world)) return void 0;
|
|
5113
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5114
|
+
const added = [];
|
|
5115
|
+
const queue = [start];
|
|
5116
|
+
let head = 0;
|
|
5117
|
+
while (head < queue.length) {
|
|
5118
|
+
const state = queue[head++];
|
|
5119
|
+
for (const next of tileNeighbors(state)) {
|
|
5120
|
+
const key = tileStateKey(next);
|
|
5121
|
+
if (seen.has(key)) continue;
|
|
5122
|
+
seen.add(key);
|
|
5123
|
+
added.push(tileVisitedAtom(next));
|
|
5124
|
+
queue.push(next);
|
|
5125
|
+
}
|
|
5126
|
+
}
|
|
5127
|
+
return {
|
|
5128
|
+
results: [[gint(queue.length), emptyBindings]],
|
|
5129
|
+
state: { counter: st.counter, world: appendSpace(env, st.world, "&dup", added) }
|
|
5130
|
+
};
|
|
5131
|
+
}
|
|
5132
|
+
function atomHasCustomGrounded(a) {
|
|
5133
|
+
if (a.kind === "gnd") return a.match !== void 0;
|
|
5134
|
+
if (a.kind === "expr") return a.items.some(atomHasCustomGrounded);
|
|
5135
|
+
return false;
|
|
5136
|
+
}
|
|
5137
|
+
var TRAIL_COUNT_BUDGET = 8e6;
|
|
5138
|
+
function seededTrail(b0) {
|
|
5139
|
+
const tr = new Trail();
|
|
5140
|
+
for (const [x, a] of valEntries(b0)) tr.bind(x, a);
|
|
5141
|
+
for (const r of eqRelations(b0)) if (tr.get(r.x) === void 0) tr.bind(r.x, variable(r.y));
|
|
5142
|
+
return tr;
|
|
5143
|
+
}
|
|
5144
|
+
function countTrailDFS(tr, getCandidates, patterns, counter0, freshCaches) {
|
|
5145
|
+
let counter = counter0;
|
|
5146
|
+
let count = 0;
|
|
5147
|
+
let bailed = false;
|
|
5148
|
+
let nodes = 0;
|
|
5149
|
+
const rec = (i) => {
|
|
5150
|
+
if (++nodes > TRAIL_COUNT_BUDGET) {
|
|
5151
|
+
bailed = true;
|
|
5152
|
+
return;
|
|
5153
|
+
}
|
|
5154
|
+
if (i === patterns.length) {
|
|
5155
|
+
count += 1;
|
|
5156
|
+
return;
|
|
5157
|
+
}
|
|
5158
|
+
const pInst = tr.resolve(patterns[i]);
|
|
5159
|
+
const source = getCandidates(pInst);
|
|
5160
|
+
const cache3 = syntheticCandidateSource(source) ? void 0 : freshCaches?.[i];
|
|
5161
|
+
for (const cand of source) {
|
|
5162
|
+
if (atomHasCustomGrounded(cand)) {
|
|
5163
|
+
bailed = true;
|
|
5164
|
+
return;
|
|
5165
|
+
}
|
|
5166
|
+
let fresh = cache3?.get(cand);
|
|
5167
|
+
if (fresh === void 0) {
|
|
5168
|
+
fresh = freshenRule(counter, cand, cand)[0];
|
|
5169
|
+
counter += 1;
|
|
5170
|
+
cache3?.set(cand, fresh);
|
|
5171
|
+
}
|
|
5172
|
+
const mk = tr.mark();
|
|
5173
|
+
if (unifyTrail(tr, pInst, fresh)) rec(i + 1);
|
|
5174
|
+
tr.undo(mk);
|
|
5175
|
+
if (bailed) return;
|
|
5176
|
+
}
|
|
5177
|
+
counter += candidateCounterPadding(source);
|
|
5178
|
+
};
|
|
5179
|
+
rec(0);
|
|
5180
|
+
return bailed ? void 0 : { count, counter };
|
|
5181
|
+
}
|
|
5182
|
+
function matchCountTrail(getCandidates, patterns, st, b0) {
|
|
5183
|
+
for (const p of patterns) if (atomHasCustomGrounded(p)) return void 0;
|
|
5184
|
+
return countTrailDFS(seededTrail(b0), getCandidates, patterns, st.counter);
|
|
5185
|
+
}
|
|
5186
|
+
function* matchSingleSolutions(env, getCandidates, pattern, st, b0) {
|
|
5187
|
+
let counter = st.counter;
|
|
5188
|
+
const pInst = inst(env, b0, pattern);
|
|
5189
|
+
const source = getCandidates(pInst);
|
|
5190
|
+
for (const atom of source) {
|
|
5191
|
+
const fresh = freshenRule(counter, atom, atom)[0];
|
|
5192
|
+
counter += 1;
|
|
5193
|
+
for (const mb of matchAtoms(pInst, fresh))
|
|
5194
|
+
for (const m of merge(b0, mb)) if (!hasLoop(m)) yield m;
|
|
5195
|
+
}
|
|
5196
|
+
counter += candidateCounterPadding(source);
|
|
5197
|
+
}
|
|
5198
|
+
function matchSingleEndState(env, getCandidates, pattern, template, st, b0) {
|
|
5199
|
+
const pInst = inst(env, b0, pattern);
|
|
5200
|
+
let valuesAreNormal = isNormalForm(env, st.world, pInst) && isNormalFormAssumingVars(env, st.world, template);
|
|
5201
|
+
let counter = st.counter;
|
|
5202
|
+
const source = getCandidates(pInst);
|
|
5203
|
+
for (const atom of source) {
|
|
5204
|
+
counter += 1;
|
|
5205
|
+
if (valuesAreNormal && !isNormalForm(env, st.world, atom)) valuesAreNormal = false;
|
|
5206
|
+
}
|
|
5207
|
+
counter += candidateCounterPadding(source);
|
|
5208
|
+
return { endState: { counter, world: st.world }, valuesAreNormal };
|
|
5209
|
+
}
|
|
5210
|
+
function matchPlan(env, st, space, pattern, template, b) {
|
|
5211
|
+
const { getCandidates, patterns } = matchSetup(env, st, space, pattern, b);
|
|
5212
|
+
if (patterns.length === 1) {
|
|
5213
|
+
const pat = patterns[0];
|
|
5214
|
+
const { endState: endState2, valuesAreNormal } = matchSingleEndState(
|
|
5215
|
+
env,
|
|
5216
|
+
getCandidates,
|
|
5217
|
+
pat,
|
|
5218
|
+
template,
|
|
5219
|
+
st,
|
|
5220
|
+
b
|
|
5221
|
+
);
|
|
5222
|
+
const solutions = () => matchSingleSolutions(env, getCandidates, pat, st, b);
|
|
5223
|
+
return {
|
|
5224
|
+
endState: endState2,
|
|
5225
|
+
valuesAreNormal,
|
|
5226
|
+
*foldItems(prev) {
|
|
5227
|
+
for (const m of solutions()) yield finItem(prev, inst(env, m, template), m);
|
|
5228
|
+
},
|
|
5229
|
+
*foldValues() {
|
|
5230
|
+
for (const m of solutions()) yield inst(env, m, template);
|
|
5231
|
+
}
|
|
5232
|
+
};
|
|
5233
|
+
}
|
|
5234
|
+
const [sols, endState] = patterns.length >= 2 ? matchConjJoin(env, getCandidates, patterns, st, b) : matchConj(env, getCandidates, patterns, st, [b]);
|
|
5235
|
+
return {
|
|
5236
|
+
endState,
|
|
5237
|
+
valuesAreNormal: false,
|
|
5238
|
+
*foldItems(prev) {
|
|
5239
|
+
for (const m of sols) if (!hasLoop(m)) yield finItem(prev, inst(env, m, template), m);
|
|
5240
|
+
},
|
|
5241
|
+
*foldValues() {
|
|
5242
|
+
for (const m of sols) if (!hasLoop(m)) yield inst(env, m, template);
|
|
5243
|
+
}
|
|
5244
|
+
};
|
|
5245
|
+
}
|
|
5246
|
+
function matchOp(env, st, prev, space, pattern, template, b) {
|
|
5247
|
+
const plan = matchPlan(env, st, space, pattern, template, b);
|
|
5248
|
+
const out = [];
|
|
5249
|
+
for (const item of plan.foldItems(prev)) out.push(item);
|
|
5250
|
+
return [out, plan.endState];
|
|
5251
|
+
}
|
|
5252
|
+
function matchItemSource(env, st, prev, space, pattern, template, b) {
|
|
5253
|
+
const plan = matchPlan(env, st, space, pattern, template, b);
|
|
5254
|
+
return {
|
|
5255
|
+
endState: plan.endState,
|
|
5256
|
+
foldItems() {
|
|
5257
|
+
return plan.foldItems(prev);
|
|
5258
|
+
}
|
|
5259
|
+
};
|
|
3307
5260
|
}
|
|
3308
5261
|
function* interpretLoopG(env, fuel, st, work, sink) {
|
|
3309
5262
|
const done = [];
|
|
@@ -3311,15 +5264,45 @@ function* interpretLoopG(env, fuel, st, work, sink) {
|
|
|
3311
5264
|
if (sink !== void 0) sink(pair);
|
|
3312
5265
|
else done.push(pair);
|
|
3313
5266
|
};
|
|
3314
|
-
|
|
3315
|
-
|
|
5267
|
+
let stack = [];
|
|
5268
|
+
let source;
|
|
5269
|
+
const suspended = [];
|
|
3316
5270
|
let cur = st;
|
|
5271
|
+
const beginSource = (src, suspend) => {
|
|
5272
|
+
if (suspend) suspended.push({ stack, source });
|
|
5273
|
+
stack = [];
|
|
5274
|
+
source = src.foldItems()[Symbol.iterator]();
|
|
5275
|
+
cur = src.endState;
|
|
5276
|
+
};
|
|
5277
|
+
if (isItemSource(work)) {
|
|
5278
|
+
beginSource(work, false);
|
|
5279
|
+
} else {
|
|
5280
|
+
for (let i = work.length - 1; i >= 0; i--) stack.push(work[i]);
|
|
5281
|
+
}
|
|
5282
|
+
const pullSourceItem = () => {
|
|
5283
|
+
while (stack.length === 0 && source !== void 0) {
|
|
5284
|
+
const next = source.next();
|
|
5285
|
+
if (next.done === true) {
|
|
5286
|
+
const prev = suspended.pop();
|
|
5287
|
+
if (prev === void 0) {
|
|
5288
|
+
source = void 0;
|
|
5289
|
+
} else {
|
|
5290
|
+
stack = prev.stack;
|
|
5291
|
+
source = prev.source;
|
|
5292
|
+
}
|
|
5293
|
+
continue;
|
|
5294
|
+
}
|
|
5295
|
+
if (isFinal(next.value)) emit(finalPair(env, next.value));
|
|
5296
|
+
else stack.push(next.value);
|
|
5297
|
+
}
|
|
5298
|
+
return stack.length > 0;
|
|
5299
|
+
};
|
|
3317
5300
|
let f = fuel;
|
|
3318
|
-
while (
|
|
5301
|
+
while (pullSourceItem()) {
|
|
3319
5302
|
if (f <= 0) {
|
|
3320
5303
|
for (let i = stack.length - 1; i >= 0; i--) {
|
|
3321
5304
|
const it2 = stack[i];
|
|
3322
|
-
emit(isFinal(it2) ? finalPair(it2) : exhaustedPair(it2));
|
|
5305
|
+
emit(isFinal(it2) ? finalPair(env, it2) : exhaustedPair(env, it2));
|
|
3323
5306
|
}
|
|
3324
5307
|
return [done, cur];
|
|
3325
5308
|
}
|
|
@@ -3328,25 +5311,28 @@ function* interpretLoopG(env, fuel, st, work, sink) {
|
|
|
3328
5311
|
let depth = 0;
|
|
3329
5312
|
for (let p = it.stack; p !== null; p = p.tail) depth++;
|
|
3330
5313
|
if (depth >= cur.world.maxStackDepth) {
|
|
3331
|
-
emit(isFinal(it) ? finalPair(it) : exhaustedPair(it));
|
|
5314
|
+
emit(isFinal(it) ? finalPair(env, it) : exhaustedPair(env, it));
|
|
3332
5315
|
continue;
|
|
3333
5316
|
}
|
|
3334
5317
|
}
|
|
3335
5318
|
const [results, st2] = yield* interpretStack1G(env, f - 1, cur, it);
|
|
3336
5319
|
cur = st2;
|
|
3337
5320
|
f -= 1;
|
|
5321
|
+
if (isItemSource(results)) {
|
|
5322
|
+
beginSource(results, true);
|
|
5323
|
+
continue;
|
|
5324
|
+
}
|
|
3338
5325
|
const more = [];
|
|
3339
5326
|
for (const r of results) {
|
|
3340
5327
|
if (isFinal(r)) {
|
|
3341
|
-
if (sink !== void 0) sink(finalPair(r));
|
|
3342
|
-
else done.push(finalPair(r));
|
|
5328
|
+
if (sink !== void 0) sink(finalPair(env, r));
|
|
5329
|
+
else done.push(finalPair(env, r));
|
|
3343
5330
|
} else more.push(r);
|
|
3344
5331
|
}
|
|
3345
5332
|
for (let i = more.length - 1; i >= 0; i--) stack.push(more[i]);
|
|
3346
5333
|
}
|
|
3347
5334
|
return [done, cur];
|
|
3348
5335
|
}
|
|
3349
|
-
var evaluatedAtoms = /* @__PURE__ */ new WeakSet();
|
|
3350
5336
|
function* reduceChildrenG(env, fuel, st, pairs, onTerminal) {
|
|
3351
5337
|
const out = [];
|
|
3352
5338
|
let cur = st;
|
|
@@ -3408,11 +5394,271 @@ var COUNT_UNIT = sym("u");
|
|
|
3408
5394
|
function countOnlyMatch(z) {
|
|
3409
5395
|
return z.kind === "expr" && z.items.length === 4 && opOf(z) === "match" ? expr([z.items[0], z.items[1], z.items[2], COUNT_UNIT]) : z;
|
|
3410
5396
|
}
|
|
5397
|
+
var COLLAPSE_ROUTE_ENV = "METTA_COLLAPSE_ROUTE";
|
|
5398
|
+
var DONE_UNIT = sym("done");
|
|
5399
|
+
var collapseRouteEnabled = () => process.env[COLLAPSE_ROUTE_ENV] !== "0";
|
|
5400
|
+
var countAggregateEnabled = () => process.env.METTA_COUNT_AGGREGATE !== "0";
|
|
5401
|
+
var voidBuildEnabled = () => process.env.METTA_VOID_BUILD !== "0";
|
|
5402
|
+
var conjCountEnabled = () => process.env.METTA_CONJ_COUNT !== "0";
|
|
5403
|
+
function splitVoidBuild(buildExpr, env) {
|
|
5404
|
+
if (buildExpr.kind !== "expr") return void 0;
|
|
5405
|
+
const voidable = (rhs) => {
|
|
5406
|
+
if (rhs.kind !== "expr" || rhs.items.length === 0 || rhs.items[0].kind !== "sym") return void 0;
|
|
5407
|
+
const op = rhs.items[0].name;
|
|
5408
|
+
const args = rhs.items.slice(1);
|
|
5409
|
+
if (env.compiled?.get(op)?.kind !== "imperative" || args.some((a) => !a.ground)) return void 0;
|
|
5410
|
+
return { op, args };
|
|
5411
|
+
};
|
|
5412
|
+
const head = opOf(buildExpr);
|
|
5413
|
+
if (head === "let" && buildExpr.items.length === 4 && atomEq(buildExpr.items[3], DONE_UNIT)) {
|
|
5414
|
+
const v = voidable(buildExpr.items[2]);
|
|
5415
|
+
if (v === void 0) return void 0;
|
|
5416
|
+
return { prefix: expr([buildExpr.items[0], buildExpr.items[1], DONE_UNIT, DONE_UNIT]), op: v.op, args: v.args };
|
|
5417
|
+
}
|
|
5418
|
+
if (head === "let*" && buildExpr.items.length === 3 && buildExpr.items[1].kind === "expr" && atomEq(buildExpr.items[2], DONE_UNIT)) {
|
|
5419
|
+
const pairs = buildExpr.items[1].items;
|
|
5420
|
+
const lastPair = pairs[pairs.length - 1];
|
|
5421
|
+
if (lastPair === void 0 || lastPair.kind !== "expr" || lastPair.items.length !== 2) return void 0;
|
|
5422
|
+
const v = voidable(lastPair.items[1]);
|
|
5423
|
+
if (v === void 0) return void 0;
|
|
5424
|
+
const newPairs = [...pairs.slice(0, -1), expr([lastPair.items[0], DONE_UNIT])];
|
|
5425
|
+
return { prefix: expr([buildExpr.items[0], expr(newPairs), DONE_UNIT]), op: v.op, args: v.args };
|
|
5426
|
+
}
|
|
5427
|
+
return void 0;
|
|
5428
|
+
}
|
|
5429
|
+
function addAtomVars(into, atom) {
|
|
5430
|
+
for (const name of atomVars(atom)) into.add(name);
|
|
5431
|
+
}
|
|
5432
|
+
function hasAnyAtomVar(vars, atoms) {
|
|
5433
|
+
for (const atom of atoms) for (const name of atomVars(atom)) if (vars.has(name)) return true;
|
|
5434
|
+
return false;
|
|
5435
|
+
}
|
|
5436
|
+
function tailMatchBuild(body) {
|
|
5437
|
+
if (body.kind !== "expr") return void 0;
|
|
5438
|
+
const op = opOf(body);
|
|
5439
|
+
if (op === "match" && body.items.length === 4)
|
|
5440
|
+
return { buildExpr: DONE_UNIT, tailMatch: body, boundVars: /* @__PURE__ */ new Set() };
|
|
5441
|
+
if (op === "let" && body.items.length === 4) {
|
|
5442
|
+
const inner = tailMatchBuild(body.items[3]);
|
|
5443
|
+
if (inner === void 0) return void 0;
|
|
5444
|
+
const boundVars = new Set(inner.boundVars);
|
|
5445
|
+
addAtomVars(boundVars, body.items[1]);
|
|
5446
|
+
return {
|
|
5447
|
+
buildExpr: expr([body.items[0], body.items[1], body.items[2], inner.buildExpr]),
|
|
5448
|
+
tailMatch: inner.tailMatch,
|
|
5449
|
+
boundVars
|
|
5450
|
+
};
|
|
5451
|
+
}
|
|
5452
|
+
if (op === "let*" && body.items.length === 3 && body.items[1].kind === "expr") {
|
|
5453
|
+
const inner = tailMatchBuild(body.items[2]);
|
|
5454
|
+
if (inner === void 0) return void 0;
|
|
5455
|
+
const boundVars = new Set(inner.boundVars);
|
|
5456
|
+
for (const pair of body.items[1].items) {
|
|
5457
|
+
if (pair.kind !== "expr" || pair.items.length !== 2) return void 0;
|
|
5458
|
+
addAtomVars(boundVars, pair.items[0]);
|
|
5459
|
+
}
|
|
5460
|
+
return {
|
|
5461
|
+
buildExpr: expr([body.items[0], body.items[1], inner.buildExpr]),
|
|
5462
|
+
tailMatch: inner.tailMatch,
|
|
5463
|
+
boundVars
|
|
5464
|
+
};
|
|
5465
|
+
}
|
|
5466
|
+
return void 0;
|
|
5467
|
+
}
|
|
5468
|
+
function prepareCollapseRoute(env, st, bnd, call) {
|
|
5469
|
+
if (!collapseRouteEnabled() || size(bnd) !== 0 || call.kind !== "expr" || !call.ground || call.items.length === 0 || call.items[0].kind !== "sym" || env.varRulesVar.length !== 0 || st.world.selfVarRules.length !== 0)
|
|
5470
|
+
return void 0;
|
|
5471
|
+
if (isDefinedHead(env, st.world, DONE_UNIT.name)) return void 0;
|
|
5472
|
+
const op = call.items[0].name;
|
|
5473
|
+
if (st.world.selfRules.has(op) || env.pureFunctors?.has(op) === true) return void 0;
|
|
5474
|
+
const rules = env.ruleIndex.get(op);
|
|
5475
|
+
if (rules === void 0 || rules.length !== 1) return void 0;
|
|
5476
|
+
const args = call.items.slice(1);
|
|
5477
|
+
if (args.some((arg) => !isNormalForm(env, st.world, arg))) return void 0;
|
|
5478
|
+
if (typeMismatch(env, st.world, op, args, env.sigs.get(op)) !== void 0) return void 0;
|
|
5479
|
+
const [lhs, rhs] = rules[0];
|
|
5480
|
+
if (lhs.kind !== "expr" || lhs.items.length !== call.items.length || !canMatchShallow(lhs, call))
|
|
5481
|
+
return void 0;
|
|
5482
|
+
const suffix = "#" + st.counter;
|
|
5483
|
+
const matches = [];
|
|
5484
|
+
for (const mb of matchAtomsScoped(lhs, call, suffix))
|
|
5485
|
+
for (const m of merge(bnd, mb)) if (!hasLoop(m)) matches.push(m);
|
|
5486
|
+
if (matches.length !== 1) return void 0;
|
|
5487
|
+
const body = inst(env, matches[0], rhs, suffix);
|
|
5488
|
+
const tail = tailMatchBuild(body);
|
|
5489
|
+
if (tail === void 0) return void 0;
|
|
5490
|
+
if (hasAnyAtomVar(tail.boundVars, tail.tailMatch.items.slice(1))) return void 0;
|
|
5491
|
+
let buildExpr = tail.buildExpr;
|
|
5492
|
+
let voidCall;
|
|
5493
|
+
if (voidBuildEnabled()) {
|
|
5494
|
+
const split = splitVoidBuild(buildExpr, env);
|
|
5495
|
+
if (split !== void 0) {
|
|
5496
|
+
buildExpr = split.prefix;
|
|
5497
|
+
voidCall = { op: split.op, args: split.args };
|
|
5498
|
+
}
|
|
5499
|
+
}
|
|
5500
|
+
return {
|
|
5501
|
+
buildExpr,
|
|
5502
|
+
tailMatch: tail.tailMatch,
|
|
5503
|
+
st: { counter: st.counter + 1, world: st.world },
|
|
5504
|
+
bnd: matches[0],
|
|
5505
|
+
voidCall
|
|
5506
|
+
};
|
|
5507
|
+
}
|
|
5508
|
+
function tryCountAggregate(env, st, bnd, match) {
|
|
5509
|
+
if (match.items.length < 3) return void 0;
|
|
5510
|
+
const { getCandidates, patterns } = matchSetup(env, st, match.items[1], match.items[2], bnd);
|
|
5511
|
+
if (patterns.length !== 1) return void 0;
|
|
5512
|
+
const pat = inst(env, bnd, patterns[0]);
|
|
5513
|
+
if (pat.kind !== "expr" || pat.items.length === 0 || pat.items[0].kind !== "sym") return void 0;
|
|
5514
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5515
|
+
for (let i = 1; i < pat.items.length; i++) {
|
|
5516
|
+
const a = pat.items[i];
|
|
5517
|
+
if (a.kind !== "var" || seen.has(a.name)) return void 0;
|
|
5518
|
+
seen.add(a.name);
|
|
5519
|
+
}
|
|
5520
|
+
if (seen.size === 0) return void 0;
|
|
5521
|
+
const k = headKey(pat);
|
|
5522
|
+
const arity = pat.items.length;
|
|
5523
|
+
const unifies = (a) => a.kind === "var" || a.kind === "expr" && a.items.length === arity && (headKey(a) === k || a.items[0].kind === "var");
|
|
5524
|
+
const w = st.world;
|
|
5525
|
+
const sn = spaceName(w, inst(env, bnd, match.items[1]));
|
|
5526
|
+
if ((sn === void 0 || sn === "&self") && w.store.size === 0 && w.flatSelfExtra === void 0 && env.varHeadedFacts.length === 0 && (env.factIndex.get(k)?.length ?? 0) === 0) {
|
|
5527
|
+
let count2 = 0;
|
|
5528
|
+
let iterated2 = 0;
|
|
5529
|
+
for (let p = w.selfExtra; p !== null; p = p.prev) {
|
|
5530
|
+
const akk = headKey(p.atom);
|
|
5531
|
+
if (akk === void 0 || akk === k) {
|
|
5532
|
+
iterated2 += 1;
|
|
5533
|
+
if (unifies(p.atom)) count2 += 1;
|
|
5534
|
+
}
|
|
5535
|
+
}
|
|
5536
|
+
return { count: count2, iterated: iterated2 };
|
|
5537
|
+
}
|
|
5538
|
+
const source = getCandidates(pat);
|
|
5539
|
+
let count = 0;
|
|
5540
|
+
let iterated = 0;
|
|
5541
|
+
for (const cand of source) {
|
|
5542
|
+
iterated += 1;
|
|
5543
|
+
if (unifies(cand)) count += 1;
|
|
5544
|
+
}
|
|
5545
|
+
iterated += candidateCounterPadding(source);
|
|
5546
|
+
return { count, iterated };
|
|
5547
|
+
}
|
|
5548
|
+
function* countTailMatchG(env, fuel, st, bnd, match) {
|
|
5549
|
+
const agg = countAggregateEnabled() ? tryCountAggregate(env, st, bnd, match) : void 0;
|
|
5550
|
+
if (agg !== void 0)
|
|
5551
|
+
return { count: agg.count, state: { counter: st.counter + agg.iterated, world: st.world } };
|
|
5552
|
+
{
|
|
5553
|
+
const { getCandidates, patterns } = matchSetup(env, st, match.items[1], match.items[2], bnd);
|
|
5554
|
+
const tc = patterns.length >= 2 && conjCountEnabled() ? matchConjCount(env, getCandidates, patterns, st, bnd) : env.useTrail === true ? matchCountTrail(getCandidates, patterns, st, bnd) : void 0;
|
|
5555
|
+
if (tc !== void 0)
|
|
5556
|
+
return { count: tc.count, state: { counter: tc.counter, world: st.world } };
|
|
5557
|
+
}
|
|
5558
|
+
let count = 0;
|
|
5559
|
+
const [, stC] = yield* interpretLoopG(
|
|
5560
|
+
env,
|
|
5561
|
+
fuel,
|
|
5562
|
+
st,
|
|
5563
|
+
[
|
|
5564
|
+
{
|
|
5565
|
+
stack: atomToStack(expr([sym("metta"), countOnlyMatch(match), UNDEF, sym("&self")]), null),
|
|
5566
|
+
bnd
|
|
5567
|
+
}
|
|
5568
|
+
],
|
|
5569
|
+
() => {
|
|
5570
|
+
count++;
|
|
5571
|
+
}
|
|
5572
|
+
);
|
|
5573
|
+
return { count, state: stC };
|
|
5574
|
+
}
|
|
5575
|
+
function* tryCollapseRouteG(env, fuel, st, bnd, call) {
|
|
5576
|
+
const route = prepareCollapseRoute(env, st, bnd, call);
|
|
5577
|
+
if (route === void 0) return void 0;
|
|
5578
|
+
const [built, stAfterPrefix] = yield* interpretLoopG(env, fuel, route.st, [
|
|
5579
|
+
{
|
|
5580
|
+
stack: atomToStack(expr([sym("metta"), route.buildExpr, UNDEF, sym("&self")]), null),
|
|
5581
|
+
bnd: route.bnd
|
|
5582
|
+
}
|
|
5583
|
+
]);
|
|
5584
|
+
if (built.length !== 1 || !atomEq(built[0][0], DONE_UNIT)) return void 0;
|
|
5585
|
+
let stAfterBuild = stAfterPrefix;
|
|
5586
|
+
if (route.voidCall !== void 0) {
|
|
5587
|
+
const cr = runCompiled(
|
|
5588
|
+
env,
|
|
5589
|
+
route.voidCall.op,
|
|
5590
|
+
route.voidCall.args,
|
|
5591
|
+
stAfterPrefix,
|
|
5592
|
+
COMPILED_IMPURE_OPS,
|
|
5593
|
+
true
|
|
5594
|
+
);
|
|
5595
|
+
if (cr === void 0 || cr.state === void 0) return void 0;
|
|
5596
|
+
stAfterBuild = cr.state;
|
|
5597
|
+
}
|
|
5598
|
+
return yield* countTailMatchG(env, fuel, stAfterBuild, built[0][1], route.tailMatch);
|
|
5599
|
+
}
|
|
5600
|
+
function canStreamStdlibCase(env, w) {
|
|
5601
|
+
return STREAM_CASE && (env.ruleIndex.get("case")?.length ?? 0) === 1 && env.varRulesVar.length === 0 && !w.selfRules.has("case") && w.selfVarRules.length === 0;
|
|
5602
|
+
}
|
|
5603
|
+
function streamCaseSource(env, st, bnd, matchExpr, cases) {
|
|
5604
|
+
if (cases.kind !== "expr" || cases.items.length !== 1) return void 0;
|
|
5605
|
+
const onlyCase = cases.items[0];
|
|
5606
|
+
if (onlyCase.kind !== "expr" || onlyCase.items.length !== 2 || onlyCase.items[0].kind !== "var")
|
|
5607
|
+
return void 0;
|
|
5608
|
+
const casePattern = inst(env, bnd, onlyCase.items[0]);
|
|
5609
|
+
const caseTemplate = inst(env, bnd, onlyCase.items[1]);
|
|
5610
|
+
const caseRuleEnd = { counter: st.counter + 1, world: st.world };
|
|
5611
|
+
const plan = matchPlan(
|
|
5612
|
+
env,
|
|
5613
|
+
caseRuleEnd,
|
|
5614
|
+
matchExpr.items[1],
|
|
5615
|
+
matchExpr.items[2],
|
|
5616
|
+
matchExpr.items[3],
|
|
5617
|
+
bnd
|
|
5618
|
+
);
|
|
5619
|
+
if (!plan.valuesAreNormal) return void 0;
|
|
5620
|
+
let valueCount = 0;
|
|
5621
|
+
const valueIter = plan.foldValues()[Symbol.iterator]();
|
|
5622
|
+
for (let next = valueIter.next(); !next.done; next = valueIter.next()) valueCount += 1;
|
|
5623
|
+
const switchCount = valueCount === 0 ? 1 : valueCount;
|
|
5624
|
+
const endState = {
|
|
5625
|
+
counter: plan.endState.counter + 2 * switchCount,
|
|
5626
|
+
world: plan.endState.world
|
|
5627
|
+
};
|
|
5628
|
+
const bodyFor = (value) => {
|
|
5629
|
+
for (const mb of matchAtoms(value, casePattern))
|
|
5630
|
+
for (const m of merge(bnd, mb)) if (!hasLoop(m)) return inst(env, m, caseTemplate);
|
|
5631
|
+
return sym("Empty");
|
|
5632
|
+
};
|
|
5633
|
+
return {
|
|
5634
|
+
endState,
|
|
5635
|
+
*foldItems() {
|
|
5636
|
+
let any = false;
|
|
5637
|
+
for (const value of plan.foldValues()) {
|
|
5638
|
+
any = true;
|
|
5639
|
+
yield {
|
|
5640
|
+
stack: atomToStack(expr([sym("metta"), bodyFor(value), UNDEF, sym("&self")]), null),
|
|
5641
|
+
bnd
|
|
5642
|
+
};
|
|
5643
|
+
}
|
|
5644
|
+
if (!any)
|
|
5645
|
+
yield {
|
|
5646
|
+
stack: atomToStack(
|
|
5647
|
+
expr([sym("metta"), bodyFor(sym("Empty")), UNDEF, sym("&self")]),
|
|
5648
|
+
null
|
|
5649
|
+
),
|
|
5650
|
+
bnd
|
|
5651
|
+
};
|
|
5652
|
+
}
|
|
5653
|
+
};
|
|
5654
|
+
}
|
|
3411
5655
|
function* mettaEvalG(env, fuel, st, bnd, a) {
|
|
3412
5656
|
if (fuel <= 0)
|
|
3413
|
-
return [[[
|
|
3414
|
-
const w =
|
|
3415
|
-
if (w.kind === "expr" && w.ground && evaluatedAtoms.has(w)) return [[[w, bnd]], st];
|
|
5657
|
+
return [[[makeExpr(env, [sym("Error"), inst(env, bnd, a), sym("StackOverflow")]), bnd]], st];
|
|
5658
|
+
const w = inst(env, bnd, a);
|
|
5659
|
+
if (w.kind === "expr" && w.ground && env.evaluatedAtoms.has(w)) return [[[w, bnd]], st];
|
|
5660
|
+
if (CTOR_SC && w.kind === "expr" && !w.ground && w.items.length > 0 && env.varRulesVar.length === 0 && st.world.selfVarRules.length === 0 && isNormalForm(env, st.world, w))
|
|
5661
|
+
return [[[w, bnd]], st];
|
|
3416
5662
|
const isErr = (x) => x.kind === "expr" && x.items.length >= 1 && x.items[0].kind === "sym" && x.items[0].name === "Error";
|
|
3417
5663
|
if (w.kind === "expr" && w.items.length > 0 && w.items[0].kind === "sym") {
|
|
3418
5664
|
let la = a;
|
|
@@ -3430,7 +5676,35 @@ function* mettaEvalG(env, fuel, st, bnd, a) {
|
|
|
3430
5676
|
reduceTrampoline: for (; ; ) {
|
|
3431
5677
|
const op = lw.items[0].name;
|
|
3432
5678
|
const args = lw.items.slice(1);
|
|
5679
|
+
if (op === "collapse" && args.length === 1) {
|
|
5680
|
+
const match = matchInsideOnce(args[0]);
|
|
5681
|
+
if (match !== void 0) {
|
|
5682
|
+
const namedMatch = tryFastNamedOnceMatch(env, lst, match, lbnd);
|
|
5683
|
+
if (namedMatch !== void 0) {
|
|
5684
|
+
const items = namedMatch.value === void 0 ? [] : [namedMatch.value];
|
|
5685
|
+
return flushReturn([[expr(items), lbnd]], namedMatch.state);
|
|
5686
|
+
}
|
|
5687
|
+
}
|
|
5688
|
+
}
|
|
5689
|
+
if (op === "if" && args.length === 3) {
|
|
5690
|
+
const added = tryFastNamedAddIfAbsent(env, lst, lw, lbnd);
|
|
5691
|
+
if (added !== void 0)
|
|
5692
|
+
return flushReturn(added.added ? [[emptyExpr, lbnd]] : [], added.state);
|
|
5693
|
+
}
|
|
5694
|
+
if (op === "add-unique-or-fail" && args.length === 2) {
|
|
5695
|
+
const added = tryFastAddUniqueOrFailCall(env, lst, lw, lbnd);
|
|
5696
|
+
if (added !== void 0)
|
|
5697
|
+
return flushReturn(added.added ? [[emptyExpr, lbnd]] : [], added.state);
|
|
5698
|
+
}
|
|
3433
5699
|
if ((op === "length" || op === "size-atom") && args.length === 1 && args[0].kind === "expr" && opOf(args[0]) === "collapse" && args[0].items.length === 2 && !env.ruleIndex.has(op) && !lst.world.selfRules.has(op)) {
|
|
5700
|
+
const z = args[0].items[1];
|
|
5701
|
+
if (z.kind === "expr" && opOf(z) === "match" && z.items.length === 4) {
|
|
5702
|
+
const counted = yield* countTailMatchG(env, fuel, lst, lbnd, z);
|
|
5703
|
+
return flushReturn([[gint(BigInt(counted.count)), lbnd]], counted.state);
|
|
5704
|
+
}
|
|
5705
|
+
const routed = yield* tryCollapseRouteG(env, fuel, lst, lbnd, z);
|
|
5706
|
+
if (routed !== void 0)
|
|
5707
|
+
return flushReturn([[gint(BigInt(routed.count)), lbnd]], routed.state);
|
|
3434
5708
|
let count = 0;
|
|
3435
5709
|
const [, stC] = yield* interpretLoopG(
|
|
3436
5710
|
env,
|
|
@@ -3483,7 +5757,21 @@ function* mettaEvalG(env, fuel, st, bnd, a) {
|
|
|
3483
5757
|
lst
|
|
3484
5758
|
);
|
|
3485
5759
|
}
|
|
3486
|
-
|
|
5760
|
+
if (op === "case" && args.length === 2 && args[0].kind === "expr" && opOf(args[0]) === "match" && args[0].items.length === 4 && args[1].kind === "expr" && canStreamStdlibCase(env, lst.world)) {
|
|
5761
|
+
const source = streamCaseSource(env, lst, lbnd, args[0], args[1]);
|
|
5762
|
+
if (source !== void 0) {
|
|
5763
|
+
const [selected, stCase] = yield* interpretLoopG(env, fuel, lst, source);
|
|
5764
|
+
const [pairs2, stReduced] = yield* reduceChildrenG(
|
|
5765
|
+
env,
|
|
5766
|
+
fuel,
|
|
5767
|
+
stCase,
|
|
5768
|
+
selected,
|
|
5769
|
+
() => void 0
|
|
5770
|
+
);
|
|
5771
|
+
return flushReturn(pairs2, stReduced);
|
|
5772
|
+
}
|
|
5773
|
+
}
|
|
5774
|
+
const queryVars = queryVarsOf(args);
|
|
3487
5775
|
const sig = opSig;
|
|
3488
5776
|
const opReturnsAtom = sig !== void 0 && sig.length > 0 && atomEq(sig[sig.length - 1], sym("Atom"));
|
|
3489
5777
|
const mask = LAZY_ARGS_OPS.has(op) ? args.map(() => false) : argMask(sig, args.length);
|
|
@@ -3498,10 +5786,10 @@ function* mettaEvalG(env, fuel, st, bnd, a) {
|
|
|
3498
5786
|
const [ps, st2] = yield* mettaEvalG(env, fuel - 1, cur, accB, ae);
|
|
3499
5787
|
cur = st2;
|
|
3500
5788
|
for (const p of ps) {
|
|
3501
|
-
nextParts.push([[...accAtoms, p[0]], mergeRestrict(queryVars, accB, p[1])]);
|
|
5789
|
+
nextParts.push([[...accAtoms, p[0]], mergeRestrict(env, queryVars, accB, p[1])]);
|
|
3502
5790
|
}
|
|
3503
5791
|
} else {
|
|
3504
|
-
nextParts.push([[...accAtoms,
|
|
5792
|
+
nextParts.push([[...accAtoms, inst(env, accB, ae)], accB]);
|
|
3505
5793
|
}
|
|
3506
5794
|
}
|
|
3507
5795
|
partials = nextParts;
|
|
@@ -3522,30 +5810,60 @@ function* mettaEvalG(env, fuel, st, bnd, a) {
|
|
|
3522
5810
|
out.push([errFound, partB]);
|
|
3523
5811
|
continue;
|
|
3524
5812
|
}
|
|
3525
|
-
const wApp =
|
|
5813
|
+
const wApp = makeExpr(env, [sym(op), ...partAtoms]);
|
|
3526
5814
|
if (env.curry && partAtoms.length >= 1) {
|
|
3527
5815
|
const ar = functionArity(env, cur2.world, op);
|
|
3528
5816
|
if (ar !== void 0 && partAtoms.length < ar) {
|
|
3529
|
-
out.push([
|
|
5817
|
+
out.push([makeExpr(env, [sym("partial"), sym(op), makeExpr(env, partAtoms)]), partB]);
|
|
3530
5818
|
continue;
|
|
3531
5819
|
}
|
|
3532
5820
|
}
|
|
3533
|
-
|
|
3534
|
-
|
|
5821
|
+
const fastTilePuzzle = tryFastTilePuzzleBfsAll(env, cur2, wApp);
|
|
5822
|
+
if (fastTilePuzzle !== void 0) {
|
|
5823
|
+
cur2 = fastTilePuzzle.state;
|
|
5824
|
+
for (const [value, rb] of fastTilePuzzle.results)
|
|
5825
|
+
out.push([value, mergeRestrict(env, queryVars, partB, rb)]);
|
|
5826
|
+
continue;
|
|
5827
|
+
}
|
|
5828
|
+
const fastQueue = tryFastQueueCall(env, cur2, wApp);
|
|
5829
|
+
if (fastQueue !== void 0) {
|
|
5830
|
+
cur2 = fastQueue.state;
|
|
5831
|
+
for (const [value, rb] of fastQueue.results)
|
|
5832
|
+
out.push([value, mergeRestrict(env, queryVars, partB, rb)]);
|
|
5833
|
+
continue;
|
|
5834
|
+
}
|
|
5835
|
+
if (env.compiled !== void 0 && !cur2.world.selfRules.has(op) && cur2.world.selfVarRules.length === 0) {
|
|
5836
|
+
const cr = runCompiled(env, op, partAtoms, cur2, COMPILED_IMPURE_OPS);
|
|
3535
5837
|
if (cr !== void 0) {
|
|
3536
|
-
|
|
5838
|
+
const impResult = cr.state !== void 0;
|
|
5839
|
+
if (cr.state !== void 0) cur2 = cr.state;
|
|
5840
|
+
else if (cr.counterDelta !== 0)
|
|
5841
|
+
cur2 = { counter: cur2.counter + cr.counterDelta, world: cur2.world };
|
|
5842
|
+
for (const r of cr.results) {
|
|
5843
|
+
const pb = mergeRestrict(env, queryVars, partB, r.bnd);
|
|
5844
|
+
if (atomEq(r.atom, notReducibleA) || atomEq(r.atom, wApp)) {
|
|
5845
|
+
if (wApp.ground) env.evaluatedAtoms.add(wApp);
|
|
5846
|
+
out.push([wApp, partB]);
|
|
5847
|
+
} else if ((opReturnsAtom || impResult) && !isEmbeddedOp(r.atom)) {
|
|
5848
|
+
out.push([r.atom, pb]);
|
|
5849
|
+
} else {
|
|
5850
|
+
const [more, st4] = yield* mettaEvalG(env, fuel - 1, cur2, pb, r.atom);
|
|
5851
|
+
cur2 = st4;
|
|
5852
|
+
for (const m of more) out.push([m[0], mergeRestrict(env, queryVars, pb, m[1])]);
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
3537
5855
|
continue;
|
|
3538
5856
|
}
|
|
3539
5857
|
}
|
|
3540
5858
|
let eligible = false;
|
|
3541
5859
|
let key = "";
|
|
3542
|
-
if (tabling && wApp.ground
|
|
5860
|
+
if (tabling && wApp.ground) {
|
|
3543
5861
|
if (cur2.world.selfRules.has(op)) {
|
|
3544
|
-
if (runtimeFunctorPure(env, cur2.world, op)) {
|
|
5862
|
+
if (runtimeFunctorPure(env, cur2.world, op) && keyWellFormed(wApp)) {
|
|
3545
5863
|
eligible = true;
|
|
3546
5864
|
key = tableKey(wApp) + "@v" + rulesVersion(cur2.world.selfRules.get(op));
|
|
3547
5865
|
}
|
|
3548
|
-
} else if (staticPure) {
|
|
5866
|
+
} else if (staticPure && keyWellFormed(wApp)) {
|
|
3549
5867
|
eligible = true;
|
|
3550
5868
|
key = tableKey(wApp);
|
|
3551
5869
|
}
|
|
@@ -3559,26 +5877,26 @@ function* mettaEvalG(env, fuel, st, bnd, a) {
|
|
|
3559
5877
|
}
|
|
3560
5878
|
const before = out.length;
|
|
3561
5879
|
const [pairs2, st3] = yield* interpretLoopG(env, fuel, cur2, [
|
|
3562
|
-
{ stack: atomToStack(
|
|
5880
|
+
{ stack: atomToStack(makeExpr(env, [sym("eval"), wApp]), null), bnd: lbnd }
|
|
3563
5881
|
]);
|
|
3564
5882
|
cur2 = st3;
|
|
3565
5883
|
if (partials.length === 1 && queryVars.length === 0 && pairs2.length === 1) {
|
|
3566
5884
|
const p = pairs2[0];
|
|
3567
5885
|
const isData = atomEq(p[0], notReducibleA) || atomEq(p[0], wApp);
|
|
3568
5886
|
if (!isData && !(opReturnsAtom && !isEmbeddedOp(p[0])) && opOf(p[0]) !== void 0) {
|
|
3569
|
-
const pb = mergeRestrict(queryVars, partB, p[1]);
|
|
5887
|
+
const pb = mergeRestrict(env, queryVars, partB, p[1]);
|
|
3570
5888
|
if (eligible) pendingKeys.push(key);
|
|
3571
5889
|
la = p[0];
|
|
3572
5890
|
lbnd = pb;
|
|
3573
5891
|
lst = cur2;
|
|
3574
|
-
lw =
|
|
5892
|
+
lw = inst(env, lbnd, la);
|
|
3575
5893
|
continue reduceTrampoline;
|
|
3576
5894
|
}
|
|
3577
5895
|
}
|
|
3578
5896
|
for (const p of pairs2) {
|
|
3579
|
-
const pb = mergeRestrict(queryVars, partB, p[1]);
|
|
5897
|
+
const pb = mergeRestrict(env, queryVars, partB, p[1]);
|
|
3580
5898
|
if (atomEq(p[0], notReducibleA) || atomEq(p[0], wApp)) {
|
|
3581
|
-
if (wApp.ground) evaluatedAtoms.add(wApp);
|
|
5899
|
+
if (wApp.ground) env.evaluatedAtoms.add(wApp);
|
|
3582
5900
|
out.push([wApp, partB]);
|
|
3583
5901
|
} else if (opReturnsAtom && !isEmbeddedOp(p[0])) {
|
|
3584
5902
|
out.push([p[0], pb]);
|
|
@@ -3586,7 +5904,7 @@ function* mettaEvalG(env, fuel, st, bnd, a) {
|
|
|
3586
5904
|
const [more, st4] = yield* mettaEvalG(env, fuel - 1, cur2, pb, p[0]);
|
|
3587
5905
|
cur2 = st4;
|
|
3588
5906
|
for (const m of more) {
|
|
3589
|
-
out.push([m[0], mergeRestrict(queryVars, pb, m[1])]);
|
|
5907
|
+
out.push([m[0], mergeRestrict(env, queryVars, pb, m[1])]);
|
|
3590
5908
|
}
|
|
3591
5909
|
}
|
|
3592
5910
|
}
|
|
@@ -3600,14 +5918,14 @@ function* mettaEvalG(env, fuel, st, bnd, a) {
|
|
|
3600
5918
|
}
|
|
3601
5919
|
if (w.kind === "expr" && w.items.length > 0) {
|
|
3602
5920
|
const [ruleRes, st12] = yield* interpretLoopG(env, fuel, st, [
|
|
3603
|
-
{ stack: atomToStack(
|
|
5921
|
+
{ stack: atomToStack(makeExpr(env, [sym("eval"), w]), null), bnd }
|
|
3604
5922
|
]);
|
|
3605
5923
|
const reduced = ruleRes.filter((p) => !atomEq(p[0], w) && !atomEq(p[0], notReducibleA));
|
|
3606
5924
|
if (reduced.length === 0) {
|
|
3607
5925
|
const [tupleRes, st2] = yield* interpretLoopG(env, fuel, st12, [
|
|
3608
5926
|
{
|
|
3609
5927
|
stack: atomToStack(
|
|
3610
|
-
|
|
5928
|
+
makeExpr(env, [sym("eval"), makeExpr(env, [sym("interpret-tuple"), w, sym("&self")])]),
|
|
3611
5929
|
null
|
|
3612
5930
|
),
|
|
3613
5931
|
bnd
|
|
@@ -3624,7 +5942,7 @@ function* mettaEvalG(env, fuel, st, bnd, a) {
|
|
|
3624
5942
|
return yield* reduceChildrenG(env, fuel, st12, reduced, () => void 0);
|
|
3625
5943
|
}
|
|
3626
5944
|
const [pairs, st1] = yield* interpretLoopG(env, fuel, st, [
|
|
3627
|
-
{ stack: atomToStack(
|
|
5945
|
+
{ stack: atomToStack(makeExpr(env, [sym("eval"), w]), null), bnd }
|
|
3628
5946
|
]);
|
|
3629
5947
|
return yield* reduceChildrenG(
|
|
3630
5948
|
env,
|
|
@@ -3638,22 +5956,22 @@ var DEFAULT_FUEL = 2e6;
|
|
|
3638
5956
|
function isNativeStackOverflow(e) {
|
|
3639
5957
|
return e instanceof RangeError && /call stack/i.test(e.message);
|
|
3640
5958
|
}
|
|
3641
|
-
function stackOverflowResult(st, bnd, a) {
|
|
3642
|
-
return [[[
|
|
5959
|
+
function stackOverflowResult(env, st, bnd, a) {
|
|
5960
|
+
return [[[makeExpr(env, [sym("Error"), inst(env, bnd, a), sym("StackOverflow")]), bnd]], st];
|
|
3643
5961
|
}
|
|
3644
5962
|
function mettaEval(env, fuel, st, bnd, a) {
|
|
3645
5963
|
ensureCompiled(env);
|
|
3646
5964
|
try {
|
|
3647
5965
|
return runGenSync(mettaEvalG(env, fuel, st, bnd, a));
|
|
3648
5966
|
} catch (e) {
|
|
3649
|
-
if (isNativeStackOverflow(e)) return stackOverflowResult(st, bnd, a);
|
|
5967
|
+
if (isNativeStackOverflow(e)) return stackOverflowResult(env, st, bnd, a);
|
|
3650
5968
|
throw e;
|
|
3651
5969
|
}
|
|
3652
5970
|
}
|
|
3653
5971
|
function mettaEvalAsync(env, fuel, st, bnd, a, signal) {
|
|
3654
5972
|
ensureCompiled(env);
|
|
3655
5973
|
return runGenAsync(mettaEvalG(env, fuel, st, bnd, a), signal).catch((e) => {
|
|
3656
|
-
if (isNativeStackOverflow(e)) return stackOverflowResult(st, bnd, a);
|
|
5974
|
+
if (isNativeStackOverflow(e)) return stackOverflowResult(env, st, bnd, a);
|
|
3657
5975
|
throw e;
|
|
3658
5976
|
});
|
|
3659
5977
|
}
|
|
@@ -4169,12 +6487,15 @@ function preludeAtoms() {
|
|
|
4169
6487
|
}
|
|
4170
6488
|
var DEFAULT_FUEL2 = 1e5;
|
|
4171
6489
|
var DEFAULT_TABLING = true;
|
|
4172
|
-
function buildDefaultEnv(imports, tabling) {
|
|
6490
|
+
function buildDefaultEnv(imports, tabling, experimental) {
|
|
4173
6491
|
const env = buildEnv(
|
|
4174
6492
|
[...preludeAtoms(), ...stdlibAtoms(), ...pettaStdlibAtoms()],
|
|
4175
6493
|
stdTable()
|
|
4176
6494
|
);
|
|
4177
6495
|
env.imports = withBuiltinModules(imports);
|
|
6496
|
+
if (experimental?.hashCons === true) env.intern = createInternTable();
|
|
6497
|
+
if (experimental?.trail === true) env.useTrail = true;
|
|
6498
|
+
if (experimental?.flatAtomspace === true) env.useFlatAtomspace = true;
|
|
4178
6499
|
if (tabling) {
|
|
4179
6500
|
env.table = /* @__PURE__ */ new Map();
|
|
4180
6501
|
env.pureFunctors = analyzePurity(env);
|
|
@@ -4187,7 +6508,7 @@ function evalSequential(atoms, fuel = DEFAULT_FUEL2, imports = /* @__PURE__ */ n
|
|
|
4187
6508
|
const out = [];
|
|
4188
6509
|
let st = initSt();
|
|
4189
6510
|
if (opts.maxStackDepth !== void 0) st.world.maxStackDepth = opts.maxStackDepth;
|
|
4190
|
-
const env = buildDefaultEnv(imports, opts.tabling ?? DEFAULT_TABLING);
|
|
6511
|
+
const env = buildDefaultEnv(imports, opts.tabling ?? DEFAULT_TABLING, opts.experimental);
|
|
4191
6512
|
if (opts.parEvalImpl !== void 0) {
|
|
4192
6513
|
const rulesSrc = atoms.filter((a) => !a.bang).map((a) => format(a.atom)).join("\n");
|
|
4193
6514
|
const impl = opts.parEvalImpl;
|
|
@@ -4209,12 +6530,13 @@ function evalSequential(atoms, fuel = DEFAULT_FUEL2, imports = /* @__PURE__ */ n
|
|
|
4209
6530
|
function runProgram(src, fuel = DEFAULT_FUEL2, imports = /* @__PURE__ */ new Map(), opts = {}) {
|
|
4210
6531
|
return evalSequential(parseAll(src, standardTokenizer()), fuel, imports, opts);
|
|
4211
6532
|
}
|
|
4212
|
-
async function runProgramAsync(src, asyncOps = /* @__PURE__ */ new Map(), fuel = DEFAULT_FUEL2, imports = /* @__PURE__ */ new Map()) {
|
|
6533
|
+
async function runProgramAsync(src, asyncOps = /* @__PURE__ */ new Map(), fuel = DEFAULT_FUEL2, imports = /* @__PURE__ */ new Map(), opts = {}) {
|
|
4213
6534
|
const parsed = parseAll(src, standardTokenizer());
|
|
4214
|
-
const env = buildDefaultEnv(imports, false);
|
|
6535
|
+
const env = buildDefaultEnv(imports, opts.tabling ?? false, opts.experimental);
|
|
4215
6536
|
for (const [k, v] of asyncOps) env.agt.set(k, v);
|
|
4216
6537
|
const out = [];
|
|
4217
6538
|
let st = initSt();
|
|
6539
|
+
if (opts.maxStackDepth !== void 0) st.world.maxStackDepth = opts.maxStackDepth;
|
|
4218
6540
|
for (const { atom, bang } of parsed) {
|
|
4219
6541
|
if (!bang) {
|
|
4220
6542
|
addAtomToEnv(env, atom);
|
|
@@ -4276,7 +6598,7 @@ var Interner = class {
|
|
|
4276
6598
|
return this.add("s\0" + name, { kind: "sym", name });
|
|
4277
6599
|
}
|
|
4278
6600
|
internGround(value) {
|
|
4279
|
-
return this.add(
|
|
6601
|
+
return this.add(groundKey2(value), { kind: "gnd", value });
|
|
4280
6602
|
}
|
|
4281
6603
|
/** The id for a symbol/ground if already interned, else undefined (a pattern symbol absent from the
|
|
4282
6604
|
* KB can never match, so its lookup short-circuits). */
|
|
@@ -4284,7 +6606,7 @@ var Interner = class {
|
|
|
4284
6606
|
return this.byKey.get("s\0" + name);
|
|
4285
6607
|
}
|
|
4286
6608
|
lookupGround(value) {
|
|
4287
|
-
return this.byKey.get(
|
|
6609
|
+
return this.byKey.get(groundKey2(value));
|
|
4288
6610
|
}
|
|
4289
6611
|
/** Reconstruct the atom for a leaf id. */
|
|
4290
6612
|
decodeLeaf(id) {
|
|
@@ -4295,7 +6617,7 @@ var Interner = class {
|
|
|
4295
6617
|
return this.entries.length;
|
|
4296
6618
|
}
|
|
4297
6619
|
};
|
|
4298
|
-
function
|
|
6620
|
+
function groundKey2(v) {
|
|
4299
6621
|
switch (v.g) {
|
|
4300
6622
|
case "int":
|
|
4301
6623
|
return "i\0" + v.n;
|
|
@@ -4586,83 +6908,13 @@ function williamTopK(kb, k, refCost = 4) {
|
|
|
4586
6908
|
gain: s.gain
|
|
4587
6909
|
}));
|
|
4588
6910
|
}
|
|
4589
|
-
|
|
4590
|
-
// src/trail.ts
|
|
4591
|
-
var Trail = class {
|
|
4592
|
-
binds = /* @__PURE__ */ new Map();
|
|
4593
|
-
trail = [];
|
|
4594
|
-
/** A restore point: the current trail length. */
|
|
4595
|
-
mark() {
|
|
4596
|
-
return this.trail.length;
|
|
4597
|
-
}
|
|
4598
|
-
/** Undo every binding made since `m`. */
|
|
4599
|
-
undo(m) {
|
|
4600
|
-
const t = this.trail;
|
|
4601
|
-
while (t.length > m) this.binds.delete(t.pop());
|
|
4602
|
-
}
|
|
4603
|
-
/** Bind `$name` to `a` and record it on the trail. The caller guarantees `$name` is currently unbound. */
|
|
4604
|
-
bind(name, a) {
|
|
4605
|
-
this.binds.set(name, a);
|
|
4606
|
-
this.trail.push(name);
|
|
4607
|
-
}
|
|
4608
|
-
/** Follow variable bindings to the representative: a non-variable, or an unbound variable. */
|
|
4609
|
-
deref(a) {
|
|
4610
|
-
let cur = a;
|
|
4611
|
-
while (cur.kind === "var") {
|
|
4612
|
-
const v = this.binds.get(cur.name);
|
|
4613
|
-
if (v === void 0) return cur;
|
|
4614
|
-
cur = v;
|
|
4615
|
-
}
|
|
4616
|
-
return cur;
|
|
4617
|
-
}
|
|
4618
|
-
/** Resolve `a` against the current bindings, one pass (the same discipline as the immutable
|
|
4619
|
-
* `instantiate`/`applySubst`): a variable becomes its bound value as-is; the value's own variables are
|
|
4620
|
-
* not re-resolved, and an expression's children are resolved. This matches the evaluator exactly,
|
|
4621
|
-
* including that a cyclic binding (`$y = (.. $y ..)`, which `matchAtoms` produces and `hasLoop` does not
|
|
4622
|
-
* reject) terminates instead of looping. A new term is built only where a child changed. */
|
|
4623
|
-
resolve(a) {
|
|
4624
|
-
if (a.kind === "var") return this.deref(a);
|
|
4625
|
-
if (a.kind !== "expr" || a.ground) return a;
|
|
4626
|
-
const its = a.items;
|
|
4627
|
-
let items = null;
|
|
4628
|
-
for (let i = 0; i < its.length; i++) {
|
|
4629
|
-
const it = its[i];
|
|
4630
|
-
const r = this.resolve(it);
|
|
4631
|
-
if (items !== null) items.push(r);
|
|
4632
|
-
else if (r !== it) {
|
|
4633
|
-
items = its.slice(0, i);
|
|
4634
|
-
items.push(r);
|
|
4635
|
-
}
|
|
4636
|
-
}
|
|
4637
|
-
return items === null ? a : { ...a, items };
|
|
4638
|
-
}
|
|
4639
|
-
};
|
|
4640
|
-
function unifyTrail(tr, l0, r0) {
|
|
4641
|
-
const l = tr.deref(l0);
|
|
4642
|
-
const r = tr.deref(r0);
|
|
4643
|
-
if (l === r) return true;
|
|
4644
|
-
if (l.kind === "var") {
|
|
4645
|
-
if (r.kind === "var" && l.name === r.name) return true;
|
|
4646
|
-
tr.bind(l.name, r);
|
|
4647
|
-
return true;
|
|
4648
|
-
}
|
|
4649
|
-
if (r.kind === "var") {
|
|
4650
|
-
tr.bind(r.name, l);
|
|
4651
|
-
return true;
|
|
4652
|
-
}
|
|
4653
|
-
if (l.kind === "sym") return r.kind === "sym" && l.name === r.name;
|
|
4654
|
-
if (l.kind === "gnd") return r.kind === "gnd" && atomEq(l, r);
|
|
4655
|
-
if (r.kind !== "expr" || l.items.length !== r.items.length) return false;
|
|
4656
|
-
for (let i = 0; i < l.items.length; i++)
|
|
4657
|
-
if (!unifyTrail(tr, l.items[i], r.items[i])) return false;
|
|
4658
|
-
return true;
|
|
4659
|
-
}
|
|
4660
6911
|
export {
|
|
4661
6912
|
AsyncInSyncError,
|
|
4662
6913
|
BAIL,
|
|
4663
6914
|
CONCURRENCY_MODULE_SRC,
|
|
4664
6915
|
CURRY_MODULE_SRC,
|
|
4665
6916
|
DEFAULT_FUEL2 as DEFAULT_FUEL,
|
|
6917
|
+
FlatAtomSpace,
|
|
4666
6918
|
FlatKB,
|
|
4667
6919
|
IMPURE_OPS,
|
|
4668
6920
|
InMemorySpace,
|
|
@@ -4692,11 +6944,14 @@ export {
|
|
|
4692
6944
|
buildEnv,
|
|
4693
6945
|
builtinModules,
|
|
4694
6946
|
callGrounded,
|
|
6947
|
+
canCompactAtom,
|
|
6948
|
+
canInternExprItems,
|
|
4695
6949
|
canonInt,
|
|
4696
6950
|
cmpIntVal,
|
|
4697
6951
|
collectImports,
|
|
4698
6952
|
collectVars,
|
|
4699
6953
|
compileEnv,
|
|
6954
|
+
createInternTable,
|
|
4700
6955
|
decodeAt,
|
|
4701
6956
|
decodeAtom,
|
|
4702
6957
|
emptyBindings,
|
|
@@ -4706,6 +6961,7 @@ export {
|
|
|
4706
6961
|
encodeAtom,
|
|
4707
6962
|
encodeInto,
|
|
4708
6963
|
encodePattern,
|
|
6964
|
+
eqRelations,
|
|
4709
6965
|
eraseSubst,
|
|
4710
6966
|
evalAtom,
|
|
4711
6967
|
evalSequential,
|
|
@@ -4713,6 +6969,7 @@ export {
|
|
|
4713
6969
|
extendSubst,
|
|
4714
6970
|
format,
|
|
4715
6971
|
freshenRule,
|
|
6972
|
+
fromRelations,
|
|
4716
6973
|
gbool,
|
|
4717
6974
|
getTypes,
|
|
4718
6975
|
gfloat,
|
|
@@ -4722,6 +6979,7 @@ export {
|
|
|
4722
6979
|
groundType,
|
|
4723
6980
|
gstr,
|
|
4724
6981
|
gunit,
|
|
6982
|
+
hasEq,
|
|
4725
6983
|
hasLoop,
|
|
4726
6984
|
hashOf,
|
|
4727
6985
|
initSt,
|
|
@@ -4729,6 +6987,10 @@ export {
|
|
|
4729
6987
|
intAbs,
|
|
4730
6988
|
intDiv,
|
|
4731
6989
|
intMod,
|
|
6990
|
+
internAtom,
|
|
6991
|
+
internBuiltExpr,
|
|
6992
|
+
internExpr,
|
|
6993
|
+
isEmpty,
|
|
4732
6994
|
isErrorAtom,
|
|
4733
6995
|
isExpr,
|
|
4734
6996
|
isGnd,
|
|
@@ -4739,6 +7001,7 @@ export {
|
|
|
4739
7001
|
keyWellFormed,
|
|
4740
7002
|
lookupSubst,
|
|
4741
7003
|
lookupVal,
|
|
7004
|
+
makeValRel,
|
|
4742
7005
|
matchAtoms,
|
|
4743
7006
|
matchAtomsScoped,
|
|
4744
7007
|
matchAtomsWith,
|
|
@@ -4747,6 +7010,7 @@ export {
|
|
|
4747
7010
|
metaType,
|
|
4748
7011
|
mettaEval,
|
|
4749
7012
|
mettaEvalAsync,
|
|
7013
|
+
mixHash,
|
|
4750
7014
|
mulInt,
|
|
4751
7015
|
occurs,
|
|
4752
7016
|
oracleReport,
|
|
@@ -4754,15 +7018,20 @@ export {
|
|
|
4754
7018
|
parseAll,
|
|
4755
7019
|
pettaOpNames,
|
|
4756
7020
|
preludeAtoms,
|
|
7021
|
+
prependValRaw,
|
|
7022
|
+
relations,
|
|
4757
7023
|
removeVal,
|
|
4758
7024
|
runCompiled,
|
|
4759
7025
|
runProgram,
|
|
4760
7026
|
runProgramAsync,
|
|
4761
7027
|
setOutputSink,
|
|
4762
7028
|
setRawSink,
|
|
7029
|
+
size,
|
|
7030
|
+
someVal,
|
|
4763
7031
|
standardTokenizer,
|
|
4764
7032
|
stdTable,
|
|
4765
7033
|
stdlibAtoms,
|
|
7034
|
+
strHash,
|
|
4766
7035
|
subInt,
|
|
4767
7036
|
sym,
|
|
4768
7037
|
tableKey,
|
|
@@ -4770,8 +7039,10 @@ export {
|
|
|
4770
7039
|
unifiable,
|
|
4771
7040
|
unifyTop,
|
|
4772
7041
|
unifyTrail,
|
|
7042
|
+
valEntries,
|
|
4773
7043
|
variable,
|
|
4774
7044
|
wcoJoin,
|
|
7045
|
+
wcoJoinFold,
|
|
4775
7046
|
williamTopK,
|
|
4776
7047
|
withBuiltinModules
|
|
4777
7048
|
};
|