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
|
@@ -1,858 +1,209 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Pattern,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const name = node.name.value;
|
|
211
|
-
if (this.seen.has(name)) return node;
|
|
212
|
-
const val = this.substs.get(name);
|
|
213
|
-
if (val) {
|
|
214
|
-
const nextSeen = new Set(this.seen);
|
|
215
|
-
nextSeen.add(name);
|
|
216
|
-
return new Instantiator(this.substs, nextSeen).instantiate(val);
|
|
217
|
-
}
|
|
218
|
-
return node;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
visitLiteralPattern(node: LiteralPattern): Pattern {
|
|
222
|
-
return node;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
visitApplicationPattern(node: ApplicationPattern): Pattern {
|
|
226
|
-
return new ApplicationPattern(
|
|
227
|
-
node.identifier,
|
|
228
|
-
node.args.map((arg) => this.instantiate(arg)),
|
|
229
|
-
node.loc,
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
visitTuplePattern(node: TuplePattern): Pattern {
|
|
234
|
-
return new TuplePattern(
|
|
235
|
-
node.elements.map((el) => this.instantiate(el)),
|
|
236
|
-
node.loc,
|
|
237
|
-
);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
visitListPattern(node: ListPattern): Pattern {
|
|
241
|
-
return new ListPattern(
|
|
242
|
-
node.elements.map((el) => this.instantiate(el)),
|
|
243
|
-
node.loc,
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
visitFunctorPattern(node: FunctorPattern): Pattern {
|
|
248
|
-
return new FunctorPattern(
|
|
249
|
-
node.identifier,
|
|
250
|
-
node.args.map((arg) => this.instantiate(arg)),
|
|
251
|
-
node.loc,
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
visitAsPattern(node: AsPattern): Pattern {
|
|
256
|
-
return new AsPattern(
|
|
257
|
-
this.instantiate(node.left) as any,
|
|
258
|
-
this.instantiate(node.right),
|
|
259
|
-
node.loc,
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
visitWildcardPattern(node: WildcardPattern): Pattern {
|
|
264
|
-
return node;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
visitUnionPattern(node: UnionPattern): Pattern {
|
|
268
|
-
return new UnionPattern(
|
|
269
|
-
node.elements.map((el) => this.instantiate(el)),
|
|
270
|
-
node.loc,
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
visitConstructorPattern(node: ConstructorPattern): Pattern {
|
|
275
|
-
return new ConstructorPattern(
|
|
276
|
-
node.identifier,
|
|
277
|
-
node.args.map((arg) => this.instantiate(arg)),
|
|
278
|
-
node.loc,
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
visitConsPattern(node: ConsPattern): Pattern {
|
|
283
|
-
return new ConsPattern(
|
|
284
|
-
this.instantiate(node.left),
|
|
285
|
-
this.instantiate(node.right),
|
|
286
|
-
node.loc,
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
visitTypePattern(node: TypePattern): Pattern {
|
|
291
|
-
return new TypePattern(
|
|
292
|
-
node.targetType,
|
|
293
|
-
node.innerPattern ? this.instantiate(node.innerPattern) : undefined,
|
|
294
|
-
node.loc,
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
instantiate(pattern: Pattern): Pattern {
|
|
299
|
-
return pattern.accept(this);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Fully instantiates a pattern by replacing all bound variables with their values.
|
|
305
|
-
*/
|
|
306
|
-
export function instantiate(
|
|
307
|
-
pattern: Pattern,
|
|
308
|
-
substs: Substitution,
|
|
309
|
-
seen: Set<string> = new Set(),
|
|
310
|
-
): Pattern {
|
|
311
|
-
return new Instantiator(substs, seen).instantiate(pattern);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
let variableCounter = 0;
|
|
315
|
-
|
|
316
|
-
class LogicVariableRenamer implements PatternVisitor<Pattern> {
|
|
317
|
-
constructor(
|
|
318
|
-
private renames: Map<string, string>,
|
|
319
|
-
private freshId: number,
|
|
320
|
-
) {}
|
|
321
|
-
|
|
322
|
-
public rename(node: any): any {
|
|
323
|
-
if (!node || typeof node !== "object") return node;
|
|
324
|
-
if (typeof node.accept === "function") {
|
|
325
|
-
return node.accept(this);
|
|
326
|
-
}
|
|
327
|
-
return node;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
visitFact(node: Fact): Fact {
|
|
331
|
-
return new Fact(
|
|
332
|
-
node.identifier,
|
|
333
|
-
node.patterns.map((p) => this.rename(p)),
|
|
334
|
-
node.loc,
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
visitRule(node: Rule): Rule {
|
|
338
|
-
const renamedEquations = node.equations.map((eq) => {
|
|
339
|
-
const body = eq.body;
|
|
340
|
-
if (!isUnguardedBody(body))
|
|
341
|
-
throw new Error("GuardedBody renaming not implemented");
|
|
342
|
-
return new Equation(
|
|
343
|
-
eq.patterns.map((p) => this.rename(p)),
|
|
344
|
-
body.accept(this),
|
|
345
|
-
eq.returnExpr,
|
|
346
|
-
eq.loc,
|
|
347
|
-
);
|
|
348
|
-
});
|
|
349
|
-
return new Rule(node.identifier, renamedEquations, node.loc);
|
|
350
|
-
}
|
|
351
|
-
visitUnguardedBody(node: UnguardedBody): UnguardedBody {
|
|
352
|
-
return new UnguardedBody(
|
|
353
|
-
new Sequence(
|
|
354
|
-
node.sequence.statements.map((stmt) => this.rename(stmt)),
|
|
355
|
-
node.sequence.loc,
|
|
356
|
-
),
|
|
357
|
-
node.loc,
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
// PatternVisitor
|
|
362
|
-
visitVariablePattern(node: VariablePattern): Pattern {
|
|
363
|
-
const name = node.name.value;
|
|
364
|
-
let newName = this.renames.get(name);
|
|
365
|
-
if (!newName) {
|
|
366
|
-
newName = `${name}_${this.freshId}`;
|
|
367
|
-
this.renames.set(name, newName);
|
|
368
|
-
}
|
|
369
|
-
return new VariablePattern(new SymbolPrimitive(newName), node.loc);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
visitLiteralPattern(node: LiteralPattern): Pattern {
|
|
373
|
-
return node;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
visitApplicationPattern(node: ApplicationPattern): Pattern {
|
|
377
|
-
return new ApplicationPattern(
|
|
378
|
-
node.identifier,
|
|
379
|
-
node.args.map((arg) => this.rename(arg)),
|
|
380
|
-
node.loc,
|
|
381
|
-
);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
visitTuplePattern(node: TuplePattern): Pattern {
|
|
385
|
-
return new TuplePattern(
|
|
386
|
-
node.elements.map((el) => this.rename(el)),
|
|
387
|
-
node.loc,
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
visitListPattern(node: ListPattern): Pattern {
|
|
392
|
-
return new ListPattern(
|
|
393
|
-
node.elements.map((el) => this.rename(el)),
|
|
394
|
-
node.loc,
|
|
395
|
-
);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
visitFunctorPattern(node: FunctorPattern): Pattern {
|
|
399
|
-
return new FunctorPattern(
|
|
400
|
-
node.identifier,
|
|
401
|
-
node.args.map((arg) => this.rename(arg)),
|
|
402
|
-
node.loc,
|
|
403
|
-
);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
visitAsPattern(node: AsPattern): Pattern {
|
|
407
|
-
return new AsPattern(
|
|
408
|
-
this.rename(node.left) as any,
|
|
409
|
-
this.rename(node.right),
|
|
410
|
-
node.loc,
|
|
411
|
-
);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
visitWildcardPattern(node: WildcardPattern): Pattern {
|
|
415
|
-
return node;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
visitUnionPattern(node: UnionPattern): Pattern {
|
|
419
|
-
return new UnionPattern(
|
|
420
|
-
node.elements.map((el) => this.rename(el)),
|
|
421
|
-
node.loc,
|
|
422
|
-
);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
visitConstructorPattern(node: ConstructorPattern): Pattern {
|
|
426
|
-
return new ConstructorPattern(
|
|
427
|
-
node.identifier,
|
|
428
|
-
node.args.map((arg) => this.rename(arg)),
|
|
429
|
-
node.loc,
|
|
430
|
-
);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
visitConsPattern(node: ConsPattern): Pattern {
|
|
434
|
-
return new ConsPattern(
|
|
435
|
-
this.rename(node.left),
|
|
436
|
-
this.rename(node.right),
|
|
437
|
-
node.loc,
|
|
438
|
-
);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
visitTypePattern(node: TypePattern): Pattern {
|
|
442
|
-
return new TypePattern(
|
|
443
|
-
node.targetType,
|
|
444
|
-
node.innerPattern ? this.rename(node.innerPattern) : undefined,
|
|
445
|
-
node.loc,
|
|
446
|
-
);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// Expression/Statement Visitor
|
|
450
|
-
visitSymbolPrimitive(node: SymbolPrimitive): any {
|
|
451
|
-
const name = node.value;
|
|
452
|
-
if (/^[A-Z_]/.test(name) && name !== "_") {
|
|
453
|
-
let newName = this.renames.get(name);
|
|
454
|
-
if (!newName) {
|
|
455
|
-
newName = `${name}_${this.freshId}`;
|
|
456
|
-
this.renames.set(name, newName);
|
|
457
|
-
}
|
|
458
|
-
return new SymbolPrimitive(newName, node.loc);
|
|
459
|
-
}
|
|
460
|
-
return node;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
visitNumberPrimitive(node: NumberPrimitive): any {
|
|
464
|
-
return node;
|
|
465
|
-
}
|
|
466
|
-
visitStringPrimitive(node: StringPrimitive): any {
|
|
467
|
-
return node;
|
|
468
|
-
}
|
|
469
|
-
visitBooleanPrimitive(node: BooleanPrimitive): any {
|
|
470
|
-
return node;
|
|
471
|
-
}
|
|
472
|
-
visitNilPrimitive(node: NilPrimitive): any {
|
|
473
|
-
return node;
|
|
474
|
-
}
|
|
475
|
-
visitCharPrimitive(node: CharPrimitive): any {
|
|
476
|
-
return node;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
visitGoal(node: Goal): any {
|
|
480
|
-
return new Goal(
|
|
481
|
-
node.identifier,
|
|
482
|
-
node.args.map((arg) => this.rename(arg)),
|
|
483
|
-
node.loc,
|
|
484
|
-
);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
visitExist(node: Exist): any {
|
|
488
|
-
return new Exist(
|
|
489
|
-
node.identifier,
|
|
490
|
-
node.patterns.map((pat) => this.rename(pat)),
|
|
491
|
-
node.loc,
|
|
492
|
-
);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
visitFindall(node: Findall): any {
|
|
496
|
-
return new Findall(
|
|
497
|
-
this.rename(node.template),
|
|
498
|
-
this.rename(node.goal),
|
|
499
|
-
this.rename(node.bag),
|
|
500
|
-
node.loc,
|
|
501
|
-
);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
visitForall(node: Forall): any {
|
|
505
|
-
return new Forall(this.rename(node.condition), this.rename(node.action), node.loc);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
visitCall(node: Call): any {
|
|
509
|
-
return new Call(
|
|
510
|
-
this.rename(node.callee),
|
|
511
|
-
node.args.map((arg) => this.rename(arg)),
|
|
512
|
-
node.loc,
|
|
513
|
-
);
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
visitNot(node: Not): any {
|
|
517
|
-
return new Not(this.rename(node.expression), node.loc);
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
visitLogicConstraint(node: LogicConstraint): any {
|
|
521
|
-
return new LogicConstraint(this.rename(node.expression), node.loc);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
visitSequence(node: Sequence): any {
|
|
525
|
-
return new Sequence(
|
|
526
|
-
node.statements.map((stmt) => this.rename(stmt)),
|
|
527
|
-
node.loc,
|
|
528
|
-
);
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
visitIf(node: If): any {
|
|
532
|
-
return new If(
|
|
533
|
-
this.rename(node.condition),
|
|
534
|
-
this.rename(node.then),
|
|
535
|
-
this.rename(node.elseExpr),
|
|
536
|
-
node.loc,
|
|
537
|
-
);
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
visitComparisonOperation(node: ComparisonOperation): any {
|
|
541
|
-
return new ComparisonOperation(
|
|
542
|
-
node.operator,
|
|
543
|
-
this.rename(node.left),
|
|
544
|
-
this.rename(node.right),
|
|
545
|
-
node.loc,
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
visitUnifyOperation(node: UnifyOperation): any {
|
|
550
|
-
return new UnifyOperation(
|
|
551
|
-
node.operator,
|
|
552
|
-
this.rename(node.left),
|
|
553
|
-
this.rename(node.right),
|
|
554
|
-
node.loc,
|
|
555
|
-
);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
visitAssignOperation(node: AssignOperation): any {
|
|
559
|
-
return new AssignOperation(
|
|
560
|
-
node.operator,
|
|
561
|
-
this.rename(node.left),
|
|
562
|
-
this.rename(node.right),
|
|
563
|
-
node.loc,
|
|
564
|
-
);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
visitArithmeticBinaryOperation(node: ArithmeticBinaryOperation): any {
|
|
568
|
-
return new ArithmeticBinaryOperation(
|
|
569
|
-
node.operator,
|
|
570
|
-
this.rename(node.left),
|
|
571
|
-
this.rename(node.right),
|
|
572
|
-
node.loc,
|
|
573
|
-
);
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
visitArithmeticUnaryOperation(node: ArithmeticUnaryOperation): any {
|
|
577
|
-
return new ArithmeticUnaryOperation(
|
|
578
|
-
node.operator,
|
|
579
|
-
this.rename(node.operand),
|
|
580
|
-
node.loc,
|
|
581
|
-
);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
visitListBinaryOperation(node: ListBinaryOperation): any {
|
|
585
|
-
return new ListBinaryOperation(
|
|
586
|
-
node.operator,
|
|
587
|
-
this.rename(node.left),
|
|
588
|
-
this.rename(node.right),
|
|
589
|
-
node.loc,
|
|
590
|
-
);
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
visitListUnaryOperation(node: ListUnaryOperation): any {
|
|
594
|
-
return new ListUnaryOperation(
|
|
595
|
-
node.operator,
|
|
596
|
-
this.rename(node.operand),
|
|
597
|
-
node.loc,
|
|
598
|
-
);
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
visitLogicalBinaryOperation(node: LogicalBinaryOperation): any {
|
|
602
|
-
return new LogicalBinaryOperation(
|
|
603
|
-
node.operator,
|
|
604
|
-
this.rename(node.left),
|
|
605
|
-
this.rename(node.right),
|
|
606
|
-
node.loc,
|
|
607
|
-
);
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
visitLogicalUnaryOperation(node: LogicalUnaryOperation): any {
|
|
611
|
-
return new LogicalUnaryOperation(
|
|
612
|
-
node.operator,
|
|
613
|
-
this.rename(node.operand),
|
|
614
|
-
node.loc,
|
|
615
|
-
);
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
visitBitwiseBinaryOperation(node: BitwiseBinaryOperation): any {
|
|
619
|
-
return new BitwiseBinaryOperation(
|
|
620
|
-
node.operator,
|
|
621
|
-
this.rename(node.left),
|
|
622
|
-
this.rename(node.right),
|
|
623
|
-
node.loc,
|
|
624
|
-
);
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
visitBitwiseUnaryOperation(node: BitwiseUnaryOperation): any {
|
|
628
|
-
return new BitwiseUnaryOperation(
|
|
629
|
-
node.operator,
|
|
630
|
-
this.rename(node.operand),
|
|
631
|
-
node.loc,
|
|
632
|
-
);
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
visitStringOperation(node: StringOperation): any {
|
|
636
|
-
return new StringOperation(
|
|
637
|
-
node.operator,
|
|
638
|
-
this.rename(node.left),
|
|
639
|
-
this.rename(node.right),
|
|
640
|
-
node.loc,
|
|
641
|
-
);
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
visitConsExpression(node: ConsExpression): any {
|
|
645
|
-
return new ConsExpression(
|
|
646
|
-
this.rename(node.head),
|
|
647
|
-
this.rename(node.tail),
|
|
648
|
-
node.loc,
|
|
649
|
-
);
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
visitListPrimitive(node: ListPrimitive): any {
|
|
653
|
-
return new ListPrimitive(
|
|
654
|
-
node.value.map((el) => this.rename(el)),
|
|
655
|
-
node.loc,
|
|
656
|
-
);
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
visitTupleExpr(node: TupleExpression): any {
|
|
660
|
-
return new TupleExpression(
|
|
661
|
-
node.elements.map((el) => this.rename(el)),
|
|
662
|
-
node.loc,
|
|
663
|
-
);
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
/**
|
|
668
|
-
* Renames all variables in a Rule or Fact to fresh names to avoid name clashes during unification.
|
|
669
|
-
*/
|
|
670
|
-
export function renameVariables<T extends Rule | Fact>(clause: T): T {
|
|
671
|
-
const renames = new Map<string, string>();
|
|
672
|
-
const freshId = ++variableCounter;
|
|
673
|
-
const renamer = new LogicVariableRenamer(renames, freshId);
|
|
674
|
-
const renamedClause = clause.accept(renamer)
|
|
675
|
-
return renamedClause;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
class CPSBodyVisitor implements Visitor<Thunk<any>> {
|
|
679
|
-
constructor(
|
|
680
|
-
private readonly solveBody: BodySolverCPS,
|
|
681
|
-
private readonly substs: Substitution,
|
|
682
|
-
private readonly onSuccess: SuccessCont,
|
|
683
|
-
private readonly onNextEq: Thunk<any>,
|
|
684
|
-
) {}
|
|
685
|
-
|
|
686
|
-
public visitUnguardedBody(body: UnguardedBody): Thunk<any> {
|
|
687
|
-
return this.solveBody(
|
|
688
|
-
body.sequence.statements,
|
|
689
|
-
this.substs,
|
|
690
|
-
this.onSuccess,
|
|
691
|
-
this.onNextEq,
|
|
692
|
-
);
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
public visitGuardedBody(body: GuardedBody): Thunk<any> {
|
|
696
|
-
return this.solveBody(
|
|
697
|
-
[body.condition],
|
|
698
|
-
this.substs,
|
|
699
|
-
(guardSubsts: Substitution, _nextGuardChoice: Thunk<any>) => {
|
|
700
|
-
return this.solveBody(
|
|
701
|
-
[body.body],
|
|
702
|
-
guardSubsts,
|
|
703
|
-
this.onSuccess,
|
|
704
|
-
this.onNextEq,
|
|
705
|
-
);
|
|
706
|
-
},
|
|
707
|
-
this.onNextEq,
|
|
708
|
-
);
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
class GoalSolverVisitor implements Visitor<Thunk<any>> {
|
|
713
|
-
constructor(
|
|
714
|
-
private readonly args: Pattern[],
|
|
715
|
-
private readonly baseSubst: Substitution,
|
|
716
|
-
private readonly solveBody: BodySolverCPS,
|
|
717
|
-
private readonly onSuccess: SuccessCont,
|
|
718
|
-
private readonly onNextClause: Thunk<any>,
|
|
719
|
-
) {}
|
|
720
|
-
|
|
721
|
-
public visitFact(fact: Fact): Thunk<any> {
|
|
722
|
-
if (fact.patterns.length !== this.args.length) return this.onNextClause;
|
|
723
|
-
|
|
724
|
-
const renamedFact = renameVariables(fact);
|
|
725
|
-
const substs = unifyParameters(
|
|
726
|
-
renamedFact.patterns,
|
|
727
|
-
this.args,
|
|
728
|
-
this.baseSubst,
|
|
729
|
-
);
|
|
730
|
-
|
|
731
|
-
if (substs) return this.onSuccess(substs, this.onNextClause);
|
|
732
|
-
return this.onNextClause;
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
public visitRule(rule: Rule): Thunk<any> {
|
|
736
|
-
if (rule.equations.length === 0) return this.onNextClause;
|
|
737
|
-
|
|
738
|
-
const arity = rule.equations[0].patterns.length;
|
|
739
|
-
if (arity !== this.args.length) return this.onNextClause;
|
|
740
|
-
|
|
741
|
-
const renamedRule = renameVariables(rule);
|
|
742
|
-
|
|
743
|
-
const tryRuleEq = (eqIndex: number): Thunk<any> => {
|
|
744
|
-
if (eqIndex >= renamedRule.equations.length) return this.onNextClause;
|
|
745
|
-
|
|
746
|
-
const eq = renamedRule.equations[eqIndex];
|
|
747
|
-
const substs = unifyParameters(eq.patterns, this.args, this.baseSubst);
|
|
748
|
-
const onNextEq = () => tryRuleEq(eqIndex + 1);
|
|
749
|
-
|
|
750
|
-
if (!substs) return onNextEq;
|
|
751
|
-
|
|
752
|
-
const bodyVisitor = new CPSBodyVisitor(
|
|
753
|
-
this.solveBody,
|
|
754
|
-
substs,
|
|
755
|
-
this.onSuccess,
|
|
756
|
-
onNextEq,
|
|
757
|
-
);
|
|
758
|
-
|
|
759
|
-
if (isUnguardedBody(eq.body)) return eq.body.accept(bodyVisitor);
|
|
760
|
-
return eq.body.forEach((branch) => branch.accept(bodyVisitor));
|
|
761
|
-
};
|
|
762
|
-
|
|
763
|
-
return () => tryRuleEq(0);
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
/**
|
|
768
|
-
* Solves a single logic goal (predicate call) using CPS.
|
|
769
|
-
*/
|
|
770
|
-
export function solveGoalCPS(
|
|
771
|
-
ctx: RuntimeContext,
|
|
772
|
-
predicateName: string,
|
|
773
|
-
args: Pattern[],
|
|
774
|
-
solveBody: BodySolverCPS,
|
|
775
|
-
baseSubst: Substitution,
|
|
776
|
-
onSuccess: SuccessCont,
|
|
777
|
-
onFailure: FailureCont,
|
|
778
|
-
): Thunk<any> {
|
|
779
|
-
const tryClause = (index: number): Thunk<any> => {
|
|
780
|
-
let equations: (Rule | Fact)[];
|
|
781
|
-
|
|
782
|
-
try {
|
|
783
|
-
const pred = ctx.lookup(predicateName);
|
|
784
|
-
if (!pred || !isRuntimePredicate(pred)) return () => onFailure();
|
|
785
|
-
equations = pred.equations;
|
|
786
|
-
} catch (error) {
|
|
787
|
-
return () => onFailure();
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
if (index >= equations.length) return () => onFailure();
|
|
791
|
-
|
|
792
|
-
const clause = equations[index];
|
|
793
|
-
const onNextClause = () => tryClause(index + 1);
|
|
794
|
-
|
|
795
|
-
const clauseVisitor = new GoalSolverVisitor(
|
|
796
|
-
args,
|
|
797
|
-
baseSubst,
|
|
798
|
-
solveBody,
|
|
799
|
-
onSuccess,
|
|
800
|
-
onNextClause,
|
|
801
|
-
);
|
|
802
|
-
|
|
803
|
-
return clause.accept(clauseVisitor);
|
|
804
|
-
};
|
|
805
|
-
|
|
806
|
-
return () => tryClause(0);
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
/**
|
|
810
|
-
* Unifies two lists of parameters. Returns the resulting Substitution or null.
|
|
811
|
-
*/
|
|
812
|
-
function unifyParameters(
|
|
813
|
-
patterns: Pattern[],
|
|
814
|
-
args: Pattern[],
|
|
815
|
-
baseSubst: Substitution,
|
|
816
|
-
): Substitution | null {
|
|
817
|
-
let subst: Substitution = new Map(baseSubst);
|
|
818
|
-
for (let i = 0; i < patterns.length; i++) {
|
|
819
|
-
const nextSubst = unify(patterns[i], args[i], subst);
|
|
820
|
-
if (!nextSubst) return null;
|
|
821
|
-
subst = nextSubst;
|
|
822
|
-
}
|
|
823
|
-
return subst;
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
/**
|
|
827
|
-
* Solves a findall/3 goal using CPS.
|
|
828
|
-
*/
|
|
829
|
-
export function solveFindallCPS(
|
|
830
|
-
node: Findall,
|
|
831
|
-
currentSubsts: Substitution,
|
|
832
|
-
solveBody: BodySolverCPS,
|
|
833
|
-
onSuccess: SuccessCont,
|
|
834
|
-
onFailure: FailureCont,
|
|
835
|
-
): Thunk<any> {
|
|
836
|
-
const gathered: Pattern[] = [];
|
|
837
|
-
|
|
838
|
-
const collectResults = (): Thunk<any> => {
|
|
839
|
-
return solveBody(
|
|
840
|
-
[node.goal],
|
|
841
|
-
currentSubsts,
|
|
842
|
-
(resultSubsts, next) => {
|
|
843
|
-
gathered.push(instantiate(node.template, resultSubsts));
|
|
844
|
-
return () => next();
|
|
845
|
-
},
|
|
846
|
-
() => {
|
|
847
|
-
const resultList = new ListPattern(gathered);
|
|
848
|
-
const finalSubsts = unify(node.bag, resultList, currentSubsts);
|
|
849
|
-
if (finalSubsts) {
|
|
850
|
-
return onSuccess(finalSubsts, onFailure);
|
|
851
|
-
}
|
|
852
|
-
return () => onFailure();
|
|
853
|
-
},
|
|
854
|
-
);
|
|
855
|
-
};
|
|
856
|
-
|
|
857
|
-
return collectResults();
|
|
858
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
Fact,
|
|
3
|
+
Rule,
|
|
4
|
+
UnguardedBody,
|
|
5
|
+
Visitor,
|
|
6
|
+
ASTNode,
|
|
7
|
+
Pattern,
|
|
8
|
+
NativeBody,
|
|
9
|
+
Guard,
|
|
10
|
+
} from "yukigo-ast";
|
|
11
|
+
import { LogicExecutable } from "./LogicEngine.js";
|
|
12
|
+
import { RuntimeContext } from "../RuntimeContext.js";
|
|
13
|
+
import { InterpreterError } from "../../errors.js";
|
|
14
|
+
import {
|
|
15
|
+
ExecutionCommand,
|
|
16
|
+
StepCommand,
|
|
17
|
+
BindCommand,
|
|
18
|
+
FailCommand,
|
|
19
|
+
ChoiceCommand,
|
|
20
|
+
BacktrackCommand,
|
|
21
|
+
} from "../kernel/commands.js";
|
|
22
|
+
import { LogicTranslator } from "./LogicTranslator.js";
|
|
23
|
+
import { VariableTerm } from "./LogicTerm.js";
|
|
24
|
+
import {
|
|
25
|
+
LogicTerm,
|
|
26
|
+
Substitution,
|
|
27
|
+
isLogicResult,
|
|
28
|
+
LogicResult,
|
|
29
|
+
LogicAnswer,
|
|
30
|
+
isRuntimePredicate,
|
|
31
|
+
YuBoolean,
|
|
32
|
+
YuNil,
|
|
33
|
+
} from "../../primitives/index.js";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Unified parameter list unification.
|
|
37
|
+
*/
|
|
38
|
+
function unifyParameters(
|
|
39
|
+
patterns: Pattern[],
|
|
40
|
+
args: LogicTerm[],
|
|
41
|
+
baseSubst: Substitution,
|
|
42
|
+
translator: LogicTranslator,
|
|
43
|
+
scope: Map<string, VariableTerm>,
|
|
44
|
+
onSuccess: (subst: Substitution) => ExecutionCommand,
|
|
45
|
+
onFailure: () => ExecutionCommand,
|
|
46
|
+
): ExecutionCommand {
|
|
47
|
+
const next = (
|
|
48
|
+
index: number,
|
|
49
|
+
currentSubst: Substitution,
|
|
50
|
+
): ExecutionCommand => {
|
|
51
|
+
if (index >= patterns.length) {
|
|
52
|
+
return onSuccess(currentSubst);
|
|
53
|
+
}
|
|
54
|
+
const term = translator.patternToTerm(patterns[index], scope);
|
|
55
|
+
return new BindCommand(term.unify(args[index], currentSubst), (res) => {
|
|
56
|
+
if (res instanceof YuBoolean && res.value) {
|
|
57
|
+
return next(index + 1, currentSubst);
|
|
58
|
+
}
|
|
59
|
+
return onFailure();
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
return next(0, new Map(baseSubst));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
class KernelBodyVisitor implements Visitor<ExecutionCommand> {
|
|
66
|
+
constructor(
|
|
67
|
+
private readonly solveBody: Solver,
|
|
68
|
+
private readonly substs: Substitution,
|
|
69
|
+
private readonly scope: Map<string, VariableTerm>,
|
|
70
|
+
) {}
|
|
71
|
+
|
|
72
|
+
public visitNativeBody(body: NativeBody): ExecutionCommand {
|
|
73
|
+
return new StepCommand(YuNil.getInstance());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public visitUnguardedBody(body: UnguardedBody): ExecutionCommand {
|
|
77
|
+
return this.solveBody(body.sequence.statements, this.substs, this.scope);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public visitGuard(guard: Guard): ExecutionCommand {
|
|
81
|
+
return new BindCommand(
|
|
82
|
+
this.solveBody([guard.condition], this.substs, this.scope),
|
|
83
|
+
(res) => {
|
|
84
|
+
if (!isLogicResult(res) || !res.allSuccessful())
|
|
85
|
+
return new BacktrackCommand();
|
|
86
|
+
|
|
87
|
+
const solutions = res.getSuccessfulSolutions();
|
|
88
|
+
if (solutions.length === 1)
|
|
89
|
+
return this.solveBody([guard.body], solutions[0], this.scope);
|
|
90
|
+
|
|
91
|
+
return new ChoiceCommand(
|
|
92
|
+
solutions.map((s) => this.solveBody([guard.body], s, this.scope)),
|
|
93
|
+
);
|
|
94
|
+
},
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public fallback(node: ASTNode): ExecutionCommand {
|
|
99
|
+
return new FailCommand(
|
|
100
|
+
new InterpreterError(
|
|
101
|
+
"Logic",
|
|
102
|
+
`Unexpected node ${node.constructor.name} in equation body`,
|
|
103
|
+
),
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
type Solver = (
|
|
109
|
+
expressions: LogicExecutable[],
|
|
110
|
+
env: Substitution,
|
|
111
|
+
scope?: Map<string, VariableTerm>,
|
|
112
|
+
) => ExecutionCommand;
|
|
113
|
+
|
|
114
|
+
export class GoalKernelVisitor implements Visitor<ExecutionCommand> {
|
|
115
|
+
constructor(
|
|
116
|
+
private readonly args: LogicTerm[],
|
|
117
|
+
private readonly baseSubst: Substitution,
|
|
118
|
+
private readonly solveBody: Solver,
|
|
119
|
+
private readonly translator: LogicTranslator,
|
|
120
|
+
) {}
|
|
121
|
+
|
|
122
|
+
public visitFact(fact: Fact): ExecutionCommand {
|
|
123
|
+
const scope = new Map<string, VariableTerm>();
|
|
124
|
+
const onSuccess = (substs: Substitution) =>
|
|
125
|
+
new StepCommand(new LogicResult([new LogicAnswer(true, substs)]));
|
|
126
|
+
|
|
127
|
+
return unifyParameters(
|
|
128
|
+
fact.patterns,
|
|
129
|
+
this.args,
|
|
130
|
+
this.baseSubst,
|
|
131
|
+
this.translator,
|
|
132
|
+
scope,
|
|
133
|
+
onSuccess,
|
|
134
|
+
() => new BacktrackCommand(),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
public visitRule(rule: Rule): ExecutionCommand {
|
|
139
|
+
const tryEquation = (eqIndex: number): ExecutionCommand => {
|
|
140
|
+
if (eqIndex >= rule.equations.length) {
|
|
141
|
+
return new BacktrackCommand();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const eq = rule.equations[eqIndex];
|
|
145
|
+
const scope = new Map<string, VariableTerm>();
|
|
146
|
+
|
|
147
|
+
const onFailure = () => tryEquation(eqIndex + 1);
|
|
148
|
+
const onSuccess = (substs: Substitution) => {
|
|
149
|
+
const bodyVisitor = new KernelBodyVisitor(
|
|
150
|
+
this.solveBody,
|
|
151
|
+
substs,
|
|
152
|
+
scope,
|
|
153
|
+
);
|
|
154
|
+
const currentCmd = eq.body.accept(bodyVisitor);
|
|
155
|
+
return new ChoiceCommand([currentCmd, tryEquation(eqIndex + 1)]);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
return unifyParameters(
|
|
159
|
+
eq.patterns,
|
|
160
|
+
this.args,
|
|
161
|
+
this.baseSubst,
|
|
162
|
+
this.translator,
|
|
163
|
+
scope,
|
|
164
|
+
onSuccess,
|
|
165
|
+
onFailure,
|
|
166
|
+
);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
return tryEquation(0);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
public fallback(node: ASTNode): ExecutionCommand {
|
|
173
|
+
return new FailCommand(
|
|
174
|
+
new InterpreterError(
|
|
175
|
+
"Logic",
|
|
176
|
+
`Unexpected node ${node.constructor.name} in predicate definition`,
|
|
177
|
+
),
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Solves a single logic goal (predicate call) using the Kernel.
|
|
184
|
+
* Returns a non-deterministic command. Aggregation should happen at top-level.
|
|
185
|
+
*/
|
|
186
|
+
export function solveGoalKernel(
|
|
187
|
+
ctx: RuntimeContext,
|
|
188
|
+
predicateName: string,
|
|
189
|
+
args: LogicTerm[],
|
|
190
|
+
solveBody: Solver,
|
|
191
|
+
baseSubst: Substitution,
|
|
192
|
+
translator: LogicTranslator,
|
|
193
|
+
): ExecutionCommand {
|
|
194
|
+
const pred = ctx.isDefined(predicateName) ? ctx.lookup(predicateName) : null;
|
|
195
|
+
|
|
196
|
+
const validPredicate =
|
|
197
|
+
isRuntimePredicate(pred) && pred.validateArity(args.length);
|
|
198
|
+
|
|
199
|
+
if (!validPredicate) return new BacktrackCommand();
|
|
200
|
+
|
|
201
|
+
const visitor = new GoalKernelVisitor(args, baseSubst, solveBody, translator);
|
|
202
|
+
|
|
203
|
+
const choices = pred
|
|
204
|
+
.apply(visitor)
|
|
205
|
+
.filter((c) => !(c instanceof FailCommand));
|
|
206
|
+
|
|
207
|
+
if (choices.length === 0) return new BacktrackCommand();
|
|
208
|
+
return choices.length === 1 ? choices[0] : new ChoiceCommand(choices);
|
|
209
|
+
}
|