@weborigami/language 0.6.9 → 0.6.11
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/index.ts +19 -4
- package/main.js +5 -2
- package/package.json +2 -2
- package/src/compiler/compile.js +11 -3
- package/src/compiler/origami.pegjs +4 -2
- package/src/compiler/parse.js +77 -68
- package/src/compiler/parserHelpers.js +16 -17
- package/src/handlers/getPackedPath.js +17 -0
- package/src/handlers/jpeg_handler.js +5 -0
- package/src/handlers/js_handler.js +3 -3
- package/src/handlers/json_handler.js +3 -1
- package/src/handlers/tsv_handler.js +1 -1
- package/src/handlers/yaml_handler.js +9 -3
- package/src/project/jsGlobals.js +3 -12
- package/src/protocols/package.js +20 -11
- package/src/runtime/asyncStorage.js +7 -0
- package/src/runtime/codeFragment.js +4 -3
- package/src/runtime/errors.js +86 -128
- package/src/runtime/evaluate.js +8 -77
- package/src/runtime/execute.js +85 -0
- package/src/runtime/explainReferenceError.js +248 -0
- package/src/runtime/explainTraverseError.js +77 -0
- package/src/runtime/expressionFunction.js +8 -7
- package/src/runtime/expressionObject.js +4 -3
- package/src/runtime/handleExtension.js +22 -8
- package/src/runtime/internal.js +1 -1
- package/src/runtime/interop.js +15 -0
- package/src/runtime/ops.js +51 -21
- package/src/runtime/symbols.js +0 -1
- package/src/runtime/typos.js +22 -3
- package/test/compiler/compile.test.js +7 -103
- package/test/compiler/parse.test.js +42 -39
- package/test/project/fixtures/withPackageJson/subfolder/README.md +1 -0
- package/test/runtime/errors.test.js +296 -0
- package/test/runtime/evaluate.test.js +110 -34
- package/test/runtime/execute.test.js +41 -0
- package/test/runtime/expressionObject.test.js +3 -3
- package/test/runtime/ops.test.js +42 -35
- package/test/runtime/typos.test.js +2 -0
package/test/runtime/ops.test.js
CHANGED
|
@@ -2,7 +2,8 @@ import { ObjectMap, Tree } from "@weborigami/async-tree";
|
|
|
2
2
|
import assert from "node:assert";
|
|
3
3
|
import { describe, test } from "node:test";
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import execute from "../../src/runtime/execute.js";
|
|
6
|
+
import { ops } from "../../src/runtime/internal.js";
|
|
6
7
|
import { createCode } from "../compiler/codeHelpers.js";
|
|
7
8
|
|
|
8
9
|
describe("ops", () => {
|
|
@@ -15,13 +16,19 @@ describe("ops", () => {
|
|
|
15
16
|
assert.strictEqual(ops.addition("hello ", "everyone"), "hello everyone");
|
|
16
17
|
assert.strictEqual(
|
|
17
18
|
ops.addition("2001", ": A Space Odyssey"),
|
|
18
|
-
"2001: A Space Odyssey"
|
|
19
|
+
"2001: A Space Odyssey",
|
|
19
20
|
);
|
|
20
21
|
});
|
|
21
22
|
|
|
23
|
+
test("ops.apply applies a function to arguments", async () => {
|
|
24
|
+
const code = createCode([ops.apply, ops.addition, [ops.array, 1, 2]]);
|
|
25
|
+
const result = await execute(code);
|
|
26
|
+
assert.strictEqual(result, 3);
|
|
27
|
+
});
|
|
28
|
+
|
|
22
29
|
test("ops.array creates an array", async () => {
|
|
23
30
|
const code = createCode([ops.array, 1, 2, 3]);
|
|
24
|
-
const result = await
|
|
31
|
+
const result = await execute(code);
|
|
25
32
|
assert.deepEqual(result, [1, 2, 3]);
|
|
26
33
|
});
|
|
27
34
|
|
|
@@ -44,25 +51,10 @@ describe("ops", () => {
|
|
|
44
51
|
|
|
45
52
|
test("ops.comma returns the last value", async () => {
|
|
46
53
|
const code = createCode([ops.comma, 1, 2, 3]);
|
|
47
|
-
const result = await
|
|
54
|
+
const result = await execute(code);
|
|
48
55
|
assert.strictEqual(result, 3);
|
|
49
56
|
});
|
|
50
57
|
|
|
51
|
-
test("ops.concat concatenates tree value text", async () => {
|
|
52
|
-
const container = {
|
|
53
|
-
name: "world",
|
|
54
|
-
};
|
|
55
|
-
const code = createCode([
|
|
56
|
-
ops.concat,
|
|
57
|
-
"Hello, ",
|
|
58
|
-
[[ops.scope, container], "name"],
|
|
59
|
-
".",
|
|
60
|
-
]);
|
|
61
|
-
|
|
62
|
-
const result = await evaluate(code);
|
|
63
|
-
assert.strictEqual(result, "Hello, world.");
|
|
64
|
-
});
|
|
65
|
-
|
|
66
58
|
test("ops.conditional", async () => {
|
|
67
59
|
assert.strictEqual(await ops.conditional(true, trueFn, falseFn), true);
|
|
68
60
|
assert.strictEqual(await ops.conditional(true, falseFn, trueFn), false);
|
|
@@ -77,6 +69,21 @@ describe("ops", () => {
|
|
|
77
69
|
assert.equal(await ops.construct(String, "hello"), "hello");
|
|
78
70
|
});
|
|
79
71
|
|
|
72
|
+
test("ops.deepText concatenates tree value text", async () => {
|
|
73
|
+
const container = {
|
|
74
|
+
name: "world",
|
|
75
|
+
};
|
|
76
|
+
const code = createCode([
|
|
77
|
+
ops.deepText,
|
|
78
|
+
"Hello, ",
|
|
79
|
+
[[ops.scope, container], "name"],
|
|
80
|
+
".",
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
const result = await execute(code);
|
|
84
|
+
assert.strictEqual(result, "Hello, world.");
|
|
85
|
+
});
|
|
86
|
+
|
|
80
87
|
test("ops.division divides two numbers", async () => {
|
|
81
88
|
assert.strictEqual(ops.division(12, 2), 6);
|
|
82
89
|
assert.strictEqual(ops.division(3, 2), 1.5);
|
|
@@ -117,9 +124,9 @@ describe("ops", () => {
|
|
|
117
124
|
[ops.literal, "count"],
|
|
118
125
|
],
|
|
119
126
|
]);
|
|
120
|
-
const result = await
|
|
127
|
+
const result = await execute(code);
|
|
121
128
|
assert.strictEqual(result, 1);
|
|
122
|
-
const result2 = await
|
|
129
|
+
const result2 = await execute(code);
|
|
123
130
|
assert.strictEqual(result2, 1);
|
|
124
131
|
});
|
|
125
132
|
|
|
@@ -183,7 +190,7 @@ describe("ops", () => {
|
|
|
183
190
|
b: {},
|
|
184
191
|
},
|
|
185
192
|
},
|
|
186
|
-
{ deep: true }
|
|
193
|
+
{ deep: true },
|
|
187
194
|
);
|
|
188
195
|
const b = await Tree.traverse(tree, "a", "b");
|
|
189
196
|
assert.equal(await ops.inherited(2, { object: b }), tree);
|
|
@@ -201,7 +208,7 @@ describe("ops", () => {
|
|
|
201
208
|
|
|
202
209
|
test("ops.lambda defines a function with no inputs", async () => {
|
|
203
210
|
const code = createCode([ops.lambda, 0, [], [ops.literal, "result"]]);
|
|
204
|
-
const fn = await
|
|
211
|
+
const fn = await execute(code);
|
|
205
212
|
assert.equal(fn.length, 0);
|
|
206
213
|
const result = await fn();
|
|
207
214
|
assert.strictEqual(result, "result");
|
|
@@ -219,7 +226,7 @@ describe("ops", () => {
|
|
|
219
226
|
[[ops.scope, container], "message"],
|
|
220
227
|
]);
|
|
221
228
|
|
|
222
|
-
const fn = await
|
|
229
|
+
const fn = await execute(code);
|
|
223
230
|
assert.equal(fn.length, 1);
|
|
224
231
|
const result = await fn();
|
|
225
232
|
assert.strictEqual(result, "Hello");
|
|
@@ -233,9 +240,9 @@ describe("ops", () => {
|
|
|
233
240
|
["a", [[ops.params, 0], 0]],
|
|
234
241
|
["b", [[ops.params, 0], 1]],
|
|
235
242
|
],
|
|
236
|
-
[ops.
|
|
243
|
+
[ops.deepText, [[ops.params, 0], "b"], [[ops.params, 0], "a"]],
|
|
237
244
|
]);
|
|
238
|
-
const fn = await
|
|
245
|
+
const fn = await execute(code);
|
|
239
246
|
assert.equal(fn.length, 2);
|
|
240
247
|
const result = await fn("x", "y");
|
|
241
248
|
assert.strictEqual(result, "yx");
|
|
@@ -311,7 +318,7 @@ describe("ops", () => {
|
|
|
311
318
|
],
|
|
312
319
|
"_result",
|
|
313
320
|
]);
|
|
314
|
-
const result = await
|
|
321
|
+
const result = await execute(code);
|
|
315
322
|
assert.deepEqual(await Tree.plain(result), { a: 1, b: 2, c: 1 });
|
|
316
323
|
});
|
|
317
324
|
|
|
@@ -335,15 +342,15 @@ describe("ops", () => {
|
|
|
335
342
|
test("ops.optional", async () => {
|
|
336
343
|
assert.equal(
|
|
337
344
|
ops.optional(null, (x) => x.a),
|
|
338
|
-
undefined
|
|
345
|
+
undefined,
|
|
339
346
|
);
|
|
340
347
|
assert.equal(
|
|
341
348
|
ops.optional(undefined, (x) => x.a),
|
|
342
|
-
undefined
|
|
349
|
+
undefined,
|
|
343
350
|
);
|
|
344
351
|
assert.equal(
|
|
345
352
|
ops.optional({ a: 1 }, (x) => x.a),
|
|
346
|
-
1
|
|
353
|
+
1,
|
|
347
354
|
);
|
|
348
355
|
});
|
|
349
356
|
|
|
@@ -383,7 +390,7 @@ describe("ops", () => {
|
|
|
383
390
|
["world", [[[ops.scope, container], "upper"], "world"]],
|
|
384
391
|
]);
|
|
385
392
|
|
|
386
|
-
const result = await
|
|
393
|
+
const result = await execute(code);
|
|
387
394
|
assert.strictEqual(result.hello, "HELLO");
|
|
388
395
|
assert.strictEqual(result.world, "WORLD");
|
|
389
396
|
});
|
|
@@ -398,7 +405,7 @@ describe("ops", () => {
|
|
|
398
405
|
1,
|
|
399
406
|
[[[ops.scope, container], "upper"], "world"],
|
|
400
407
|
]);
|
|
401
|
-
const result = await
|
|
408
|
+
const result = await execute(code);
|
|
402
409
|
assert.deepEqual(result, ["Hello", 1, "WORLD"]);
|
|
403
410
|
});
|
|
404
411
|
|
|
@@ -407,7 +414,7 @@ describe("ops", () => {
|
|
|
407
414
|
const frame1 = { a: 1 };
|
|
408
415
|
const frame2 = { b: 2 };
|
|
409
416
|
const stack = [frame1, frame2];
|
|
410
|
-
const result = await
|
|
417
|
+
const result = await execute(code, { stack });
|
|
411
418
|
assert.strictEqual(result, frame1);
|
|
412
419
|
});
|
|
413
420
|
|
|
@@ -434,7 +441,7 @@ describe("ops", () => {
|
|
|
434
441
|
},
|
|
435
442
|
c: 1,
|
|
436
443
|
},
|
|
437
|
-
{ deep: true }
|
|
444
|
+
{ deep: true },
|
|
438
445
|
);
|
|
439
446
|
const a = await tree.get("a");
|
|
440
447
|
const b = await a.get("b");
|
|
@@ -481,7 +488,7 @@ describe("ops", () => {
|
|
|
481
488
|
assert.strictEqual(ops.typeOf(undefined), "undefined");
|
|
482
489
|
assert.strictEqual(
|
|
483
490
|
ops.typeOf(() => null),
|
|
484
|
-
"function"
|
|
491
|
+
"function",
|
|
485
492
|
);
|
|
486
493
|
});
|
|
487
494
|
|
|
@@ -13,6 +13,8 @@ describe("typos", () => {
|
|
|
13
13
|
assert(isTypo("cat", "act")); // transposition
|
|
14
14
|
assert(!isTypo("cat", "dog")); // more than 1 edit
|
|
15
15
|
assert(!isTypo("a", "b")); // single character
|
|
16
|
+
assert(isTypo("cat", "CAT")); // differ only by case
|
|
17
|
+
assert(isTypo("café", "cafe")); // differ only by accents
|
|
16
18
|
});
|
|
17
19
|
|
|
18
20
|
test("typos", () => {
|