@weborigami/language 0.1.0 → 0.2.1

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 CHANGED
@@ -12,6 +12,7 @@ export type Code = Array<any> & {
12
12
  start: Position;
13
13
  end: Position;
14
14
  };
15
+ source: string;
15
16
  };
16
17
 
17
18
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weborigami/language",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Web Origami expression language compiler and runtime",
5
5
  "type": "module",
6
6
  "main": "./main.js",
@@ -8,15 +8,17 @@
8
8
  "devDependencies": {
9
9
  "@types/node": "22.7.4",
10
10
  "peggy": "4.0.3",
11
- "typescript": "5.6.2"
11
+ "typescript": "5.6.2",
12
+ "yaml": "2.5.1"
12
13
  },
13
14
  "dependencies": {
14
- "@weborigami/async-tree": "0.1.0",
15
- "@weborigami/types": "0.1.0",
15
+ "@weborigami/async-tree": "0.2.1",
16
+ "@weborigami/types": "0.2.1",
16
17
  "watcher": "2.3.1"
17
18
  },
18
19
  "scripts": {
19
20
  "build": "peggy --allowed-start-rules=\"*\" --format es src/compiler/origami.pegjs --output src/compiler/parse.js",
21
+ "buildTests": "node ./test/generator/generateTests.js",
20
22
  "prepublishOnly": "npm run build",
21
23
  "test": "node --test --test-reporter=spec",
22
24
  "typecheck": "tsc"
@@ -2,11 +2,11 @@ import { trailingSlash } from "@weborigami/async-tree";
2
2
  import { createExpressionFunction } from "../runtime/expressionFunction.js";
3
3
  import { ops } from "../runtime/internal.js";
4
4
  import { parse } from "./parse.js";
5
- import { annotate } from "./parserHelpers.js";
5
+ import { annotate, undetermined } from "./parserHelpers.js";
6
6
 
7
7
  function compile(source, options) {
8
8
  const { startRule } = options;
9
- const scopeCaching = options.scopeCaching ?? true;
9
+ const enableCaching = options.scopeCaching ?? true;
10
10
  if (typeof source === "string") {
11
11
  source = { text: source };
12
12
  }
@@ -15,9 +15,7 @@ function compile(source, options) {
15
15
  startRule,
16
16
  });
17
17
  const cache = {};
18
- const modified = scopeCaching
19
- ? cacheExternalScopeReferences(code, cache)
20
- : code;
18
+ const modified = transformScopeReferences(code, cache, enableCaching);
21
19
  const fn = createExpressionFunction(modified);
22
20
  return fn;
23
21
  }
@@ -29,24 +27,39 @@ export function expression(source, options = {}) {
29
27
  });
30
28
  }
31
29
 
32
- // Given code containing ops.scope calls, upgrade them to ops.cache calls unless
33
- // they refer to local variables: variables defined by object literals or lambda
34
- // parameters.
35
- export function cacheExternalScopeReferences(code, cache, locals = {}) {
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(
35
+ code,
36
+ cache,
37
+ enableCaching,
38
+ locals = {}
39
+ ) {
36
40
  const [fn, ...args] = code;
37
41
 
38
42
  let additionalLocalNames;
39
43
  switch (fn) {
44
+ case undetermined:
40
45
  case ops.scope:
41
46
  const key = args[0];
42
47
  const normalizedKey = trailingSlash.remove(key);
43
- if (locals[normalizedKey]) {
44
- return code;
45
- } else {
46
- // Upgrade to cached scope lookup
47
- const modified = [ops.cache, key, cache];
48
+ if (enableCaching && !locals[normalizedKey]) {
49
+ // Upgrade to cached external reference
50
+ const modified = [ops.external, key, cache];
51
+ // @ts-ignore
52
+ annotate(modified, code.location);
53
+ return modified;
54
+ } else if (fn === undetermined) {
55
+ // Transform undetermined reference to regular scope call
56
+ const modified = [ops.scope, key];
57
+ // @ts-ignore
48
58
  annotate(modified, code.location);
49
59
  return modified;
60
+ } else {
61
+ // Internal ops.scope call; leave as is
62
+ return code;
50
63
  }
51
64
 
52
65
  case ops.lambda:
@@ -74,7 +87,12 @@ export function cacheExternalScopeReferences(code, cache, locals = {}) {
74
87
  // be preferable to only descend into instructions. This would require
75
88
  // surrounding ops.lambda parameters with ops.literal, and ops.object
76
89
  // entries with ops.array.
77
- return cacheExternalScopeReferences(child, cache, updatedLocals);
90
+ return transformScopeReferences(
91
+ child,
92
+ cache,
93
+ enableCaching,
94
+ updatedLocals
95
+ );
78
96
  } else {
79
97
  return child;
80
98
  }