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,203 @@
|
|
|
1
|
+
import { YukigoKernel } from "./index.js";
|
|
2
|
+
import { ListTerm } from "../logic/LogicTerm.js";
|
|
3
|
+
import { isLogicResult, LogicResult, LogicAnswer, } from "../../primitives/index.js";
|
|
4
|
+
import { InterpreterVisitor } from "../evaluators/index.js";
|
|
5
|
+
/**
|
|
6
|
+
* Commands the Kernel to evaluate an AST node.
|
|
7
|
+
*/
|
|
8
|
+
export class EvalCommand {
|
|
9
|
+
node;
|
|
10
|
+
name = "EVAL";
|
|
11
|
+
constructor(node) {
|
|
12
|
+
this.node = node;
|
|
13
|
+
}
|
|
14
|
+
execute(kernel) {
|
|
15
|
+
return kernel.evaluator.evaluate(this.node);
|
|
16
|
+
}
|
|
17
|
+
createTraceEntry() {
|
|
18
|
+
const { constructor, loc } = this.node;
|
|
19
|
+
const frame = {
|
|
20
|
+
nodeType: constructor.name,
|
|
21
|
+
loc,
|
|
22
|
+
};
|
|
23
|
+
const startLoc = loc ? `${loc.line}:${loc.column}:` : "";
|
|
24
|
+
const key = `${startLoc}${constructor.name}`;
|
|
25
|
+
return { key, frame };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Commands the Kernel to move to the next step with a produced value.
|
|
30
|
+
* It triggers the popping of the continuation stack in the kernel.
|
|
31
|
+
*/
|
|
32
|
+
export class StepCommand {
|
|
33
|
+
value;
|
|
34
|
+
name = "STEP";
|
|
35
|
+
constructor(value) {
|
|
36
|
+
this.value = value;
|
|
37
|
+
}
|
|
38
|
+
execute(kernel) {
|
|
39
|
+
return kernel.popAndExecute(this.value);
|
|
40
|
+
}
|
|
41
|
+
createTraceEntry() { }
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Commands the Kernel to bind a produced value to a continuation.
|
|
45
|
+
* It pushes the continuation to the kernel's stack and proceeds with the command.
|
|
46
|
+
*/
|
|
47
|
+
export class BindCommand {
|
|
48
|
+
command;
|
|
49
|
+
next;
|
|
50
|
+
name = "BIND";
|
|
51
|
+
constructor(command, next) {
|
|
52
|
+
this.command = command;
|
|
53
|
+
this.next = next;
|
|
54
|
+
}
|
|
55
|
+
execute(kernel) {
|
|
56
|
+
kernel.pushContinuation(this.next);
|
|
57
|
+
return this.command;
|
|
58
|
+
}
|
|
59
|
+
createTraceEntry() { }
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Commands the Kernel to handle multiple branches of execution (non-determinism).
|
|
63
|
+
* It will try the first one and save the others as choice points.
|
|
64
|
+
*/
|
|
65
|
+
export class ChoiceCommand {
|
|
66
|
+
alternatives;
|
|
67
|
+
name = "CHOICE";
|
|
68
|
+
constructor(alternatives) {
|
|
69
|
+
this.alternatives = alternatives;
|
|
70
|
+
}
|
|
71
|
+
execute(kernel) {
|
|
72
|
+
return kernel.handleChoice(this.alternatives);
|
|
73
|
+
}
|
|
74
|
+
createTraceEntry() { }
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Commands the Kernel to halt execution due to an error.
|
|
78
|
+
*/
|
|
79
|
+
export class FailCommand {
|
|
80
|
+
error;
|
|
81
|
+
name = "FAIL";
|
|
82
|
+
constructor(error) {
|
|
83
|
+
this.error = error;
|
|
84
|
+
}
|
|
85
|
+
execute(kernel) {
|
|
86
|
+
throw kernel.buildSemanticError(this.error);
|
|
87
|
+
}
|
|
88
|
+
createTraceEntry() { }
|
|
89
|
+
}
|
|
90
|
+
// error handling commands
|
|
91
|
+
export class RaiseCommand {
|
|
92
|
+
exceptionObj;
|
|
93
|
+
name = "RAISE";
|
|
94
|
+
constructor(exceptionObj) {
|
|
95
|
+
this.exceptionObj = exceptionObj;
|
|
96
|
+
}
|
|
97
|
+
execute(kernel) {
|
|
98
|
+
// Le decimos al kernel que inicie el proceso de desapilado para buscar un Catch
|
|
99
|
+
return kernel.handleRaise(this.exceptionObj);
|
|
100
|
+
}
|
|
101
|
+
createTraceEntry() { }
|
|
102
|
+
}
|
|
103
|
+
export class CatchCommand {
|
|
104
|
+
handler;
|
|
105
|
+
innerCommand;
|
|
106
|
+
name = "CATCH";
|
|
107
|
+
constructor(handler, innerCommand // El cuerpo del try
|
|
108
|
+
) {
|
|
109
|
+
this.handler = handler;
|
|
110
|
+
this.innerCommand = innerCommand;
|
|
111
|
+
}
|
|
112
|
+
execute(kernel) {
|
|
113
|
+
// 1. Registramos este manejador de errores en el Kernel
|
|
114
|
+
kernel.pushCatchHandler(this.handler);
|
|
115
|
+
// 2. Ejecutamos el cuerpo del try envuelto en una limpieza
|
|
116
|
+
// Si el innerCommand termina con éxito (sin errores), necesitamos sacar el handler de la pila
|
|
117
|
+
return new BindCommand(this.innerCommand, (result) => {
|
|
118
|
+
kernel.popCatchHandler(); // Removemos el handler porque no hubo error
|
|
119
|
+
return new StepCommand(result);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
createTraceEntry() { }
|
|
123
|
+
}
|
|
124
|
+
// Specific commands for LogicRuntime
|
|
125
|
+
/**
|
|
126
|
+
* Commands the Kernel to stop execution and backtrack due to logical failure.
|
|
127
|
+
*/
|
|
128
|
+
export class BacktrackCommand {
|
|
129
|
+
name = "BACKTRACK";
|
|
130
|
+
constructor() { }
|
|
131
|
+
execute(kernel) {
|
|
132
|
+
// the backtracking is delegated to the kernel because it manipulates the execution stack
|
|
133
|
+
return kernel.handleBacktrack();
|
|
134
|
+
}
|
|
135
|
+
createTraceEntry() { }
|
|
136
|
+
}
|
|
137
|
+
export class NotCommand {
|
|
138
|
+
innerGoalCmd;
|
|
139
|
+
currentSubsts;
|
|
140
|
+
name = "NOT";
|
|
141
|
+
constructor(innerGoalCmd, currentSubsts) {
|
|
142
|
+
this.innerGoalCmd = innerGoalCmd;
|
|
143
|
+
this.currentSubsts = currentSubsts;
|
|
144
|
+
}
|
|
145
|
+
execute(kernel) {
|
|
146
|
+
const isolatedContext = kernel.evaluator.getContext().clone();
|
|
147
|
+
const isolatedEvaluator = new InterpreterVisitor(isolatedContext);
|
|
148
|
+
const isolatedKernel = new YukigoKernel(isolatedEvaluator, "first");
|
|
149
|
+
// Clone substs to avoid leaking bindings from the inner search
|
|
150
|
+
const result = isolatedKernel.run(this.innerGoalCmd);
|
|
151
|
+
if (isLogicResult(result) && result.allSuccessful())
|
|
152
|
+
return new BacktrackCommand();
|
|
153
|
+
return new StepCommand(new LogicResult([new LogicAnswer(true, new Map(this.currentSubsts))]));
|
|
154
|
+
}
|
|
155
|
+
createTraceEntry() { }
|
|
156
|
+
}
|
|
157
|
+
export class FindallCommand {
|
|
158
|
+
template;
|
|
159
|
+
bag;
|
|
160
|
+
innerGoalCmd;
|
|
161
|
+
currentSubsts;
|
|
162
|
+
scope;
|
|
163
|
+
translator;
|
|
164
|
+
name = "FINDALL";
|
|
165
|
+
constructor(template, bag, innerGoalCmd, currentSubsts, scope, translator) {
|
|
166
|
+
this.template = template;
|
|
167
|
+
this.bag = bag;
|
|
168
|
+
this.innerGoalCmd = innerGoalCmd;
|
|
169
|
+
this.currentSubsts = currentSubsts;
|
|
170
|
+
this.scope = scope;
|
|
171
|
+
this.translator = translator;
|
|
172
|
+
}
|
|
173
|
+
execute(kernel) {
|
|
174
|
+
// we need to _find all_ (jaja lol) successful branches
|
|
175
|
+
const isolatedContext = kernel.evaluator.getContext().clone();
|
|
176
|
+
const isolatedEvaluator = new InterpreterVisitor(isolatedContext);
|
|
177
|
+
const isolatedKernel = new YukigoKernel(isolatedEvaluator, "all");
|
|
178
|
+
// run inner goal - it will return an array of LogicResult if successful
|
|
179
|
+
const results = isolatedKernel.run(this.innerGoalCmd);
|
|
180
|
+
const gathered = [];
|
|
181
|
+
if (Array.isArray(results)) {
|
|
182
|
+
for (const res of results) {
|
|
183
|
+
if (isLogicResult(res) && res.allSuccessful()) {
|
|
184
|
+
// then we extract all solutions and instantiate the template
|
|
185
|
+
res.getSuccessfulSolutions().forEach((solutionEnv) => {
|
|
186
|
+
const templateTerm = this.translator.patternToTerm(this.template, this.scope);
|
|
187
|
+
gathered.push(templateTerm.instantiate(solutionEnv));
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// then we build a logic list
|
|
193
|
+
const resultList = new ListTerm(gathered);
|
|
194
|
+
const bagTerm = this.translator.patternToTerm(this.bag, this.scope);
|
|
195
|
+
// then we try to unify the list with the bag
|
|
196
|
+
const finalSubsts = new Map(this.currentSubsts);
|
|
197
|
+
if (bagTerm.unify(resultList, finalSubsts))
|
|
198
|
+
return new StepCommand(new LogicResult([new LogicAnswer(true, finalSubsts)]));
|
|
199
|
+
// finally if unification fails, findall fails
|
|
200
|
+
return new BacktrackCommand();
|
|
201
|
+
}
|
|
202
|
+
createTraceEntry() { }
|
|
203
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { CatchHandler, Continuation, ExecutionCommand } from "./commands.js";
|
|
2
|
+
import { EnvStack } from "../../utils.js";
|
|
3
|
+
import { InterpreterError } from "../../errors.js";
|
|
4
|
+
import { YuValue } from "../../primitives/index.js";
|
|
5
|
+
import { Evaluator } from "../evaluators/BaseEvaluator.js";
|
|
6
|
+
export type LogicSearchMode = "first" | "all" | "stream";
|
|
7
|
+
export interface ChoicePoint {
|
|
8
|
+
alternatives: ExecutionCommand[];
|
|
9
|
+
continuationStack: Continuation[];
|
|
10
|
+
envSnapshot: EnvStack;
|
|
11
|
+
}
|
|
12
|
+
export declare class YukigoKernel {
|
|
13
|
+
readonly evaluator: Evaluator;
|
|
14
|
+
private readonly mode;
|
|
15
|
+
readonly kid: number;
|
|
16
|
+
private logicalTrace;
|
|
17
|
+
private continuationStack;
|
|
18
|
+
private choiceStack;
|
|
19
|
+
private finalResult;
|
|
20
|
+
private searchExhausted;
|
|
21
|
+
private catchHandlerStack;
|
|
22
|
+
constructor(evaluator: Evaluator, mode?: LogicSearchMode);
|
|
23
|
+
/**
|
|
24
|
+
* Pushes a continuation to the logical stack.
|
|
25
|
+
*/
|
|
26
|
+
pushContinuation(cont: Continuation): void;
|
|
27
|
+
/**
|
|
28
|
+
* Pops a continuation from the stack and executes it with the provided value.
|
|
29
|
+
* If the stack is empty, sets the final result.
|
|
30
|
+
*/
|
|
31
|
+
popAndExecute(value: YuValue): ExecutionCommand | void;
|
|
32
|
+
pushCatchHandler(handler: CatchHandler): void;
|
|
33
|
+
popCatchHandler(): CatchHandler | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Handles RaiseCommand.
|
|
36
|
+
*/
|
|
37
|
+
handleRaise(exception: YuValue | InterpreterError): ExecutionCommand | void;
|
|
38
|
+
/**
|
|
39
|
+
* Handles a choice point by trying the first alternative and saving the others.
|
|
40
|
+
*/
|
|
41
|
+
handleChoice(alternatives: ExecutionCommand[]): ExecutionCommand | void;
|
|
42
|
+
/**
|
|
43
|
+
* Attempts to backtrack to the last saved choice point.
|
|
44
|
+
*/
|
|
45
|
+
handleBacktrack(): ExecutionCommand;
|
|
46
|
+
run(initialCommand: ExecutionCommand): any;
|
|
47
|
+
private executionStream;
|
|
48
|
+
getLogicalTrace(): ExecutionCommand[];
|
|
49
|
+
buildSemanticError(baseError: Error): Error;
|
|
50
|
+
private getStackFromTrace;
|
|
51
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { boolean } from "../../utils.js";
|
|
2
|
+
import { InterpreterError } from "../../errors.js";
|
|
3
|
+
import { YuNil } from "../../primitives/index.js";
|
|
4
|
+
export class YukigoKernel {
|
|
5
|
+
evaluator;
|
|
6
|
+
mode;
|
|
7
|
+
kid = Math.floor(Math.random() * 9999);
|
|
8
|
+
logicalTrace = [];
|
|
9
|
+
continuationStack = [];
|
|
10
|
+
choiceStack = [];
|
|
11
|
+
finalResult;
|
|
12
|
+
searchExhausted = false;
|
|
13
|
+
catchHandlerStack = [];
|
|
14
|
+
constructor(evaluator, mode = "first") {
|
|
15
|
+
this.evaluator = evaluator;
|
|
16
|
+
this.mode = mode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Pushes a continuation to the logical stack.
|
|
20
|
+
*/
|
|
21
|
+
pushContinuation(cont) {
|
|
22
|
+
this.continuationStack.push(cont);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Pops a continuation from the stack and executes it with the provided value.
|
|
26
|
+
* If the stack is empty, sets the final result.
|
|
27
|
+
*/
|
|
28
|
+
popAndExecute(value) {
|
|
29
|
+
const next = this.continuationStack.pop();
|
|
30
|
+
if (!next) {
|
|
31
|
+
this.finalResult = value;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
return next(value);
|
|
35
|
+
}
|
|
36
|
+
pushCatchHandler(handler) {
|
|
37
|
+
// Save current continuation stack length so we know where to unwind if an error is raised inside the try block
|
|
38
|
+
this.catchHandlerStack.push({
|
|
39
|
+
handler,
|
|
40
|
+
continuationDepth: this.continuationStack.length,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
popCatchHandler() {
|
|
44
|
+
const entry = this.catchHandlerStack.pop();
|
|
45
|
+
return entry?.handler;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Handles RaiseCommand.
|
|
49
|
+
*/
|
|
50
|
+
handleRaise(exception) {
|
|
51
|
+
const entry = this.catchHandlerStack.pop();
|
|
52
|
+
if (!entry) {
|
|
53
|
+
// if no catch found, we have no other option than to throw the error and break the flow.
|
|
54
|
+
if (exception instanceof InterpreterError) {
|
|
55
|
+
throw this.buildSemanticError(exception);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// TODO: I think this if-else is unnecessary
|
|
59
|
+
throw this.buildSemanticError(new InterpreterError("UncaughtException", String(exception)));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Unwind continuation stack to the point where the try block was entered
|
|
63
|
+
this.continuationStack.length = entry.continuationDepth;
|
|
64
|
+
return entry.handler(exception);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Handles a choice point by trying the first alternative and saving the others.
|
|
68
|
+
*/
|
|
69
|
+
handleChoice(alternatives) {
|
|
70
|
+
if (alternatives.length === 0)
|
|
71
|
+
return this.handleBacktrack();
|
|
72
|
+
const [first, ...rest] = alternatives;
|
|
73
|
+
if (rest.length > 0) {
|
|
74
|
+
this.choiceStack.push({
|
|
75
|
+
alternatives: rest,
|
|
76
|
+
continuationStack: [...this.continuationStack],
|
|
77
|
+
envSnapshot: this.evaluator.getContext().cloneEnv(),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return first;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Attempts to backtrack to the last saved choice point.
|
|
84
|
+
*/
|
|
85
|
+
handleBacktrack() {
|
|
86
|
+
const lastChoice = this.choiceStack.pop();
|
|
87
|
+
if (!lastChoice) {
|
|
88
|
+
// logic tree is empty sooo
|
|
89
|
+
this.searchExhausted = true;
|
|
90
|
+
this.continuationStack = [];
|
|
91
|
+
return boolean(false);
|
|
92
|
+
}
|
|
93
|
+
this.searchExhausted = false;
|
|
94
|
+
// clones the stack and environment
|
|
95
|
+
this.continuationStack = [...lastChoice.continuationStack];
|
|
96
|
+
const clonedEnv = this.evaluator
|
|
97
|
+
.getContext()
|
|
98
|
+
.cloneEnv(lastChoice.envSnapshot);
|
|
99
|
+
this.evaluator.getContext().setEnv(clonedEnv);
|
|
100
|
+
const [next, ...remaining] = lastChoice.alternatives;
|
|
101
|
+
if (remaining.length > 0) {
|
|
102
|
+
this.choiceStack.push({
|
|
103
|
+
...lastChoice,
|
|
104
|
+
alternatives: remaining,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return next;
|
|
108
|
+
}
|
|
109
|
+
// TODO: remove this f- any
|
|
110
|
+
run(initialCommand) {
|
|
111
|
+
const stream = this.executionStream(initialCommand);
|
|
112
|
+
switch (this.mode) {
|
|
113
|
+
case "stream":
|
|
114
|
+
return stream;
|
|
115
|
+
case "first":
|
|
116
|
+
const result = stream.next();
|
|
117
|
+
return result.done ? undefined : result.value;
|
|
118
|
+
case "all":
|
|
119
|
+
return Array.from(stream);
|
|
120
|
+
default:
|
|
121
|
+
throw new Error(`Output mode "${this.mode}" not supported.`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
*executionStream(initialCommand) {
|
|
125
|
+
let current = initialCommand;
|
|
126
|
+
this.searchExhausted = false;
|
|
127
|
+
let steps = 0;
|
|
128
|
+
while (current) {
|
|
129
|
+
steps++;
|
|
130
|
+
this.logicalTrace.push(current);
|
|
131
|
+
// cleans the older traces to avoid consuming memory
|
|
132
|
+
if (this.logicalTrace.length > 50)
|
|
133
|
+
this.logicalTrace.shift();
|
|
134
|
+
current = current.execute(this);
|
|
135
|
+
if (!current) {
|
|
136
|
+
if (this.searchExhausted)
|
|
137
|
+
break;
|
|
138
|
+
yield this.finalResult || YuNil.getInstance();
|
|
139
|
+
current = this.handleBacktrack();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
getLogicalTrace() {
|
|
144
|
+
return this.logicalTrace;
|
|
145
|
+
}
|
|
146
|
+
buildSemanticError(baseError) {
|
|
147
|
+
if (baseError.constructor.name === "FailedAssert")
|
|
148
|
+
return baseError;
|
|
149
|
+
const frames = this.getStackFromTrace();
|
|
150
|
+
if (baseError instanceof InterpreterError) {
|
|
151
|
+
if (baseError.frames.length === 0) {
|
|
152
|
+
frames.forEach((f) => baseError.pushFrame(f));
|
|
153
|
+
}
|
|
154
|
+
return baseError;
|
|
155
|
+
}
|
|
156
|
+
const newErr = new InterpreterError("Yukigo VM Error", baseError.message);
|
|
157
|
+
frames.forEach((f) => newErr.pushFrame(f));
|
|
158
|
+
return newErr;
|
|
159
|
+
}
|
|
160
|
+
getStackFromTrace() {
|
|
161
|
+
const frames = [];
|
|
162
|
+
let index = this.logicalTrace.length - 1;
|
|
163
|
+
// loops through logicalTrace and collects traces
|
|
164
|
+
for (index; index >= 0; index--) {
|
|
165
|
+
const cmd = this.logicalTrace[index];
|
|
166
|
+
const trace = cmd.createTraceEntry();
|
|
167
|
+
// not all commands leave traces
|
|
168
|
+
if (!trace)
|
|
169
|
+
continue;
|
|
170
|
+
frames.push(trace.frame);
|
|
171
|
+
if (frames.length >= 10)
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
return frames;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -1,29 +1,32 @@
|
|
|
1
|
-
import { Exist, Expression, Findall, Forall, Goal,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { Exist, Expression, Findall, Forall, Goal, Query, Statement, Not, Assert, Call, If } from "yukigo-ast";
|
|
2
|
+
import { RuntimeContext } from "../RuntimeContext.js";
|
|
3
|
+
import { ExecutionCommand } from "../kernel/commands.js";
|
|
4
|
+
import { VariableTerm } from "./LogicTerm.js";
|
|
5
|
+
import { Substitution } from "../../primitives/index.js";
|
|
6
|
+
import { Evaluator } from "../evaluators/BaseEvaluator.js";
|
|
7
|
+
export type LogicExecutable = Expression | Statement | Goal | Exist | Findall | Forall | Not | Assert | Call | If;
|
|
8
|
+
export type Scope = Map<string, VariableTerm>;
|
|
6
9
|
export declare class LogicEngine {
|
|
7
10
|
private context;
|
|
8
11
|
private translator;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
private
|
|
18
|
-
|
|
19
|
-
private
|
|
12
|
+
private readonly dispatch;
|
|
13
|
+
constructor(evaluator: Evaluator, context: RuntimeContext);
|
|
14
|
+
private buildDispatch;
|
|
15
|
+
unifyExpr(left: Expression, right: Expression, substs?: Substitution, scope?: Scope): ExecutionCommand;
|
|
16
|
+
solveQuery(node: Query): ExecutionCommand;
|
|
17
|
+
solveGoalLike(node: Goal | Exist, outerSubsts?: Substitution, outerScope?: Scope): ExecutionCommand;
|
|
18
|
+
solveNot(node: Not, substs?: Substitution, scope?: Scope): ExecutionCommand;
|
|
19
|
+
solveFindall(node: Findall, substs?: Substitution, scope?: Scope): ExecutionCommand;
|
|
20
|
+
private solveAssign;
|
|
21
|
+
solveForall(node: Forall, substs?: Substitution, scope?: Scope): ExecutionCommand;
|
|
22
|
+
private aggregateResults;
|
|
23
|
+
private branchSolutions;
|
|
24
|
+
solveConjunction(nodes: LogicExecutable[], substs: Substitution, scope?: Scope): ExecutionCommand;
|
|
20
25
|
private solveCondition;
|
|
21
|
-
private isLogicGoal;
|
|
22
26
|
private createLocalEnv;
|
|
23
|
-
private
|
|
24
|
-
private
|
|
25
|
-
private
|
|
26
|
-
private
|
|
27
|
-
private
|
|
28
|
-
private formatLogicResult;
|
|
27
|
+
private finalizeUserResult;
|
|
28
|
+
private resolveTerms;
|
|
29
|
+
private resolveArgSequentially;
|
|
30
|
+
private runKernel;
|
|
31
|
+
private solveIf;
|
|
29
32
|
}
|