@weborigami/language 0.2.2 → 0.2.4

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Jan Miksovsky and other contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/main.js CHANGED
@@ -13,5 +13,6 @@ export { default as InvokeFunctionsTransform } from "./src/runtime/InvokeFunctio
13
13
  export { default as OrigamiFiles } from "./src/runtime/OrigamiFiles.js";
14
14
  export * as symbols from "./src/runtime/symbols.js";
15
15
  export { default as taggedTemplate } from "./src/runtime/taggedTemplate.js";
16
+ export { default as taggedTemplateIndent } from "./src/runtime/taggedTemplateIndent.js";
16
17
  export { default as TreeEvent } from "./src/runtime/TreeEvent.js";
17
18
  export { default as WatchFilesMixin } from "./src/runtime/WatchFilesMixin.js";
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@weborigami/language",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
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.7.4",
10
- "peggy": "4.0.3",
11
- "typescript": "5.6.2",
12
- "yaml": "2.5.1"
9
+ "@types/node": "22.10.2",
10
+ "peggy": "4.2.0.",
11
+ "typescript": "5.7.2",
12
+ "yaml": "2.6.1"
13
13
  },
14
14
  "dependencies": {
15
- "@weborigami/async-tree": "0.2.2",
16
- "@weborigami/types": "0.2.2",
15
+ "@weborigami/async-tree": "0.2.4",
16
+ "@weborigami/types": "0.2.4",
17
17
  "watcher": "2.3.1"
18
18
  },
19
19
  "scripts": {
@@ -5,7 +5,7 @@ import { parse } from "./parse.js";
5
5
  import { annotate, undetermined } from "./parserHelpers.js";
6
6
 
7
7
  function compile(source, options) {
8
- const { startRule } = options;
8
+ const { macros, startRule } = options;
9
9
  const enableCaching = options.scopeCaching ?? true;
10
10
  if (typeof source === "string") {
11
11
  source = { text: source };
@@ -15,7 +15,7 @@ function compile(source, options) {
15
15
  startRule,
16
16
  });
17
17
  const cache = {};
18
- const modified = transformScopeReferences(code, cache, enableCaching);
18
+ const modified = transformReferences(code, cache, enableCaching, macros);
19
19
  const fn = createExpressionFunction(modified);
20
20
  return fn;
21
21
  }
@@ -27,14 +27,34 @@ export function expression(source, options = {}) {
27
27
  });
28
28
  }
29
29
 
30
- // Transform any remaining undetermined references to scope references. At the
31
- // same time, transform those or explicit ops.scope calls to ops.external calls
32
- // unless they refer to local variables (variables defined by object literals or
33
- // lambda parameters).
34
- export function transformScopeReferences(
30
+ export function program(source, options = {}) {
31
+ return compile(source, {
32
+ ...options,
33
+ startRule: "program",
34
+ });
35
+ }
36
+
37
+ export function templateDocument(source, options = {}) {
38
+ return compile(source, {
39
+ ...options,
40
+ startRule: "templateDocument",
41
+ });
42
+ }
43
+
44
+ /**
45
+ * Transform any remaining undetermined references to scope references.
46
+ *
47
+ * At the same time, transform those or explicit ops.scope calls to ops.external
48
+ * calls unless they refer to local variables (variables defined by object
49
+ * literals or lambda parameters).
50
+ *
51
+ * Also apply any macros to the code.
52
+ */
53
+ export function transformReferences(
35
54
  code,
36
55
  cache,
37
56
  enableCaching,
57
+ macros,
38
58
  locals = {}
39
59
  ) {
40
60
  const [fn, ...args] = code;
@@ -45,7 +65,20 @@ export function transformScopeReferences(
45
65
  case ops.scope:
46
66
  const key = args[0];
47
67
  const normalizedKey = trailingSlash.remove(key);
48
- if (enableCaching && !locals[normalizedKey]) {
68
+ if (macros?.[normalizedKey]) {
69
+ // Apply macro
70
+ const macroBody = macros[normalizedKey];
71
+ const modified = transformReferences(
72
+ macroBody,
73
+ cache,
74
+ enableCaching,
75
+ macros,
76
+ locals
77
+ );
78
+ // @ts-ignore
79
+ annotate(modified, code.location);
80
+ return modified;
81
+ } else if (enableCaching && !locals[normalizedKey]) {
49
82
  // Upgrade to cached external reference
50
83
  const modified = [ops.external, key, cache];
51
84
  // @ts-ignore
@@ -87,10 +120,11 @@ export function transformScopeReferences(
87
120
  // be preferable to only descend into instructions. This would require
88
121
  // surrounding ops.lambda parameters with ops.literal, and ops.object
89
122
  // entries with ops.array.
90
- return transformScopeReferences(
123
+ return transformReferences(
91
124
  child,
92
125
  cache,
93
126
  enableCaching,
127
+ macros,
94
128
  updatedLocals
95
129
  );
96
130
  } else {
@@ -103,17 +137,3 @@ export function transformScopeReferences(
103
137
  }
104
138
  return modified;
105
139
  }
106
-
107
- export function program(source, options = {}) {
108
- return compile(source, {
109
- ...options,
110
- startRule: "program",
111
- });
112
- }
113
-
114
- export function templateDocument(source, options = {}) {
115
- return compile(source, {
116
- ...options,
117
- startRule: "templateDocument",
118
- });
119
- }
@@ -31,12 +31,12 @@ import {
31
31
 
32
32
  // A block of optional whitespace
33
33
  __
34
- = (inlineSpace / newLine / comment)* {
34
+ = whitespace* {
35
35
  return null;
36
36
  }
37
37
 
38
38
  additiveExpression
39
- = head:multiplicativeExpression tail:(__ @additiveOperator __ @multiplicativeExpression)* {
39
+ = head:multiplicativeExpression tail:(whitespace @additiveOperator whitespace @multiplicativeExpression)* {
40
40
  return annotate(tail.reduce(makeBinaryOperation, head), location());
41
41
  }
42
42
 
@@ -148,8 +148,8 @@ comment "comment"
148
148
 
149
149
  conditionalExpression
150
150
  = condition:logicalOrExpression tail:(__
151
- "?" __ @pipelineExpression __
152
- ":" __ @pipelineExpression)?
151
+ "?" __ @shorthandFunction __
152
+ ":" __ @shorthandFunction)?
153
153
  {
154
154
  if (!tail) {
155
155
  return condition;
@@ -310,7 +310,7 @@ multiLineComment
310
310
  = "/*" (!"*/" .)* "*/" { return null; }
311
311
 
312
312
  multiplicativeExpression
313
- = head:exponentiationExpression tail:(__ @multiplicativeOperator __ @exponentiationExpression)* {
313
+ = head:exponentiationExpression tail:(whitespace @multiplicativeOperator whitespace @exponentiationExpression)* {
314
314
  return annotate(tail.reduce(makeBinaryOperation, head), location());
315
315
  }
316
316
 
@@ -571,20 +571,17 @@ stringLiteral "string"
571
571
  // A top-level document defining a template. This is the same as a template
572
572
  // literal, but can contain backticks at the top level.
573
573
  templateDocument "template"
574
- = contents:templateDocumentContents {
575
- return annotate([ops.lambda, ["_"], contents], location());
574
+ = head:templateDocumentText tail:(templateSubstitution templateDocumentText)* {
575
+ return annotate(
576
+ [ops.lambda, ["_"], makeTemplate(ops.templateIndent, head, tail)],
577
+ location()
578
+ );
576
579
  }
577
580
 
578
581
  // Template documents can contain backticks at the top level.
579
582
  templateDocumentChar
580
583
  = !("${") @textChar
581
584
 
582
- // The contents of a template document containing plain text and substitutions
583
- templateDocumentContents
584
- = head:templateDocumentText tail:(templateSubstitution templateDocumentText)* {
585
- return annotate(makeTemplate(ops.template, head, tail), location());
586
- }
587
-
588
585
  templateDocumentText "template text"
589
586
  = chars:templateDocumentChar* {
590
587
  return chars.join("");
@@ -592,17 +589,13 @@ templateDocumentText "template text"
592
589
 
593
590
  // A backtick-quoted template literal
594
591
  templateLiteral "template literal"
595
- = "`" contents:templateLiteralContents "`" {
596
- return annotate(makeTemplate(ops.template, contents[0], contents[1]), location());
592
+ = "`" head:templateLiteralText tail:(templateSubstitution templateLiteralText)* "`" {
593
+ return annotate(makeTemplate(ops.template, head, tail), location());
597
594
  }
598
595
 
599
596
  templateLiteralChar
600
597
  = !("`" / "${") @textChar
601
598
 
602
- // The contents of a template literal containing plain text and substitutions
603
- templateLiteralContents
604
- = head:templateLiteralText tail:(templateSubstitution templateLiteralText)*
605
-
606
599
  // Plain text in a template literal
607
600
  templateLiteralText
608
601
  = chars:templateLiteralChar* {
@@ -632,5 +625,10 @@ unaryOperator
632
625
  / "-"
633
626
  / "~"
634
627
 
628
+ whitespace
629
+ = inlineSpace
630
+ / newLine
631
+ / comment
632
+
635
633
  whitespaceWithNewLine
636
634
  = inlineSpace* comment? newLine __