@dallaylaen/ski-interpreter 2.2.0 → 2.3.0
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 +51 -0
- package/README.md +86 -11
- package/bin/ski.js +195 -82
- package/lib/ski-interpreter.cjs.js +522 -329
- package/lib/ski-interpreter.cjs.js.map +3 -3
- package/lib/ski-interpreter.esm.js +522 -329
- package/lib/ski-interpreter.esm.js.map +2 -2
- package/lib/ski-interpreter.min.js +4 -0
- package/lib/ski-interpreter.min.js.map +7 -0
- package/lib/ski-quest.min.js +4 -0
- package/lib/ski-quest.min.js.map +7 -0
- package/package.json +11 -4
- package/types/src/expr.d.ts +201 -102
- package/types/src/extras.d.ts +17 -1
- package/types/src/internal.d.ts +23 -10
- package/types/src/parser.d.ts +46 -19
- package/types/src/quest.d.ts +87 -41
package/types/src/parser.d.ts
CHANGED
|
@@ -24,7 +24,8 @@ export class SKI {
|
|
|
24
24
|
};
|
|
25
25
|
hasNumbers: boolean;
|
|
26
26
|
hasLambdas: boolean;
|
|
27
|
-
|
|
27
|
+
/** @type {Set<string>} */
|
|
28
|
+
allow: Set<string>;
|
|
28
29
|
/**
|
|
29
30
|
* @desc Declare a new term
|
|
30
31
|
* If the first argument is an Alias, it is added as is.
|
|
@@ -41,20 +42,41 @@ export class SKI {
|
|
|
41
42
|
*
|
|
42
43
|
* @param {Alias|String} term
|
|
43
44
|
* @param {String|Expr|function(Expr):Partial} [impl]
|
|
44
|
-
* @param {
|
|
45
|
+
* @param {object|string} [options]
|
|
46
|
+
* @param {string} [options.note] - optional annotation for the term, default is auto-generated if this.annotate is true
|
|
47
|
+
* @param {boolean} [options.canonize] - whether to canonize the term's implementation, default is this.annotate
|
|
48
|
+
* @param {boolean} [options.fancy] - alternative HTML-friendly name for the term
|
|
49
|
+
* @param {number} [options.arity] - custom arity for the term, default is inferred from the implementation
|
|
45
50
|
* @return {SKI} chainable
|
|
46
51
|
*/
|
|
47
|
-
add(term: typeof classes.Alias | string, impl?: string | typeof classes.Expr | ((arg0: typeof classes.Expr) => Partial),
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
add(term: typeof classes.Alias | string, impl?: string | typeof classes.Expr | ((arg0: typeof classes.Expr) => Partial), options?: object | string): SKI;
|
|
53
|
+
/**
|
|
54
|
+
* @desc Internal helper for add() that creates an Alias or Native term from the given arguments.
|
|
55
|
+
* @param {Alias|string} term
|
|
56
|
+
* @param {string|Expr|function(Expr):Partial} impl
|
|
57
|
+
* @returns {Native|Alias}
|
|
58
|
+
* @private
|
|
59
|
+
*/
|
|
60
|
+
private _named;
|
|
61
|
+
/**
|
|
62
|
+
* @desc Declare a new term if it is not known, otherwise just allow it.
|
|
63
|
+
* Currently only used by quests.
|
|
64
|
+
* Use with caution, this function may change its signature, behavior, or even be removed in the future.
|
|
65
|
+
*
|
|
66
|
+
* @experimental
|
|
67
|
+
* @param {string|Alias} name
|
|
68
|
+
* @param {string|Expr|function(Expr):Partial} impl
|
|
69
|
+
* @returns {SKI}
|
|
70
|
+
*/
|
|
71
|
+
maybeAdd(name: string | typeof classes.Alias, impl: string | typeof classes.Expr | ((arg0: typeof classes.Expr) => Partial)): SKI;
|
|
50
72
|
/**
|
|
51
73
|
* @desc Declare and remove multiple terms at once
|
|
52
74
|
* term=impl adds term
|
|
53
75
|
* term= removes term
|
|
54
|
-
* @param {string[]
|
|
76
|
+
* @param {string[]} list
|
|
55
77
|
* @return {SKI} chainable
|
|
56
78
|
*/
|
|
57
|
-
bulkAdd(list:
|
|
79
|
+
bulkAdd(list: string[]): SKI;
|
|
58
80
|
/**
|
|
59
81
|
* Restrict the interpreter to given terms. Terms prepended with '+' will be added
|
|
60
82
|
* and terms preceeded with '-' will be removed.
|
|
@@ -92,44 +114,46 @@ export class SKI {
|
|
|
92
114
|
*/
|
|
93
115
|
declare(): string[];
|
|
94
116
|
/**
|
|
95
|
-
*
|
|
117
|
+
* @template T
|
|
96
118
|
* @param {string} source
|
|
97
119
|
* @param {Object} [options]
|
|
98
120
|
* @param {{[keys: string]: Expr}} [options.env]
|
|
99
|
-
* @param {
|
|
121
|
+
* @param {T} [options.scope]
|
|
100
122
|
* @param {boolean} [options.numbers]
|
|
101
123
|
* @param {boolean} [options.lambdas]
|
|
102
124
|
* @param {string} [options.allow]
|
|
103
125
|
* @return {Expr}
|
|
104
126
|
*/
|
|
105
|
-
parse(source: string, options?: {
|
|
127
|
+
parse<T_1>(source: string, options?: {
|
|
106
128
|
env?: {
|
|
107
129
|
[keys: string]: typeof classes.Expr;
|
|
108
130
|
};
|
|
109
|
-
scope?:
|
|
131
|
+
scope?: T_1;
|
|
110
132
|
numbers?: boolean;
|
|
111
133
|
lambdas?: boolean;
|
|
112
134
|
allow?: string;
|
|
113
135
|
}): typeof classes.Expr;
|
|
114
136
|
/**
|
|
115
|
-
*
|
|
137
|
+
* @desc Parse a single line of source code, without splitting it into declarations.
|
|
138
|
+
* Internal, always use parse() instead.
|
|
139
|
+
* @template T
|
|
116
140
|
* @param {String} source S(KI)I
|
|
117
141
|
* @param {{[keys: string]: Expr}} env
|
|
118
142
|
* @param {Object} [options]
|
|
119
143
|
* @param {{[keys: string]: Expr}} [options.env] - unused, see 'env' argument
|
|
120
|
-
* @param {
|
|
144
|
+
* @param {T} [options.scope]
|
|
121
145
|
* @param {boolean} [options.numbers]
|
|
122
146
|
* @param {boolean} [options.lambdas]
|
|
123
147
|
* @param {string} [options.allow]
|
|
124
148
|
* @return {Expr} parsed expression
|
|
125
149
|
*/
|
|
126
|
-
parseLine(source: string, env?: {
|
|
150
|
+
parseLine<T_1>(source: string, env?: {
|
|
127
151
|
[keys: string]: typeof classes.Expr;
|
|
128
152
|
}, options?: {
|
|
129
153
|
env?: {
|
|
130
154
|
[keys: string]: typeof classes.Expr;
|
|
131
155
|
};
|
|
132
|
-
scope?:
|
|
156
|
+
scope?: T_1;
|
|
133
157
|
numbers?: boolean;
|
|
134
158
|
lambdas?: boolean;
|
|
135
159
|
allow?: string;
|
|
@@ -159,9 +183,11 @@ export namespace SKI {
|
|
|
159
183
|
* x instanceof FreeVar; // true
|
|
160
184
|
* x.apply(y).apply(z); // x(y)(z)
|
|
161
185
|
*
|
|
186
|
+
* @template T
|
|
187
|
+
* @param {T} [scope] - optional context to bind the generated variables to
|
|
162
188
|
* @return {{[key: string]: FreeVar}}
|
|
163
189
|
*/
|
|
164
|
-
export function vars(
|
|
190
|
+
export function vars<T_1>(scope?: T_1): {
|
|
165
191
|
[key: string]: typeof import("./expr").FreeVar;
|
|
166
192
|
};
|
|
167
193
|
/**
|
|
@@ -173,9 +199,10 @@ export namespace SKI {
|
|
|
173
199
|
export { classes };
|
|
174
200
|
export { native };
|
|
175
201
|
export let control: {
|
|
176
|
-
descend: (arg0:
|
|
177
|
-
prune: (arg0:
|
|
178
|
-
|
|
202
|
+
descend: (arg0: T) => TraverseControl<T>;
|
|
203
|
+
prune: (arg0: T) => TraverseControl<T>;
|
|
204
|
+
redo: (arg0: T) => TraverseControl<T>;
|
|
205
|
+
stop: (arg0: T) => TraverseControl<T>;
|
|
179
206
|
};
|
|
180
207
|
}
|
|
181
208
|
import classes = require("./expr");
|
package/types/src/quest.d.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
export type CaseResult = {
|
|
2
2
|
pass: boolean;
|
|
3
|
-
reason
|
|
3
|
+
reason?: string;
|
|
4
4
|
steps: number;
|
|
5
5
|
start: typeof import("./expr").Expr;
|
|
6
6
|
found: typeof import("./expr").Expr;
|
|
7
7
|
expected: typeof import("./expr").Expr;
|
|
8
|
-
note
|
|
8
|
+
note?: string;
|
|
9
9
|
args: typeof import("./expr").Expr[];
|
|
10
10
|
case: Case;
|
|
11
11
|
};
|
|
12
12
|
export type Capability = {
|
|
13
|
-
linear
|
|
14
|
-
affine
|
|
15
|
-
normal
|
|
16
|
-
proper
|
|
17
|
-
discard
|
|
18
|
-
duplicate
|
|
19
|
-
arity
|
|
13
|
+
linear?: boolean;
|
|
14
|
+
affine?: boolean;
|
|
15
|
+
normal?: boolean;
|
|
16
|
+
proper?: boolean;
|
|
17
|
+
discard?: boolean;
|
|
18
|
+
duplicate?: boolean;
|
|
19
|
+
arity?: number;
|
|
20
20
|
};
|
|
21
21
|
export type InputSpec = string | {
|
|
22
22
|
name: string;
|
|
@@ -34,35 +34,39 @@ export type QuestResult = {
|
|
|
34
34
|
steps: number;
|
|
35
35
|
weight?: number;
|
|
36
36
|
};
|
|
37
|
+
export type SelfCheck = {
|
|
38
|
+
accepted?: string[][];
|
|
39
|
+
rejected?: string[][];
|
|
40
|
+
};
|
|
37
41
|
/**
|
|
38
42
|
* @typedef {{
|
|
39
43
|
* pass: boolean,
|
|
40
|
-
* reason
|
|
44
|
+
* reason?: string,
|
|
41
45
|
* steps: number,
|
|
42
46
|
* start: Expr,
|
|
43
47
|
* found: Expr,
|
|
44
48
|
* expected: Expr,
|
|
45
|
-
* note
|
|
49
|
+
* note?: string,
|
|
46
50
|
* args: Expr[],
|
|
47
51
|
* case: Case
|
|
48
52
|
* }} CaseResult
|
|
49
53
|
*/
|
|
50
54
|
/**
|
|
51
55
|
* @typedef {{
|
|
52
|
-
* linear
|
|
53
|
-
* affine
|
|
54
|
-
* normal
|
|
55
|
-
* proper
|
|
56
|
-
* discard
|
|
57
|
-
* duplicate
|
|
58
|
-
* arity
|
|
56
|
+
* linear?: boolean,
|
|
57
|
+
* affine?: boolean,
|
|
58
|
+
* normal?: boolean,
|
|
59
|
+
* proper?: boolean,
|
|
60
|
+
* discard?: boolean,
|
|
61
|
+
* duplicate?: boolean,
|
|
62
|
+
* arity?: number,
|
|
59
63
|
* }} Capability
|
|
60
64
|
*/
|
|
61
65
|
/**
|
|
62
66
|
* @typedef {
|
|
63
67
|
* [string, string]
|
|
64
|
-
* | [{max
|
|
65
|
-
* | [{caps: Capability, max
|
|
68
|
+
* | [{max?: number}, string, string]
|
|
69
|
+
* | [{caps: Capability, max?: number}, string]
|
|
66
70
|
* } TestCase
|
|
67
71
|
*/
|
|
68
72
|
/**
|
|
@@ -79,27 +83,32 @@ export type QuestResult = {
|
|
|
79
83
|
* weight?: number
|
|
80
84
|
* }} QuestResult
|
|
81
85
|
*/
|
|
86
|
+
/**
|
|
87
|
+
* @typedef {{
|
|
88
|
+
* input: InputSpec | InputSpec[],
|
|
89
|
+
* cases: TestCase[],
|
|
90
|
+
*
|
|
91
|
+
* // the rest is optional
|
|
92
|
+
*
|
|
93
|
+
* allow?: string,
|
|
94
|
+
* numbers?: boolean,
|
|
95
|
+
* env?: string[],
|
|
96
|
+
* engine?: SKI,
|
|
97
|
+
* engineFull?: SKI,
|
|
98
|
+
*
|
|
99
|
+
* // metadata, also any fields not listed here will go to quest.meta.???
|
|
100
|
+
* id?: string|number,
|
|
101
|
+
* name?: string,
|
|
102
|
+
* intro?: string|string[], // multiple strings will be concatenated with spaces
|
|
103
|
+
* }} QuestSpec
|
|
104
|
+
*/
|
|
105
|
+
/**
|
|
106
|
+
* @typedef {{ accepted?: string[][], rejected?: string[][] }} SelfCheck
|
|
107
|
+
*/
|
|
82
108
|
export class Quest {
|
|
83
109
|
/**
|
|
84
110
|
* @description A combinator problem with a set of test cases for the proposed solution.
|
|
85
|
-
* @param {
|
|
86
|
-
* input: InputSpec | InputSpec[],
|
|
87
|
-
* cases: TestCase[],
|
|
88
|
-
*
|
|
89
|
-
* // the rest is optional
|
|
90
|
-
|
|
91
|
-
* allow?: string,
|
|
92
|
-
* numbers?: boolean,
|
|
93
|
-
* env?: string[],
|
|
94
|
-
* engine?: SKI,
|
|
95
|
-
* engineFull?: SKI,
|
|
96
|
-
*
|
|
97
|
-
* // metadata, also any fields not listed here will go to quest.meta.???
|
|
98
|
-
* id?: string|number,
|
|
99
|
-
* name?: string,
|
|
100
|
-
* intro?: string|string[], // multiple strings will be concatenated with spaces
|
|
101
|
-
* }} options
|
|
102
|
-
*
|
|
111
|
+
* @param {QuestSpec} options
|
|
103
112
|
* @example const quest = new Quest({
|
|
104
113
|
* input: 'identity',
|
|
105
114
|
* cases: [
|
|
@@ -114,11 +123,11 @@ export class Quest {
|
|
|
114
123
|
* // despite having the same name.
|
|
115
124
|
* quest.check('I'); // fail! I not in the allowed list.
|
|
116
125
|
*/
|
|
117
|
-
constructor(options
|
|
126
|
+
constructor(options: QuestSpec);
|
|
118
127
|
engine: any;
|
|
119
128
|
engineFull: any;
|
|
120
129
|
restrict: {
|
|
121
|
-
allow:
|
|
130
|
+
allow: QuestSpec;
|
|
122
131
|
numbers: any;
|
|
123
132
|
lambdas: any;
|
|
124
133
|
};
|
|
@@ -129,7 +138,7 @@ export class Quest {
|
|
|
129
138
|
name: any;
|
|
130
139
|
intro: any;
|
|
131
140
|
id: any;
|
|
132
|
-
meta:
|
|
141
|
+
meta: QuestSpec;
|
|
133
142
|
/**
|
|
134
143
|
* Display allowed terms based on what engine thinks of this.env + this.restrict.allow
|
|
135
144
|
* @return {string}
|
|
@@ -158,12 +167,39 @@ export class Quest {
|
|
|
158
167
|
* @return {QuestResult}
|
|
159
168
|
*/
|
|
160
169
|
check(...input: string): QuestResult;
|
|
170
|
+
verify(options: any): {
|
|
171
|
+
date: string;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* @desc Verify that solutions that are expected to pass/fail do so.
|
|
175
|
+
* @param {SelfCheck|{[key: string]: SelfCheck}} dataset
|
|
176
|
+
* @return {{shouldPass: {input: string[], result: QuestResult}[], shouldFail: {input: string[], result: QuestResult}[]} | null}
|
|
177
|
+
*/
|
|
178
|
+
verifySolutions(dataset: SelfCheck | {
|
|
179
|
+
[key: string]: SelfCheck;
|
|
180
|
+
}): {
|
|
181
|
+
shouldPass: {
|
|
182
|
+
input: string[];
|
|
183
|
+
result: QuestResult;
|
|
184
|
+
}[];
|
|
185
|
+
shouldFail: {
|
|
186
|
+
input: string[];
|
|
187
|
+
result: QuestResult;
|
|
188
|
+
}[];
|
|
189
|
+
} | null;
|
|
190
|
+
verifyMeta(options?: {}): {
|
|
191
|
+
date: string;
|
|
192
|
+
};
|
|
161
193
|
/**
|
|
162
194
|
*
|
|
163
195
|
* @return {TestCase[]}
|
|
164
196
|
*/
|
|
165
197
|
show(): TestCase[];
|
|
166
198
|
}
|
|
199
|
+
export namespace Quest {
|
|
200
|
+
export { Group };
|
|
201
|
+
export { Case };
|
|
202
|
+
}
|
|
167
203
|
declare class Case {
|
|
168
204
|
/**
|
|
169
205
|
* @param {FreeVar[]} input
|
|
@@ -196,6 +232,16 @@ declare class Case {
|
|
|
196
232
|
*/
|
|
197
233
|
check(...expr: typeof import("./expr").Expr): CaseResult;
|
|
198
234
|
}
|
|
235
|
+
declare class Group {
|
|
236
|
+
constructor(options: any);
|
|
237
|
+
name: any;
|
|
238
|
+
intro: string;
|
|
239
|
+
id: any;
|
|
240
|
+
content: any;
|
|
241
|
+
verify(options: any): {
|
|
242
|
+
content: any;
|
|
243
|
+
};
|
|
244
|
+
}
|
|
199
245
|
import { SKI } from "./parser";
|
|
200
246
|
declare class Subst {
|
|
201
247
|
/**
|