yukigo 0.2.3 → 0.3.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/.mocharc.json +3 -3
- package/CHANGELOG.md +105 -40
- 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 +22 -14
- package/dist/analyzer/inspections/generic/generic.js +82 -60
- 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 +13 -5
- package/dist/utils/helpers.js +38 -85
- 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 -577
- 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 +113 -169
- 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 +156 -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,477 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ArithmeticBinaryOperation,
|
|
3
|
+
ArithmeticUnaryOperation,
|
|
4
|
+
AssignOperation,
|
|
5
|
+
BinaryOperation,
|
|
6
|
+
BitwiseBinaryOperation,
|
|
7
|
+
BitwiseUnaryOperation,
|
|
8
|
+
ComparisonOperation,
|
|
9
|
+
ListBinaryOperation,
|
|
10
|
+
ListUnaryOperation,
|
|
11
|
+
LogicalBinaryOperation,
|
|
12
|
+
LogicalUnaryOperation,
|
|
13
|
+
OperationVisitor,
|
|
14
|
+
StringOperation,
|
|
15
|
+
SymbolPrimitive,
|
|
16
|
+
UnaryOperation,
|
|
17
|
+
UnifyOperation,
|
|
18
|
+
} from "yukigo-ast";
|
|
19
|
+
import {
|
|
20
|
+
BindCommand,
|
|
21
|
+
EvalCommand,
|
|
22
|
+
ExecutionCommand,
|
|
23
|
+
FailCommand,
|
|
24
|
+
RaiseCommand,
|
|
25
|
+
StepCommand,
|
|
26
|
+
} from "../kernel/commands.js";
|
|
27
|
+
import { Constructor, EvaluatorBase } from "./BaseEvaluator.js";
|
|
28
|
+
import {
|
|
29
|
+
ArithmeticBinaryTable,
|
|
30
|
+
ArithmeticUnaryTable,
|
|
31
|
+
BinaryTable,
|
|
32
|
+
BitwiseBinaryTable,
|
|
33
|
+
BitwiseUnaryTable,
|
|
34
|
+
ComparisonOperationTable,
|
|
35
|
+
ListBinaryTable,
|
|
36
|
+
ListUnaryTable,
|
|
37
|
+
LogicalBinaryTable,
|
|
38
|
+
LogicalUnaryTable,
|
|
39
|
+
StringOperationTable,
|
|
40
|
+
UnaryTable,
|
|
41
|
+
} from "../Operations.js";
|
|
42
|
+
import { InterpreterError } from "../../errors.js";
|
|
43
|
+
import { YuSequence } from "../../primitives/capabilities.js";
|
|
44
|
+
import {
|
|
45
|
+
LazyList,
|
|
46
|
+
RuntimeObject,
|
|
47
|
+
YuBoolean,
|
|
48
|
+
YuNumber,
|
|
49
|
+
YuValue,
|
|
50
|
+
} from "../../primitives/index.js";
|
|
51
|
+
import { YukigoKernel } from "../kernel/index.js";
|
|
52
|
+
import { EqualityComparer } from "../EqualityComparer.js";
|
|
53
|
+
import { boolean, Environment, error, isTrue, raise } from "../../utils.js";
|
|
54
|
+
import { RuntimeContext } from "../RuntimeContext.js";
|
|
55
|
+
import { getLogicEngine } from "./utils.js";
|
|
56
|
+
|
|
57
|
+
const processBinary = <T extends YuValue>(
|
|
58
|
+
evaluator: EvaluatorBase,
|
|
59
|
+
node: BinaryOperation,
|
|
60
|
+
table: BinaryTable<T>,
|
|
61
|
+
typeGuard: (a: YuValue, b: YuValue) => boolean,
|
|
62
|
+
contextName: string,
|
|
63
|
+
): ExecutionCommand => {
|
|
64
|
+
return new BindCommand(evaluator.evaluate(node.left), (rawLeft) => {
|
|
65
|
+
return new BindCommand(evaluator.context.forceValue(rawLeft), (left) => {
|
|
66
|
+
return new BindCommand(evaluator.evaluate(node.right), (rawRight) => {
|
|
67
|
+
return new BindCommand(
|
|
68
|
+
evaluator.context.forceValue(rawRight),
|
|
69
|
+
(right) => {
|
|
70
|
+
if (!typeGuard(left, right)) {
|
|
71
|
+
return new FailCommand(
|
|
72
|
+
new InterpreterError(
|
|
73
|
+
contextName,
|
|
74
|
+
`Type mismatch: ${left.getType()}, ${right.getType()}`,
|
|
75
|
+
),
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const fn = table[node.operator];
|
|
80
|
+
if (!fn) {
|
|
81
|
+
return new FailCommand(
|
|
82
|
+
new InterpreterError(
|
|
83
|
+
contextName,
|
|
84
|
+
`Unknown op: ${node.operator}`,
|
|
85
|
+
),
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
return fn(left as T, right as T);
|
|
91
|
+
} catch (e) {
|
|
92
|
+
return new FailCommand(e as Error);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const processUnary = <T extends YuValue>(
|
|
102
|
+
evaluator: EvaluatorBase,
|
|
103
|
+
node: UnaryOperation,
|
|
104
|
+
table: UnaryTable<T>,
|
|
105
|
+
typeGuard: (a: YuValue) => boolean,
|
|
106
|
+
contextName: string,
|
|
107
|
+
): ExecutionCommand => {
|
|
108
|
+
return new BindCommand(evaluator.evaluate(node.operand), (rawOperand) => {
|
|
109
|
+
return new BindCommand(
|
|
110
|
+
evaluator.context.forceValue(rawOperand),
|
|
111
|
+
(operand) => {
|
|
112
|
+
if (!typeGuard(operand))
|
|
113
|
+
return new FailCommand(
|
|
114
|
+
new InterpreterError(
|
|
115
|
+
contextName,
|
|
116
|
+
`Type mismatch: ${operand.getType()}`,
|
|
117
|
+
),
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const fn = table[node.operator];
|
|
121
|
+
if (!fn)
|
|
122
|
+
return new FailCommand(
|
|
123
|
+
new InterpreterError(contextName, `Unknown op: ${node.operator}`),
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
return fn(operand as T);
|
|
128
|
+
} catch (e) {
|
|
129
|
+
return new FailCommand(e as Error);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export function OperationEvaluator<TBase extends Constructor<EvaluatorBase>>(
|
|
137
|
+
Base: TBase,
|
|
138
|
+
) {
|
|
139
|
+
return class extends Base implements OperationVisitor<ExecutionCommand> {
|
|
140
|
+
visitArithmeticUnaryOperation(
|
|
141
|
+
node: ArithmeticUnaryOperation,
|
|
142
|
+
): ExecutionCommand {
|
|
143
|
+
return processUnary(
|
|
144
|
+
this,
|
|
145
|
+
node,
|
|
146
|
+
ArithmeticUnaryTable,
|
|
147
|
+
(a) => !!a.asNumeric,
|
|
148
|
+
"ArithmeticUnaryOperation",
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
visitListUnaryOperation(node: ListUnaryOperation): ExecutionCommand {
|
|
152
|
+
return new BindCommand(this.evaluate(node.operand), (rawOperand) => {
|
|
153
|
+
return new BindCommand(
|
|
154
|
+
this.context.forceValue(rawOperand),
|
|
155
|
+
(operand) => {
|
|
156
|
+
if (!operand.asSequence)
|
|
157
|
+
return new FailCommand(
|
|
158
|
+
new InterpreterError(
|
|
159
|
+
"ListUnaryOperation",
|
|
160
|
+
`Expected Sequence but got ${operand.getType()}`,
|
|
161
|
+
),
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
return new BindCommand(
|
|
165
|
+
this.context.lazyRuntime.realizeList(operand),
|
|
166
|
+
(arr) => {
|
|
167
|
+
const seq = arr.asSequence;
|
|
168
|
+
if (!seq)
|
|
169
|
+
return new RaiseCommand(
|
|
170
|
+
new InterpreterError(
|
|
171
|
+
`[${node.operator}]`,
|
|
172
|
+
`Expected ${arr} to be a YuSequence.`,
|
|
173
|
+
),
|
|
174
|
+
);
|
|
175
|
+
const fn = ListUnaryTable[node.operator];
|
|
176
|
+
if (!fn)
|
|
177
|
+
return new FailCommand(
|
|
178
|
+
new InterpreterError(
|
|
179
|
+
"ListUnaryOperation",
|
|
180
|
+
`Unknown operator: ${node.operator}`,
|
|
181
|
+
),
|
|
182
|
+
);
|
|
183
|
+
return fn(seq);
|
|
184
|
+
},
|
|
185
|
+
);
|
|
186
|
+
},
|
|
187
|
+
);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
visitListBinaryOperation(node: ListBinaryOperation): ExecutionCommand {
|
|
191
|
+
if (node.operator === "Concat") {
|
|
192
|
+
const capturedCtx = this.context.clone();
|
|
193
|
+
return new BindCommand(this.evaluate(node.left), (rawLeft) => {
|
|
194
|
+
return new BindCommand(this.context.forceValue(rawLeft), (left) => {
|
|
195
|
+
const seqL = left.asSequence as YuSequence;
|
|
196
|
+
if (!seqL)
|
|
197
|
+
return new RaiseCommand(
|
|
198
|
+
new InterpreterError(
|
|
199
|
+
"ListBinaryOperation",
|
|
200
|
+
"Invalid left operand for lazy Concat",
|
|
201
|
+
),
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
if (this.context.config.lazyLoading) {
|
|
205
|
+
const lazyRight = new LazyList(
|
|
206
|
+
() => {
|
|
207
|
+
if (!capturedCtx.evaluatorFactory)
|
|
208
|
+
return new RaiseCommand(
|
|
209
|
+
new InterpreterError(
|
|
210
|
+
"ListBinaryOperation",
|
|
211
|
+
"EvaluatorFactory not initialized in RuntimeContext",
|
|
212
|
+
),
|
|
213
|
+
);
|
|
214
|
+
const subEvaluator =
|
|
215
|
+
capturedCtx.evaluatorFactory(capturedCtx);
|
|
216
|
+
const subKernel = new YukigoKernel(subEvaluator);
|
|
217
|
+
const rawRight = subKernel.run(new EvalCommand(node.right));
|
|
218
|
+
const right = subKernel.run(capturedCtx.forceValue(rawRight));
|
|
219
|
+
const seqR = right.asSequence as YuSequence;
|
|
220
|
+
if (!seqR)
|
|
221
|
+
return new RaiseCommand(
|
|
222
|
+
new InterpreterError(
|
|
223
|
+
"ListBinaryOperation",
|
|
224
|
+
"Invalid right operand for lazy Concat",
|
|
225
|
+
),
|
|
226
|
+
);
|
|
227
|
+
return seqR.step();
|
|
228
|
+
},
|
|
229
|
+
"LazyRight",
|
|
230
|
+
capturedCtx,
|
|
231
|
+
);
|
|
232
|
+
return this.context.lazyRuntime.evaluateConcat(seqL, lazyRight);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return new BindCommand(this.evaluate(node.right), (rawRight) => {
|
|
236
|
+
return new BindCommand(
|
|
237
|
+
this.context.forceValue(rawRight),
|
|
238
|
+
(right) => {
|
|
239
|
+
const seqR = right.asSequence as YuSequence;
|
|
240
|
+
if (!seqR)
|
|
241
|
+
return new RaiseCommand(
|
|
242
|
+
new InterpreterError(
|
|
243
|
+
"ListBinaryOperation",
|
|
244
|
+
"Invalid right operand for lazy Concat",
|
|
245
|
+
),
|
|
246
|
+
);
|
|
247
|
+
return seqL.concat(seqR);
|
|
248
|
+
},
|
|
249
|
+
);
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return processBinary(
|
|
256
|
+
this,
|
|
257
|
+
node,
|
|
258
|
+
ListBinaryTable,
|
|
259
|
+
(a, b) => !!a.asSequence && !!b.asSequence,
|
|
260
|
+
"ListBinaryOperation",
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
visitComparisonOperation(node: ComparisonOperation): ExecutionCommand {
|
|
264
|
+
return new BindCommand(this.evaluate(node.left), (rawLeft) => {
|
|
265
|
+
return new BindCommand(this.context.forceValue(rawLeft), (left) => {
|
|
266
|
+
return new BindCommand(this.evaluate(node.right), (rawRight) => {
|
|
267
|
+
return new BindCommand(
|
|
268
|
+
this.context.forceValue(rawRight),
|
|
269
|
+
(right) => {
|
|
270
|
+
if (node.operator === "Equal" || node.operator === "NotEqual") {
|
|
271
|
+
return new BindCommand(
|
|
272
|
+
EqualityComparer.compare(left, right, this.context),
|
|
273
|
+
(eq) => {
|
|
274
|
+
const isEq = isTrue(eq);
|
|
275
|
+
return new StepCommand(
|
|
276
|
+
new YuBoolean(node.operator === "Equal" ? isEq : !isEq),
|
|
277
|
+
);
|
|
278
|
+
},
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (left instanceof RuntimeObject) {
|
|
283
|
+
const objRuntime = this.context.objRuntime;
|
|
284
|
+
const chain = objRuntime.getResolutionChain(left);
|
|
285
|
+
const hasCompare =
|
|
286
|
+
!!objRuntime.findMethodInChain(chain, "compare/1") ||
|
|
287
|
+
!!objRuntime.findMethodInChain(chain, "compare");
|
|
288
|
+
if (hasCompare) {
|
|
289
|
+
return new BindCommand(
|
|
290
|
+
this.context.objRuntime.dispatch(left, "compare", [
|
|
291
|
+
right,
|
|
292
|
+
]),
|
|
293
|
+
(compRes) => {
|
|
294
|
+
if (compRes instanceof YuNumber) {
|
|
295
|
+
const val = compRes.value;
|
|
296
|
+
let isTrue = false;
|
|
297
|
+
if (node.operator === "GreaterOrEqualThan")
|
|
298
|
+
isTrue = val >= 0;
|
|
299
|
+
else if (node.operator === "GreaterThan")
|
|
300
|
+
isTrue = val > 0;
|
|
301
|
+
else if (node.operator === "LessOrEqualThan")
|
|
302
|
+
isTrue = val <= 0;
|
|
303
|
+
else if (node.operator === "LessThan")
|
|
304
|
+
isTrue = val < 0;
|
|
305
|
+
return new StepCommand(new YuBoolean(isTrue));
|
|
306
|
+
}
|
|
307
|
+
return new RaiseCommand(
|
|
308
|
+
new InterpreterError(
|
|
309
|
+
"ComparisonOperation",
|
|
310
|
+
"compare method did not return a number",
|
|
311
|
+
),
|
|
312
|
+
);
|
|
313
|
+
},
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (!ComparisonOperationTable[node.operator]) {
|
|
319
|
+
return new FailCommand(
|
|
320
|
+
new InterpreterError(
|
|
321
|
+
"ComparisonOperation",
|
|
322
|
+
`Unknown op: ${node.operator}`,
|
|
323
|
+
),
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
try {
|
|
327
|
+
return ComparisonOperationTable[node.operator](
|
|
328
|
+
left as any,
|
|
329
|
+
right as any,
|
|
330
|
+
);
|
|
331
|
+
} catch (error) {
|
|
332
|
+
return new FailCommand(
|
|
333
|
+
new InterpreterError(
|
|
334
|
+
"ComparisonOperation",
|
|
335
|
+
(error as Error).message,
|
|
336
|
+
),
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
);
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
visitLogicalBinaryOperation(
|
|
346
|
+
node: LogicalBinaryOperation,
|
|
347
|
+
): ExecutionCommand {
|
|
348
|
+
return new BindCommand(this.evaluate(node.left), (left) => {
|
|
349
|
+
const logicValue = left.asLogic;
|
|
350
|
+
if (!logicValue)
|
|
351
|
+
return new FailCommand(
|
|
352
|
+
new InterpreterError(
|
|
353
|
+
"LogicalBinaryOperation",
|
|
354
|
+
`Expected left side to be boolean and got: ${left}`,
|
|
355
|
+
),
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
if (this.context.config.lazyLoading) {
|
|
359
|
+
if (node.operator === "And") {
|
|
360
|
+
const val = logicValue.toJSON();
|
|
361
|
+
if (val === false) return boolean(false);
|
|
362
|
+
}
|
|
363
|
+
if (node.operator === "Or") {
|
|
364
|
+
const val = logicValue.toJSON();
|
|
365
|
+
if (val === true) return boolean(true);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const fn = LogicalBinaryTable[node.operator];
|
|
370
|
+
if (!fn)
|
|
371
|
+
return new FailCommand(
|
|
372
|
+
new InterpreterError(
|
|
373
|
+
"LogicalBinaryOperation",
|
|
374
|
+
`Unknown operator '${node.operator}'`,
|
|
375
|
+
),
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
return fn(logicValue, () => this.evaluate(node.right));
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
visitLogicalUnaryOperation(node: LogicalUnaryOperation): ExecutionCommand {
|
|
382
|
+
return processUnary(
|
|
383
|
+
this,
|
|
384
|
+
node,
|
|
385
|
+
LogicalUnaryTable,
|
|
386
|
+
(a) => !!a.asLogic,
|
|
387
|
+
"LogicalUnaryOperation",
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
visitBitwiseBinaryOperation(
|
|
391
|
+
node: BitwiseBinaryOperation,
|
|
392
|
+
): ExecutionCommand {
|
|
393
|
+
return processBinary(
|
|
394
|
+
this,
|
|
395
|
+
node,
|
|
396
|
+
BitwiseBinaryTable,
|
|
397
|
+
(a, b) => !!a.asNumeric && !!b.asNumeric,
|
|
398
|
+
"BitwiseBinaryOperation",
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
visitBitwiseUnaryOperation(node: BitwiseUnaryOperation): ExecutionCommand {
|
|
402
|
+
return processUnary(
|
|
403
|
+
this,
|
|
404
|
+
node,
|
|
405
|
+
BitwiseUnaryTable,
|
|
406
|
+
(a) => !!a.asNumeric,
|
|
407
|
+
"BitwiseUnaryOperation",
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
visitStringOperation(node: StringOperation): ExecutionCommand {
|
|
411
|
+
return processBinary(
|
|
412
|
+
this,
|
|
413
|
+
node,
|
|
414
|
+
StringOperationTable,
|
|
415
|
+
(a, b) => !!a.asSummable && !!b.asSummable,
|
|
416
|
+
"StringOperation",
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
visitUnifyOperation(node: UnifyOperation): ExecutionCommand {
|
|
420
|
+
return getLogicEngine(this, this.context).unifyExpr(
|
|
421
|
+
node.left,
|
|
422
|
+
node.right,
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
visitAssignOperation(node: AssignOperation): ExecutionCommand {
|
|
426
|
+
if (!this.context.config.mutability) {
|
|
427
|
+
return raise(
|
|
428
|
+
error(
|
|
429
|
+
"AssignOperation",
|
|
430
|
+
`Cannot perform assignment operation: mutability is disabled`,
|
|
431
|
+
),
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (!(node.left instanceof SymbolPrimitive))
|
|
436
|
+
return new FailCommand(
|
|
437
|
+
new InterpreterError(
|
|
438
|
+
"AssignOperation",
|
|
439
|
+
"Left side must be a SymbolPrimitive",
|
|
440
|
+
),
|
|
441
|
+
);
|
|
442
|
+
const name = node.left.value;
|
|
443
|
+
|
|
444
|
+
return new BindCommand(this.evaluate(node.right), (value) => {
|
|
445
|
+
const onReplace = (scope: Environment) => {
|
|
446
|
+
if (scope.has("self")) {
|
|
447
|
+
const self = scope.get("self");
|
|
448
|
+
if (self instanceof RuntimeObject && self.fields.has(name)) {
|
|
449
|
+
self.fields.set(name, value);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
if (!this.context.replace(name, value, onReplace)) {
|
|
455
|
+
this.context.define(name, value);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return boolean(true);
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
visitArithmeticBinaryOperation(node: ArithmeticBinaryOperation) {
|
|
462
|
+
const isPlus = node.operator === "Plus";
|
|
463
|
+
const summablePair = (a: YuValue, b: YuValue) =>
|
|
464
|
+
!!a.asSummable && !!b.asSummable;
|
|
465
|
+
const numericPair = (a: YuValue, b: YuValue) =>
|
|
466
|
+
!!a.asNumeric && !!b.asNumeric;
|
|
467
|
+
|
|
468
|
+
return processBinary(
|
|
469
|
+
this,
|
|
470
|
+
node,
|
|
471
|
+
ArithmeticBinaryTable,
|
|
472
|
+
isPlus ? summablePair : numericPair,
|
|
473
|
+
"ArithmeticBinaryOperation",
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BooleanPrimitive,
|
|
3
|
+
CharPrimitive,
|
|
4
|
+
ListPrimitive,
|
|
5
|
+
NilPrimitive,
|
|
6
|
+
NumberPrimitive,
|
|
7
|
+
PrimitiveVisitor,
|
|
8
|
+
StringPrimitive,
|
|
9
|
+
SymbolPrimitive,
|
|
10
|
+
} from "yukigo-ast";
|
|
11
|
+
import {
|
|
12
|
+
BindCommand,
|
|
13
|
+
ExecutionCommand,
|
|
14
|
+
FailCommand,
|
|
15
|
+
StepCommand,
|
|
16
|
+
} from "../kernel/commands.js";
|
|
17
|
+
import { Constructor, EvaluatorBase } from "./BaseEvaluator.js";
|
|
18
|
+
import {
|
|
19
|
+
YuArray,
|
|
20
|
+
YuBoolean,
|
|
21
|
+
YuNil,
|
|
22
|
+
YuNumber,
|
|
23
|
+
YuString,
|
|
24
|
+
YuValue,
|
|
25
|
+
} from "../../primitives/index.js";
|
|
26
|
+
import { InterpreterError } from "../../errors.js";
|
|
27
|
+
|
|
28
|
+
export function PrimitiveEvaluator<TBase extends Constructor<EvaluatorBase>>(
|
|
29
|
+
Base: TBase,
|
|
30
|
+
) {
|
|
31
|
+
return class extends Base implements PrimitiveVisitor<ExecutionCommand> {
|
|
32
|
+
visitStringPrimitive(node: StringPrimitive): ExecutionCommand {
|
|
33
|
+
return new StepCommand(new YuString(node.value));
|
|
34
|
+
}
|
|
35
|
+
visitListPrimitive(node: ListPrimitive): ExecutionCommand {
|
|
36
|
+
if (node.value.length === 0) return new StepCommand(new YuArray([]));
|
|
37
|
+
|
|
38
|
+
const results: YuValue[] = [];
|
|
39
|
+
const evaluateNext = (index: number): ExecutionCommand => {
|
|
40
|
+
if (index >= node.value.length)
|
|
41
|
+
return new StepCommand(new YuArray(results));
|
|
42
|
+
|
|
43
|
+
return new BindCommand(this.evaluate(node.value[index]), (val) => {
|
|
44
|
+
results.push(val);
|
|
45
|
+
return evaluateNext(index + 1);
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return evaluateNext(0);
|
|
50
|
+
}
|
|
51
|
+
visitNilPrimitive(node: NilPrimitive): ExecutionCommand {
|
|
52
|
+
return new StepCommand(YuNil.getInstance());
|
|
53
|
+
}
|
|
54
|
+
visitSymbolPrimitive(node: SymbolPrimitive): ExecutionCommand {
|
|
55
|
+
try {
|
|
56
|
+
const isLogic = !!this.context.logicState;
|
|
57
|
+
const isVar = /^[A-Z_]/.test(node.value);
|
|
58
|
+
if (isLogic && !isVar && !this.context.isDefined(node.value)) {
|
|
59
|
+
return new StepCommand(new YuString(node.value));
|
|
60
|
+
}
|
|
61
|
+
const val = this.context.lookup(node.value);
|
|
62
|
+
return new StepCommand(val);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
return new FailCommand(
|
|
65
|
+
new InterpreterError("Symbol Lookup", (error as Error).message),
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
visitCharPrimitive(node: CharPrimitive): ExecutionCommand {
|
|
70
|
+
return new StepCommand(new YuString(node.value));
|
|
71
|
+
}
|
|
72
|
+
visitNumberPrimitive(node: NumberPrimitive): ExecutionCommand {
|
|
73
|
+
return new StepCommand(new YuNumber(node.value));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
visitBooleanPrimitive(node: BooleanPrimitive): ExecutionCommand {
|
|
77
|
+
return new StepCommand(new YuBoolean(node.value));
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|