@valbuild/core 0.26.0 → 0.27.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/package.json +12 -3
- package/CHANGELOG.md +0 -0
- package/ROADMAP.md +0 -106
- package/jest.config.js +0 -4
- package/src/Json.ts +0 -4
- package/src/ValApi.ts +0 -81
- package/src/expr/README.md +0 -193
- package/src/expr/eval.test.ts +0 -198
- package/src/expr/eval.ts +0 -251
- package/src/expr/expr.ts +0 -91
- package/src/expr/index.ts +0 -3
- package/src/expr/parser.test.ts +0 -158
- package/src/expr/parser.ts +0 -229
- package/src/expr/repl.ts +0 -88
- package/src/expr/tokenizer.test.ts +0 -539
- package/src/expr/tokenizer.ts +0 -117
- package/src/fp/array.ts +0 -30
- package/src/fp/index.ts +0 -3
- package/src/fp/result.ts +0 -214
- package/src/fp/util.ts +0 -52
- package/src/future/fetchVal.test.ts +0 -164
- package/src/future/fetchVal.ts +0 -206
- package/src/getSha256.ts +0 -8
- package/src/index.ts +0 -132
- package/src/initSchema.ts +0 -50
- package/src/initVal.ts +0 -73
- package/src/module.test.ts +0 -170
- package/src/module.ts +0 -397
- package/src/patch/deref.test.ts +0 -298
- package/src/patch/deref.ts +0 -136
- package/src/patch/index.ts +0 -12
- package/src/patch/json.test.ts +0 -582
- package/src/patch/json.ts +0 -304
- package/src/patch/operation.ts +0 -86
- package/src/patch/ops.ts +0 -83
- package/src/patch/parse.test.ts +0 -202
- package/src/patch/parse.ts +0 -202
- package/src/patch/patch.ts +0 -49
- package/src/patch/util.ts +0 -74
- package/src/schema/array.ts +0 -93
- package/src/schema/boolean.ts +0 -49
- package/src/schema/future/i18n.ts +0 -69
- package/src/schema/future/oneOf.ts +0 -63
- package/src/schema/image.ts +0 -137
- package/src/schema/index.ts +0 -70
- package/src/schema/keyOf.ts +0 -167
- package/src/schema/literal.ts +0 -63
- package/src/schema/number.ts +0 -56
- package/src/schema/object.ts +0 -110
- package/src/schema/record.ts +0 -103
- package/src/schema/richtext.ts +0 -44
- package/src/schema/string.ts +0 -95
- package/src/schema/union.ts +0 -63
- package/src/schema/validation/ValidationError.ts +0 -16
- package/src/schema/validation/ValidationFix.ts +0 -6
- package/src/schema/validation.test.ts +0 -291
- package/src/selector/SelectorProxy.ts +0 -238
- package/src/selector/array.ts +0 -13
- package/src/selector/boolean.ts +0 -4
- package/src/selector/file.ts +0 -6
- package/src/selector/future/ExprProxy.test.ts +0 -203
- package/src/selector/future/ExprProxy.ts +0 -216
- package/src/selector/future/SelectorProxy.test.ts +0 -172
- package/src/selector/future/SelectorProxy.ts +0 -238
- package/src/selector/future/array.ts +0 -37
- package/src/selector/future/boolean.ts +0 -4
- package/src/selector/future/file.ts +0 -14
- package/src/selector/future/i18n.ts +0 -13
- package/src/selector/future/index.ts +0 -169
- package/src/selector/future/number.ts +0 -4
- package/src/selector/future/object.ts +0 -22
- package/src/selector/future/primitive.ts +0 -17
- package/src/selector/future/remote.ts +0 -9
- package/src/selector/future/selector.test.ts +0 -429
- package/src/selector/future/selectorOf.ts +0 -7
- package/src/selector/future/string.ts +0 -4
- package/src/selector/index.ts +0 -121
- package/src/selector/number.ts +0 -4
- package/src/selector/object.ts +0 -5
- package/src/selector/primitive.ts +0 -4
- package/src/selector/string.ts +0 -4
- package/src/source/file.ts +0 -45
- package/src/source/future/i18n.ts +0 -60
- package/src/source/future/remote.ts +0 -54
- package/src/source/index.ts +0 -53
- package/src/source/link.ts +0 -14
- package/src/source/richtext.ts +0 -178
- package/src/val/array.ts +0 -10
- package/src/val/index.ts +0 -100
- package/src/val/object.ts +0 -13
- package/src/val/primitive.ts +0 -8
- package/tsconfig.json +0 -8
package/src/expr/eval.ts
DELETED
@@ -1,251 +0,0 @@
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
2
|
-
import { Call, Expr, StringLiteral, StringTemplate, Sym } from "./expr";
|
3
|
-
import { Source } from "../source";
|
4
|
-
import { result } from "../fp";
|
5
|
-
import { Path, SourceOrExpr } from "../selector/future";
|
6
|
-
import { newSelectorProxy } from "../selector/future/SelectorProxy";
|
7
|
-
import { isSerializedVal, SourcePath } from "../val";
|
8
|
-
import { Json } from "../Json";
|
9
|
-
|
10
|
-
export class EvalError {
|
11
|
-
constructor(public readonly message: string, public readonly expr: Expr) {}
|
12
|
-
|
13
|
-
toString() {
|
14
|
-
return `${this.message} in: ${this.expr.transpile()}`;
|
15
|
-
}
|
16
|
-
}
|
17
|
-
|
18
|
-
type LocalSelector<S extends Source> = {
|
19
|
-
readonly [key: string | number]:
|
20
|
-
| LocalSelector<Source>
|
21
|
-
| ((...args: any[]) => any);
|
22
|
-
} & {
|
23
|
-
[SourceOrExpr]: S;
|
24
|
-
[Path]: SourcePath | undefined;
|
25
|
-
};
|
26
|
-
|
27
|
-
const MAX_STACK_SIZE = 100; // an arbitrary semi-large number
|
28
|
-
function evaluateSync(
|
29
|
-
expr: Expr,
|
30
|
-
getSource: (path: string) => Json,
|
31
|
-
stack: readonly LocalSelector<Source>[][]
|
32
|
-
): LocalSelector<Source> {
|
33
|
-
// TODO: amount of evaluates should be limited?
|
34
|
-
if (stack.length > MAX_STACK_SIZE) {
|
35
|
-
throw new EvalError(
|
36
|
-
`Stack overflow. Final frames: ${stack
|
37
|
-
.slice(-10)
|
38
|
-
.map((frame, i) =>
|
39
|
-
frame.map((s, j) => `@[${i},${j}]: ${JSON.stringify(s)}`).join(", ")
|
40
|
-
)
|
41
|
-
.join(" -> ")}`,
|
42
|
-
expr
|
43
|
-
);
|
44
|
-
}
|
45
|
-
if (expr instanceof Call) {
|
46
|
-
if (expr.children[0] instanceof Sym) {
|
47
|
-
if (expr.children[0].value === "val") {
|
48
|
-
if (expr.isAnon) {
|
49
|
-
throw new EvalError("cannot call 'val' as anonymous function", expr);
|
50
|
-
}
|
51
|
-
if (expr.children[1] instanceof StringLiteral) {
|
52
|
-
const path = expr.children[1].value as SourcePath;
|
53
|
-
return newSelectorProxy(getSource(path), path);
|
54
|
-
} else {
|
55
|
-
throw new EvalError(
|
56
|
-
"argument of 'val' must be a string literal",
|
57
|
-
expr
|
58
|
-
);
|
59
|
-
}
|
60
|
-
} else if (expr.children[0].value === "json") {
|
61
|
-
if (expr.children.length !== 2) {
|
62
|
-
throw new EvalError(
|
63
|
-
"must call 'json' with exactly one argument",
|
64
|
-
expr
|
65
|
-
);
|
66
|
-
}
|
67
|
-
const value = evaluateSync(expr.children[1], getSource, stack);
|
68
|
-
|
69
|
-
const valObj = value[SourceOrExpr];
|
70
|
-
const valPath = value[Path];
|
71
|
-
if (typeof valObj !== "string") {
|
72
|
-
throw new EvalError(
|
73
|
-
`cannot parse JSON: ${JSON.stringify(valObj)}, expected string`,
|
74
|
-
expr.children[1]
|
75
|
-
);
|
76
|
-
}
|
77
|
-
try {
|
78
|
-
const serialized = JSON.parse(valObj);
|
79
|
-
if (isSerializedVal(serialized)) {
|
80
|
-
return newSelectorProxy(serialized.val, serialized.valPath);
|
81
|
-
}
|
82
|
-
const parsedValue = newSelectorProxy(JSON.parse(valObj), valPath);
|
83
|
-
return parsedValue;
|
84
|
-
} catch (e) {
|
85
|
-
if (e instanceof SyntaxError) {
|
86
|
-
throw new EvalError(
|
87
|
-
`cannot parse JSON: ${valObj}, ${
|
88
|
-
e.message
|
89
|
-
} - value: ${JSON.stringify(value)}`,
|
90
|
-
expr.children[1]
|
91
|
-
);
|
92
|
-
}
|
93
|
-
throw e;
|
94
|
-
}
|
95
|
-
} else if (expr.children[0].value === "stringify") {
|
96
|
-
// TODO: remove stringify
|
97
|
-
if (expr.children.length !== 2) {
|
98
|
-
throw new EvalError(
|
99
|
-
"must call 'stringify' with exactly one argument",
|
100
|
-
expr
|
101
|
-
);
|
102
|
-
}
|
103
|
-
const res = evaluateSync(expr.children[1], getSource, stack);
|
104
|
-
return newSelectorProxy(JSON.stringify(res[SourceOrExpr]));
|
105
|
-
}
|
106
|
-
}
|
107
|
-
const prop = evaluateSync(expr.children[0], getSource, stack)[SourceOrExpr];
|
108
|
-
if (expr.children.length === 1) {
|
109
|
-
// TODO: return if literal only?
|
110
|
-
return newSelectorProxy(prop);
|
111
|
-
}
|
112
|
-
const obj = evaluateSync(expr.children[1], getSource, stack);
|
113
|
-
if (typeof prop !== "string" && typeof prop !== "number") {
|
114
|
-
throw new EvalError(
|
115
|
-
`cannot access ${JSON.stringify(obj)} with property ${JSON.stringify(
|
116
|
-
prop
|
117
|
-
)}: is not a string or number`,
|
118
|
-
expr
|
119
|
-
);
|
120
|
-
}
|
121
|
-
|
122
|
-
if (prop in obj) {
|
123
|
-
if (expr.isAnon) {
|
124
|
-
// anon functions:
|
125
|
-
const maybeFunction = obj[prop];
|
126
|
-
if (typeof maybeFunction !== "function") {
|
127
|
-
throw new EvalError(
|
128
|
-
`cannot access property ${JSON.stringify(prop)} of ${JSON.stringify(
|
129
|
-
obj
|
130
|
-
)}: required higher ordered function got ${typeof obj[prop]}`,
|
131
|
-
expr
|
132
|
-
);
|
133
|
-
}
|
134
|
-
if (expr.children[0] instanceof Sym) {
|
135
|
-
return maybeFunction((...args: any[]) => {
|
136
|
-
return evaluateSync(
|
137
|
-
expr.children[2],
|
138
|
-
getSource,
|
139
|
-
stack.concat([args])
|
140
|
-
);
|
141
|
-
});
|
142
|
-
} else {
|
143
|
-
throw new EvalError(
|
144
|
-
`cannot call an expression that is not a symbol, got: '${expr.children[0].type}'`,
|
145
|
-
expr
|
146
|
-
);
|
147
|
-
}
|
148
|
-
} else {
|
149
|
-
// non-anon functions:
|
150
|
-
if (expr.children[0] instanceof Sym) {
|
151
|
-
if (expr.children[0].value === "val") {
|
152
|
-
if (expr.children[1] instanceof StringLiteral) {
|
153
|
-
const path = expr.children[1].value as SourcePath;
|
154
|
-
return newSelectorProxy(getSource(path), path);
|
155
|
-
} else {
|
156
|
-
throw new EvalError(
|
157
|
-
"argument of 'val' must be a string literal",
|
158
|
-
expr
|
159
|
-
);
|
160
|
-
}
|
161
|
-
}
|
162
|
-
}
|
163
|
-
const args = expr.children.slice(2);
|
164
|
-
if (args.length > 0) {
|
165
|
-
const maybeFunction = obj[prop];
|
166
|
-
if (typeof maybeFunction !== "function") {
|
167
|
-
throw new EvalError(
|
168
|
-
`cannot access property ${JSON.stringify(
|
169
|
-
prop
|
170
|
-
)} of ${JSON.stringify(obj)}: required function got ${typeof obj[
|
171
|
-
prop
|
172
|
-
]}`,
|
173
|
-
expr
|
174
|
-
);
|
175
|
-
}
|
176
|
-
return maybeFunction(
|
177
|
-
...args.map((arg) => evaluateSync(arg, getSource, stack))
|
178
|
-
);
|
179
|
-
}
|
180
|
-
const maybeValue = obj[prop];
|
181
|
-
if (typeof maybeValue === "function") {
|
182
|
-
throw new EvalError(
|
183
|
-
`cannot access property ${JSON.stringify(prop)} of ${JSON.stringify(
|
184
|
-
obj
|
185
|
-
)}: required value got ${typeof obj[prop]}`,
|
186
|
-
expr
|
187
|
-
);
|
188
|
-
}
|
189
|
-
return maybeValue;
|
190
|
-
}
|
191
|
-
}
|
192
|
-
} else if (expr instanceof Sym) {
|
193
|
-
if (expr.value.startsWith("@")) {
|
194
|
-
const [i, j, rest] = expr.value.slice(2, -1).split(",");
|
195
|
-
if (rest) {
|
196
|
-
throw new EvalError(`cannot access stack: too many indices`, expr);
|
197
|
-
}
|
198
|
-
const stackValue = stack[Number(i)]?.[Number(j)];
|
199
|
-
if (stackValue === undefined) {
|
200
|
-
throw new EvalError(`cannot access stack: out of bounds`, expr);
|
201
|
-
}
|
202
|
-
return stackValue;
|
203
|
-
} else if (expr.value === "()") {
|
204
|
-
return newSelectorProxy(null);
|
205
|
-
}
|
206
|
-
return newSelectorProxy(expr.value);
|
207
|
-
} else if (expr instanceof StringLiteral) {
|
208
|
-
return newSelectorProxy(expr.value);
|
209
|
-
} else if (expr instanceof StringTemplate) {
|
210
|
-
return newSelectorProxy(
|
211
|
-
expr.children
|
212
|
-
.map((child) => {
|
213
|
-
if (child instanceof Sym && child.value === "()") {
|
214
|
-
return "null";
|
215
|
-
}
|
216
|
-
const evalRes = evaluateSync(child, getSource, stack);
|
217
|
-
if (
|
218
|
-
child.type === "StringLiteral" ||
|
219
|
-
child.type === "StringTemplate"
|
220
|
-
) {
|
221
|
-
return evalRes[SourceOrExpr];
|
222
|
-
}
|
223
|
-
if (Path in evalRes) {
|
224
|
-
// a selector, so serialize to Val
|
225
|
-
return JSON.stringify({
|
226
|
-
val: evalRes[SourceOrExpr],
|
227
|
-
valPath: evalRes[Path],
|
228
|
-
});
|
229
|
-
}
|
230
|
-
return JSON.stringify(evalRes[SourceOrExpr]);
|
231
|
-
})
|
232
|
-
.join("")
|
233
|
-
);
|
234
|
-
}
|
235
|
-
throw new EvalError(`could not evaluate`, expr);
|
236
|
-
}
|
237
|
-
|
238
|
-
export function evaluate(
|
239
|
-
expr: Expr,
|
240
|
-
source: (ref: string) => Json,
|
241
|
-
stack: readonly LocalSelector<Source>[][]
|
242
|
-
): result.Result<LocalSelector<Source>, EvalError> {
|
243
|
-
try {
|
244
|
-
return result.ok(evaluateSync(expr, source, stack));
|
245
|
-
} catch (err) {
|
246
|
-
if (err instanceof EvalError) {
|
247
|
-
return result.err(err);
|
248
|
-
}
|
249
|
-
throw err;
|
250
|
-
}
|
251
|
-
}
|
package/src/expr/expr.ts
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
2
|
-
|
3
|
-
export abstract class Expr {
|
4
|
-
abstract type: "StringLiteral" | "Sym" | "StringTemplate" | "Call";
|
5
|
-
abstract transpile(): string;
|
6
|
-
constructor(public readonly span?: [number, number?]) {}
|
7
|
-
}
|
8
|
-
|
9
|
-
export class StringLiteral extends Expr {
|
10
|
-
public type = "StringLiteral" as const;
|
11
|
-
constructor(
|
12
|
-
public readonly value: string,
|
13
|
-
span?: [start: number, stop: number]
|
14
|
-
) {
|
15
|
-
super(span);
|
16
|
-
}
|
17
|
-
|
18
|
-
transpile() {
|
19
|
-
return `'${this.value}'`;
|
20
|
-
}
|
21
|
-
}
|
22
|
-
|
23
|
-
export class Sym extends Expr {
|
24
|
-
public type = "Sym" as const;
|
25
|
-
constructor(
|
26
|
-
public readonly value: string,
|
27
|
-
span?: [start: number, stop: number]
|
28
|
-
) {
|
29
|
-
super(span);
|
30
|
-
}
|
31
|
-
|
32
|
-
transpile() {
|
33
|
-
return this.value;
|
34
|
-
}
|
35
|
-
}
|
36
|
-
|
37
|
-
export const NilSym = new Sym("()");
|
38
|
-
|
39
|
-
export class StringTemplate extends Expr {
|
40
|
-
public type = "StringTemplate" as const;
|
41
|
-
constructor(
|
42
|
-
public readonly children: readonly Expr[],
|
43
|
-
span?: [number, number]
|
44
|
-
) {
|
45
|
-
super(span);
|
46
|
-
}
|
47
|
-
|
48
|
-
transpile() {
|
49
|
-
return `'${this.children
|
50
|
-
.map((child) => {
|
51
|
-
if (child instanceof StringLiteral) {
|
52
|
-
return child.value;
|
53
|
-
} else {
|
54
|
-
return `\${${child.transpile()}}`;
|
55
|
-
}
|
56
|
-
})
|
57
|
-
.join("")}'`;
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
export class Call extends Expr {
|
62
|
-
public type = "Call" as const;
|
63
|
-
constructor(
|
64
|
-
public readonly children: readonly Expr[],
|
65
|
-
public readonly isAnon: boolean,
|
66
|
-
span?: [number, number]
|
67
|
-
) {
|
68
|
-
super(span);
|
69
|
-
}
|
70
|
-
|
71
|
-
transpile() {
|
72
|
-
if (this.isAnon) {
|
73
|
-
return `!(${this.children.map((child) => child.transpile()).join(" ")})`;
|
74
|
-
}
|
75
|
-
return `(${this.children.map((child) => child.transpile()).join(" ")})`;
|
76
|
-
}
|
77
|
-
}
|
78
|
-
|
79
|
-
// export function interpret(
|
80
|
-
// expr: SExpr,
|
81
|
-
// moduleId: string,
|
82
|
-
// schemas: {
|
83
|
-
// [moduleId: string]: Schema<Source>;
|
84
|
-
// },
|
85
|
-
// getSource: (moduleId: string) => Promise<Source>
|
86
|
-
// ) {}
|
87
|
-
|
88
|
-
// TODO: use this instead of including the unescaped strings in the parser
|
89
|
-
function escapeString(str: string) {
|
90
|
-
return str.replace(/\\/g, "\\\\");
|
91
|
-
}
|
package/src/expr/index.ts
DELETED
package/src/expr/parser.test.ts
DELETED
@@ -1,158 +0,0 @@
|
|
1
|
-
import { result } from "../fp";
|
2
|
-
import { parse } from "./parser";
|
3
|
-
|
4
|
-
const ParserTestCases: {
|
5
|
-
input: string;
|
6
|
-
error?: {
|
7
|
-
span: [start: number, stop: number];
|
8
|
-
};
|
9
|
-
overrideTest?: string;
|
10
|
-
}[] = [
|
11
|
-
{
|
12
|
-
input: "!(",
|
13
|
-
error: {
|
14
|
-
span: [0, 0],
|
15
|
-
},
|
16
|
-
},
|
17
|
-
{
|
18
|
-
input: "')'",
|
19
|
-
},
|
20
|
-
{
|
21
|
-
input: "(",
|
22
|
-
error: {
|
23
|
-
span: [0, 0],
|
24
|
-
},
|
25
|
-
},
|
26
|
-
{
|
27
|
-
input: "()",
|
28
|
-
},
|
29
|
-
{
|
30
|
-
input: " ( ) ",
|
31
|
-
overrideTest: "()",
|
32
|
-
},
|
33
|
-
{
|
34
|
-
input: "(reverse foo ())",
|
35
|
-
},
|
36
|
-
{
|
37
|
-
input: "(b ab)", // single character tokens
|
38
|
-
},
|
39
|
-
{
|
40
|
-
input: "!(map fn value)",
|
41
|
-
},
|
42
|
-
{
|
43
|
-
input: "!(map (map foo bar) value)",
|
44
|
-
},
|
45
|
-
{
|
46
|
-
input: "'foo'",
|
47
|
-
},
|
48
|
-
// this is the JS equivalent: 'f\'oo'
|
49
|
-
{
|
50
|
-
input: "'f\\'oo'",
|
51
|
-
},
|
52
|
-
// lenient tokenization (errors must handled by the parser)
|
53
|
-
// this is the JS equivalent: 'f\\'oofail'
|
54
|
-
{
|
55
|
-
input: "'f\\\\'oo'fail",
|
56
|
-
error: {
|
57
|
-
span: [5, 11],
|
58
|
-
},
|
59
|
-
},
|
60
|
-
{
|
61
|
-
input: "(fo() (fail zoo))",
|
62
|
-
error: {
|
63
|
-
span: [1, 3], // this would preferably be [1, 4]
|
64
|
-
},
|
65
|
-
},
|
66
|
-
// this is the JS equivalent: 'f\\\'oo'
|
67
|
-
{
|
68
|
-
input: "'f\\\\\\'oo'",
|
69
|
-
},
|
70
|
-
{
|
71
|
-
input: "(foo (bar zoo))",
|
72
|
-
},
|
73
|
-
{
|
74
|
-
input: " (foo (bar 'he\\'pp' zoo)) ",
|
75
|
-
overrideTest: "(foo (bar 'he\\'pp' zoo))",
|
76
|
-
},
|
77
|
-
{
|
78
|
-
input: "''",
|
79
|
-
},
|
80
|
-
//interpolation:
|
81
|
-
{
|
82
|
-
input: "'${'str'}'",
|
83
|
-
overrideTest: "'str'",
|
84
|
-
},
|
85
|
-
{
|
86
|
-
input: "'${'${(foo bar)}'}'",
|
87
|
-
},
|
88
|
-
{
|
89
|
-
input: "'foo${(bar baz)}'",
|
90
|
-
},
|
91
|
-
{
|
92
|
-
input: "'${'foo ${(foo bar)}'}'",
|
93
|
-
},
|
94
|
-
{
|
95
|
-
input: "'${'${'${(foo bar)}'}'}'",
|
96
|
-
},
|
97
|
-
{
|
98
|
-
input: `(json '{"foo": "bar"}')`,
|
99
|
-
},
|
100
|
-
{
|
101
|
-
input: `(json '{"foo": \${(foo bar)}}')`,
|
102
|
-
},
|
103
|
-
{
|
104
|
-
input: `(json '{"foo": \${(foo bar)}, "baz": "baz"}')`,
|
105
|
-
},
|
106
|
-
{
|
107
|
-
input: `!(map 'title' )`,
|
108
|
-
overrideTest: `!(map 'title')`,
|
109
|
-
},
|
110
|
-
{
|
111
|
-
input: `!(map
|
112
|
-
(ref '/foo/bar')
|
113
|
-
('title' @0)
|
114
|
-
)`,
|
115
|
-
overrideTest: `!(map (ref '/foo/bar') ('title' @0))`,
|
116
|
-
},
|
117
|
-
];
|
118
|
-
|
119
|
-
describe("parser", () => {
|
120
|
-
test.each(ParserTestCases)(
|
121
|
-
'expr: "$input"',
|
122
|
-
({ input, error, overrideTest }) => {
|
123
|
-
const res = parse(input);
|
124
|
-
if (error) {
|
125
|
-
if (result.isErr(res)) {
|
126
|
-
expect(res.error.span).toEqual(error.span);
|
127
|
-
} else {
|
128
|
-
expect(res).toHaveProperty("error");
|
129
|
-
}
|
130
|
-
} else if (result.isErr(res)) {
|
131
|
-
process.stdout.write(res.error.message + ":\n\n");
|
132
|
-
process.stdout.write(input + "\n");
|
133
|
-
let underline = "";
|
134
|
-
for (let i = 0; i < input.length; i++) {
|
135
|
-
if (
|
136
|
-
res.error.span &&
|
137
|
-
i >= res.error.span[0] &&
|
138
|
-
i <= (res.error.span?.[1] || -1)
|
139
|
-
) {
|
140
|
-
underline += "^";
|
141
|
-
} else {
|
142
|
-
if (input[i] === "\n") {
|
143
|
-
if (!underline.includes("^")) {
|
144
|
-
underline = "";
|
145
|
-
}
|
146
|
-
} else {
|
147
|
-
underline += " ";
|
148
|
-
}
|
149
|
-
}
|
150
|
-
}
|
151
|
-
process.stderr.write(underline + "\n");
|
152
|
-
expect(res).toHaveProperty("value");
|
153
|
-
} else {
|
154
|
-
expect(res.value.transpile()).toBe(overrideTest || input);
|
155
|
-
}
|
156
|
-
}
|
157
|
-
);
|
158
|
-
});
|