@weborigami/language 0.0.66-beta.1 → 0.0.66
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 +5 -5
- package/src/compiler/origami.pegjs +41 -23
- package/src/compiler/parse.js +280 -202
- package/src/compiler/parserHelpers.js +39 -4
- package/src/runtime/HandleExtensionsTransform.js +3 -4
- package/src/runtime/ImportModulesMixin.js +13 -10
- package/src/runtime/InvokeFunctionsTransform.js +0 -6
- package/src/runtime/expressionObject.js +3 -3
- package/src/runtime/extensions.js +55 -47
- package/src/runtime/formatError.js +5 -1
- package/src/runtime/ops.js +71 -28
- package/test/compiler/compile.test.js +7 -1
- package/test/compiler/parse.test.js +72 -29
- package/test/runtime/extensions.test.js +9 -6
- package/test/runtime/ops.test.js +38 -31
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weborigami/language",
|
|
3
|
-
"version": "0.0.66
|
|
3
|
+
"version": "0.0.66",
|
|
4
4
|
"description": "Web Origami expression language compiler and runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./main.js",
|
|
7
7
|
"types": "./index.ts",
|
|
8
8
|
"devDependencies": {
|
|
9
|
-
"@types/node": "22.
|
|
9
|
+
"@types/node": "22.7.4",
|
|
10
10
|
"peggy": "4.0.3",
|
|
11
|
-
"typescript": "5.
|
|
11
|
+
"typescript": "5.6.2"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@weborigami/async-tree": "0.0.66
|
|
15
|
-
"@weborigami/types": "0.0.66
|
|
14
|
+
"@weborigami/async-tree": "0.0.66",
|
|
15
|
+
"@weborigami/types": "0.0.66",
|
|
16
16
|
"watcher": "2.3.1"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
@@ -63,6 +63,7 @@ callTarget "function call"
|
|
|
63
63
|
/ parameterizedLambda
|
|
64
64
|
/ protocolCall
|
|
65
65
|
/ group
|
|
66
|
+
/ scopeTraverse
|
|
66
67
|
/ scopeReference
|
|
67
68
|
|
|
68
69
|
// Required closing curly brace. We use this for the `object` term: if the
|
|
@@ -161,8 +162,10 @@ guillemetStringChar
|
|
|
161
162
|
// This is used as a special case at the head of a path, where we want to
|
|
162
163
|
// interpret a colon as part of a text identifier.
|
|
163
164
|
host "HTTP/HTTPS host"
|
|
164
|
-
= identifier (":" number)? {
|
|
165
|
-
|
|
165
|
+
= identifier:identifier port:(":" @number)? {
|
|
166
|
+
const portText = port ? `:${port[1]}` : "";
|
|
167
|
+
const hostText = identifier + portText;
|
|
168
|
+
return annotate([ops.primitive, hostText], location());
|
|
166
169
|
}
|
|
167
170
|
|
|
168
171
|
identifier "identifier"
|
|
@@ -202,11 +205,8 @@ lambda "lambda function"
|
|
|
202
205
|
|
|
203
206
|
// A path that begins with a slash: `/foo/bar`
|
|
204
207
|
leadingSlashPath "path with a leading slash"
|
|
205
|
-
= "/" path:path {
|
|
206
|
-
return annotate(path, location());
|
|
207
|
-
}
|
|
208
|
-
/ "/" {
|
|
209
|
-
return annotate([""], location());
|
|
208
|
+
= "/" path:path? {
|
|
209
|
+
return annotate(path ?? [], location());
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
// A separated list of expressions
|
|
@@ -259,13 +259,6 @@ objectKey "object key"
|
|
|
259
259
|
= objectHiddenKey
|
|
260
260
|
/ objectPublicKey
|
|
261
261
|
|
|
262
|
-
objectPublicKey
|
|
263
|
-
= identifier
|
|
264
|
-
/ string:string {
|
|
265
|
-
// Remove `ops.primitive` from the string code
|
|
266
|
-
return string[1];
|
|
267
|
-
}
|
|
268
|
-
|
|
269
262
|
// A property definition in an object literal: `x: 1`
|
|
270
263
|
objectProperty "object property"
|
|
271
264
|
= key:objectKey __ ":" __ value:expr {
|
|
@@ -278,6 +271,15 @@ objectShorthandProperty "object identifier"
|
|
|
278
271
|
return annotate([key, [ops.inherited, key]], location());
|
|
279
272
|
}
|
|
280
273
|
|
|
274
|
+
objectPublicKey
|
|
275
|
+
= identifier:identifier slash:"/"? {
|
|
276
|
+
return identifier + (slash ?? "");
|
|
277
|
+
}
|
|
278
|
+
/ string:string {
|
|
279
|
+
// Remove `ops.primitive` from the string code
|
|
280
|
+
return string[1];
|
|
281
|
+
}
|
|
282
|
+
|
|
281
283
|
parameterizedLambda
|
|
282
284
|
= "(" __ parameters:identifierList? __ ")" __ doubleArrow __ expr:expr {
|
|
283
285
|
return annotate([ops.lambda, parameters ?? [], expr], location());
|
|
@@ -296,14 +298,17 @@ pipeline
|
|
|
296
298
|
|
|
297
299
|
// A slash-separated path of keys
|
|
298
300
|
path "slash-separated path"
|
|
299
|
-
=
|
|
301
|
+
= head:pathElement|0..| tail:pathTail? {
|
|
302
|
+
let path = tail ? [...head, tail] : head;
|
|
303
|
+
// Remove parts for consecutive slashes
|
|
304
|
+
path = path.filter((part) => part[1] !== "/");
|
|
300
305
|
return annotate(path, location());
|
|
301
306
|
}
|
|
302
307
|
|
|
303
|
-
// A
|
|
304
|
-
|
|
305
|
-
= chars:pathKeyChar* {
|
|
306
|
-
return annotate([ops.primitive, chars.join("")], location());
|
|
308
|
+
// A path key followed by a slash
|
|
309
|
+
pathElement
|
|
310
|
+
= chars:pathKeyChar* "/" {
|
|
311
|
+
return annotate([ops.primitive, chars.join("") + "/"], location());
|
|
307
312
|
}
|
|
308
313
|
|
|
309
314
|
// A single character in a slash-separated path.
|
|
@@ -313,6 +318,12 @@ pathKeyChar
|
|
|
313
318
|
= [^(){}\[\],:/\\ \t\n\r]
|
|
314
319
|
/ escapedChar
|
|
315
320
|
|
|
321
|
+
// A path key without a slash
|
|
322
|
+
pathTail
|
|
323
|
+
= chars:pathKeyChar+ {
|
|
324
|
+
return annotate([ops.primitive, chars.join("")], location());
|
|
325
|
+
}
|
|
326
|
+
|
|
316
327
|
// Parse a protocol call like `fn://foo/bar`.
|
|
317
328
|
// There can be zero, one, or two slashes after the colon.
|
|
318
329
|
protocolCall "function call using protocol: syntax"
|
|
@@ -325,19 +336,26 @@ protocol "protocol"
|
|
|
325
336
|
/ scopeReference
|
|
326
337
|
|
|
327
338
|
reservedProtocol "reserved protocol"
|
|
328
|
-
= "
|
|
339
|
+
= "explore" { return ops.explorableSite; }
|
|
340
|
+
/ "https" { return ops.https; } // Must come before "http"
|
|
329
341
|
/ "http" { return ops.http; }
|
|
330
342
|
/ "new" { return ops.constructor; }
|
|
331
343
|
/ "package" { return [ops.scope, "@package"] } // Alias
|
|
332
|
-
/ "treehttps" { return ops.treeHttps; }
|
|
333
|
-
/ "treehttp" { return ops.treeHttp; }
|
|
334
|
-
/ "tree" { return ops.treeHttps; }
|
|
344
|
+
/ "treehttps" { return ops.treeHttps; } // Must come before `treehttp`
|
|
345
|
+
/ "treehttp" { return ops.treeHttp; } // Must come before `tree`
|
|
346
|
+
/ "tree" { return ops.treeHttps; }
|
|
335
347
|
|
|
336
348
|
scopeReference "scope reference"
|
|
337
349
|
= key:identifier {
|
|
338
350
|
return annotate([ops.scope, key], location());
|
|
339
351
|
}
|
|
340
352
|
|
|
353
|
+
scopeTraverse
|
|
354
|
+
= ref:scopeReference "/" path:path {
|
|
355
|
+
const head = [ops.scope, `${ ref[1] }/`];
|
|
356
|
+
return annotate([ops.traverse, head, ...path], location());
|
|
357
|
+
}
|
|
358
|
+
|
|
341
359
|
separator
|
|
342
360
|
= __ "," __
|
|
343
361
|
/ whitespaceWithNewLine
|