@weborigami/language 0.6.8 → 0.6.10
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 +13 -13
- 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 +1 -1
- package/src/project/jsGlobals.js +3 -3
- package/src/protocols/package.js +3 -3
- package/src/runtime/asyncStorage.js +7 -0
- package/src/runtime/codeFragment.js +4 -3
- package/src/runtime/errors.js +82 -129
- package/src/runtime/evaluate.js +8 -77
- package/src/runtime/execute.js +82 -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 +9 -6
- 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 +24 -19
- 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 +38 -31
- 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 +4 -4
- package/test/runtime/ops.test.js +36 -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,13 @@ 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
|
|
|
22
23
|
test("ops.array creates an array", async () => {
|
|
23
24
|
const code = createCode([ops.array, 1, 2, 3]);
|
|
24
|
-
const result = await
|
|
25
|
+
const result = await execute(code);
|
|
25
26
|
assert.deepEqual(result, [1, 2, 3]);
|
|
26
27
|
});
|
|
27
28
|
|
|
@@ -44,25 +45,10 @@ describe("ops", () => {
|
|
|
44
45
|
|
|
45
46
|
test("ops.comma returns the last value", async () => {
|
|
46
47
|
const code = createCode([ops.comma, 1, 2, 3]);
|
|
47
|
-
const result = await
|
|
48
|
+
const result = await execute(code);
|
|
48
49
|
assert.strictEqual(result, 3);
|
|
49
50
|
});
|
|
50
51
|
|
|
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
52
|
test("ops.conditional", async () => {
|
|
67
53
|
assert.strictEqual(await ops.conditional(true, trueFn, falseFn), true);
|
|
68
54
|
assert.strictEqual(await ops.conditional(true, falseFn, trueFn), false);
|
|
@@ -77,6 +63,21 @@ describe("ops", () => {
|
|
|
77
63
|
assert.equal(await ops.construct(String, "hello"), "hello");
|
|
78
64
|
});
|
|
79
65
|
|
|
66
|
+
test("ops.deepText concatenates tree value text", async () => {
|
|
67
|
+
const container = {
|
|
68
|
+
name: "world",
|
|
69
|
+
};
|
|
70
|
+
const code = createCode([
|
|
71
|
+
ops.deepText,
|
|
72
|
+
"Hello, ",
|
|
73
|
+
[[ops.scope, container], "name"],
|
|
74
|
+
".",
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
const result = await execute(code);
|
|
78
|
+
assert.strictEqual(result, "Hello, world.");
|
|
79
|
+
});
|
|
80
|
+
|
|
80
81
|
test("ops.division divides two numbers", async () => {
|
|
81
82
|
assert.strictEqual(ops.division(12, 2), 6);
|
|
82
83
|
assert.strictEqual(ops.division(3, 2), 1.5);
|
|
@@ -117,9 +118,9 @@ describe("ops", () => {
|
|
|
117
118
|
[ops.literal, "count"],
|
|
118
119
|
],
|
|
119
120
|
]);
|
|
120
|
-
const result = await
|
|
121
|
+
const result = await execute(code);
|
|
121
122
|
assert.strictEqual(result, 1);
|
|
122
|
-
const result2 = await
|
|
123
|
+
const result2 = await execute(code);
|
|
123
124
|
assert.strictEqual(result2, 1);
|
|
124
125
|
});
|
|
125
126
|
|
|
@@ -183,7 +184,7 @@ describe("ops", () => {
|
|
|
183
184
|
b: {},
|
|
184
185
|
},
|
|
185
186
|
},
|
|
186
|
-
{ deep: true }
|
|
187
|
+
{ deep: true },
|
|
187
188
|
);
|
|
188
189
|
const b = await Tree.traverse(tree, "a", "b");
|
|
189
190
|
assert.equal(await ops.inherited(2, { object: b }), tree);
|
|
@@ -201,7 +202,7 @@ describe("ops", () => {
|
|
|
201
202
|
|
|
202
203
|
test("ops.lambda defines a function with no inputs", async () => {
|
|
203
204
|
const code = createCode([ops.lambda, 0, [], [ops.literal, "result"]]);
|
|
204
|
-
const fn = await
|
|
205
|
+
const fn = await execute(code);
|
|
205
206
|
assert.equal(fn.length, 0);
|
|
206
207
|
const result = await fn();
|
|
207
208
|
assert.strictEqual(result, "result");
|
|
@@ -219,7 +220,7 @@ describe("ops", () => {
|
|
|
219
220
|
[[ops.scope, container], "message"],
|
|
220
221
|
]);
|
|
221
222
|
|
|
222
|
-
const fn = await
|
|
223
|
+
const fn = await execute(code);
|
|
223
224
|
assert.equal(fn.length, 1);
|
|
224
225
|
const result = await fn();
|
|
225
226
|
assert.strictEqual(result, "Hello");
|
|
@@ -233,9 +234,9 @@ describe("ops", () => {
|
|
|
233
234
|
["a", [[ops.params, 0], 0]],
|
|
234
235
|
["b", [[ops.params, 0], 1]],
|
|
235
236
|
],
|
|
236
|
-
[ops.
|
|
237
|
+
[ops.deepText, [[ops.params, 0], "b"], [[ops.params, 0], "a"]],
|
|
237
238
|
]);
|
|
238
|
-
const fn = await
|
|
239
|
+
const fn = await execute(code);
|
|
239
240
|
assert.equal(fn.length, 2);
|
|
240
241
|
const result = await fn("x", "y");
|
|
241
242
|
assert.strictEqual(result, "yx");
|
|
@@ -311,7 +312,7 @@ describe("ops", () => {
|
|
|
311
312
|
],
|
|
312
313
|
"_result",
|
|
313
314
|
]);
|
|
314
|
-
const result = await
|
|
315
|
+
const result = await execute(code);
|
|
315
316
|
assert.deepEqual(await Tree.plain(result), { a: 1, b: 2, c: 1 });
|
|
316
317
|
});
|
|
317
318
|
|
|
@@ -335,15 +336,15 @@ describe("ops", () => {
|
|
|
335
336
|
test("ops.optional", async () => {
|
|
336
337
|
assert.equal(
|
|
337
338
|
ops.optional(null, (x) => x.a),
|
|
338
|
-
undefined
|
|
339
|
+
undefined,
|
|
339
340
|
);
|
|
340
341
|
assert.equal(
|
|
341
342
|
ops.optional(undefined, (x) => x.a),
|
|
342
|
-
undefined
|
|
343
|
+
undefined,
|
|
343
344
|
);
|
|
344
345
|
assert.equal(
|
|
345
346
|
ops.optional({ a: 1 }, (x) => x.a),
|
|
346
|
-
1
|
|
347
|
+
1,
|
|
347
348
|
);
|
|
348
349
|
});
|
|
349
350
|
|
|
@@ -383,7 +384,7 @@ describe("ops", () => {
|
|
|
383
384
|
["world", [[[ops.scope, container], "upper"], "world"]],
|
|
384
385
|
]);
|
|
385
386
|
|
|
386
|
-
const result = await
|
|
387
|
+
const result = await execute(code);
|
|
387
388
|
assert.strictEqual(result.hello, "HELLO");
|
|
388
389
|
assert.strictEqual(result.world, "WORLD");
|
|
389
390
|
});
|
|
@@ -398,7 +399,7 @@ describe("ops", () => {
|
|
|
398
399
|
1,
|
|
399
400
|
[[[ops.scope, container], "upper"], "world"],
|
|
400
401
|
]);
|
|
401
|
-
const result = await
|
|
402
|
+
const result = await execute(code);
|
|
402
403
|
assert.deepEqual(result, ["Hello", 1, "WORLD"]);
|
|
403
404
|
});
|
|
404
405
|
|
|
@@ -407,7 +408,7 @@ describe("ops", () => {
|
|
|
407
408
|
const frame1 = { a: 1 };
|
|
408
409
|
const frame2 = { b: 2 };
|
|
409
410
|
const stack = [frame1, frame2];
|
|
410
|
-
const result = await
|
|
411
|
+
const result = await execute(code, { stack });
|
|
411
412
|
assert.strictEqual(result, frame1);
|
|
412
413
|
});
|
|
413
414
|
|
|
@@ -434,7 +435,7 @@ describe("ops", () => {
|
|
|
434
435
|
},
|
|
435
436
|
c: 1,
|
|
436
437
|
},
|
|
437
|
-
{ deep: true }
|
|
438
|
+
{ deep: true },
|
|
438
439
|
);
|
|
439
440
|
const a = await tree.get("a");
|
|
440
441
|
const b = await a.get("b");
|
|
@@ -481,7 +482,7 @@ describe("ops", () => {
|
|
|
481
482
|
assert.strictEqual(ops.typeOf(undefined), "undefined");
|
|
482
483
|
assert.strictEqual(
|
|
483
484
|
ops.typeOf(() => null),
|
|
484
|
-
"function"
|
|
485
|
+
"function",
|
|
485
486
|
);
|
|
486
487
|
});
|
|
487
488
|
|
|
@@ -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", () => {
|