@weborigami/language 0.0.65-beta.1 → 0.0.65
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 +0 -2
- package/package.json +3 -3
- package/src/compiler/origami.pegjs +45 -23
- package/src/compiler/parse.d.ts +2 -2
- package/src/compiler/parse.js +139 -104
- package/src/compiler/parserHelpers.js +10 -2
- package/src/runtime/codeFragment.js +19 -0
- package/src/runtime/evaluate.js +21 -16
- package/src/runtime/expressionFunction.js +5 -6
- package/src/runtime/formatError.js +6 -6
- package/src/runtime/ops.js +8 -0
- package/test/compiler/parse.test.js +237 -112
- package/test/runtime/evaluate.test.js +20 -7
- package/test/runtime/ops.test.js +28 -10
|
@@ -7,7 +7,7 @@ import evaluate from "../../src/runtime/evaluate.js";
|
|
|
7
7
|
|
|
8
8
|
describe("evaluate", () => {
|
|
9
9
|
test("can retrieve values from scope", async () => {
|
|
10
|
-
const code = [ops.scope, "message"];
|
|
10
|
+
const code = createCode([ops.scope, "message"]);
|
|
11
11
|
const parent = new ObjectTree({
|
|
12
12
|
message: "Hello",
|
|
13
13
|
});
|
|
@@ -19,10 +19,10 @@ describe("evaluate", () => {
|
|
|
19
19
|
|
|
20
20
|
test("can invoke functions in scope", async () => {
|
|
21
21
|
// Match the array representation of code generated by the parser.
|
|
22
|
-
const code = [
|
|
22
|
+
const code = createCode([
|
|
23
23
|
[ops.scope, "greet"],
|
|
24
24
|
[ops.scope, "name"],
|
|
25
|
-
];
|
|
25
|
+
]);
|
|
26
26
|
|
|
27
27
|
const tree = new ObjectTree({
|
|
28
28
|
async greet(name) {
|
|
@@ -36,7 +36,7 @@ describe("evaluate", () => {
|
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
test("passes context to invoked functions", async () => {
|
|
39
|
-
const code = [ops.scope, "fn"];
|
|
39
|
+
const code = createCode([ops.scope, "fn"]);
|
|
40
40
|
const tree = new ObjectTree({
|
|
41
41
|
async fn() {
|
|
42
42
|
assert.equal(this, tree);
|
|
@@ -49,7 +49,7 @@ describe("evaluate", () => {
|
|
|
49
49
|
const fn = (x, y) => ({
|
|
50
50
|
c: `${x}${y}c`,
|
|
51
51
|
});
|
|
52
|
-
const code = [ops.traverse, fn, "a", "b", "c"];
|
|
52
|
+
const code = createCode([ops.traverse, fn, "a", "b", "c"]);
|
|
53
53
|
assert.equal(await evaluate.call(null, code), "abc");
|
|
54
54
|
});
|
|
55
55
|
|
|
@@ -57,16 +57,29 @@ describe("evaluate", () => {
|
|
|
57
57
|
const fn = (...args) => args.join(",");
|
|
58
58
|
const packed = new String();
|
|
59
59
|
/** @type {any} */ (packed).unpack = async () => fn;
|
|
60
|
-
const code = [packed, "a", "b", "c"];
|
|
60
|
+
const code = createCode([packed, "a", "b", "c"]);
|
|
61
61
|
const result = await evaluate.call(null, code);
|
|
62
62
|
assert.equal(result, "a,b,c");
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
test("by defalut sets the parent of a returned tree to the current tree", async () => {
|
|
66
66
|
const fn = () => new ObjectTree({});
|
|
67
|
-
const code = [fn];
|
|
67
|
+
const code = createCode([fn]);
|
|
68
68
|
const tree = new ObjectTree({});
|
|
69
69
|
const result = await evaluate.call(tree, code);
|
|
70
70
|
assert.equal(result.parent, tree);
|
|
71
71
|
});
|
|
72
72
|
});
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @returns {import("../../index.ts").Code}
|
|
76
|
+
*/
|
|
77
|
+
function createCode(array) {
|
|
78
|
+
const code = array;
|
|
79
|
+
/** @type {any} */ (code).location = {
|
|
80
|
+
source: {
|
|
81
|
+
text: "",
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
return code;
|
|
85
|
+
}
|
package/test/runtime/ops.test.js
CHANGED
|
@@ -10,7 +10,7 @@ describe("ops", () => {
|
|
|
10
10
|
name: "world",
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
const code = [ops.concat, "Hello, ", [ops.scope, "name"], "."];
|
|
13
|
+
const code = createCode([ops.concat, "Hello, ", [ops.scope, "name"], "."]);
|
|
14
14
|
|
|
15
15
|
const result = await evaluate.call(scope, code);
|
|
16
16
|
assert.equal(result, "Hello, world.");
|
|
@@ -21,7 +21,7 @@ describe("ops", () => {
|
|
|
21
21
|
message: "Hello",
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
-
const code = [ops.lambda, null, [ops.scope, "message"]];
|
|
24
|
+
const code = createCode([ops.lambda, null, [ops.scope, "message"]]);
|
|
25
25
|
|
|
26
26
|
const fn = await evaluate.call(scope, code);
|
|
27
27
|
const result = await fn.call(scope);
|
|
@@ -29,25 +29,25 @@ describe("ops", () => {
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
test("lambda adds input to scope as `_`", async () => {
|
|
32
|
-
const code = [ops.lambda, null, [ops.scope, "_"]];
|
|
32
|
+
const code = createCode([ops.lambda, null, [ops.scope, "_"]]);
|
|
33
33
|
const fn = await evaluate.call(null, code);
|
|
34
34
|
const result = await fn("Hello");
|
|
35
35
|
assert.equal(result, "Hello");
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
test("parameterized lambda adds input args to scope", async () => {
|
|
39
|
-
const code = [
|
|
39
|
+
const code = createCode([
|
|
40
40
|
ops.lambda,
|
|
41
41
|
["a", "b"],
|
|
42
42
|
[ops.concat, [ops.scope, "b"], [ops.scope, "a"]],
|
|
43
|
-
];
|
|
43
|
+
]);
|
|
44
44
|
const fn = await evaluate.call(null, code);
|
|
45
45
|
const result = await fn("x", "y");
|
|
46
46
|
assert.equal(result, "yx");
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
test("a lambda can reference itself with @recurse", async () => {
|
|
50
|
-
const code = [ops.lambda, null, [ops.scope, "@recurse"]];
|
|
50
|
+
const code = createCode([ops.lambda, null, [ops.scope, "@recurse"]]);
|
|
51
51
|
const fn = await evaluate.call(null, code);
|
|
52
52
|
const result = await fn();
|
|
53
53
|
// We're expecting the function to return itself, but testing recursion is
|
|
@@ -60,11 +60,11 @@ describe("ops", () => {
|
|
|
60
60
|
upper: (s) => s.toUpperCase(),
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
-
const code = [
|
|
63
|
+
const code = createCode([
|
|
64
64
|
ops.object,
|
|
65
65
|
["hello", [[ops.scope, "upper"], "hello"]],
|
|
66
66
|
["world", [[ops.scope, "upper"], "world"]],
|
|
67
|
-
];
|
|
67
|
+
]);
|
|
68
68
|
|
|
69
69
|
const result = await evaluate.call(scope, code);
|
|
70
70
|
assert.equal(result.hello, "HELLO");
|
|
@@ -75,7 +75,12 @@ describe("ops", () => {
|
|
|
75
75
|
const scope = new ObjectTree({
|
|
76
76
|
upper: (s) => s.toUpperCase(),
|
|
77
77
|
});
|
|
78
|
-
const code = [
|
|
78
|
+
const code = createCode([
|
|
79
|
+
ops.array,
|
|
80
|
+
"Hello",
|
|
81
|
+
1,
|
|
82
|
+
[[ops.scope, "upper"], "world"],
|
|
83
|
+
]);
|
|
79
84
|
const result = await evaluate.call(scope, code);
|
|
80
85
|
assert.deepEqual(result, ["Hello", 1, "WORLD"]);
|
|
81
86
|
});
|
|
@@ -89,7 +94,7 @@ describe("ops", () => {
|
|
|
89
94
|
a: 2, // Should be ignored
|
|
90
95
|
});
|
|
91
96
|
child.parent = parent;
|
|
92
|
-
const code = [ops.inherited, "a"];
|
|
97
|
+
const code = createCode([ops.inherited, "a"]);
|
|
93
98
|
const result = await evaluate.call(child, code);
|
|
94
99
|
assert.equal(result, 1);
|
|
95
100
|
});
|
|
@@ -106,3 +111,16 @@ describe("ops", () => {
|
|
|
106
111
|
assert.equal(number, 1);
|
|
107
112
|
});
|
|
108
113
|
});
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @returns {import("../../index.ts").Code}
|
|
117
|
+
*/
|
|
118
|
+
function createCode(array) {
|
|
119
|
+
const code = array;
|
|
120
|
+
/** @type {any} */ (code).location = {
|
|
121
|
+
source: {
|
|
122
|
+
text: "",
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
return code;
|
|
126
|
+
}
|