@bablr/bablr-vm 0.18.1 → 0.19.0

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/lib/node.js CHANGED
@@ -1,97 +1,226 @@
1
- import { parsePath } from '@bablr/agast-helpers/path';
2
- import { ReferenceTag } from '@bablr/agast-helpers/symbols';
3
1
  import {
2
+ buildCloseNodeTag,
4
3
  buildGapTag,
4
+ buildOpenNodeTag,
5
+ buildReferenceTag,
5
6
  buildStubNode,
6
- get,
7
- getCloseTag,
8
- getOpenTag,
7
+ isFragmentNode,
8
+ isNullNode,
9
+ parseReference,
10
+ referenceFlags,
9
11
  } from '@bablr/agast-helpers/tree';
12
+ import { getStreamIterator } from '@bablr/agast-helpers/stream';
13
+ import { agast } from '@bablr/agast-vm';
10
14
  import * as btree from '@bablr/agast-helpers/btree';
15
+ import { Pump } from './utils/pump.js';
16
+ import { OpenNodeTag, ReferenceTag } from '@bablr/agast-helpers/symbols';
17
+ import { get, getProperties } from '@bablr/agast-helpers/path';
18
+ import { isArray } from '@bablr/helpers/object';
19
+
20
+ export const states = new WeakMap();
21
+ export const internalStates = new WeakMap();
11
22
 
12
23
  const { hasOwn } = Object;
13
24
 
14
- export const contexts = new WeakMap();
15
- export const actuals = new WeakMap();
16
- // eslint-disable-next-line no-undef
17
- export const transparentFacades = new WeakSet();
25
+ const buildFullRange = (node) => {
26
+ const sum = btree.getSum(node.children);
27
+ return sum ? [0, sum - 1] : null;
28
+ };
18
29
 
19
- export const NodeFacade = class BABLRNodeFacade {
20
- static wrap(node, context, transparent) {
21
- if (!node || !context) throw new Error();
22
- return node && new NodeFacade(node, context, transparent);
30
+ export const FragmentFacade = class BABLRFragmentFacade {
31
+ static wrap(
32
+ node,
33
+ context,
34
+ transparent = false,
35
+ childrenIndexRange = node && buildFullRange(node),
36
+ dotPropertyName = null,
37
+ dotPropertyIndex = null,
38
+ ) {
39
+ return (
40
+ node &&
41
+ new FragmentFacade(
42
+ node,
43
+ context,
44
+ transparent,
45
+ childrenIndexRange,
46
+ dotPropertyName,
47
+ dotPropertyIndex,
48
+ )
49
+ );
23
50
  }
24
51
 
25
- constructor(node, context, transparent) {
26
- actuals.set(this, node);
27
- contexts.set(this, context);
28
- if (transparent) {
29
- transparentFacades.add(this);
52
+ constructor(node, context, transparent, childrenIndexRange, dotPropertyName, dotPropertyIndex) {
53
+ if (childrenIndexRange && (childrenIndexRange[0] == null || !childrenIndexRange[1] == null)) {
54
+ throw new Error();
30
55
  }
56
+
57
+ if (!context) throw new Error();
58
+
59
+ if (dotPropertyName && !hasOwn(node.properties, dotPropertyName)) throw new Error();
60
+
61
+ if (isArray(node.properties[dotPropertyName]) && dotPropertyIndex == null) throw new Error();
62
+
63
+ states.set(this, {
64
+ context,
65
+ openTag: buildOpenNodeTag(),
66
+ closeTag: buildCloseNodeTag(),
67
+ node,
68
+ transparent,
69
+ childrenIndexRange,
70
+ dotPropertyName,
71
+ dotPropertyIndex,
72
+ });
31
73
  }
32
74
 
33
75
  get isTransparent() {
34
- return transparentFacades.has(this);
76
+ return states.get(this).transparent;
77
+ }
78
+
79
+ get isFragmentNode() {
80
+ return isFragmentNode(states.get(this).node);
35
81
  }
36
82
 
37
83
  get children() {
38
- const node = actuals.get(this);
39
- const isTransparent = transparentFacades.has(this);
84
+ const { node, transparent, childrenIndexRange } = states.get(this);
85
+
40
86
  return {
41
87
  *[Symbol.iterator]() {
42
- if (isTransparent) {
43
- yield* btree.traverse(node.children);
44
- } else {
45
- for (const child of btree.traverse(node.children)) {
46
- const interpolated = false; // TODO
47
- if (!interpolated) {
48
- yield child;
49
- }
88
+ for (let i = childrenIndexRange[0]; i <= childrenIndexRange[1]; i++) {
89
+ const interpolated = false; // TODO
90
+ if (!interpolated || transparent) {
91
+ yield btree.getAt(i, node.children);
50
92
  }
51
93
  }
52
94
  },
53
95
  };
54
96
  }
55
97
 
98
+ getRootIndex() {
99
+ const { node, dotPropertyName, childrenIndexRange } = states.get(this);
100
+
101
+ if (!childrenIndexRange) return null;
102
+
103
+ if (childrenIndexRange[0] > childrenIndexRange[1]) throw new Error();
104
+
105
+ for (let i = childrenIndexRange[0]; i <= childrenIndexRange[1]; i++) {
106
+ let tag = btree.getAt(i, node.children);
107
+ if (tag.type === ReferenceTag) {
108
+ const { name, isArray } = tag.value;
109
+ let resolvedTagName = name === '.' ? dotPropertyName : name;
110
+
111
+ if (resolvedTagName === dotPropertyName) {
112
+ return i;
113
+ }
114
+ }
115
+ }
116
+
117
+ return null;
118
+ }
119
+
56
120
  get flags() {
57
- return actuals.get(this).flags;
121
+ const { openTag } = this;
122
+
123
+ return openTag.type === OpenNodeTag ? openTag.value.flags : null;
58
124
  }
59
125
 
60
126
  get language() {
61
- return actuals.get(this).language;
127
+ let { node } = states.get(this);
128
+
129
+ return node.language;
62
130
  }
63
131
 
64
132
  get type() {
65
- return actuals.get(this).type;
133
+ let { node } = states.get(this);
134
+
135
+ return node.type;
66
136
  }
67
137
 
68
138
  get attributes() {
69
- return actuals.get(this).attributes;
139
+ let { node } = states.get(this);
140
+
141
+ return node.attributes;
70
142
  }
71
143
 
72
144
  get openTag() {
73
- return getOpenTag(actuals.get(this));
145
+ const state = states.get(this);
146
+ const { children } = state.node;
147
+
148
+ return state.openTag || btree.getAt(0, children);
74
149
  }
75
150
 
76
151
  get closeTag() {
77
- return getCloseTag(actuals.get(this));
152
+ const state = states.get(this);
153
+ const { children } = state.node;
154
+
155
+ return state.closeTag || btree.getAt(btree.getSum(children) - 1, children);
78
156
  }
79
157
 
80
158
  get(path) {
81
- const context = contexts.get(this);
82
- const node = get(actuals.get(this), path);
83
- const isTransparent = transparentFacades.has(this);
159
+ let {
160
+ node,
161
+ context,
162
+ transparent,
163
+ dotPropertyName,
164
+ dotPropertyIndex: dotIndex,
165
+ } = states.get(this);
166
+ // let { path: nodePath } = internalStates.get(node);
167
+ const parsedRef = parseReference(path);
168
+ // const resolvedPath = resolvePath(node, path);
169
+ // const childNode = getAtPath(resolvedPath, node);
170
+
171
+ // array resolve
172
+
173
+ if (dotPropertyName) {
174
+ let dotReference = buildReferenceTag(
175
+ dotPropertyName,
176
+ dotIndex != null,
177
+ referenceFlags,
178
+ dotIndex,
179
+ );
180
+
181
+ node = get(dotReference, node);
182
+ }
183
+
184
+ const binding = getProperties(parsedRef, node.properties);
185
+
186
+ if (!binding) return null;
187
+
188
+ const ref = binding.reference;
84
189
 
85
- const ref = node && context.agast.getPreviousTag(btree.getAt(0, node.children));
86
190
  const node_ =
87
- (ref && ref.type === ReferenceTag && !ref.value.hasGap) || isTransparent
88
- ? node
191
+ (ref && ref.type === ReferenceTag && !ref.value.flags.hasGap) || transparent
192
+ ? binding.node
89
193
  : buildStubNode(buildGapTag());
90
194
 
91
- return node && NodeFacade.wrap(node_, context, isTransparent);
195
+ return isNullNode(node_) ? null : FragmentFacade.wrap(node_, context, transparent);
92
196
  }
93
197
 
94
198
  has(path) {
95
- return hasOwn(actuals.get(this).properties, parsePath(path).name);
199
+ return hasOwn(states.get(this).node.properties, parseReference(path).value.name);
96
200
  }
97
201
  };
202
+
203
+ Object.seal(FragmentFacade);
204
+
205
+ export const buildInternalState = () => {
206
+ let instructionsPump = new Pump();
207
+ let expressionsPump = new Pump();
208
+ let agastState = null;
209
+ let agast_ = getStreamIterator(
210
+ agast(
211
+ (ctx, s) => {
212
+ agastState = s;
213
+ return instructionsPump;
214
+ },
215
+ { expressions: expressionsPump },
216
+ ),
217
+ );
218
+ let internalState = {
219
+ instructionsPump,
220
+ expressionsPump,
221
+ agastState,
222
+ agast: agast_,
223
+ path: agastState.path,
224
+ };
225
+ return internalState;
226
+ };
package/lib/source.js CHANGED
@@ -187,8 +187,8 @@ export const Source = class BABLRSource extends WeakStackFrame {
187
187
  return Source.create(exchange.allocateFork(), exchange);
188
188
  }
189
189
 
190
- constructor(fork, exchange, index = -1, holding = false) {
191
- super();
190
+ constructor(parent, fork, exchange, index = -1, holding = false) {
191
+ super(parent);
192
192
 
193
193
  if (!fork || !exchange) throw new Error();
194
194
 
package/lib/spans.js CHANGED
@@ -1,14 +1,16 @@
1
1
  import { ReferenceTag } from '@bablr/agast-helpers/symbols';
2
2
  import { getOpenTag } from '@bablr/agast-helpers/tree';
3
3
 
4
- export function updateSpans(ctx, s, node, phase) {
4
+ export function updateSpans(m, node, phase) {
5
+ const { state: s } = m;
5
6
  const { flags, attributes } = node;
7
+ const refPath = m.reference;
6
8
 
7
- const openTag = getOpenTag(node);
9
+ if (refPath && refPath.tag.type !== ReferenceTag) throw new Error();
8
10
 
9
- const ref = ctx.agast.getPreviousTag(openTag);
11
+ const openTag = getOpenTag(node);
10
12
 
11
- const intrinsic = ref.type === ReferenceTag && !ref.hasGap;
13
+ const intrinsic = !refPath || (refPath.tag.type === ReferenceTag && !refPath.tag.value.hasGap);
12
14
 
13
15
  switch (phase) {
14
16
  case 'open': {
@@ -24,51 +26,52 @@ export function updateSpans(ctx, s, node, phase) {
24
26
  s.spans = s.spans.push({
25
27
  type: 'Explicit',
26
28
  name: openSpan,
27
- path: s.path,
28
29
  guard: null,
29
30
  });
30
31
  }
31
32
 
32
- if (balancer) {
33
- const balancedNode = s.balanced.value;
34
-
35
- if (!s.balanced.size) throw new Error();
36
-
37
- if (!balancedNode.attributes.balanced) {
38
- throw new Error();
39
- }
40
-
41
- s.balanced = s.balanced.pop();
42
-
43
- s.spans = s.spans.pop();
44
- }
45
-
46
33
  if (innerSpan) {
47
34
  s.spans = s.spans.push({
48
35
  type: 'Inner',
49
36
  name: innerSpan,
50
- path: s.path,
51
37
  guard: null,
52
38
  });
53
39
  }
54
40
 
41
+ if (m.language !== m.parent.language) {
42
+ s.spans = s.spans.push({ name: 'Bare' });
43
+ }
44
+
55
45
  break;
56
46
  }
57
47
 
58
48
  case 'close': {
59
- const { balancedSpan, span: innerSpan, closeSpan, balanced } = attributes || {};
49
+ const { balancedSpan, span: innerSpan, closeSpan, balanced, balancer } = attributes || {};
60
50
 
61
51
  if (balanced) {
62
- s.balanced = s.balanced.push(s.nodeForTag(s.result));
52
+ s.balanced = s.balanced.push(node);
63
53
 
64
54
  s.spans = s.spans.push({
65
55
  type: 'Lexical',
66
56
  name: balancedSpan || s.span.name,
67
- path: s.path,
68
57
  guard: balanced === true ? null : balanced,
69
58
  });
70
59
  }
71
60
 
61
+ if (balancer) {
62
+ const balancedNode = s.balanced.value;
63
+
64
+ if (!s.balanced.size) throw new Error();
65
+
66
+ if (!balancedNode.attributes.balanced) {
67
+ throw new Error();
68
+ }
69
+
70
+ s.balanced = s.balanced.pop();
71
+
72
+ s.spans = s.spans.pop();
73
+ }
74
+
72
75
  if (closeSpan) {
73
76
  if (s.spans.value.type !== 'Explicit') throw new Error();
74
77
  s.spans = s.spans.pop();
@@ -77,6 +80,11 @@ export function updateSpans(ctx, s, node, phase) {
77
80
  if (innerSpan) {
78
81
  s.spans = s.spans.pop();
79
82
  }
83
+
84
+ if (m.language !== m.parent.language) {
85
+ s.spans = s.spans.pop();
86
+ }
87
+
80
88
  break;
81
89
  }
82
90
  default: