@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/context.js +28 -35
- package/lib/evaluate.js +503 -0
- package/lib/index.js +1 -1
- package/lib/match.js +470 -0
- package/lib/node.js +172 -43
- package/lib/source.js +2 -2
- package/lib/spans.js +31 -23
- package/lib/state.js +264 -49
- package/lib/utils/pattern.js +16 -13
- package/lib/utils/pump.js +20 -0
- package/package.json +7 -6
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
const buildFullRange = (node) => {
|
|
26
|
+
const sum = btree.getSum(node.children);
|
|
27
|
+
return sum ? [0, sum - 1] : null;
|
|
28
|
+
};
|
|
18
29
|
|
|
19
|
-
export const
|
|
20
|
-
static wrap(
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
27
|
-
|
|
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
|
|
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 =
|
|
39
|
-
|
|
84
|
+
const { node, transparent, childrenIndexRange } = states.get(this);
|
|
85
|
+
|
|
40
86
|
return {
|
|
41
87
|
*[Symbol.iterator]() {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
121
|
+
const { openTag } = this;
|
|
122
|
+
|
|
123
|
+
return openTag.type === OpenNodeTag ? openTag.value.flags : null;
|
|
58
124
|
}
|
|
59
125
|
|
|
60
126
|
get language() {
|
|
61
|
-
|
|
127
|
+
let { node } = states.get(this);
|
|
128
|
+
|
|
129
|
+
return node.language;
|
|
62
130
|
}
|
|
63
131
|
|
|
64
132
|
get type() {
|
|
65
|
-
|
|
133
|
+
let { node } = states.get(this);
|
|
134
|
+
|
|
135
|
+
return node.type;
|
|
66
136
|
}
|
|
67
137
|
|
|
68
138
|
get attributes() {
|
|
69
|
-
|
|
139
|
+
let { node } = states.get(this);
|
|
140
|
+
|
|
141
|
+
return node.attributes;
|
|
70
142
|
}
|
|
71
143
|
|
|
72
144
|
get openTag() {
|
|
73
|
-
|
|
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
|
-
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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) ||
|
|
88
|
-
? node
|
|
191
|
+
(ref && ref.type === ReferenceTag && !ref.value.flags.hasGap) || transparent
|
|
192
|
+
? binding.node
|
|
89
193
|
: buildStubNode(buildGapTag());
|
|
90
194
|
|
|
91
|
-
return
|
|
195
|
+
return isNullNode(node_) ? null : FragmentFacade.wrap(node_, context, transparent);
|
|
92
196
|
}
|
|
93
197
|
|
|
94
198
|
has(path) {
|
|
95
|
-
return hasOwn(
|
|
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(
|
|
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
|
-
|
|
9
|
+
if (refPath && refPath.tag.type !== ReferenceTag) throw new Error();
|
|
8
10
|
|
|
9
|
-
const
|
|
11
|
+
const openTag = getOpenTag(node);
|
|
10
12
|
|
|
11
|
-
const intrinsic =
|
|
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(
|
|
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:
|