yukigo 0.2.2 → 0.3.1
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/.mocharc.json +3 -3
- package/CHANGELOG.md +102 -41
- package/README.md +193 -193
- package/dist/analyzer/GraphBuilder.d.ts +1 -0
- package/dist/analyzer/GraphBuilder.js +2 -1
- package/dist/analyzer/index.d.ts +0 -7
- package/dist/analyzer/index.js +3 -3
- package/dist/analyzer/inspections/functional/functional.d.ts +1 -1
- package/dist/analyzer/inspections/functional/functional.js +1 -1
- package/dist/analyzer/inspections/functional/smells.d.ts +3 -3
- package/dist/analyzer/inspections/functional/smells.js +27 -35
- package/dist/analyzer/inspections/generic/generic.d.ts +21 -14
- package/dist/analyzer/inspections/generic/generic.js +78 -59
- package/dist/analyzer/inspections/generic/smells.d.ts +2 -0
- package/dist/analyzer/inspections/generic/smells.js +55 -64
- package/dist/analyzer/inspections/imperative/imperative.d.ts +3 -3
- package/dist/analyzer/inspections/imperative/imperative.js +3 -3
- package/dist/analyzer/inspections/imperative/smells.d.ts +1 -0
- package/dist/analyzer/inspections/imperative/smells.js +8 -5
- package/dist/analyzer/inspections/logic/logic.d.ts +8 -8
- package/dist/analyzer/inspections/logic/logic.js +5 -5
- package/dist/analyzer/inspections/logic/smells.js +2 -2
- package/dist/analyzer/inspections/object/object.d.ts +5 -5
- package/dist/analyzer/inspections/object/object.js +22 -21
- package/dist/analyzer/inspections/object/smells.js +11 -23
- package/dist/analyzer/utils.d.ts +6 -2
- package/dist/analyzer/utils.js +6 -2
- package/dist/interpreter/components/EnvBuilder.d.ts +20 -1
- package/dist/interpreter/components/EnvBuilder.js +211 -66
- package/dist/interpreter/components/EqualityComparer.d.ts +15 -0
- package/dist/interpreter/components/EqualityComparer.js +69 -0
- package/dist/interpreter/components/Operations.d.ts +17 -14
- package/dist/interpreter/components/Operations.js +61 -62
- package/dist/interpreter/components/PatternMatcher.d.ts +19 -58
- package/dist/interpreter/components/PatternMatcher.js +185 -286
- package/dist/interpreter/components/RuntimeContext.d.ts +24 -15
- package/dist/interpreter/components/RuntimeContext.js +43 -4
- package/dist/interpreter/components/TestRunner.d.ts +15 -13
- package/dist/interpreter/components/TestRunner.js +86 -53
- package/dist/interpreter/components/evaluators/BaseEvaluator.d.ts +19 -0
- package/dist/interpreter/components/evaluators/BaseEvaluator.js +20 -0
- package/dist/interpreter/components/evaluators/ExpressionEvaluator.d.ts +34 -0
- package/dist/interpreter/components/evaluators/ExpressionEvaluator.js +298 -0
- package/dist/interpreter/components/evaluators/OperationEvaluator.d.ts +25 -0
- package/dist/interpreter/components/evaluators/OperationEvaluator.js +226 -0
- package/dist/interpreter/components/evaluators/PrimitiveEvaluator.d.ts +19 -0
- package/dist/interpreter/components/evaluators/PrimitiveEvaluator.js +50 -0
- package/dist/interpreter/components/evaluators/StatementEvaluator.d.ts +28 -0
- package/dist/interpreter/components/evaluators/StatementEvaluator.js +240 -0
- package/dist/interpreter/components/evaluators/TestingEvaluator.d.ts +15 -0
- package/dist/interpreter/components/evaluators/TestingEvaluator.js +14 -0
- package/dist/interpreter/components/evaluators/index.d.ts +110 -0
- package/dist/interpreter/components/evaluators/index.js +21 -0
- package/dist/interpreter/components/evaluators/utils.d.ts +7 -0
- package/dist/interpreter/components/evaluators/utils.js +50 -0
- package/dist/interpreter/components/hooks/YukigoHook.d.ts +27 -0
- package/dist/interpreter/components/hooks/YukigoHook.js +1 -0
- package/dist/interpreter/components/kernel/commands.d.ts +122 -0
- package/dist/interpreter/components/kernel/commands.js +203 -0
- package/dist/interpreter/components/kernel/index.d.ts +51 -0
- package/dist/interpreter/components/kernel/index.js +176 -0
- package/dist/interpreter/components/logic/LogicEngine.d.ts +26 -23
- package/dist/interpreter/components/logic/LogicEngine.js +234 -221
- package/dist/interpreter/components/logic/LogicResolver.d.ts +22 -51
- package/dist/interpreter/components/logic/LogicResolver.js +73 -440
- package/dist/interpreter/components/logic/LogicTerm.d.ts +104 -0
- package/dist/interpreter/components/logic/LogicTerm.js +423 -0
- package/dist/interpreter/components/logic/LogicTranslator.d.ts +25 -9
- package/dist/interpreter/components/logic/LogicTranslator.js +211 -74
- package/dist/interpreter/components/runtimes/FunctionRuntime.d.ts +6 -4
- package/dist/interpreter/components/runtimes/FunctionRuntime.js +82 -84
- package/dist/interpreter/components/runtimes/LazyRuntime.d.ts +13 -14
- package/dist/interpreter/components/runtimes/LazyRuntime.js +112 -239
- package/dist/interpreter/components/runtimes/ObjectRuntime.d.ts +17 -14
- package/dist/interpreter/components/runtimes/ObjectRuntime.js +105 -74
- package/dist/interpreter/errors.d.ts +10 -0
- package/dist/interpreter/errors.js +17 -0
- package/dist/interpreter/index.d.ts +9 -5
- package/dist/interpreter/index.js +11 -13
- package/dist/interpreter/primitives/YuValue.d.ts +21 -0
- package/dist/interpreter/primitives/YuValue.js +40 -0
- package/dist/interpreter/primitives/capabilities.d.ts +90 -0
- package/dist/interpreter/primitives/capabilities.js +1 -0
- package/dist/interpreter/primitives/entities/LazyList.d.ts +48 -0
- package/dist/interpreter/primitives/entities/LazyList.js +164 -0
- package/dist/interpreter/primitives/entities/LogicResult.d.ts +51 -0
- package/dist/interpreter/primitives/entities/LogicResult.js +101 -0
- package/dist/interpreter/primitives/entities/RuntimeClass.d.ts +24 -0
- package/dist/interpreter/primitives/entities/RuntimeClass.js +57 -0
- package/dist/interpreter/primitives/entities/RuntimeFunction.d.ts +40 -0
- package/dist/interpreter/primitives/entities/RuntimeFunction.js +73 -0
- package/dist/interpreter/primitives/entities/RuntimeObject.d.ts +27 -0
- package/dist/interpreter/primitives/entities/RuntimeObject.js +82 -0
- package/dist/interpreter/primitives/entities/RuntimePredicate.d.ts +19 -0
- package/dist/interpreter/primitives/entities/RuntimePredicate.js +59 -0
- package/dist/interpreter/primitives/index.d.ts +14 -0
- package/dist/interpreter/primitives/index.js +14 -0
- package/dist/interpreter/primitives/scalars/YuBoolean.d.ts +24 -0
- package/dist/interpreter/primitives/scalars/YuBoolean.js +69 -0
- package/dist/interpreter/primitives/scalars/YuChar.d.ts +28 -0
- package/dist/interpreter/primitives/scalars/YuChar.js +78 -0
- package/dist/interpreter/primitives/scalars/YuNil.d.ts +25 -0
- package/dist/interpreter/primitives/scalars/YuNil.js +73 -0
- package/dist/interpreter/primitives/scalars/YuNumber.d.ts +49 -0
- package/dist/interpreter/primitives/scalars/YuNumber.js +165 -0
- package/dist/interpreter/primitives/sequences/YuArray.d.ts +33 -0
- package/dist/interpreter/primitives/sequences/YuArray.js +150 -0
- package/dist/interpreter/primitives/sequences/YuString.d.ts +40 -0
- package/dist/interpreter/primitives/sequences/YuString.js +130 -0
- package/dist/interpreter/utils.d.ts +23 -10
- package/dist/interpreter/utils.js +25 -30
- package/dist/tester/index.d.ts +3 -3
- package/dist/tester/index.js +39 -28
- package/dist/utils/helpers.d.ts +12 -5
- package/dist/utils/helpers.js +6 -79
- package/package.json +3 -16
- package/src/analyzer/GraphBuilder.ts +143 -142
- package/src/analyzer/index.ts +185 -194
- package/src/analyzer/inspections/functional/functional.ts +121 -121
- package/src/analyzer/inspections/functional/smells.ts +88 -102
- package/src/analyzer/inspections/generic/generic.ts +610 -581
- package/src/analyzer/inspections/generic/smells.ts +355 -365
- package/src/analyzer/inspections/imperative/imperative.ts +104 -101
- package/src/analyzer/inspections/imperative/smells.ts +58 -54
- package/src/analyzer/inspections/logic/logic.ts +84 -90
- package/src/analyzer/inspections/logic/smells.ts +54 -54
- package/src/analyzer/inspections/object/object.ts +295 -264
- package/src/analyzer/inspections/object/smells.ts +130 -144
- package/src/analyzer/utils.ts +115 -109
- package/src/index.ts +3 -3
- package/src/interpreter/components/EnvBuilder.ts +405 -202
- package/src/interpreter/components/EqualityComparer.ts +107 -0
- package/src/interpreter/components/Operations.ts +126 -99
- package/src/interpreter/components/PatternMatcher.ts +375 -475
- package/src/interpreter/components/RuntimeContext.ts +181 -119
- package/src/interpreter/components/TestRunner.ts +223 -151
- package/src/interpreter/components/evaluators/BaseEvaluator.ts +36 -0
- package/src/interpreter/components/evaluators/ExpressionEvaluator.ts +475 -0
- package/src/interpreter/components/evaluators/OperationEvaluator.ts +477 -0
- package/src/interpreter/components/evaluators/PrimitiveEvaluator.ts +80 -0
- package/src/interpreter/components/evaluators/StatementEvaluator.ts +372 -0
- package/src/interpreter/components/evaluators/TestingEvaluator.ts +26 -0
- package/src/interpreter/components/evaluators/index.ts +34 -0
- package/src/interpreter/components/evaluators/utils.ts +64 -0
- package/src/interpreter/components/hooks/YukigoHook.ts +45 -0
- package/src/interpreter/components/kernel/commands.ts +255 -0
- package/src/interpreter/components/kernel/index.ts +222 -0
- package/src/interpreter/components/logic/LogicEngine.ts +509 -519
- package/src/interpreter/components/logic/LogicResolver.ts +209 -858
- package/src/interpreter/components/logic/LogicTerm.ts +477 -0
- package/src/interpreter/components/logic/LogicTranslator.ts +362 -149
- package/src/interpreter/components/runtimes/FunctionRuntime.ts +249 -227
- package/src/interpreter/components/runtimes/LazyRuntime.ts +226 -334
- package/src/interpreter/components/runtimes/ObjectRuntime.ts +262 -224
- package/src/interpreter/errors.ts +68 -47
- package/src/interpreter/index.ts +50 -52
- package/src/interpreter/primitives/YuValue.ts +64 -0
- package/src/interpreter/primitives/capabilities.ts +111 -0
- package/src/interpreter/primitives/entities/LazyList.ts +225 -0
- package/src/interpreter/primitives/entities/LogicResult.ts +133 -0
- package/src/interpreter/primitives/entities/RuntimeClass.ts +70 -0
- package/src/interpreter/primitives/entities/RuntimeFunction.ts +108 -0
- package/src/interpreter/primitives/entities/RuntimeObject.ts +110 -0
- package/src/interpreter/primitives/entities/RuntimePredicate.ts +77 -0
- package/src/interpreter/primitives/index.ts +17 -0
- package/src/interpreter/primitives/scalars/YuBoolean.ts +79 -0
- package/src/interpreter/primitives/scalars/YuChar.ts +94 -0
- package/src/interpreter/primitives/scalars/YuNil.ts +84 -0
- package/src/interpreter/primitives/scalars/YuNumber.ts +187 -0
- package/src/interpreter/primitives/sequences/YuArray.ts +178 -0
- package/src/interpreter/primitives/sequences/YuString.ts +165 -0
- package/src/interpreter/utils.ts +105 -84
- package/src/tester/index.ts +157 -128
- package/src/utils/helpers.ts +81 -168
- package/tests/analyzer/functional.spec.ts +221 -207
- package/tests/analyzer/generic.spec.ts +178 -178
- package/tests/analyzer/helpers.spec.ts +83 -89
- package/tests/analyzer/logic.spec.ts +237 -237
- package/tests/analyzer/oop.spec.ts +320 -323
- package/tests/analyzer/transitive.spec.ts +166 -166
- package/tests/interpreter/EnvBuilder.spec.ts +181 -183
- package/tests/interpreter/FunctionRuntime.spec.ts +224 -223
- package/tests/interpreter/LazyRuntime.spec.ts +227 -225
- package/tests/interpreter/LogicEngine.spec.ts +371 -327
- package/tests/interpreter/LogicSubstitution.spec.ts +90 -80
- package/tests/interpreter/ObjectRuntime.spec.ts +431 -606
- package/tests/interpreter/Operations.spec.ts +312 -220
- package/tests/interpreter/PatternSystem.spec.ts +254 -213
- package/tests/interpreter/Tests.spec.ts +122 -122
- package/tests/interpreter/interpreter.spec.ts +1143 -991
- package/tests/kernel/YukigoKernel.spec.ts +112 -0
- package/tests/tester/Tester.spec.ts +188 -152
- package/tsconfig.build.json +16 -15
- package/tsconfig.json +27 -25
- package/dist/interpreter/components/Visitor.d.ts +0 -70
- package/dist/interpreter/components/Visitor.js +0 -634
- package/dist/interpreter/entities.d.ts +0 -105
- package/dist/interpreter/entities.js +0 -96
- package/dist/interpreter/trampoline.d.ts +0 -17
- package/dist/interpreter/trampoline.js +0 -38
- package/dist/src/analyzer/GraphBuilder.d.ts +0 -30
- package/dist/src/analyzer/GraphBuilder.js +0 -100
- package/dist/src/analyzer/index.d.ts +0 -59
- package/dist/src/analyzer/index.js +0 -152
- package/dist/src/analyzer/inspections/functional/functional.d.ts +0 -44
- package/dist/src/analyzer/inspections/functional/functional.js +0 -149
- package/dist/src/analyzer/inspections/functional/smells.d.ts +0 -16
- package/dist/src/analyzer/inspections/functional/smells.js +0 -98
- package/dist/src/analyzer/inspections/generic/generic.d.ts +0 -178
- package/dist/src/analyzer/inspections/generic/generic.js +0 -604
- package/dist/src/analyzer/inspections/generic/smells.d.ts +0 -61
- package/dist/src/analyzer/inspections/generic/smells.js +0 -349
- package/dist/src/analyzer/inspections/imperative/imperative.d.ts +0 -35
- package/dist/src/analyzer/inspections/imperative/imperative.js +0 -109
- package/dist/src/analyzer/inspections/imperative/smells.d.ts +0 -16
- package/dist/src/analyzer/inspections/imperative/smells.js +0 -58
- package/dist/src/analyzer/inspections/logic/logic.d.ts +0 -32
- package/dist/src/analyzer/inspections/logic/logic.js +0 -96
- package/dist/src/analyzer/inspections/logic/smells.d.ts +0 -15
- package/dist/src/analyzer/inspections/logic/smells.js +0 -60
- package/dist/src/analyzer/inspections/object/object.d.ts +0 -90
- package/dist/src/analyzer/inspections/object/object.js +0 -321
- package/dist/src/analyzer/inspections/object/smells.d.ts +0 -30
- package/dist/src/analyzer/inspections/object/smells.js +0 -135
- package/dist/src/analyzer/utils.d.ts +0 -30
- package/dist/src/analyzer/utils.js +0 -78
- package/dist/src/index.d.ts +0 -4
- package/dist/src/index.js +0 -4
- package/dist/src/interpreter/components/EnvBuilder.d.ts +0 -21
- package/dist/src/interpreter/components/EnvBuilder.js +0 -155
- package/dist/src/interpreter/components/Operations.d.ts +0 -14
- package/dist/src/interpreter/components/Operations.js +0 -84
- package/dist/src/interpreter/components/PatternMatcher.d.ts +0 -73
- package/dist/src/interpreter/components/PatternMatcher.js +0 -358
- package/dist/src/interpreter/components/RuntimeContext.d.ts +0 -35
- package/dist/src/interpreter/components/RuntimeContext.js +0 -93
- package/dist/src/interpreter/components/TestRunner.d.ts +0 -19
- package/dist/src/interpreter/components/TestRunner.js +0 -110
- package/dist/src/interpreter/components/Visitor.d.ts +0 -71
- package/dist/src/interpreter/components/Visitor.js +0 -638
- package/dist/src/interpreter/components/logic/LogicEngine.d.ts +0 -29
- package/dist/src/interpreter/components/logic/LogicEngine.js +0 -259
- package/dist/src/interpreter/components/logic/LogicResolver.d.ts +0 -53
- package/dist/src/interpreter/components/logic/LogicResolver.js +0 -484
- package/dist/src/interpreter/components/logic/LogicTranslator.d.ts +0 -14
- package/dist/src/interpreter/components/logic/LogicTranslator.js +0 -99
- package/dist/src/interpreter/components/runtimes/FunctionRuntime.d.ts +0 -12
- package/dist/src/interpreter/components/runtimes/FunctionRuntime.js +0 -149
- package/dist/src/interpreter/components/runtimes/LazyRuntime.d.ts +0 -19
- package/dist/src/interpreter/components/runtimes/LazyRuntime.js +0 -269
- package/dist/src/interpreter/components/runtimes/ObjectRuntime.d.ts +0 -35
- package/dist/src/interpreter/components/runtimes/ObjectRuntime.js +0 -126
- package/dist/src/interpreter/errors.d.ts +0 -19
- package/dist/src/interpreter/errors.js +0 -36
- package/dist/src/interpreter/index.d.ts +0 -24
- package/dist/src/interpreter/index.js +0 -41
- package/dist/src/interpreter/trampoline.d.ts +0 -17
- package/dist/src/interpreter/trampoline.js +0 -38
- package/dist/src/interpreter/utils.d.ts +0 -11
- package/dist/src/interpreter/utils.js +0 -65
- package/dist/src/tester/index.d.ts +0 -25
- package/dist/src/tester/index.js +0 -113
- package/dist/src/utils/helpers.d.ts +0 -13
- package/dist/src/utils/helpers.js +0 -52
- package/src/interpreter/components/Visitor.ts +0 -1065
- package/src/interpreter/trampoline.ts +0 -71
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { StepCommand, BindCommand, } from "../../components/kernel/commands.js";
|
|
2
|
+
import { NotConcatenable } from "../../errors.js";
|
|
3
|
+
import { boolean, error, raise } from "../../utils.js";
|
|
4
|
+
import { YuNil } from "../scalars/YuNil.js";
|
|
5
|
+
import { YuArray } from "../sequences/YuArray.js";
|
|
6
|
+
import { YuValue } from "../YuValue.js";
|
|
7
|
+
/**
|
|
8
|
+
* Represents the result of forcing one step of a LazyList.
|
|
9
|
+
* If null, the list is empty.
|
|
10
|
+
*/
|
|
11
|
+
export class LazyStepResult extends YuValue {
|
|
12
|
+
head;
|
|
13
|
+
tail;
|
|
14
|
+
constructor(head, tail) {
|
|
15
|
+
super();
|
|
16
|
+
this.head = head;
|
|
17
|
+
this.tail = tail;
|
|
18
|
+
}
|
|
19
|
+
get asStepResult() {
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
equals(other) {
|
|
23
|
+
return boolean(other === this);
|
|
24
|
+
}
|
|
25
|
+
compare(other) {
|
|
26
|
+
return raise(error("LazyStepResult", "Step results are not comparable"));
|
|
27
|
+
}
|
|
28
|
+
toString() {
|
|
29
|
+
return `StepResult(${this.head}, ${this.tail})`;
|
|
30
|
+
}
|
|
31
|
+
toJSON() {
|
|
32
|
+
return { head: this.head.toJSON(), tail: this.tail?.toJSON() };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A LazyList represents a potentially infinite sequence of values evaluated on demand.
|
|
37
|
+
*/
|
|
38
|
+
export class LazyList extends YuValue {
|
|
39
|
+
producer;
|
|
40
|
+
identifier;
|
|
41
|
+
capturedContext;
|
|
42
|
+
// Use 'undefined' for un-evaluated, 'null' for empty list.
|
|
43
|
+
memoized = undefined;
|
|
44
|
+
constructor(producer, identifier = "lazy", capturedContext) {
|
|
45
|
+
super();
|
|
46
|
+
this.producer = producer;
|
|
47
|
+
this.identifier = identifier;
|
|
48
|
+
this.capturedContext = capturedContext;
|
|
49
|
+
}
|
|
50
|
+
equals(other) {
|
|
51
|
+
return boolean(other === this);
|
|
52
|
+
}
|
|
53
|
+
compare(other) {
|
|
54
|
+
return raise(error("LazyList.compare", "LazyLists are not comparable"));
|
|
55
|
+
}
|
|
56
|
+
get asSequence() {
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
*[Symbol.iterator]() {
|
|
60
|
+
throw new Error("Cannot synchronously iterate a LazyList. Use realize() or step().");
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Evaluates the first element of the list and returns it along with the tail.
|
|
64
|
+
*/
|
|
65
|
+
step() {
|
|
66
|
+
if (this.memoized !== undefined) {
|
|
67
|
+
return new StepCommand(this.memoized === null ? YuNil.getInstance() : this.memoized);
|
|
68
|
+
}
|
|
69
|
+
return new BindCommand(this.producer(this.capturedContext), (result) => {
|
|
70
|
+
if (result === null ||
|
|
71
|
+
result === undefined ||
|
|
72
|
+
result instanceof YuNil) {
|
|
73
|
+
this.memoized = null;
|
|
74
|
+
}
|
|
75
|
+
else if (result instanceof LazyStepResult) {
|
|
76
|
+
this.memoized = result;
|
|
77
|
+
}
|
|
78
|
+
else if (result instanceof YuValue) {
|
|
79
|
+
this.memoized = new LazyStepResult(result, null);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// Fallback for raw JS values if any still exist
|
|
83
|
+
return raise(error("LazyList.step", "LazyList producer returned non-YuValue"));
|
|
84
|
+
}
|
|
85
|
+
return new StepCommand(this.memoized === null ? YuNil.getInstance() : this.memoized);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
size() {
|
|
89
|
+
return raise(error("[LazyList.size]", "Cannot calculate the length of a LazyList"));
|
|
90
|
+
}
|
|
91
|
+
realize() {
|
|
92
|
+
const result = [];
|
|
93
|
+
const next = (list) => {
|
|
94
|
+
return new BindCommand(list.step(), (stepRes) => {
|
|
95
|
+
if (stepRes instanceof YuNil)
|
|
96
|
+
return new StepCommand(new YuArray(result));
|
|
97
|
+
if (!(stepRes instanceof LazyStepResult))
|
|
98
|
+
return raise(error("LazyList.realize", "LazyList step did not return LazyStepResult"));
|
|
99
|
+
result.push(stepRes.head);
|
|
100
|
+
if (stepRes.tail) {
|
|
101
|
+
const tailSeq = stepRes.tail.asSequence;
|
|
102
|
+
if (tailSeq)
|
|
103
|
+
return next(tailSeq);
|
|
104
|
+
}
|
|
105
|
+
return new StepCommand(new YuArray(result));
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
return next(this);
|
|
109
|
+
}
|
|
110
|
+
concat(other) {
|
|
111
|
+
const rightSeq = other.asSequence;
|
|
112
|
+
if (!rightSeq)
|
|
113
|
+
return raise(error("LazyList.concat", "Cannot concatenate with a non-sequence"));
|
|
114
|
+
return new StepCommand(this.createLazyConcat(this, rightSeq));
|
|
115
|
+
}
|
|
116
|
+
concatWithArray(arr) {
|
|
117
|
+
const leftSeq = arr.asSequence;
|
|
118
|
+
if (!leftSeq)
|
|
119
|
+
return raise(new NotConcatenable());
|
|
120
|
+
return new StepCommand(this.createLazyConcat(leftSeq, this));
|
|
121
|
+
}
|
|
122
|
+
concatWithString(str) {
|
|
123
|
+
const leftSeq = str.asSequence;
|
|
124
|
+
if (!leftSeq)
|
|
125
|
+
return raise(new NotConcatenable());
|
|
126
|
+
return new StepCommand(this.createLazyConcat(leftSeq, this));
|
|
127
|
+
}
|
|
128
|
+
createLazyConcat(left, right) {
|
|
129
|
+
return new LazyList((ctx) => {
|
|
130
|
+
// Step through the left sequence first
|
|
131
|
+
return new BindCommand(left.step(), (stepRes) => {
|
|
132
|
+
// if left is exhausted, fallback immediately to stepping the right sequence
|
|
133
|
+
if (stepRes.isNil)
|
|
134
|
+
return right.step();
|
|
135
|
+
// ensure we have a valid step result
|
|
136
|
+
const stepResult = stepRes.asStepResult;
|
|
137
|
+
if (!stepResult)
|
|
138
|
+
return raise(error("LazyList.createLazyConcat", "Invalid sequence step: Expected a StepResult"));
|
|
139
|
+
// recursively and lazily build the tail sequence
|
|
140
|
+
const nextTail = stepResult.tail && !stepResult.tail.isNil
|
|
141
|
+
? this.createLazyConcat(stepResult.tail, right)
|
|
142
|
+
: right;
|
|
143
|
+
return new StepCommand(new LazyStepResult(stepResult.head, nextTail));
|
|
144
|
+
});
|
|
145
|
+
}, `lazyConcat`, this.capturedContext);
|
|
146
|
+
}
|
|
147
|
+
toJSON() {
|
|
148
|
+
return {
|
|
149
|
+
identifier: this.identifier,
|
|
150
|
+
memoized: this.memoized === undefined
|
|
151
|
+
? "?"
|
|
152
|
+
: this.memoized === null
|
|
153
|
+
? "[]"
|
|
154
|
+
: this.memoized.toJSON(),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
toString() {
|
|
158
|
+
const state = this.memoized === undefined ? "?" : this.memoized === null ? "[]" : "...";
|
|
159
|
+
return `[LazyList ${this.identifier} ${state}]`;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
export function isLazyList(prim) {
|
|
163
|
+
return prim instanceof LazyList;
|
|
164
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ExecutionCommand } from "../../components/kernel/commands.js";
|
|
2
|
+
import { YuValue } from "../YuValue.js";
|
|
3
|
+
/**
|
|
4
|
+
* Interface for logic terms that can be treated as runtime values.
|
|
5
|
+
*/
|
|
6
|
+
export declare abstract class LogicTerm extends YuValue {
|
|
7
|
+
abstract readonly logicTermType: string;
|
|
8
|
+
abstract unify(other: LogicTerm, env: Substitution): ExecutionCommand;
|
|
9
|
+
abstract resolve(env: Substitution): LogicTerm;
|
|
10
|
+
abstract instantiate(env: Substitution, seen?: Set<number>): LogicTerm;
|
|
11
|
+
abstract toPrimitive(env: Substitution): YuValue;
|
|
12
|
+
abstract occurs(v: any, env: Substitution): boolean;
|
|
13
|
+
equals(other: YuValue): ExecutionCommand;
|
|
14
|
+
compare(other: YuValue): ExecutionCommand;
|
|
15
|
+
}
|
|
16
|
+
export declare function isLogicTerm(val: unknown): val is LogicTerm;
|
|
17
|
+
/**
|
|
18
|
+
* Substitution map that supports numeric IDs (internally) and string names (for results).
|
|
19
|
+
*/
|
|
20
|
+
export type Substitution = Map<string | number, LogicTerm>;
|
|
21
|
+
export declare class LogicAnswer extends YuValue {
|
|
22
|
+
private _success;
|
|
23
|
+
private _solution;
|
|
24
|
+
constructor(success: boolean, solution: Substitution);
|
|
25
|
+
equals(other: YuValue): ExecutionCommand;
|
|
26
|
+
compare(other: YuValue): ExecutionCommand;
|
|
27
|
+
isSuccessful(): boolean;
|
|
28
|
+
getSolution(): Substitution;
|
|
29
|
+
get success(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Returns a view of the solutions containing only string-named variables (for the user).
|
|
32
|
+
*/
|
|
33
|
+
get solutions(): Substitution;
|
|
34
|
+
toJSON(): unknown;
|
|
35
|
+
toString(): string;
|
|
36
|
+
}
|
|
37
|
+
export declare class LogicResult extends YuValue {
|
|
38
|
+
private answers;
|
|
39
|
+
constructor(answers: LogicAnswer[]);
|
|
40
|
+
equals(other: YuValue): ExecutionCommand;
|
|
41
|
+
compare(other: YuValue): ExecutionCommand;
|
|
42
|
+
get allAnswers(): LogicAnswer[];
|
|
43
|
+
getAllSuccessful(): LogicAnswer[];
|
|
44
|
+
allSuccessful(): boolean;
|
|
45
|
+
getSuccessfulSolutions(): Substitution[];
|
|
46
|
+
get success(): boolean;
|
|
47
|
+
get solutions(): Substitution;
|
|
48
|
+
toJSON(): unknown;
|
|
49
|
+
toString(): string;
|
|
50
|
+
}
|
|
51
|
+
export declare function isLogicResult(value: YuValue): value is LogicResult;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { boolean, error, raise } from "../../utils.js";
|
|
2
|
+
import { YuValue } from "../YuValue.js";
|
|
3
|
+
/**
|
|
4
|
+
* Interface for logic terms that can be treated as runtime values.
|
|
5
|
+
*/
|
|
6
|
+
export class LogicTerm extends YuValue {
|
|
7
|
+
equals(other) {
|
|
8
|
+
return boolean(this === other);
|
|
9
|
+
}
|
|
10
|
+
compare(other) {
|
|
11
|
+
return raise(error("LogicTerm.compare", `Comparison not supported for LogicTerm: ${this.logicTermType}`));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function isLogicTerm(val) {
|
|
15
|
+
return val !== null && typeof val === "object" && "logicTermType" in val;
|
|
16
|
+
}
|
|
17
|
+
export class LogicAnswer extends YuValue {
|
|
18
|
+
_success;
|
|
19
|
+
_solution;
|
|
20
|
+
constructor(success, solution) {
|
|
21
|
+
super();
|
|
22
|
+
this._success = success;
|
|
23
|
+
this._solution = solution;
|
|
24
|
+
}
|
|
25
|
+
equals(other) {
|
|
26
|
+
return boolean(other === this);
|
|
27
|
+
}
|
|
28
|
+
compare(other) {
|
|
29
|
+
return raise(error("LogicAnswer.compare", "LogicAnswer is not comparable"));
|
|
30
|
+
}
|
|
31
|
+
isSuccessful() {
|
|
32
|
+
return this._success;
|
|
33
|
+
}
|
|
34
|
+
getSolution() {
|
|
35
|
+
return this._solution;
|
|
36
|
+
}
|
|
37
|
+
get success() {
|
|
38
|
+
return this.isSuccessful();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns a view of the solutions containing only string-named variables (for the user).
|
|
42
|
+
*/
|
|
43
|
+
get solutions() {
|
|
44
|
+
return this._solution;
|
|
45
|
+
}
|
|
46
|
+
toJSON() {
|
|
47
|
+
const sol = {};
|
|
48
|
+
for (const [key, val] of this._solution) {
|
|
49
|
+
if (typeof key === "string")
|
|
50
|
+
sol[key] = val.toJSON();
|
|
51
|
+
}
|
|
52
|
+
return { success: this._success, solution: sol };
|
|
53
|
+
}
|
|
54
|
+
toString() {
|
|
55
|
+
return `Answer(${this._success})`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export class LogicResult extends YuValue {
|
|
59
|
+
answers;
|
|
60
|
+
constructor(answers) {
|
|
61
|
+
super();
|
|
62
|
+
this.answers = answers;
|
|
63
|
+
}
|
|
64
|
+
equals(other) {
|
|
65
|
+
return boolean(other === this);
|
|
66
|
+
}
|
|
67
|
+
compare(other) {
|
|
68
|
+
return raise(error("LogicResult.compare", "LogicResult is not comparable"));
|
|
69
|
+
}
|
|
70
|
+
get allAnswers() {
|
|
71
|
+
return this.answers;
|
|
72
|
+
}
|
|
73
|
+
getAllSuccessful() {
|
|
74
|
+
return this.answers.filter((answer) => answer.isSuccessful());
|
|
75
|
+
}
|
|
76
|
+
allSuccessful() {
|
|
77
|
+
return (this.answers.length > 0 &&
|
|
78
|
+
this.answers.every((answer) => answer.isSuccessful()));
|
|
79
|
+
}
|
|
80
|
+
getSuccessfulSolutions() {
|
|
81
|
+
return this.getAllSuccessful().map((ans) => ans.getSolution());
|
|
82
|
+
}
|
|
83
|
+
get success() {
|
|
84
|
+
return (this.answers.length > 0 && this.answers.every((a) => a.isSuccessful()));
|
|
85
|
+
}
|
|
86
|
+
get solutions() {
|
|
87
|
+
const answers = this.getAllSuccessful();
|
|
88
|
+
if (answers.length === 0)
|
|
89
|
+
return new Map();
|
|
90
|
+
return answers[0].solutions;
|
|
91
|
+
}
|
|
92
|
+
toJSON() {
|
|
93
|
+
return this.answers.map((a) => a.toJSON());
|
|
94
|
+
}
|
|
95
|
+
toString() {
|
|
96
|
+
return `LogicResult(${this.answers.length})`;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export function isLogicResult(value) {
|
|
100
|
+
return value instanceof LogicResult;
|
|
101
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ExecutionCommand } from "../../components/kernel/commands.js";
|
|
2
|
+
import { YuValue } from "../YuValue.js";
|
|
3
|
+
import { RuntimeFunction } from "./RuntimeFunction.js";
|
|
4
|
+
import { RuntimeObject } from "./RuntimeObject.js";
|
|
5
|
+
export declare class RuntimeClass extends YuValue {
|
|
6
|
+
identifier: string;
|
|
7
|
+
fields: Map<string, YuValue>;
|
|
8
|
+
methods: Map<string, RuntimeFunction>;
|
|
9
|
+
mixins: string[];
|
|
10
|
+
superclass?: string | undefined;
|
|
11
|
+
fieldInitializers?: Map<string, any> | undefined;
|
|
12
|
+
private isAbstract;
|
|
13
|
+
constructor(identifier: string, fields: Map<string, YuValue>, methods: Map<string, RuntimeFunction>, mixins: string[], superclass?: string | undefined, fieldInitializers?: Map<string, any> | undefined, isAbstract?: boolean);
|
|
14
|
+
equals(other: YuValue): ExecutionCommand;
|
|
15
|
+
compare(other: YuValue): ExecutionCommand;
|
|
16
|
+
getHierarchy(): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Creates a new instance of an Object.
|
|
19
|
+
*/
|
|
20
|
+
instantiate(identifier: string): RuntimeObject;
|
|
21
|
+
toJSON(): unknown;
|
|
22
|
+
toString(): string;
|
|
23
|
+
}
|
|
24
|
+
export declare function isRuntimeClass(val: YuValue): val is RuntimeClass;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { InterpreterError } from "../../errors.js";
|
|
2
|
+
import { boolean, error, raise } from "../../utils.js";
|
|
3
|
+
import { YuValue } from "../YuValue.js";
|
|
4
|
+
import { RuntimeObject } from "./RuntimeObject.js";
|
|
5
|
+
export class RuntimeClass extends YuValue {
|
|
6
|
+
identifier;
|
|
7
|
+
fields;
|
|
8
|
+
methods;
|
|
9
|
+
mixins;
|
|
10
|
+
superclass;
|
|
11
|
+
fieldInitializers;
|
|
12
|
+
isAbstract;
|
|
13
|
+
constructor(identifier, fields, methods, mixins, superclass, fieldInitializers, isAbstract = false) {
|
|
14
|
+
super();
|
|
15
|
+
this.identifier = identifier;
|
|
16
|
+
this.fields = fields;
|
|
17
|
+
this.methods = methods;
|
|
18
|
+
this.mixins = mixins;
|
|
19
|
+
this.superclass = superclass;
|
|
20
|
+
this.fieldInitializers = fieldInitializers;
|
|
21
|
+
this.isAbstract = isAbstract;
|
|
22
|
+
}
|
|
23
|
+
equals(other) {
|
|
24
|
+
return boolean(other === this);
|
|
25
|
+
}
|
|
26
|
+
compare(other) {
|
|
27
|
+
return raise(error("RuntimeClass.compare", "Classes are not comparable"));
|
|
28
|
+
}
|
|
29
|
+
getHierarchy() {
|
|
30
|
+
const hierarchy = [...this.mixins.reverse()];
|
|
31
|
+
if (this.superclass)
|
|
32
|
+
hierarchy.push(this.superclass);
|
|
33
|
+
return hierarchy;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a new instance of an Object.
|
|
37
|
+
*/
|
|
38
|
+
instantiate(identifier) {
|
|
39
|
+
if (this.isAbstract)
|
|
40
|
+
throw new InterpreterError("[ObjectRuntime]", `Cannot instantiate abstract class ${this.identifier}`);
|
|
41
|
+
return new RuntimeObject(identifier, this.identifier, new Map(this.fields), new Map());
|
|
42
|
+
}
|
|
43
|
+
toJSON() {
|
|
44
|
+
return {
|
|
45
|
+
identifier: this.identifier,
|
|
46
|
+
superclass: this.superclass,
|
|
47
|
+
mixins: this.mixins,
|
|
48
|
+
isAbstract: this.isAbstract,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
toString() {
|
|
52
|
+
return `[Class: ${this.identifier}]`;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function isRuntimeClass(val) {
|
|
56
|
+
return val instanceof RuntimeClass;
|
|
57
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Body, Pattern } from "yukigo-ast";
|
|
2
|
+
import { YuValue } from "../YuValue.js";
|
|
3
|
+
import { EnvStack, PrimitiveThunk } from "../../utils.js";
|
|
4
|
+
import { ExecutionCommand } from "../../components/kernel/commands.js";
|
|
5
|
+
export interface EquationRuntime {
|
|
6
|
+
patterns: Pattern[];
|
|
7
|
+
body: Body;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Runtime Function used in the Interpreter
|
|
11
|
+
*/
|
|
12
|
+
export declare class RuntimeFunction extends YuValue {
|
|
13
|
+
arity: number;
|
|
14
|
+
equations: EquationRuntime[];
|
|
15
|
+
identifier?: string | undefined;
|
|
16
|
+
pendingArgs?: (YuValue | PrimitiveThunk)[] | undefined;
|
|
17
|
+
closure?: EnvStack | undefined;
|
|
18
|
+
constructor(arity: number, equations: EquationRuntime[], identifier?: string | undefined, pendingArgs?: (YuValue | PrimitiveThunk)[] | undefined, closure?: EnvStack | undefined);
|
|
19
|
+
equals(other: YuValue): ExecutionCommand;
|
|
20
|
+
compare(other: YuValue): ExecutionCommand;
|
|
21
|
+
get name(): string;
|
|
22
|
+
get remainingArity(): number;
|
|
23
|
+
get isFullyApplied(): boolean;
|
|
24
|
+
get hasPendingArgs(): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Partially applies the function with new arguments.
|
|
27
|
+
*/
|
|
28
|
+
bind(...args: (YuValue | PrimitiveThunk)[]): RuntimeFunction;
|
|
29
|
+
/**
|
|
30
|
+
* Returns a new RuntimeFunction with the given closure.
|
|
31
|
+
*/
|
|
32
|
+
withClosure(closure: EnvStack): RuntimeFunction;
|
|
33
|
+
/**
|
|
34
|
+
* Evaluates all pending arguments (resolving thunks).
|
|
35
|
+
*/
|
|
36
|
+
getEvaluatedArgs(): YuValue[];
|
|
37
|
+
toJSON(): unknown;
|
|
38
|
+
toString(): string;
|
|
39
|
+
}
|
|
40
|
+
export declare function isRuntimeFunction(val: YuValue): val is RuntimeFunction;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { YuValue } from "../YuValue.js";
|
|
2
|
+
import { boolean, error, raise, } from "../../utils.js";
|
|
3
|
+
/**
|
|
4
|
+
* Runtime Function used in the Interpreter
|
|
5
|
+
*/
|
|
6
|
+
export class RuntimeFunction extends YuValue {
|
|
7
|
+
arity;
|
|
8
|
+
equations;
|
|
9
|
+
identifier;
|
|
10
|
+
pendingArgs;
|
|
11
|
+
closure;
|
|
12
|
+
constructor(arity, equations, identifier, pendingArgs, closure) {
|
|
13
|
+
super();
|
|
14
|
+
this.arity = arity;
|
|
15
|
+
this.equations = equations;
|
|
16
|
+
this.identifier = identifier;
|
|
17
|
+
this.pendingArgs = pendingArgs;
|
|
18
|
+
this.closure = closure;
|
|
19
|
+
}
|
|
20
|
+
equals(other) {
|
|
21
|
+
return boolean(other === this);
|
|
22
|
+
}
|
|
23
|
+
compare(other) {
|
|
24
|
+
return raise(error("RuntimeFunction.compare", "Functions are not comparable"));
|
|
25
|
+
}
|
|
26
|
+
get name() {
|
|
27
|
+
return this.identifier ?? "<anonymous>";
|
|
28
|
+
}
|
|
29
|
+
get remainingArity() {
|
|
30
|
+
return this.arity - (this.pendingArgs?.length ?? 0);
|
|
31
|
+
}
|
|
32
|
+
get isFullyApplied() {
|
|
33
|
+
return this.remainingArity <= 0;
|
|
34
|
+
}
|
|
35
|
+
get hasPendingArgs() {
|
|
36
|
+
return (this.pendingArgs?.length ?? 0) > 0;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Partially applies the function with new arguments.
|
|
40
|
+
*/
|
|
41
|
+
bind(...args) {
|
|
42
|
+
return new RuntimeFunction(this.arity, this.equations, this.identifier, [...(this.pendingArgs ?? []), ...args], this.closure);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns a new RuntimeFunction with the given closure.
|
|
46
|
+
*/
|
|
47
|
+
withClosure(closure) {
|
|
48
|
+
return new RuntimeFunction(this.arity, this.equations, this.identifier, this.pendingArgs, closure);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Evaluates all pending arguments (resolving thunks).
|
|
52
|
+
*/
|
|
53
|
+
getEvaluatedArgs() {
|
|
54
|
+
return (this.pendingArgs ?? []).map((arg) => typeof arg === "function" ? arg() : arg);
|
|
55
|
+
}
|
|
56
|
+
toJSON() {
|
|
57
|
+
return {
|
|
58
|
+
name: this.name,
|
|
59
|
+
arity: this.arity,
|
|
60
|
+
remainingArity: this.remainingArity,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
toString() {
|
|
64
|
+
const arityInfo = this.arity > 0 ? `/${this.arity}` : "";
|
|
65
|
+
const pendingInfo = this.hasPendingArgs
|
|
66
|
+
? ` (applied ${this.pendingArgs.length})`
|
|
67
|
+
: "";
|
|
68
|
+
return `[Function: ${this.name}${arityInfo}${pendingInfo}]`;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export function isRuntimeFunction(val) {
|
|
72
|
+
return val instanceof RuntimeFunction;
|
|
73
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ExecutionCommand } from "../../components/kernel/commands.js";
|
|
2
|
+
import { YuValue } from "../YuValue.js";
|
|
3
|
+
import { RuntimeClass } from "./RuntimeClass.js";
|
|
4
|
+
import { RuntimeFunction } from "./RuntimeFunction.js";
|
|
5
|
+
type OOPMatch = {
|
|
6
|
+
method: RuntimeFunction;
|
|
7
|
+
holder: RuntimeObject | RuntimeClass;
|
|
8
|
+
};
|
|
9
|
+
export declare class RuntimeObject extends YuValue {
|
|
10
|
+
identifier: string;
|
|
11
|
+
className: string;
|
|
12
|
+
fields: Map<string, YuValue>;
|
|
13
|
+
methods: Map<string, RuntimeFunction>;
|
|
14
|
+
constructor(identifier: string, className: string, fields: Map<string, YuValue>, methods: Map<string, RuntimeFunction>);
|
|
15
|
+
equals(other: YuValue): ExecutionCommand;
|
|
16
|
+
compare(other: YuValue): ExecutionCommand;
|
|
17
|
+
hasField(name: string): boolean;
|
|
18
|
+
getField(name: string): YuValue;
|
|
19
|
+
setField(name: string, value: YuValue): void;
|
|
20
|
+
getMethod(name: string): RuntimeFunction;
|
|
21
|
+
hasMethod(name: string): boolean;
|
|
22
|
+
createDispatchScope(match: OOPMatch, targetName: YuValue): Map<string, YuValue>;
|
|
23
|
+
toJSON(keyOrSeen?: string | Set<YuValue>): unknown;
|
|
24
|
+
toString(seen?: Set<YuValue>): string;
|
|
25
|
+
}
|
|
26
|
+
export declare function isRuntimeObject(val: YuValue): val is RuntimeObject;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { InterpreterError } from "../../errors.js";
|
|
2
|
+
import { boolean, error, raise } from "../../utils.js";
|
|
3
|
+
import { YuValue } from "../YuValue.js";
|
|
4
|
+
export class RuntimeObject extends YuValue {
|
|
5
|
+
identifier;
|
|
6
|
+
className;
|
|
7
|
+
fields;
|
|
8
|
+
methods;
|
|
9
|
+
constructor(identifier, className, fields, methods) {
|
|
10
|
+
super();
|
|
11
|
+
this.identifier = identifier;
|
|
12
|
+
this.className = className;
|
|
13
|
+
this.fields = fields;
|
|
14
|
+
this.methods = methods;
|
|
15
|
+
}
|
|
16
|
+
equals(other) {
|
|
17
|
+
return boolean(other === this);
|
|
18
|
+
}
|
|
19
|
+
compare(other) {
|
|
20
|
+
return raise(error("RuntimeClass.compare", "Objects are not comparable"));
|
|
21
|
+
}
|
|
22
|
+
hasField(name) {
|
|
23
|
+
return this.fields.has(name);
|
|
24
|
+
}
|
|
25
|
+
getField(name) {
|
|
26
|
+
if (!this.hasField(name))
|
|
27
|
+
throw new InterpreterError("[ObjectRuntime]", `Field '${name}' not found in ${this.className}`);
|
|
28
|
+
return this.fields.get(name);
|
|
29
|
+
}
|
|
30
|
+
setField(name, value) {
|
|
31
|
+
if (!this.hasField(name))
|
|
32
|
+
throw new InterpreterError("[ObjectRuntime]", `Cannot set unknown field '${name}'`);
|
|
33
|
+
this.fields.set(name, value);
|
|
34
|
+
}
|
|
35
|
+
getMethod(name) {
|
|
36
|
+
if (!this.hasMethod(name))
|
|
37
|
+
throw new InterpreterError("[ObjectRuntime]", `${this.className} does not understand '${name}`);
|
|
38
|
+
return this.methods.get(name);
|
|
39
|
+
}
|
|
40
|
+
hasMethod(name) {
|
|
41
|
+
return this.methods.has(name);
|
|
42
|
+
}
|
|
43
|
+
createDispatchScope(match, targetName) {
|
|
44
|
+
const objectScope = new Map();
|
|
45
|
+
objectScope.set("self", this);
|
|
46
|
+
objectScope.set("__CONTEXT_CLASS__", match.holder);
|
|
47
|
+
objectScope.set("__METHOD_NAME__", targetName);
|
|
48
|
+
for (const [key, val] of this.fields)
|
|
49
|
+
objectScope.set(key, val);
|
|
50
|
+
return objectScope;
|
|
51
|
+
}
|
|
52
|
+
toJSON(keyOrSeen) {
|
|
53
|
+
const seen = keyOrSeen instanceof Set ? keyOrSeen : new Set();
|
|
54
|
+
if (seen.has(this))
|
|
55
|
+
return { identifier: this.identifier, circular: true };
|
|
56
|
+
seen.add(this);
|
|
57
|
+
const fieldsJSON = {};
|
|
58
|
+
for (const [key, val] of this.fields)
|
|
59
|
+
fieldsJSON[key] = val.toJSON(seen);
|
|
60
|
+
seen.delete(this);
|
|
61
|
+
return {
|
|
62
|
+
identifier: this.identifier,
|
|
63
|
+
className: this.className,
|
|
64
|
+
fields: fieldsJSON,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
toString(seen = new Set()) {
|
|
68
|
+
if (seen.has(this))
|
|
69
|
+
return this.identifier || this.className || "object (circular)";
|
|
70
|
+
seen.add(this);
|
|
71
|
+
const fieldsArray = [];
|
|
72
|
+
for (const [k, v] of this.fields.entries()) {
|
|
73
|
+
fieldsArray.push(`${k}=${v ? v.toString(seen) : "nil"}`);
|
|
74
|
+
}
|
|
75
|
+
const name = this.identifier || this.className || "object";
|
|
76
|
+
seen.delete(this);
|
|
77
|
+
return `${name}[${fieldsArray.join(", ")}]`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export function isRuntimeObject(val) {
|
|
81
|
+
return val instanceof RuntimeObject;
|
|
82
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Fact, Rule, Visitor } from "yukigo-ast";
|
|
2
|
+
import { YuValue } from "../YuValue.js";
|
|
3
|
+
import { ExecutionCommand } from "../../components/kernel/commands.js";
|
|
4
|
+
export declare class RuntimePredicate extends YuValue {
|
|
5
|
+
identifier: string;
|
|
6
|
+
equations: (Fact | Rule)[];
|
|
7
|
+
readonly arity: number;
|
|
8
|
+
constructor(identifier: string, equations: (Fact | Rule)[]);
|
|
9
|
+
equals(other: YuValue): ExecutionCommand;
|
|
10
|
+
compare(other: YuValue): ExecutionCommand;
|
|
11
|
+
apply<T>(visitor: Visitor<T>): T[];
|
|
12
|
+
addClause(clause: Fact | Rule): void;
|
|
13
|
+
private validateClause;
|
|
14
|
+
validateArity(args: number): boolean;
|
|
15
|
+
private getArityFromClause;
|
|
16
|
+
toJSON(): unknown;
|
|
17
|
+
toString(): string;
|
|
18
|
+
}
|
|
19
|
+
export declare const isRuntimePredicate: (prim: unknown) => prim is RuntimePredicate;
|