@weborigami/language 0.3.4-jse.6 → 0.3.4-jse.8
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 +3 -3
- package/src/compiler/optimize.js +29 -18
- package/src/compiler/origami.pegjs +27 -7
- package/src/compiler/parse.js +268 -175
- package/src/runtime/errors.js +56 -24
- package/src/runtime/evaluate.js +5 -27
- package/src/runtime/symbols.js +1 -0
- package/test/compiler/optimize.test.js +3 -3
- package/test/compiler/parse.test.js +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weborigami/language",
|
|
3
|
-
"version": "0.3.4-jse.
|
|
3
|
+
"version": "0.3.4-jse.8",
|
|
4
4
|
"description": "Web Origami expression language compiler and runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./main.js",
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"typescript": "5.8.2"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@weborigami/async-tree": "0.3.4-jse.
|
|
15
|
-
"@weborigami/types": "0.3.4-jse.
|
|
14
|
+
"@weborigami/async-tree": "0.3.4-jse.8",
|
|
15
|
+
"@weborigami/types": "0.3.4-jse.8",
|
|
16
16
|
"watcher": "2.3.1",
|
|
17
17
|
"yaml": "2.7.0"
|
|
18
18
|
},
|
package/src/compiler/optimize.js
CHANGED
|
@@ -37,8 +37,8 @@ export default function optimize(code, options = {}) {
|
|
|
37
37
|
const [op, ...args] = code;
|
|
38
38
|
switch (op) {
|
|
39
39
|
case markers.global:
|
|
40
|
-
// Replace
|
|
41
|
-
return
|
|
40
|
+
// Replace with the indicated global
|
|
41
|
+
return globals[args[0]];
|
|
42
42
|
|
|
43
43
|
case markers.traverse:
|
|
44
44
|
return resolvePath(code, globals, locals, cache);
|
|
@@ -140,7 +140,7 @@ function compoundReference(key, globals, locals, location) {
|
|
|
140
140
|
const type = referenceType(head, globals, locals);
|
|
141
141
|
let result;
|
|
142
142
|
if (type === REFERENCE_GLOBAL) {
|
|
143
|
-
result = globalReference(head, globals
|
|
143
|
+
result = globalReference(head, globals);
|
|
144
144
|
} else if (type === REFERENCE_LOCAL) {
|
|
145
145
|
result = localReference(head, locals, location);
|
|
146
146
|
} else {
|
|
@@ -177,9 +177,9 @@ function getLocalReferenceDepth(locals, key) {
|
|
|
177
177
|
return depth;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
function globalReference(key, globals
|
|
180
|
+
function globalReference(key, globals) {
|
|
181
181
|
const normalized = trailingSlash.remove(key);
|
|
182
|
-
return
|
|
182
|
+
return globals[normalized];
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
function inlineLiteral(code) {
|
|
@@ -249,24 +249,29 @@ function reference(code, globals, locals) {
|
|
|
249
249
|
|
|
250
250
|
// See if the whole key is a global or local variable
|
|
251
251
|
let type = referenceType(key, globals, locals);
|
|
252
|
-
let result;
|
|
253
252
|
if (type === REFERENCE_GLOBAL) {
|
|
254
|
-
|
|
253
|
+
return {
|
|
254
|
+
type,
|
|
255
|
+
result: globalReference(key, globals),
|
|
256
|
+
};
|
|
255
257
|
} else if (type === REFERENCE_LOCAL) {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
result = compound?.result;
|
|
261
|
-
type = compound?.type;
|
|
258
|
+
return {
|
|
259
|
+
type,
|
|
260
|
+
result: localReference(key, locals, location),
|
|
261
|
+
};
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
264
|
+
// Try key as a compound reference x.y.z
|
|
265
|
+
const compound = compoundReference(key, globals, locals, location);
|
|
266
|
+
if (compound.type !== REFERENCE_EXTERNAL) {
|
|
267
|
+
return compound;
|
|
267
268
|
}
|
|
268
269
|
|
|
269
|
-
|
|
270
|
+
// Not a compound reference, must be external
|
|
271
|
+
return {
|
|
272
|
+
type: REFERENCE_EXTERNAL,
|
|
273
|
+
result: externalReference(key, locals, location),
|
|
274
|
+
};
|
|
270
275
|
}
|
|
271
276
|
|
|
272
277
|
function referenceType(key, globals, locals) {
|
|
@@ -287,7 +292,13 @@ function resolvePath(code, globals, locals, cache) {
|
|
|
287
292
|
|
|
288
293
|
let { type, result } = reference(head, globals, locals);
|
|
289
294
|
|
|
290
|
-
|
|
295
|
+
if (tail.length > 0) {
|
|
296
|
+
if (result instanceof Array) {
|
|
297
|
+
result.push(...tail);
|
|
298
|
+
} else {
|
|
299
|
+
result = annotate([result, ...tail], code.location);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
291
302
|
|
|
292
303
|
if (type === REFERENCE_EXTERNAL && cache !== null) {
|
|
293
304
|
// Cache external path
|
|
@@ -164,10 +164,17 @@ comment "comment"
|
|
|
164
164
|
/ singleLineComment
|
|
165
165
|
|
|
166
166
|
computedPropertyAccess
|
|
167
|
-
=
|
|
167
|
+
= computedPropertySpace "[" expression:expectExpression expectClosingBracket {
|
|
168
168
|
return annotate([markers.property, expression], location());
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
// A space before a computed property access. This is allowed when in not in
|
|
172
|
+
// shell mode, but not in shell mode. In shell mode `foo [bar]` should parse as
|
|
173
|
+
// a function call with a single argument of an array, not as a property access.
|
|
174
|
+
computedPropertySpace
|
|
175
|
+
= shellMode
|
|
176
|
+
/ !shellMode __
|
|
177
|
+
|
|
171
178
|
conditionalExpression
|
|
172
179
|
= condition:logicalOrExpression tail:(__
|
|
173
180
|
"?" __ @shorthandFunction __
|
|
@@ -254,7 +261,7 @@ expectDoubleQuote
|
|
|
254
261
|
expectExpression
|
|
255
262
|
= expression
|
|
256
263
|
/ .? {
|
|
257
|
-
error("Expected an
|
|
264
|
+
error("Expected an expression");
|
|
258
265
|
}
|
|
259
266
|
|
|
260
267
|
expectFrontDelimiter
|
|
@@ -282,6 +289,12 @@ expectPipelineExpression
|
|
|
282
289
|
error("Expected an expression");
|
|
283
290
|
}
|
|
284
291
|
|
|
292
|
+
expectUnaryExpression
|
|
293
|
+
= unaryExpression
|
|
294
|
+
/ .? {
|
|
295
|
+
error("Expected an expression");
|
|
296
|
+
}
|
|
297
|
+
|
|
285
298
|
exponentiationExpression
|
|
286
299
|
= left:unaryExpression right:(whitespace "**" whitespace @exponentiationExpression)? {
|
|
287
300
|
return right ? annotate([ops.exponentiation, left, right], location()) : left;
|
|
@@ -319,7 +332,7 @@ frontMatterYaml "YAML front matter"
|
|
|
319
332
|
|
|
320
333
|
// An expression in parentheses: `(foo)`
|
|
321
334
|
group "parenthetical group"
|
|
322
|
-
= "(" expression:
|
|
335
|
+
= "(" expression:expectExpression expectClosingParenthesis {
|
|
323
336
|
return annotate(expression, location());
|
|
324
337
|
}
|
|
325
338
|
|
|
@@ -767,7 +780,12 @@ templateBodyText "template text"
|
|
|
767
780
|
|
|
768
781
|
templateDocument "template document"
|
|
769
782
|
= front:frontMatterExpression __ body:templateBody {
|
|
783
|
+
// TODO: Deprecate @template
|
|
770
784
|
const macroName = text().includes("@template") ? "@template" : "_template";
|
|
785
|
+
if (macroName === "@template") {
|
|
786
|
+
// If the front matter is a macro, apply it to the body
|
|
787
|
+
console.warn("Warning: the @template() macro is deprecated. Use _template() instead.");
|
|
788
|
+
}
|
|
771
789
|
return annotate(applyMacro(front, macroName, body), location());
|
|
772
790
|
}
|
|
773
791
|
/ front:frontMatterYaml body:templateBody {
|
|
@@ -811,7 +829,7 @@ textChar
|
|
|
811
829
|
|
|
812
830
|
// A unary prefix operator: `!x`
|
|
813
831
|
unaryExpression
|
|
814
|
-
= operator:unaryOperator __ expression:
|
|
832
|
+
= operator:unaryOperator __ expression:expectUnaryExpression {
|
|
815
833
|
return makeUnaryOperation(operator, expression, location());
|
|
816
834
|
}
|
|
817
835
|
/ callExpression
|
|
@@ -848,7 +866,8 @@ uriKey
|
|
|
848
866
|
// A single character in a URI key
|
|
849
867
|
uriKeyChar
|
|
850
868
|
// Accept anything that doesn't end the URI key or path
|
|
851
|
-
|
|
869
|
+
// Note: Peggy doesn't support `/s` so we list space and tab explicitly.
|
|
870
|
+
= [^/,\)\]\} \t]
|
|
852
871
|
/ escapedChar
|
|
853
872
|
|
|
854
873
|
// A slash-separated path of keys: `a/b/c`
|
|
@@ -871,8 +890,9 @@ unaryOperator
|
|
|
871
890
|
/ minus
|
|
872
891
|
|
|
873
892
|
whitespace
|
|
874
|
-
|
|
875
|
-
|
|
893
|
+
// JavaScript considers a large number of characters whitespace so we use the
|
|
894
|
+
// `/s` definition to avoid missing any.
|
|
895
|
+
= char:. &{ return /\s/.test(char); } { return char; }
|
|
876
896
|
/ comment
|
|
877
897
|
|
|
878
898
|
whitespaceWithNewLine
|