@weborigami/language 0.6.4 → 0.6.6
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/main.js +4 -0
- package/package.json +2 -2
- package/src/compiler/optimize.js +17 -11
- package/src/compiler/origami.pegjs +192 -58
- package/src/compiler/parse.js +2182 -1172
- package/src/compiler/parserHelpers.js +172 -10
- package/src/project/projectConfig.js +2 -2
- package/src/project/projectGlobals.js +2 -2
- package/src/project/projectRoot.js +5 -54
- package/src/project/projectRootFromPath.js +58 -0
- package/src/protocols/fetchAndHandleExtension.js +5 -0
- package/src/protocols/package.js +26 -39
- package/src/runtime/expressionObject.js +162 -150
- package/src/runtime/handleExtension.js +18 -2
- package/src/runtime/ops.js +30 -9
- package/test/compiler/compile.test.js +39 -0
- package/test/compiler/optimize.test.js +2 -1
- package/test/compiler/parse.test.js +355 -112
- package/test/project/{projectRoot.test.js → projectRootFromPath.test.js} +5 -5
- package/test/protocols/package.test.js +6 -1
- package/test/runtime/expressionObject.test.js +25 -10
- package/test/runtime/ops.test.js +32 -4
package/main.js
CHANGED
|
@@ -4,14 +4,18 @@ export * as compile from "./src/compiler/compile.js";
|
|
|
4
4
|
export { default as isOrigamiFrontMatter } from "./src/compiler/isOrigamiFrontMatter.js";
|
|
5
5
|
export * as Handlers from "./src/handlers/handlers.js";
|
|
6
6
|
export { default as builtins } from "./src/project/builtins.js";
|
|
7
|
+
export { default as coreGlobals } from "./src/project/coreGlobals.js";
|
|
7
8
|
export { default as jsGlobals } from "./src/project/jsGlobals.js";
|
|
9
|
+
export { default as projectConfig } from "./src/project/projectConfig.js";
|
|
8
10
|
export { default as projectGlobals } from "./src/project/projectGlobals.js";
|
|
9
11
|
export { default as projectRoot } from "./src/project/projectRoot.js";
|
|
12
|
+
export { default as projectRootFromPath } from "./src/project/projectRootFromPath.js";
|
|
10
13
|
export * as Protocols from "./src/protocols/protocols.js";
|
|
11
14
|
export { formatError, highlightError } from "./src/runtime/errors.js";
|
|
12
15
|
export { default as evaluate } from "./src/runtime/evaluate.js";
|
|
13
16
|
export { default as EventTargetMixin } from "./src/runtime/EventTargetMixin.js";
|
|
14
17
|
export * as expressionFunction from "./src/runtime/expressionFunction.js";
|
|
18
|
+
export { default as expressionObject } from "./src/runtime/expressionObject.js";
|
|
15
19
|
export * from "./src/runtime/handleExtension.js";
|
|
16
20
|
export { default as handleExtension } from "./src/runtime/handleExtension.js";
|
|
17
21
|
export { default as HandleExtensionsTransform } from "./src/runtime/HandleExtensionsTransform.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weborigami/language",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6",
|
|
4
4
|
"description": "Web Origami expression language compiler and runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./main.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"typescript": "5.9.3"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@weborigami/async-tree": "0.6.
|
|
14
|
+
"@weborigami/async-tree": "0.6.6",
|
|
15
15
|
"exif-parser": "0.1.12",
|
|
16
16
|
"watcher": "2.3.1",
|
|
17
17
|
"yaml": "2.8.1"
|
package/src/compiler/optimize.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { pathFromKeys, trailingSlash } from "@weborigami/async-tree";
|
|
2
2
|
import jsGlobals from "../project/jsGlobals.js";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
KEY_TYPE,
|
|
5
|
+
normalizeKey,
|
|
6
|
+
propertyInfo,
|
|
7
|
+
} from "../runtime/expressionObject.js";
|
|
4
8
|
import { ops } from "../runtime/internal.js";
|
|
5
9
|
import { annotate, markers, spanLocations } from "./parserHelpers.js";
|
|
6
10
|
|
|
@@ -47,9 +51,9 @@ export default function optimize(code, options = {}) {
|
|
|
47
51
|
return resolvePath(code, globals, parent, locals, cache);
|
|
48
52
|
|
|
49
53
|
case ops.lambda:
|
|
50
|
-
const parameters = args[
|
|
54
|
+
const parameters = args[1];
|
|
51
55
|
if (parameters.length > 0) {
|
|
52
|
-
const paramNames = parameters.map((param) => param[
|
|
56
|
+
const paramNames = parameters.map((param) => param[0]);
|
|
53
57
|
locals.push({
|
|
54
58
|
type: REFERENCE_PARAM,
|
|
55
59
|
names: paramNames,
|
|
@@ -62,10 +66,7 @@ export default function optimize(code, options = {}) {
|
|
|
62
66
|
|
|
63
67
|
case ops.object:
|
|
64
68
|
const entries = args;
|
|
65
|
-
|
|
66
|
-
const propertyNames = entries
|
|
67
|
-
.map((entry) => entryKey(entry))
|
|
68
|
-
.filter((key) => key !== null);
|
|
69
|
+
const propertyNames = getPropertyNames(entries);
|
|
69
70
|
locals.push({
|
|
70
71
|
type: REFERENCE_INHERITED,
|
|
71
72
|
names: propertyNames,
|
|
@@ -76,10 +77,7 @@ export default function optimize(code, options = {}) {
|
|
|
76
77
|
// Optimize children
|
|
77
78
|
const optimized = annotate(
|
|
78
79
|
code.map((child, index) => {
|
|
79
|
-
|
|
80
|
-
if (op === ops.lambda && index === 1) {
|
|
81
|
-
return child;
|
|
82
|
-
} else if (op === ops.object && index > 0) {
|
|
80
|
+
if (op === ops.object && index > 0) {
|
|
83
81
|
const [key, value] = child;
|
|
84
82
|
const adjustedLocals = avoidLocalRecursion(locals, key);
|
|
85
83
|
const optimizedKey =
|
|
@@ -210,6 +208,14 @@ function findLocalDetails(key, locals) {
|
|
|
210
208
|
return null;
|
|
211
209
|
}
|
|
212
210
|
|
|
211
|
+
function getPropertyNames(entries) {
|
|
212
|
+
const infos = entries.map(([key, value]) => propertyInfo(key, value));
|
|
213
|
+
// Filter out computed property keys when determining local variables
|
|
214
|
+
return infos
|
|
215
|
+
.filter((info) => info.keyType !== KEY_TYPE.COMPUTED)
|
|
216
|
+
.map((info) => normalizeKey(info));
|
|
217
|
+
}
|
|
218
|
+
|
|
213
219
|
function globalReference(key, globals) {
|
|
214
220
|
const normalized = trailingSlash.remove(key);
|
|
215
221
|
return globals[normalized];
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
makeCallChain,
|
|
22
22
|
makeDeferredArguments,
|
|
23
23
|
makeDocument,
|
|
24
|
+
makeLambda,
|
|
24
25
|
makeObject,
|
|
25
26
|
makePath,
|
|
26
27
|
makePipeline,
|
|
@@ -101,18 +102,18 @@ arrayEntries
|
|
|
101
102
|
arrayEntry
|
|
102
103
|
= spreadElement
|
|
103
104
|
/ pipelineExpression
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
/ &separator {
|
|
106
|
+
// Missing value is allowed
|
|
106
107
|
return annotate([ops.literal, undefined], location());
|
|
107
108
|
}
|
|
108
109
|
|
|
109
110
|
arrowFunction
|
|
110
|
-
= ("async" __)? "(" __ parameters:
|
|
111
|
-
|
|
112
|
-
return
|
|
111
|
+
= ("async" __)? "(" __ parameters:paramList? __ ")" __ doubleArrow __ body:expectPipelineExpression {
|
|
112
|
+
parameters ??= annotate([], location());
|
|
113
|
+
return makeLambda(parameters, body, location());
|
|
113
114
|
}
|
|
114
|
-
/
|
|
115
|
-
return
|
|
115
|
+
/ parameters:paramSingleton __ doubleArrow __ body:expectPipelineExpression {
|
|
116
|
+
return makeLambda(parameters, body, location());
|
|
116
117
|
}
|
|
117
118
|
/ conditionalExpression
|
|
118
119
|
|
|
@@ -162,16 +163,18 @@ comment "comment"
|
|
|
162
163
|
/ singleLineComment
|
|
163
164
|
|
|
164
165
|
computedPropertyAccess
|
|
165
|
-
= computedPropertySpace "[" expression:expectExpression expectClosingBracket {
|
|
166
|
+
= computedPropertySpace? "[" expression:expectExpression expectClosingBracket {
|
|
166
167
|
return annotate([markers.property, expression], location());
|
|
167
168
|
}
|
|
168
169
|
|
|
169
|
-
//
|
|
170
|
-
// mode. In shell mode `foo [bar]` should parse as a function call with
|
|
171
|
-
// argument of an array, not as a property access.
|
|
170
|
+
// An inline space before a computed property access. This is allowed when not
|
|
171
|
+
// in shell mode. In shell mode `foo [bar]` should parse as a function call with
|
|
172
|
+
// a single argument of an array, not as a property access. In program made, we
|
|
173
|
+
// allow an inline space per JavaScript. JavaScript also allows newlines, but we
|
|
174
|
+
// disallow those to avoid confusion with array/list/object entry separators.
|
|
172
175
|
computedPropertySpace
|
|
173
176
|
= shellMode
|
|
174
|
-
/ !shellMode
|
|
177
|
+
/ !shellMode inlineSpace
|
|
175
178
|
|
|
176
179
|
conditionalExpression
|
|
177
180
|
= condition:logicalOrExpression tail:(__
|
|
@@ -189,9 +192,6 @@ conditionalExpression
|
|
|
189
192
|
deferred[1]
|
|
190
193
|
], location());
|
|
191
194
|
}
|
|
192
|
-
|
|
193
|
-
digits
|
|
194
|
-
= @[0-9]+
|
|
195
195
|
|
|
196
196
|
doubleArrow = "⇒" / "=>"
|
|
197
197
|
|
|
@@ -269,7 +269,13 @@ expectFrontDelimiter
|
|
|
269
269
|
error("Expected \"---\"");
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
|
|
272
|
+
expectLeftGuillemet
|
|
273
|
+
= '«'
|
|
274
|
+
/ .? {
|
|
275
|
+
error("Expected closing guillemet");
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
expectRightGuillemet
|
|
273
279
|
= '»'
|
|
274
280
|
/ .? {
|
|
275
281
|
error("Expected closing guillemet");
|
|
@@ -303,11 +309,6 @@ exponentiationExpression
|
|
|
303
309
|
expression
|
|
304
310
|
= __ @commaExpression __
|
|
305
311
|
|
|
306
|
-
floatLiteral "floating-point number"
|
|
307
|
-
= digits? "." digits {
|
|
308
|
-
return annotate([ops.literal, parseFloat(text())], location());
|
|
309
|
-
}
|
|
310
|
-
|
|
311
312
|
// Marker for the beginning or end of front matter
|
|
312
313
|
frontDelimiter
|
|
313
314
|
= "---\n"
|
|
@@ -336,19 +337,22 @@ group "parenthetical group"
|
|
|
336
337
|
}
|
|
337
338
|
|
|
338
339
|
guillemetString "guillemet string"
|
|
339
|
-
=
|
|
340
|
-
|
|
341
|
-
|
|
340
|
+
= "«" chars:guillemetStringChar* expectRightGuillemet {
|
|
341
|
+
return annotate([ops.literal, chars.join("")], location());
|
|
342
|
+
}
|
|
343
|
+
/ "»" chars:guillemetStringChar* expectLeftGuillemet {
|
|
344
|
+
return annotate([ops.literal, chars.join("")], location());
|
|
345
|
+
}
|
|
342
346
|
|
|
343
347
|
guillemetStringChar
|
|
344
|
-
= !(
|
|
348
|
+
= !("«" / "»" / newLine) @textChar
|
|
345
349
|
|
|
346
350
|
// A host identifier that may include a colon and port number: `example.com:80`.
|
|
347
351
|
// This is used as a special case at the head of a path, where we want to
|
|
348
352
|
// interpret a colon as part of a text identifier.
|
|
349
353
|
host "HTTP/HTTPS host"
|
|
350
|
-
= name:hostname port:
|
|
351
|
-
const portText = port
|
|
354
|
+
= name:hostname port:port? slashFollows:slashFollows? {
|
|
355
|
+
const portText = port ?? "";
|
|
352
356
|
const slashText = slashFollows ? "/" : "";
|
|
353
357
|
const host = name + portText + slashText;
|
|
354
358
|
return annotate([ops.literal, host], location());
|
|
@@ -407,11 +411,6 @@ implicitParenthesesCallExpression "function call with implicit parentheses"
|
|
|
407
411
|
inlineSpace
|
|
408
412
|
= [ \t]
|
|
409
413
|
|
|
410
|
-
integerLiteral "integer"
|
|
411
|
-
= digits {
|
|
412
|
-
return annotate([ops.literal, parseInt(text())], location());
|
|
413
|
-
}
|
|
414
|
-
|
|
415
414
|
// A key in a path or an expression that looks like one
|
|
416
415
|
key
|
|
417
416
|
= keyCharStart keyChar* {
|
|
@@ -435,7 +434,7 @@ keyChar
|
|
|
435
434
|
keyCharStart
|
|
436
435
|
// All JS identifier characters
|
|
437
436
|
= char:. &{ return char.match(/[$_\p{ID_Continue}]/u) }
|
|
438
|
-
/ "."
|
|
437
|
+
/ "." !".." // a dot, but not a spread/rest operator
|
|
439
438
|
/ "@"
|
|
440
439
|
/ "~"
|
|
441
440
|
|
|
@@ -494,10 +493,52 @@ newLine
|
|
|
494
493
|
/ "\r\n"
|
|
495
494
|
/ "\r"
|
|
496
495
|
|
|
496
|
+
number
|
|
497
|
+
= numberBigInt
|
|
498
|
+
/ numberStandard {
|
|
499
|
+
const stripped = text().replace("_", ""); // remove underscores
|
|
500
|
+
return Number(stripped);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
numberBigInt
|
|
504
|
+
= digits:numberDecimalDigits "n" {
|
|
505
|
+
const stripped = digits.replace("_", ""); // remove underscores
|
|
506
|
+
return BigInt(stripped);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
numberBinary
|
|
510
|
+
= "0" [bB] digits:[01_]+
|
|
511
|
+
|
|
512
|
+
numberDecimal
|
|
513
|
+
= numberDecimalDigits? "." numberDecimalDigits numberExponent?
|
|
514
|
+
/ numberDecimalDigits numberExponent?
|
|
515
|
+
|
|
516
|
+
numberDecimalDigits
|
|
517
|
+
= [0-9]([_]*[0-9])* {
|
|
518
|
+
return text();
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
numberExponent
|
|
522
|
+
= [eE] [+\-]? digits:numberDecimalDigits
|
|
523
|
+
|
|
524
|
+
numberHex
|
|
525
|
+
= "0" [xX] digits:[0-9a-fA-F_]+
|
|
526
|
+
|
|
497
527
|
// A number
|
|
498
|
-
|
|
499
|
-
=
|
|
500
|
-
|
|
528
|
+
numberLiteral "number"
|
|
529
|
+
= number:number {
|
|
530
|
+
return annotate([ops.literal, number], location());
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
numberOctal
|
|
534
|
+
= "0" [oO] digits:[0-7]+
|
|
535
|
+
|
|
536
|
+
// Any number that can be parsed with Number(); i.e., not a bigint
|
|
537
|
+
numberStandard
|
|
538
|
+
= numberBinary
|
|
539
|
+
/ numberOctal
|
|
540
|
+
/ numberHex
|
|
541
|
+
/ numberDecimal
|
|
501
542
|
|
|
502
543
|
nullishCoalescingExpression
|
|
503
544
|
= head:logicalAndExpression tail:(__ "??" __ @logicalAndExpression)* {
|
|
@@ -586,20 +627,112 @@ optional
|
|
|
586
627
|
return annotate([ops.optional, propertyAccess], location());
|
|
587
628
|
}
|
|
588
629
|
|
|
589
|
-
|
|
590
|
-
|
|
630
|
+
paramArray
|
|
631
|
+
= "[" __ entries:paramArrayEntries __ "]" {
|
|
632
|
+
return annotate([markers.paramArray, ...entries], location());
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// A list of parameters inside array destructuring: `a, b` in `([a, b]) => a + b`
|
|
636
|
+
// Different than top-level parameters because elements can be elided: `a, , b`
|
|
637
|
+
paramArrayEntries
|
|
638
|
+
= entries:paramArrayEntry|1.., separator| rest:(separator @paramRest?)? {
|
|
639
|
+
if (rest) {
|
|
640
|
+
entries.push(rest);
|
|
641
|
+
}
|
|
642
|
+
return annotate(entries, location());
|
|
643
|
+
}
|
|
644
|
+
/ rest:paramRest {
|
|
645
|
+
return annotate([rest], location());
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// Single parameter in a function's parameter list
|
|
649
|
+
param
|
|
650
|
+
= paramNameWithInitilializer
|
|
651
|
+
/ pattern:paramBindingPattern initializer:paramInitializer? {
|
|
652
|
+
return initializer
|
|
653
|
+
? annotate([markers.paramInitializer, pattern, initializer], location())
|
|
654
|
+
: pattern;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
paramArrayEntry
|
|
658
|
+
= param
|
|
659
|
+
/ &separator {
|
|
660
|
+
// Missing value is allowed
|
|
661
|
+
return undefined;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
paramBindingPattern
|
|
665
|
+
= paramArray
|
|
666
|
+
/ paramObject
|
|
667
|
+
|
|
668
|
+
paramInitializer
|
|
669
|
+
= __ "=" __ @pipelineExpression
|
|
670
|
+
|
|
671
|
+
// A list of lambda parameters inside the parentheses: `a, b` in `(a, b) => a + b`
|
|
672
|
+
paramList
|
|
673
|
+
= entries:param|1.., separator| rest:(separator @paramRest?)? {
|
|
674
|
+
if (rest) {
|
|
675
|
+
entries.push(rest);
|
|
676
|
+
}
|
|
677
|
+
return annotate(entries, location());
|
|
678
|
+
}
|
|
679
|
+
/ rest:paramRest {
|
|
680
|
+
return annotate([rest], location());
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// A single name in a parameter list: `a` in `a, b`
|
|
684
|
+
paramName
|
|
591
685
|
= key:key {
|
|
592
|
-
return annotate([
|
|
686
|
+
return annotate([markers.paramName, key], location());
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
paramNameWithInitilializer
|
|
690
|
+
= name:paramName initializer:paramInitializer? {
|
|
691
|
+
return initializer
|
|
692
|
+
? annotate([markers.paramInitializer, name, initializer], location())
|
|
693
|
+
: name;
|
|
593
694
|
}
|
|
594
695
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
696
|
+
// Object binding pattern in function parameter: `{ a, b: c }`
|
|
697
|
+
paramObject
|
|
698
|
+
= "{" __ entries:paramObjectEntries? __ "}" {
|
|
699
|
+
return annotate([markers.paramObject, ...(entries ?? [])], location());
|
|
598
700
|
}
|
|
599
701
|
|
|
600
|
-
// A list
|
|
601
|
-
|
|
602
|
-
=
|
|
702
|
+
// A separated list of parameter object entries inside the curly braces
|
|
703
|
+
paramObjectEntries
|
|
704
|
+
= entries:paramObjectEntry|1.., separator| rest:(separator @paramRest)? {
|
|
705
|
+
if (rest) {
|
|
706
|
+
entries.push(rest);
|
|
707
|
+
}
|
|
708
|
+
return annotate(entries, location());
|
|
709
|
+
}
|
|
710
|
+
/ rest:paramRest {
|
|
711
|
+
return annotate([rest], location());
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// An entry in a parameter object: `a: b` in `{ a: b }`
|
|
715
|
+
paramObjectEntry
|
|
716
|
+
= key:objectPublicKey __ ":" __ param:param {
|
|
717
|
+
return annotate([key, param], location());
|
|
718
|
+
}
|
|
719
|
+
/ name:paramName initializer:paramInitializer? {
|
|
720
|
+
const binding = initializer
|
|
721
|
+
? annotate([markers.paramInitializer, name, initializer], location())
|
|
722
|
+
: name;
|
|
723
|
+
return annotate([name[1], binding], location());
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// Optional rest parameter for param array or object
|
|
727
|
+
paramRest
|
|
728
|
+
= "..." __ param:param {
|
|
729
|
+
return annotate([markers.paramRest, param], location());
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// A lambda parameter list with a single identifier with no parentheses:
|
|
733
|
+
// `x` in `x => x + 1`
|
|
734
|
+
paramSingleton
|
|
735
|
+
= param:paramName {
|
|
603
736
|
return annotate([param], location());
|
|
604
737
|
}
|
|
605
738
|
|
|
@@ -619,7 +752,7 @@ parenthesesArgumentList "list"
|
|
|
619
752
|
// Function arguments in parentheses
|
|
620
753
|
parenthesesArguments "function arguments in parentheses"
|
|
621
754
|
= inlineSpace* "(" __ list:parenthesesArgumentList? __ expectClosingParenthesis {
|
|
622
|
-
return annotate(list ?? [
|
|
755
|
+
return annotate(list ?? [], location());
|
|
623
756
|
}
|
|
624
757
|
|
|
625
758
|
// A slash-separated path of keys that follows a call target, such as the path
|
|
@@ -660,6 +793,11 @@ pipelineExpression
|
|
|
660
793
|
);
|
|
661
794
|
}
|
|
662
795
|
|
|
796
|
+
port
|
|
797
|
+
= ":" [0-9]+ {
|
|
798
|
+
return text();
|
|
799
|
+
}
|
|
800
|
+
|
|
663
801
|
primary
|
|
664
802
|
// The following start with distinct characters
|
|
665
803
|
= stringLiteral
|
|
@@ -671,7 +809,7 @@ primary
|
|
|
671
809
|
/ templateLiteral
|
|
672
810
|
|
|
673
811
|
// These are more ambiguous
|
|
674
|
-
/ @
|
|
812
|
+
/ @numberLiteral !keyChar // numbers + chars would be a key
|
|
675
813
|
/ pathLiteral
|
|
676
814
|
|
|
677
815
|
// Top-level Origami progam with possible shebang directive (which is ignored)
|
|
@@ -741,15 +879,13 @@ shiftOperator
|
|
|
741
879
|
// A shorthand lambda expression: `=foo(_)`
|
|
742
880
|
shorthandFunction "lambda function"
|
|
743
881
|
// Avoid a following equal sign (for an equality)
|
|
744
|
-
= (shellMode / programMode) "=" !"=" __
|
|
882
|
+
= (shellMode / programMode) "=" !"=" __ body:implicitParenthesesCallExpression {
|
|
745
883
|
if (options.mode === "program") {
|
|
746
884
|
throw new Error("Parse error: shorthand function syntax isn't allowed in Origami programs. Use arrow syntax instead.");
|
|
747
885
|
}
|
|
748
|
-
const
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
);
|
|
752
|
-
return annotate([ops.lambda, lambdaParameters, definition], location());
|
|
886
|
+
const underscore = annotate([markers.paramName, "_"], location());
|
|
887
|
+
const parameters = annotate([underscore], location());
|
|
888
|
+
return makeLambda(parameters, body, location());
|
|
753
889
|
}
|
|
754
890
|
/ implicitParenthesesCallExpression
|
|
755
891
|
|
|
@@ -824,11 +960,9 @@ templateDocument "template document"
|
|
|
824
960
|
if (options.front) {
|
|
825
961
|
return makeDocument(options.front, body, location());
|
|
826
962
|
}
|
|
827
|
-
const
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
);
|
|
831
|
-
return annotate([ops.lambda, lambdaParameters, body], location());
|
|
963
|
+
const underscore = annotate([markers.paramName, "_"], location());
|
|
964
|
+
const parameters = annotate([underscore], location());
|
|
965
|
+
return makeLambda(parameters, body, location());
|
|
832
966
|
}
|
|
833
967
|
|
|
834
968
|
// A backtick-quoted template literal
|