yukigo 0.3.2 → 0.3.6
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/CHANGELOG.md +82 -40
- package/dist/analyzer/index.d.ts +7 -0
- package/dist/utils/helpers.d.ts +5 -2
- package/dist/utils/helpers.js +85 -38
- package/package.json +1 -1
- package/src/analyzer/index.ts +9 -0
- package/src/utils/helpers.ts +181 -113
- package/tests/analyzer/helpers.spec.ts +173 -83
package/CHANGELOG.md
CHANGED
|
@@ -1,68 +1,110 @@
|
|
|
1
|
-
## 0.3.
|
|
1
|
+
## 0.3.6 (2026-09-13)
|
|
2
2
|
|
|
3
|
-
###
|
|
3
|
+
### 🧱 Updated Dependencies
|
|
4
4
|
|
|
5
|
-
-
|
|
5
|
+
- Updated yukigo-ast to 0.3.6
|
|
6
|
+
|
|
7
|
+
## 0.3.5 (2026-09-13)
|
|
6
8
|
|
|
7
9
|
### 🧱 Updated Dependencies
|
|
8
10
|
|
|
9
|
-
- Updated yukigo-ast to 0.3.
|
|
11
|
+
- Updated yukigo-ast to 0.3.5
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
## 0.3.4 (2026-08-05)
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
### 🩹 Fixes
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
- **yukigo:** Fix MulangAdapter target suffix and matcher ([4d0a988](https://github.com/miyukiproject/yukigo/commit/4d0a988))
|
|
18
|
+
- **yukigo:** fix v0 Mulang Inspections translation ([2995ccc](https://github.com/miyukiproject/yukigo/commit/2995ccc))
|
|
16
19
|
|
|
17
20
|
### 🧱 Updated Dependencies
|
|
18
21
|
|
|
19
|
-
- Updated yukigo-ast to 0.3.
|
|
22
|
+
- Updated yukigo-ast to 0.3.4
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
### ❤️ Thank You
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
- noiseArch
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
- **interpreter:** implement semantic error handling and stack traces ([b61768f](https://github.com/miyukiproject/yukigo/commit/b61768f))
|
|
27
|
-
- **interpreter:** integrate Kernel as the primary execution engine ([503af3d](https://github.com/miyukiproject/yukigo/commit/503af3d))
|
|
28
|
-
- **interpreter:** introduce YukigoKernel and command-based infrastructure ([9380892](https://github.com/miyukiproject/yukigo/commit/9380892))
|
|
29
|
-
- **yukigo:** implement and test YukigoKernel ([3d42ac4](https://github.com/miyukiproject/yukigo/commit/3d42ac4))
|
|
28
|
+
## 0.3.3 (2026-08-05)
|
|
30
29
|
|
|
31
30
|
### 🩹 Fixes
|
|
32
31
|
|
|
33
|
-
- **yukigo
|
|
34
|
-
- **yukigo:**
|
|
35
|
-
- **yukigo:** fix circular dependency ([64534a8](https://github.com/miyukiproject/yukigo/commit/64534a8))
|
|
36
|
-
- **yukigo:** failed test didnt throw bc now it handles 1 + "a" ([23ebeb6](https://github.com/miyukiproject/yukigo/commit/23ebeb6))
|
|
37
|
-
- **yukigo:** zero-arity functions and Wollok bugs ([995dad4](https://github.com/miyukiproject/yukigo/commit/995dad4))
|
|
38
|
-
- **yukigo:** ObjectRuntime error should return RaiseCommand not FailCommand ([ccb31fa](https://github.com/miyukiproject/yukigo/commit/ccb31fa))
|
|
39
|
-
- **yukigo:** method registration with arity to allow overload ([8ffcb36](https://github.com/miyukiproject/yukigo/commit/8ffcb36))
|
|
40
|
-
- TypeSignature is not a Binding ([13c2c5a](https://github.com/miyukiproject/yukigo/commit/13c2c5a))
|
|
41
|
-
- **yukigo:** support If and Call nodes in LogicEngine ([a0f4086](https://github.com/miyukiproject/yukigo/commit/a0f4086))
|
|
42
|
-
- **yukigo:** fixed functional tester was evaluating logic tests ([914310e](https://github.com/miyukiproject/yukigo/commit/914310e))
|
|
43
|
-
- **yukigo:** solved scope leak at logical binary operations ([8779899](https://github.com/miyukiproject/yukigo/commit/8779899))
|
|
44
|
-
- ToString operator ([f5284ab](https://github.com/miyukiproject/yukigo/commit/f5284ab))
|
|
45
|
-
- **yukigo:** fix pattern matching in FunctionRuntime ([467cdf7](https://github.com/miyukiproject/yukigo/commit/467cdf7))
|
|
46
|
-
- **yukigo:** fix bitwise negation ([b13ef4d](https://github.com/miyukiproject/yukigo/commit/b13ef4d))
|
|
47
|
-
- **yukigo:** fix asynchronous logic unification and parameter resolution ([e467068](https://github.com/miyukiproject/yukigo/commit/e467068))
|
|
48
|
-
- **yukigo:** arreglo operaciones y sustitucion logica ([c95f33f](https://github.com/miyukiproject/yukigo/commit/c95f33f))
|
|
49
|
-
- fix parsers grammar compilation to export to .cjs ([ef59727](https://github.com/miyukiproject/yukigo/commit/ef59727))
|
|
50
|
-
- **yukigo:** fix tests to reflect correct representations ([76b1512](https://github.com/miyukiproject/yukigo/commit/76b1512))
|
|
51
|
-
- **yukigo:** fix Visitor and LazyRuntime to use new correct methods from context ([0eb9168](https://github.com/miyukiproject/yukigo/commit/0eb9168))
|
|
52
|
-
- **yukigo:** arreglos en logicengine ([0604555](https://github.com/miyukiproject/yukigo/commit/0604555))
|
|
53
|
-
- **yukigo:** fix mini error in oop test ([b9fd07e](https://github.com/miyukiproject/yukigo/commit/b9fd07e))
|
|
54
|
-
- **yukigo:** removed unwanted error handling ([0d1ff15](https://github.com/miyukiproject/yukigo/commit/0d1ff15))
|
|
55
|
-
- **yukigo:** replace instanceof with .is method in analyzer ([d953413](https://github.com/miyukiproject/yukigo/commit/d953413))
|
|
56
|
-
- **yukigo:** add InterpreterConfig as export ([280146c](https://github.com/miyukiproject/yukigo/commit/280146c))
|
|
32
|
+
- **yukigo:** Fix MulangAdapter target suffix and matcher ([4d0a988](https://github.com/miyukiproject/yukigo/commit/4d0a988))
|
|
33
|
+
- **yukigo:** fix v0 Mulang Inspections translation ([2995ccc](https://github.com/miyukiproject/yukigo/commit/2995ccc))
|
|
57
34
|
|
|
58
35
|
### 🧱 Updated Dependencies
|
|
59
36
|
|
|
60
|
-
- Updated yukigo-ast to 0.3.
|
|
37
|
+
- Updated yukigo-ast to 0.3.3
|
|
61
38
|
|
|
62
39
|
### ❤️ Thank You
|
|
63
40
|
|
|
64
41
|
- noiseArch
|
|
65
42
|
|
|
43
|
+
## 0.3.2 (2026-08-05)
|
|
44
|
+
|
|
45
|
+
### 🩹 Fixes
|
|
46
|
+
|
|
47
|
+
- **yukigo:** fix v0 Mulang Inspections translation ([2995ccc](https://github.com/miyukiproject/yukigo/commit/2995ccc))
|
|
48
|
+
|
|
49
|
+
### 🧱 Updated Dependencies
|
|
50
|
+
|
|
51
|
+
- Updated yukigo-ast to 0.3.2
|
|
52
|
+
|
|
53
|
+
### ❤️ Thank You
|
|
54
|
+
|
|
55
|
+
- noiseArch
|
|
56
|
+
|
|
57
|
+
## 0.3.1 (2026-08-01)
|
|
58
|
+
|
|
59
|
+
### 🧱 Updated Dependencies
|
|
60
|
+
|
|
61
|
+
- Updated yukigo-ast to 0.3.1
|
|
62
|
+
|
|
63
|
+
## 0.3.0 (2026-08-01)
|
|
64
|
+
|
|
65
|
+
### 🚀 Features
|
|
66
|
+
|
|
67
|
+
- Interpreter NativeBody support & YukigoHooks ([0b854b4](https://github.com/miyukiproject/yukigo/commit/0b854b4))
|
|
68
|
+
- **interpreter:** implement semantic error handling and stack traces ([b61768f](https://github.com/miyukiproject/yukigo/commit/b61768f))
|
|
69
|
+
- **interpreter:** integrate Kernel as the primary execution engine ([503af3d](https://github.com/miyukiproject/yukigo/commit/503af3d))
|
|
70
|
+
- **interpreter:** introduce YukigoKernel and command-based infrastructure ([9380892](https://github.com/miyukiproject/yukigo/commit/9380892))
|
|
71
|
+
- **yukigo:** implement and test YukigoKernel ([3d42ac4](https://github.com/miyukiproject/yukigo/commit/3d42ac4))
|
|
72
|
+
|
|
73
|
+
### 🩹 Fixes
|
|
74
|
+
|
|
75
|
+
- **yukigo-e2e:** fixes to pass E2E tests ([02d895f](https://github.com/miyukiproject/yukigo/commit/02d895f))
|
|
76
|
+
- **yukigo:** allow concatenation with Plus operator ([7799416](https://github.com/miyukiproject/yukigo/commit/7799416))
|
|
77
|
+
- **yukigo:** fix circular dependency ([64534a8](https://github.com/miyukiproject/yukigo/commit/64534a8))
|
|
78
|
+
- **yukigo:** failed test didnt throw bc now it handles 1 + "a" ([23ebeb6](https://github.com/miyukiproject/yukigo/commit/23ebeb6))
|
|
79
|
+
- **yukigo:** zero-arity functions and Wollok bugs ([995dad4](https://github.com/miyukiproject/yukigo/commit/995dad4))
|
|
80
|
+
- **yukigo:** ObjectRuntime error should return RaiseCommand not FailCommand ([ccb31fa](https://github.com/miyukiproject/yukigo/commit/ccb31fa))
|
|
81
|
+
- **yukigo:** method registration with arity to allow overload ([8ffcb36](https://github.com/miyukiproject/yukigo/commit/8ffcb36))
|
|
82
|
+
- TypeSignature is not a Binding ([13c2c5a](https://github.com/miyukiproject/yukigo/commit/13c2c5a))
|
|
83
|
+
- **yukigo:** support If and Call nodes in LogicEngine ([a0f4086](https://github.com/miyukiproject/yukigo/commit/a0f4086))
|
|
84
|
+
- **yukigo:** fixed functional tester was evaluating logic tests ([914310e](https://github.com/miyukiproject/yukigo/commit/914310e))
|
|
85
|
+
- **yukigo:** solved scope leak at logical binary operations ([8779899](https://github.com/miyukiproject/yukigo/commit/8779899))
|
|
86
|
+
- ToString operator ([f5284ab](https://github.com/miyukiproject/yukigo/commit/f5284ab))
|
|
87
|
+
- **yukigo:** fix pattern matching in FunctionRuntime ([467cdf7](https://github.com/miyukiproject/yukigo/commit/467cdf7))
|
|
88
|
+
- **yukigo:** fix bitwise negation ([b13ef4d](https://github.com/miyukiproject/yukigo/commit/b13ef4d))
|
|
89
|
+
- **yukigo:** fix asynchronous logic unification and parameter resolution ([e467068](https://github.com/miyukiproject/yukigo/commit/e467068))
|
|
90
|
+
- **yukigo:** arreglo operaciones y sustitucion logica ([c95f33f](https://github.com/miyukiproject/yukigo/commit/c95f33f))
|
|
91
|
+
- fix parsers grammar compilation to export to .cjs ([ef59727](https://github.com/miyukiproject/yukigo/commit/ef59727))
|
|
92
|
+
- **yukigo:** fix tests to reflect correct representations ([76b1512](https://github.com/miyukiproject/yukigo/commit/76b1512))
|
|
93
|
+
- **yukigo:** fix Visitor and LazyRuntime to use new correct methods from context ([0eb9168](https://github.com/miyukiproject/yukigo/commit/0eb9168))
|
|
94
|
+
- **yukigo:** arreglos en logicengine ([0604555](https://github.com/miyukiproject/yukigo/commit/0604555))
|
|
95
|
+
- **yukigo:** fix mini error in oop test ([b9fd07e](https://github.com/miyukiproject/yukigo/commit/b9fd07e))
|
|
96
|
+
- **yukigo:** removed unwanted error handling ([0d1ff15](https://github.com/miyukiproject/yukigo/commit/0d1ff15))
|
|
97
|
+
- **yukigo:** replace instanceof with .is method in analyzer ([d953413](https://github.com/miyukiproject/yukigo/commit/d953413))
|
|
98
|
+
- **yukigo:** add InterpreterConfig as export ([280146c](https://github.com/miyukiproject/yukigo/commit/280146c))
|
|
99
|
+
|
|
100
|
+
### 🧱 Updated Dependencies
|
|
101
|
+
|
|
102
|
+
- Updated yukigo-ast to 0.3.0
|
|
103
|
+
|
|
104
|
+
### ❤️ Thank You
|
|
105
|
+
|
|
106
|
+
- noiseArch
|
|
107
|
+
|
|
66
108
|
## 0.2.3 (2026-05-02)
|
|
67
109
|
|
|
68
110
|
### 🩹 Fixes
|
package/dist/analyzer/index.d.ts
CHANGED
|
@@ -6,11 +6,18 @@ export type AnalysisResult = {
|
|
|
6
6
|
actual: boolean;
|
|
7
7
|
error?: string;
|
|
8
8
|
};
|
|
9
|
+
export type TargetSuffix = "named" | "like" | "except";
|
|
10
|
+
export type InspectionMatcher = {
|
|
11
|
+
type: string;
|
|
12
|
+
value?: string;
|
|
13
|
+
};
|
|
9
14
|
export type InspectionRule = {
|
|
10
15
|
inspection: string;
|
|
11
16
|
binding?: string;
|
|
12
17
|
args?: string[];
|
|
13
18
|
expected: boolean;
|
|
19
|
+
targetSuffix?: TargetSuffix;
|
|
20
|
+
matcher?: InspectionMatcher;
|
|
14
21
|
};
|
|
15
22
|
export declare const DefaultInspectionSet: InspectionMap;
|
|
16
23
|
export declare const DefaultSmellsSet: InspectionMap;
|
package/dist/utils/helpers.d.ts
CHANGED
|
@@ -16,7 +16,10 @@ export interface InterpreterConfig {
|
|
|
16
16
|
* @returns An array of InspectionRule objects.
|
|
17
17
|
*/
|
|
18
18
|
export declare class MulangAdapter {
|
|
19
|
-
translateMulangInspection(mulangInspection:
|
|
19
|
+
translateMulangInspection(mulangInspection: unknown): InspectionRule;
|
|
20
20
|
translateMulangExpectations(mulangYamlString: string): InspectionRule[];
|
|
21
|
-
private
|
|
21
|
+
private transformToV2;
|
|
22
|
+
private parseNegation;
|
|
23
|
+
private applyV0ToV2;
|
|
24
|
+
private retrieveArguments;
|
|
22
25
|
}
|
package/dist/utils/helpers.js
CHANGED
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
import { parseDocument } from "yaml";
|
|
2
|
-
const
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"HasAnonymousVariable",
|
|
13
|
-
"HasNot",
|
|
14
|
-
"HasForall",
|
|
15
|
-
"HasFindall",
|
|
16
|
-
];
|
|
17
|
-
const V0_INSPECTIONS_Declares = new Map([
|
|
18
|
-
["HasBinding", "Declares"],
|
|
19
|
-
["HasTypeDeclaration", "DeclaresTypeAlias"],
|
|
20
|
-
["HasTypeSignature", "DeclaresTypeSignature"],
|
|
21
|
-
["HasVariable", "DeclaresVariable"],
|
|
22
|
-
["HasArity", "DeclaresComputationWithArity"],
|
|
23
|
-
["HasDirectRecursion", "DeclaresRecursively"],
|
|
24
|
-
["HasUsage", "Uses"],
|
|
2
|
+
const declareMap = {
|
|
3
|
+
HasBinding: "Declares",
|
|
4
|
+
HasTypeDeclaration: "DeclaresTypeAlias",
|
|
5
|
+
HasTypeSignature: "DeclaresTypeSignature",
|
|
6
|
+
HasVariable: "DeclaresVariable",
|
|
7
|
+
};
|
|
8
|
+
const V0_HAS_INSPECTIONS = new Set([
|
|
9
|
+
"HasBinding", "HasTypeDeclaration", "HasTypeSignature", "HasVariable",
|
|
10
|
+
"HasArity", "HasDirectRecursion", "HasComposition", "HasComprehension",
|
|
11
|
+
"HasForeach", "HasIf", "HasGuards", "HasConditional", "HasLambda",
|
|
12
|
+
"HasRepeat", "HasWhile", "HasUsage", "HasAnonymousVariable",
|
|
13
|
+
"HasNot", "HasForall", "HasFindall",
|
|
25
14
|
]);
|
|
15
|
+
const NEGATION_PREFIXES = new Set(["Not", "Except"]);
|
|
16
|
+
const SUFFIX_ARGS = new Set(["like", "except"]);
|
|
26
17
|
const isValidFormat = (inspection) => typeof inspection === "object" &&
|
|
27
18
|
"inspection" in inspection &&
|
|
28
19
|
"binding" in inspection;
|
|
@@ -35,16 +26,17 @@ export class MulangAdapter {
|
|
|
35
26
|
translateMulangInspection(mulangInspection) {
|
|
36
27
|
if (!isValidFormat(mulangInspection))
|
|
37
28
|
throw new Error(`Skipping malformed Mulang inspection entry: ${mulangInspection}`);
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const inspectionV0 = expected ? inspection[0] : inspection[1];
|
|
42
|
-
const inspectionV2 = this.translateV0Inspection(inspectionV0);
|
|
29
|
+
// transforms Mulang v0 to v2
|
|
30
|
+
const { inspection, expected, binding, args } = this.transformToV2(mulangInspection);
|
|
31
|
+
const { resolvedArgs, targetSuffix, matcher } = this.retrieveArguments(args);
|
|
43
32
|
return {
|
|
44
|
-
inspection
|
|
33
|
+
inspection,
|
|
45
34
|
expected,
|
|
46
|
-
|
|
47
|
-
|
|
35
|
+
binding,
|
|
36
|
+
args: resolvedArgs,
|
|
37
|
+
// these should not exist in the InspectionRule if they are undefined
|
|
38
|
+
...(targetSuffix !== undefined && { targetSuffix }),
|
|
39
|
+
...(matcher !== undefined && { matcher }),
|
|
48
40
|
};
|
|
49
41
|
}
|
|
50
42
|
translateMulangExpectations(mulangYamlString) {
|
|
@@ -63,14 +55,69 @@ export class MulangAdapter {
|
|
|
63
55
|
else {
|
|
64
56
|
throw new Error("Invalid Mulang YAML structure. Expected 'expectations' to be an array.");
|
|
65
57
|
}
|
|
66
|
-
const inspectionRules =
|
|
58
|
+
const inspectionRules = [];
|
|
59
|
+
for (const mulangInspection of expectations) {
|
|
60
|
+
const inspection = this.translateMulangInspection(mulangInspection);
|
|
61
|
+
inspectionRules.push(inspection);
|
|
62
|
+
}
|
|
67
63
|
return inspectionRules;
|
|
68
64
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return
|
|
65
|
+
transformToV2(mulangInspection) {
|
|
66
|
+
const parts = mulangInspection.inspection.split(":");
|
|
67
|
+
const { expected, inspection, args: parsedArgs, } = this.parseNegation(parts);
|
|
68
|
+
const args = mulangInspection.args ?? parsedArgs;
|
|
69
|
+
const v2 = this.applyV0ToV2(inspection, args, mulangInspection.binding);
|
|
70
|
+
return { expected, ...v2 };
|
|
71
|
+
}
|
|
72
|
+
parseNegation(parts) {
|
|
73
|
+
const negated = NEGATION_PREFIXES.has(parts[0]);
|
|
74
|
+
return {
|
|
75
|
+
expected: !negated,
|
|
76
|
+
inspection: parts[negated ? 1 : 0],
|
|
77
|
+
args: parts.slice(negated ? 2 : 1),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
applyV0ToV2(inspection, args, binding) {
|
|
81
|
+
if (inspection in declareMap)
|
|
82
|
+
return {
|
|
83
|
+
inspection: declareMap[inspection],
|
|
84
|
+
...promoteBindingToTarget(args, binding),
|
|
85
|
+
};
|
|
86
|
+
if (inspection === "HasArity")
|
|
87
|
+
return {
|
|
88
|
+
inspection: "DeclaresComputationWithArity",
|
|
89
|
+
args: [args[0], ...(binding && binding !== "*" ? [binding] : [])],
|
|
90
|
+
binding: "*",
|
|
91
|
+
};
|
|
92
|
+
if (V0_HAS_INSPECTIONS.has(inspection))
|
|
93
|
+
return { inspection: inspection === "HasUsage" ? "Uses" : inspection.replace(/^Has/, "Uses"), args, binding };
|
|
94
|
+
return { inspection, args, binding };
|
|
95
|
+
}
|
|
96
|
+
retrieveArguments(args) {
|
|
97
|
+
const targetSuffix = args.find((a) => SUFFIX_ARGS.has(a));
|
|
98
|
+
const matcherIndex = args.findIndex((a) => a.startsWith("With"));
|
|
99
|
+
const matcher = matcherIndex !== -1
|
|
100
|
+
? {
|
|
101
|
+
type: "with_" + args[matcherIndex].slice(4).toLowerCase(),
|
|
102
|
+
value: args[matcherIndex + 1],
|
|
103
|
+
}
|
|
104
|
+
: undefined;
|
|
105
|
+
const consumed = new Set([
|
|
106
|
+
...(targetSuffix ? [targetSuffix] : []),
|
|
107
|
+
...(matcherIndex !== -1
|
|
108
|
+
? [args[matcherIndex], args[matcherIndex + 1]]
|
|
109
|
+
: []),
|
|
110
|
+
]);
|
|
111
|
+
const resolvedArgs = args.filter((a) => !consumed.has(a));
|
|
112
|
+
return {
|
|
113
|
+
targetSuffix: targetSuffix ??
|
|
114
|
+
(resolvedArgs.length > 0 ? "named" : undefined),
|
|
115
|
+
matcher,
|
|
116
|
+
resolvedArgs,
|
|
117
|
+
};
|
|
75
118
|
}
|
|
76
119
|
}
|
|
120
|
+
const promoteBindingToTarget = (args, binding) => ({
|
|
121
|
+
args: binding && binding !== "*" ? [binding, ...args] : args,
|
|
122
|
+
binding: "*",
|
|
123
|
+
});
|
package/package.json
CHANGED
package/src/analyzer/index.ts
CHANGED
|
@@ -19,11 +19,20 @@ export type AnalysisResult = {
|
|
|
19
19
|
error?: string;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
export type TargetSuffix = "named" | "like" | "except";
|
|
23
|
+
|
|
24
|
+
export type InspectionMatcher = {
|
|
25
|
+
type: string;
|
|
26
|
+
value?: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
22
29
|
export type InspectionRule = {
|
|
23
30
|
inspection: string;
|
|
24
31
|
binding?: string;
|
|
25
32
|
args?: string[];
|
|
26
33
|
expected: boolean;
|
|
34
|
+
targetSuffix?: TargetSuffix;
|
|
35
|
+
matcher?: InspectionMatcher;
|
|
27
36
|
};
|
|
28
37
|
|
|
29
38
|
export const DefaultInspectionSet: InspectionMap = {
|
package/src/utils/helpers.ts
CHANGED
|
@@ -1,113 +1,181 @@
|
|
|
1
|
-
import { parseDocument } from "yaml";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
mulangYamlString
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (Array.isArray(parsedYaml)) {
|
|
89
|
-
expectations = parsedYaml;
|
|
90
|
-
} else
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
this.translateMulangInspection(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
1
|
+
import { parseDocument } from "yaml";
|
|
2
|
+
import {
|
|
3
|
+
InspectionRule,
|
|
4
|
+
TargetSuffix,
|
|
5
|
+
} from "../analyzer/index.js";
|
|
6
|
+
import { NativeExtension } from "../interpreter/utils.js";
|
|
7
|
+
import { YukigoHook } from "../interpreter/components/hooks/YukigoHook.js";
|
|
8
|
+
|
|
9
|
+
const declareMap: Record<string, string> = {
|
|
10
|
+
HasBinding: "Declares",
|
|
11
|
+
HasTypeDeclaration: "DeclaresTypeAlias",
|
|
12
|
+
HasTypeSignature: "DeclaresTypeSignature",
|
|
13
|
+
HasVariable: "DeclaresVariable",
|
|
14
|
+
};
|
|
15
|
+
const V0_HAS_INSPECTIONS = new Set([
|
|
16
|
+
"HasBinding", "HasTypeDeclaration", "HasTypeSignature", "HasVariable",
|
|
17
|
+
"HasArity", "HasDirectRecursion", "HasComposition", "HasComprehension",
|
|
18
|
+
"HasForeach", "HasIf", "HasGuards", "HasConditional", "HasLambda",
|
|
19
|
+
"HasRepeat", "HasWhile", "HasUsage", "HasAnonymousVariable",
|
|
20
|
+
"HasNot", "HasForall", "HasFindall",
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
type MulangInspection = {
|
|
24
|
+
inspection: string;
|
|
25
|
+
binding: string;
|
|
26
|
+
args?: string[];
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type LogicSearchMode = "first" | "all" | "stream";
|
|
30
|
+
export interface InterpreterConfig {
|
|
31
|
+
nativeProviders: Map<string, NativeExtension>;
|
|
32
|
+
lazyLoading: boolean;
|
|
33
|
+
debug: boolean;
|
|
34
|
+
outputMode: LogicSearchMode;
|
|
35
|
+
mutability: boolean;
|
|
36
|
+
hooks?: YukigoHook[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const NEGATION_PREFIXES = new Set(["Not", "Except"]);
|
|
40
|
+
const SUFFIX_ARGS = new Set<TargetSuffix>(["like", "except"]);
|
|
41
|
+
|
|
42
|
+
const isValidFormat = (inspection: any): inspection is MulangInspection =>
|
|
43
|
+
typeof inspection === "object" &&
|
|
44
|
+
"inspection" in inspection &&
|
|
45
|
+
"binding" in inspection;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Translates Mulang inspections (YAML format) to an array of `InspectionRule` objects.
|
|
49
|
+
* @param mulangYamlString The Mulang inspection syntax as a YAML string.
|
|
50
|
+
* @returns An array of InspectionRule objects.
|
|
51
|
+
*/
|
|
52
|
+
export class MulangAdapter {
|
|
53
|
+
public translateMulangInspection(mulangInspection: unknown): InspectionRule {
|
|
54
|
+
if (!isValidFormat(mulangInspection))
|
|
55
|
+
throw new Error(
|
|
56
|
+
`Skipping malformed Mulang inspection entry: ${mulangInspection}`,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
// transforms Mulang v0 to v2
|
|
60
|
+
const { inspection, expected, binding, args } =
|
|
61
|
+
this.transformToV2(mulangInspection);
|
|
62
|
+
|
|
63
|
+
const { resolvedArgs, targetSuffix, matcher } =
|
|
64
|
+
this.retrieveArguments(args);
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
inspection,
|
|
68
|
+
expected,
|
|
69
|
+
binding,
|
|
70
|
+
args: resolvedArgs,
|
|
71
|
+
// these should not exist in the InspectionRule if they are undefined
|
|
72
|
+
...(targetSuffix !== undefined && { targetSuffix }),
|
|
73
|
+
...(matcher !== undefined && { matcher }),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public translateMulangExpectations(
|
|
78
|
+
mulangYamlString: string
|
|
79
|
+
): InspectionRule[] {
|
|
80
|
+
if (!mulangYamlString) return [];
|
|
81
|
+
const parsedYaml = parseDocument(mulangYamlString).toJS();
|
|
82
|
+
|
|
83
|
+
if (!parsedYaml) return [];
|
|
84
|
+
|
|
85
|
+
let expectations: any[] = [];
|
|
86
|
+
if (Array.isArray(parsedYaml)) {
|
|
87
|
+
expectations = parsedYaml;
|
|
88
|
+
} else if (Array.isArray(parsedYaml.expectations)) {
|
|
89
|
+
expectations = parsedYaml.expectations;
|
|
90
|
+
} else {
|
|
91
|
+
throw new Error(
|
|
92
|
+
"Invalid Mulang YAML structure. Expected 'expectations' to be an array."
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const inspectionRules: InspectionRule[] = [];
|
|
97
|
+
|
|
98
|
+
for (const mulangInspection of expectations) {
|
|
99
|
+
const inspection = this.translateMulangInspection(mulangInspection);
|
|
100
|
+
inspectionRules.push(inspection);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return inspectionRules;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private transformToV2(mulangInspection: MulangInspection) {
|
|
107
|
+
const parts = mulangInspection.inspection.split(":");
|
|
108
|
+
const {
|
|
109
|
+
expected,
|
|
110
|
+
inspection,
|
|
111
|
+
args: parsedArgs,
|
|
112
|
+
} = this.parseNegation(parts);
|
|
113
|
+
const args = mulangInspection.args ?? parsedArgs;
|
|
114
|
+
const v2 = this.applyV0ToV2(inspection, args, mulangInspection.binding);
|
|
115
|
+
return { expected, ...v2 };
|
|
116
|
+
}
|
|
117
|
+
private parseNegation(parts: string[]) {
|
|
118
|
+
const negated = NEGATION_PREFIXES.has(parts[0]);
|
|
119
|
+
return {
|
|
120
|
+
expected: !negated,
|
|
121
|
+
inspection: parts[negated ? 1 : 0],
|
|
122
|
+
args: parts.slice(negated ? 2 : 1),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
private applyV0ToV2(inspection: string, args: string[], binding: string) {
|
|
126
|
+
if (inspection in declareMap)
|
|
127
|
+
return {
|
|
128
|
+
inspection: declareMap[inspection],
|
|
129
|
+
...promoteBindingToTarget(args, binding),
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
if (inspection === "HasArity")
|
|
133
|
+
return {
|
|
134
|
+
inspection: "DeclaresComputationWithArity",
|
|
135
|
+
args: [args[0], ...(binding && binding !== "*" ? [binding] : [])],
|
|
136
|
+
binding: "*",
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
if (V0_HAS_INSPECTIONS.has(inspection))
|
|
140
|
+
return { inspection: inspection === "HasUsage" ? "Uses" : inspection.replace(/^Has/, "Uses"), args, binding };
|
|
141
|
+
|
|
142
|
+
return { inspection, args, binding };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private retrieveArguments(args: string[]) {
|
|
146
|
+
const targetSuffix = args.find((a): a is TargetSuffix =>
|
|
147
|
+
SUFFIX_ARGS.has(a as TargetSuffix),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const matcherIndex = args.findIndex((a) => a.startsWith("With"));
|
|
151
|
+
const matcher =
|
|
152
|
+
matcherIndex !== -1
|
|
153
|
+
? {
|
|
154
|
+
type: "with_" + args[matcherIndex].slice(4).toLowerCase(),
|
|
155
|
+
value: args[matcherIndex + 1],
|
|
156
|
+
}
|
|
157
|
+
: undefined;
|
|
158
|
+
|
|
159
|
+
const consumed = new Set([
|
|
160
|
+
...(targetSuffix ? [targetSuffix] : []),
|
|
161
|
+
...(matcherIndex !== -1
|
|
162
|
+
? [args[matcherIndex], args[matcherIndex + 1]]
|
|
163
|
+
: []),
|
|
164
|
+
]);
|
|
165
|
+
|
|
166
|
+
const resolvedArgs = args.filter((a) => !consumed.has(a));
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
targetSuffix:
|
|
170
|
+
targetSuffix ??
|
|
171
|
+
(resolvedArgs.length > 0 ? ("named" as TargetSuffix) : undefined),
|
|
172
|
+
matcher,
|
|
173
|
+
resolvedArgs,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const promoteBindingToTarget = (args: string[], binding: string) => ({
|
|
179
|
+
args: binding && binding !== "*" ? [binding, ...args] : args,
|
|
180
|
+
binding: "*",
|
|
181
|
+
});
|
|
@@ -1,83 +1,173 @@
|
|
|
1
|
-
import { MulangAdapter } from "../../src/index.js";
|
|
2
|
-
import { isYukigoPrimitive, NumberPrimitive, Otherwise } from "yukigo-ast";
|
|
3
|
-
import { assert } from "chai";
|
|
4
|
-
|
|
5
|
-
describe("Helpers Spec", () => {
|
|
6
|
-
it("translates correctly mulang's expectations", () => {
|
|
7
|
-
const mulangAdapter = new MulangAdapter();
|
|
8
|
-
const mulangExpectations = `
|
|
9
|
-
expectations:
|
|
10
|
-
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
11
|
-
binding: squareList
|
|
12
|
-
inspection: HasBinding
|
|
13
|
-
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
14
|
-
binding: squareList
|
|
15
|
-
inspection: HasLambdaExpression
|
|
16
|
-
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
17
|
-
binding: square
|
|
18
|
-
inspection: HasArithmetic
|
|
19
|
-
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
20
|
-
binding: doble
|
|
21
|
-
inspection: Not:HasBinding
|
|
22
|
-
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
23
|
-
binding: square
|
|
24
|
-
inspection: Uses:x
|
|
25
|
-
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
26
|
-
binding: squareList
|
|
27
|
-
inspection: Uses:map
|
|
28
|
-
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
29
|
-
binding: squareList
|
|
30
|
-
inspection: Not:Uses:map`;
|
|
31
|
-
|
|
32
|
-
const yukigoExpectations =
|
|
33
|
-
mulangAdapter.translateMulangExpectations(mulangExpectations);
|
|
34
|
-
assert.deepEqual(yukigoExpectations, [
|
|
35
|
-
{
|
|
36
|
-
inspection: "Declares",
|
|
37
|
-
binding: "
|
|
38
|
-
args: [],
|
|
39
|
-
expected: true,
|
|
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
|
-
});
|
|
1
|
+
import { MulangAdapter } from "../../src/index.js";
|
|
2
|
+
import { isYukigoPrimitive, NumberPrimitive, Otherwise } from "yukigo-ast";
|
|
3
|
+
import { assert } from "chai";
|
|
4
|
+
|
|
5
|
+
describe("Helpers Spec", () => {
|
|
6
|
+
it("translates correctly mulang's expectations", () => {
|
|
7
|
+
const mulangAdapter = new MulangAdapter();
|
|
8
|
+
const mulangExpectations = `
|
|
9
|
+
expectations:
|
|
10
|
+
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
11
|
+
binding: squareList
|
|
12
|
+
inspection: HasBinding
|
|
13
|
+
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
14
|
+
binding: squareList
|
|
15
|
+
inspection: HasLambdaExpression
|
|
16
|
+
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
17
|
+
binding: square
|
|
18
|
+
inspection: HasArithmetic
|
|
19
|
+
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
20
|
+
binding: doble
|
|
21
|
+
inspection: Not:HasBinding
|
|
22
|
+
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
23
|
+
binding: square
|
|
24
|
+
inspection: Uses:x
|
|
25
|
+
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
26
|
+
binding: squareList
|
|
27
|
+
inspection: Uses:map
|
|
28
|
+
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
29
|
+
binding: squareList
|
|
30
|
+
inspection: Not:Uses:map`;
|
|
31
|
+
|
|
32
|
+
const yukigoExpectations =
|
|
33
|
+
mulangAdapter.translateMulangExpectations(mulangExpectations);
|
|
34
|
+
assert.deepEqual(yukigoExpectations, [
|
|
35
|
+
{
|
|
36
|
+
inspection: "Declares",
|
|
37
|
+
binding: "*",
|
|
38
|
+
args: ["squareList"],
|
|
39
|
+
expected: true,
|
|
40
|
+
targetSuffix: "named",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
inspection: "HasLambdaExpression",
|
|
44
|
+
binding: "squareList",
|
|
45
|
+
args: [],
|
|
46
|
+
expected: true,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
inspection: "HasArithmetic",
|
|
50
|
+
binding: "square",
|
|
51
|
+
args: [],
|
|
52
|
+
expected: true,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
inspection: "Declares",
|
|
56
|
+
binding: "*",
|
|
57
|
+
args: ["doble"],
|
|
58
|
+
expected: false,
|
|
59
|
+
targetSuffix: "named",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
inspection: "Uses",
|
|
63
|
+
binding: "square",
|
|
64
|
+
args: ["x"],
|
|
65
|
+
expected: true,
|
|
66
|
+
targetSuffix: "named",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
inspection: "Uses",
|
|
70
|
+
binding: "squareList",
|
|
71
|
+
args: ["map"],
|
|
72
|
+
expected: true,
|
|
73
|
+
targetSuffix: "named",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
inspection: "Uses",
|
|
77
|
+
binding: "squareList",
|
|
78
|
+
args: ["map"],
|
|
79
|
+
expected: false,
|
|
80
|
+
targetSuffix: "named",
|
|
81
|
+
},
|
|
82
|
+
]);
|
|
83
|
+
});
|
|
84
|
+
it("translates mulang's expectations with target suffixes and matchers", () => {
|
|
85
|
+
const mulangAdapter = new MulangAdapter();
|
|
86
|
+
const expectations = `
|
|
87
|
+
expectations:
|
|
88
|
+
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
89
|
+
binding: "*"
|
|
90
|
+
inspection: Calls:foo:except:WithNumber:4
|
|
91
|
+
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
92
|
+
binding: "*"
|
|
93
|
+
inspection: Calls:bar:like:WithAnything
|
|
94
|
+
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
95
|
+
binding: "*"
|
|
96
|
+
inspection: Calls:baz:WithTrue
|
|
97
|
+
- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
|
|
98
|
+
binding: "*"
|
|
99
|
+
inspection: Calls:WithAnything
|
|
100
|
+
`;
|
|
101
|
+
const yukigoExpectations = mulangAdapter.translateMulangExpectations(expectations);
|
|
102
|
+
assert.deepEqual(yukigoExpectations, [
|
|
103
|
+
{
|
|
104
|
+
inspection: "Calls",
|
|
105
|
+
binding: "*",
|
|
106
|
+
args: ["foo"],
|
|
107
|
+
expected: true,
|
|
108
|
+
targetSuffix: "except",
|
|
109
|
+
matcher: {
|
|
110
|
+
type: "with_number",
|
|
111
|
+
value: "4"
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
inspection: "Calls",
|
|
116
|
+
binding: "*",
|
|
117
|
+
args: ["bar"],
|
|
118
|
+
expected: true,
|
|
119
|
+
targetSuffix: "like",
|
|
120
|
+
matcher: {
|
|
121
|
+
type: "with_anything",
|
|
122
|
+
value: undefined
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
inspection: "Calls",
|
|
127
|
+
binding: "*",
|
|
128
|
+
args: ["baz"],
|
|
129
|
+
expected: true,
|
|
130
|
+
targetSuffix: "named",
|
|
131
|
+
matcher: {
|
|
132
|
+
type: "with_true",
|
|
133
|
+
value: undefined
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
inspection: "Calls",
|
|
138
|
+
binding: "*",
|
|
139
|
+
args: [],
|
|
140
|
+
expected: true,
|
|
141
|
+
matcher: {
|
|
142
|
+
type: "with_anything",
|
|
143
|
+
value: undefined
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
]);
|
|
147
|
+
});
|
|
148
|
+
it("translates correctly expectations that provide arguments in the args property instead of the inspection string", () => {
|
|
149
|
+
const mulangAdapter = new MulangAdapter();
|
|
150
|
+
const rules = [
|
|
151
|
+
{
|
|
152
|
+
binding: "cantidadRuedasMoto",
|
|
153
|
+
inspection: "HasUsage",
|
|
154
|
+
args: ["cantidadRuedasBicicleta"],
|
|
155
|
+
expected: true
|
|
156
|
+
}
|
|
157
|
+
];
|
|
158
|
+
const yukigoExpectations = rules.map((r) => mulangAdapter.translateMulangInspection(r));
|
|
159
|
+
assert.deepEqual(yukigoExpectations, [
|
|
160
|
+
{
|
|
161
|
+
inspection: "Uses",
|
|
162
|
+
binding: "cantidadRuedasMoto",
|
|
163
|
+
args: ["cantidadRuedasBicicleta"],
|
|
164
|
+
expected: true,
|
|
165
|
+
targetSuffix: "named"
|
|
166
|
+
}
|
|
167
|
+
]);
|
|
168
|
+
});
|
|
169
|
+
it("detects correctly YukigoPrimitive", () => {
|
|
170
|
+
assert.isFalse(isYukigoPrimitive(new Otherwise()));
|
|
171
|
+
assert.isTrue(isYukigoPrimitive(new NumberPrimitive(4)));
|
|
172
|
+
});
|
|
173
|
+
});
|