astronomical 1.0.0-beta.13 → 1.0.0-beta.14

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/cjs/index.js CHANGED
@@ -1,32 +1,13 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
4
  };
25
5
  Object.defineProperty(exports, "__esModule", { value: true });
26
6
  exports.parseSource = exports.multiQuery = exports.query = exports.isAvailableFunction = exports.functions = void 0;
27
- const traverse_1 = __importStar(require("./traverse"));
7
+ const traverse_1 = __importDefault(require("./traverse"));
28
8
  const parseQuery_1 = require("./parseQuery");
29
9
  const meriyah_1 = require("meriyah");
10
+ const nodeutils_1 = require("./nodeutils");
30
11
  const debugLogEnabled = false;
31
12
  const log = {
32
13
  debug: (...args) => {
@@ -83,10 +64,6 @@ function isAvailableFunction(name) {
83
64
  return functionNames.includes(name);
84
65
  }
85
66
  exports.isAvailableFunction = isAvailableFunction;
86
- function beginHandle(queries, path) {
87
- const rootPath = (0, traverse_1.createNodePath)(path, undefined, undefined, undefined);
88
- return travHandle(queries, rootPath);
89
- }
90
67
  function breadCrumb(path) {
91
68
  return {
92
69
  valueOf() {
@@ -96,354 +73,369 @@ function breadCrumb(path) {
96
73
  }
97
74
  };
98
75
  }
99
- function createFilter(filter, filterResult) {
100
- if (filter.type == "and" || filter.type == "or" || filter.type == "equals") {
101
- return {
102
- type: filter.type,
103
- left: createFilter(filter.left, []),
104
- right: createFilter(filter.right, [])
105
- };
76
+ function createQuerier() {
77
+ const traverser = (0, traverse_1.default)();
78
+ const { getChildren, getBinding, createNodePath, traverse } = traverser;
79
+ function createFilter(filter, filterResult) {
80
+ if (filter.type == "and" || filter.type == "or" || filter.type == "equals") {
81
+ return {
82
+ type: filter.type,
83
+ left: createFilter(filter.left, []),
84
+ right: createFilter(filter.right, [])
85
+ };
86
+ }
87
+ else if (filter.type == "literal") {
88
+ const r = [filter.value];
89
+ return {
90
+ node: filter,
91
+ result: r
92
+ };
93
+ }
94
+ return createFNode(filter, filterResult);
106
95
  }
107
- else if (filter.type == "literal") {
108
- const r = [filter.value];
96
+ function createFNode(token, result) {
109
97
  return {
110
- node: filter,
111
- result: r
98
+ node: token,
99
+ result: result
112
100
  };
113
101
  }
114
- return createFNode(filter, filterResult);
115
- }
116
- function createFNode(token, result) {
117
- return {
118
- node: token,
119
- result: result
120
- };
121
- }
122
- function addFilterChildrenToState(filter, state) {
123
- if ("type" in filter && (filter.type == "and" || filter.type == "or" || filter.type == "equals")) {
124
- addFilterChildrenToState(filter.left, state);
125
- addFilterChildrenToState(filter.right, state);
126
- }
127
- else if ("node" in filter) {
128
- if (filter.node.type == "child") {
129
- log.debug("ADDING FILTER CHILD", filter.node);
130
- state.child[state.depth + 1].push(filter);
102
+ function addFilterChildrenToState(filter, state) {
103
+ if ("type" in filter && (filter.type == "and" || filter.type == "or" || filter.type == "equals")) {
104
+ addFilterChildrenToState(filter.left, state);
105
+ addFilterChildrenToState(filter.right, state);
131
106
  }
132
- if (filter.node.type == "descendant") {
133
- log.debug("ADDING FILTER DESCENDANT", filter.node);
134
- state.descendant[state.depth + 1].push(filter);
107
+ else if ("node" in filter) {
108
+ if (filter.node.type == "child") {
109
+ log.debug("ADDING FILTER CHILD", filter.node);
110
+ state.child[state.depth + 1].push(filter);
111
+ }
112
+ if (filter.node.type == "descendant") {
113
+ log.debug("ADDING FILTER DESCENDANT", filter.node);
114
+ state.descendant[state.depth + 1].push(filter);
115
+ }
135
116
  }
136
117
  }
137
- }
138
- function createFNodeAndAddToState(token, result, state) {
139
- log.debug("ADDING FNODE", token);
140
- const fnode = createFNode(token, result);
141
- if (token.type == "child") {
142
- state.child[state.depth + 1].push(fnode);
143
- }
144
- else if (token.type == "descendant") {
145
- state.descendant[state.depth + 1].push(fnode);
118
+ function createFNodeAndAddToState(token, result, state) {
119
+ log.debug("ADDING FNODE", token);
120
+ const fnode = createFNode(token, result);
121
+ if (token.type == "child") {
122
+ state.child[state.depth + 1].push(fnode);
123
+ }
124
+ else if (token.type == "descendant") {
125
+ state.descendant[state.depth + 1].push(fnode);
126
+ }
127
+ return fnode;
146
128
  }
147
- return fnode;
148
- }
149
- function isMatch(fnode, path) {
150
- if (fnode.node.attribute) {
151
- const m = fnode.node.value == path.parentKey || fnode.node.value == path.key;
129
+ function isMatch(fnode, path) {
130
+ if (fnode.node.attribute) {
131
+ const m = fnode.node.value == path.parentKey || fnode.node.value == path.key;
132
+ if (m)
133
+ log.debug("ATTR MATCH", fnode.node.value, breadCrumb(path));
134
+ return m;
135
+ }
136
+ if (fnode.node.value == "*") {
137
+ return true;
138
+ }
139
+ const m = fnode.node.value == path.node.type;
152
140
  if (m)
153
- log.debug("ATTR MATCH", fnode.node.value, breadCrumb(path));
141
+ log.debug("NODE MATCH", fnode.node.value, breadCrumb(path));
154
142
  return m;
155
143
  }
156
- if (fnode.node.value == "*") {
157
- return true;
158
- }
159
- const m = fnode.node.value == path.node.type;
160
- if (m)
161
- log.debug("NODE MATCH", fnode.node.value, breadCrumb(path));
162
- return m;
163
- }
164
- function addIfTokenMatch(fnode, path, state) {
165
- if (!isMatch(fnode, path))
166
- return;
167
- state.matches[state.depth].push([fnode, path]);
168
- if (fnode.node.filter) {
169
- const filter = createFilter(fnode.node.filter, []);
170
- const filteredResult = [];
171
- state.filters[state.depth].push({ filter: filter, qNode: fnode.node, node: path.node, result: filteredResult });
172
- addFilterChildrenToState(filter, state);
173
- const child = fnode.node.child;
174
- if (child) {
175
- if (child.type == "function") {
144
+ function addIfTokenMatch(fnode, path, state) {
145
+ if (!isMatch(fnode, path))
146
+ return;
147
+ state.matches[state.depth].push([fnode, path]);
148
+ if (fnode.node.filter) {
149
+ const filter = createFilter(fnode.node.filter, []);
150
+ const filteredResult = [];
151
+ state.filters[state.depth].push({ filter: filter, qNode: fnode.node, node: path.node, result: filteredResult });
152
+ addFilterChildrenToState(filter, state);
153
+ const child = fnode.node.child;
154
+ if (child) {
155
+ if (child.type == "function") {
156
+ const fr = addFunction(fnode, child, path, state);
157
+ state.functionCalls[state.depth].push(fr);
158
+ }
159
+ else {
160
+ createFNodeAndAddToState(child, filteredResult, state);
161
+ }
162
+ }
163
+ }
164
+ else {
165
+ const child = fnode.node.child;
166
+ if (child?.type == "function") {
176
167
  const fr = addFunction(fnode, child, path, state);
177
168
  state.functionCalls[state.depth].push(fr);
178
169
  }
179
- else {
180
- createFNodeAndAddToState(child, filteredResult, state);
170
+ else if (child && !fnode.node.binding && !fnode.node.resolve) {
171
+ createFNodeAndAddToState(child, fnode.result, state);
181
172
  }
182
173
  }
183
174
  }
184
- else {
185
- const child = fnode.node.child;
186
- if (child?.type == "function") {
187
- const fr = addFunction(fnode, child, path, state);
188
- state.functionCalls[state.depth].push(fr);
189
- }
190
- else if (child && !fnode.node.binding && !fnode.node.resolve) {
191
- createFNodeAndAddToState(child, fnode.result, state);
192
- }
193
- }
194
- }
195
- function addFunction(rootNode, functionCall, path, state) {
196
- const functionNode = { node: rootNode.node, functionCall: functionCall, parameters: [], result: [] };
197
- for (const param of functionCall.parameters) {
198
- if (param.type == "literal") {
199
- functionNode.parameters.push({ node: param, result: [param.value] });
200
- }
201
- else {
202
- if (param.type == "function") {
203
- functionNode.parameters.push(addFunction(functionNode, param, path, state));
175
+ function addFunction(rootNode, functionCall, path, state) {
176
+ const functionNode = { node: rootNode.node, functionCall: functionCall, parameters: [], result: [] };
177
+ for (const param of functionCall.parameters) {
178
+ if (param.type == "literal") {
179
+ functionNode.parameters.push({ node: param, result: [param.value] });
204
180
  }
205
181
  else {
206
- functionNode.parameters.push(createFNodeAndAddToState(param, [], state));
182
+ if (param.type == "function") {
183
+ functionNode.parameters.push(addFunction(functionNode, param, path, state));
184
+ }
185
+ else {
186
+ functionNode.parameters.push(createFNodeAndAddToState(param, [], state));
187
+ }
207
188
  }
208
189
  }
190
+ return functionNode;
209
191
  }
210
- return functionNode;
211
- }
212
- function isPrimitive(value) {
213
- return typeof value == "string" || typeof value == "number" || typeof value == "boolean";
214
- }
215
- function addPrimitiveAttributeIfMatch(fnode, path) {
216
- if (!fnode.node.attribute || !fnode.node.value)
217
- return;
218
- if (fnode.node.child || fnode.node.filter)
219
- return;
220
- if (!Object.hasOwn(path.node, fnode.node.value))
221
- return;
222
- const lookup = (0, traverse_1.getChildren)(fnode.node.value, path);
223
- const nodes = (Array.isArray(lookup) ? lookup : [lookup])
224
- .filter(n => n.node != undefined)
225
- .filter(n => isPrimitive(n.node));
226
- if (nodes.length == 0)
227
- return;
228
- log.debug("PRIMITIVE", fnode.node.value, nodes.map(n => n.node));
229
- fnode.result.push(...nodes.map(n => n.node));
230
- }
231
- function evaluateFilter(filter, path) {
232
- log.debug("EVALUATING FILTER", filter, breadCrumb(path));
233
- if ("type" in filter) {
234
- if (filter.type == "and") {
235
- const left = evaluateFilter(filter.left, path);
236
- if (left.length == 0)
237
- return [];
238
- return evaluateFilter(filter.right, path);
239
- }
240
- if (filter.type == "or") {
241
- const left = evaluateFilter(filter.left, path);
242
- if (left.length > 0)
243
- return left;
244
- return evaluateFilter(filter.right, path);
192
+ function addPrimitiveAttributeIfMatch(fnode, path) {
193
+ if (!fnode.node.attribute || !fnode.node.value)
194
+ return;
195
+ if (fnode.node.child || fnode.node.filter)
196
+ return;
197
+ if (!Object.hasOwn(path.node, fnode.node.value))
198
+ return;
199
+ const lookup = getChildren(fnode.node.value, path);
200
+ const nodes = toArray(lookup)
201
+ .filter(n => n.node != undefined)
202
+ .filter(n => (0, nodeutils_1.isPrimitive)(n.node));
203
+ if (nodes.length == 0)
204
+ return;
205
+ log.debug("PRIMITIVE", fnode.node.value, nodes.map(n => n.node));
206
+ fnode.result.push(...nodes.map(n => n.node));
207
+ }
208
+ function evaluateFilter(filter, path) {
209
+ log.debug("EVALUATING FILTER", filter, breadCrumb(path));
210
+ if ("type" in filter) {
211
+ if (filter.type == "and") {
212
+ const left = evaluateFilter(filter.left, path);
213
+ if (left.length == 0)
214
+ return [];
215
+ return evaluateFilter(filter.right, path);
216
+ }
217
+ if (filter.type == "or") {
218
+ const left = evaluateFilter(filter.left, path);
219
+ if (left.length > 0)
220
+ return left;
221
+ return evaluateFilter(filter.right, path);
222
+ }
223
+ if (filter.type == "equals") {
224
+ const left = evaluateFilter(filter.left, path);
225
+ const right = evaluateFilter(filter.right, path);
226
+ return left.filter(x => right.includes(x));
227
+ }
228
+ throw new Error("Unknown filter type: " + filter.type);
245
229
  }
246
- if (filter.type == "equals") {
247
- const left = evaluateFilter(filter.left, path);
248
- const right = evaluateFilter(filter.right, path);
249
- return left.filter(x => right.includes(x));
230
+ if (filter.node.type == "parent") {
231
+ return resolveFilterWithParent(filter.node, path);
250
232
  }
251
- throw new Error("Unknown filter type: " + filter.type);
233
+ return filter.result;
252
234
  }
253
- if (filter.node.type == "parent") {
254
- return resolveFilterWithParent(filter.node, path);
235
+ function resolveBinding(path) {
236
+ if (!(0, nodeutils_1.isIdentifier)(path.node))
237
+ return undefined;
238
+ log.debug("RESOLVING BINDING FOR ", path.node);
239
+ const name = path.node.name;
240
+ if (name == undefined || typeof name != "string")
241
+ return undefined;
242
+ //const binding = path.scope.getBinding(name);
243
+ const binding = getBinding(path.scopeId, name);
244
+ if (!binding)
245
+ return undefined;
246
+ log.debug("THIS IS THE BINDING", binding);
247
+ return binding.path;
255
248
  }
256
- return filter.result;
257
- }
258
- function isIdentifier(node) {
259
- return node.type == "Identifier";
260
- }
261
- function resolveBinding(path) {
262
- if (!isIdentifier(path.node))
263
- return undefined;
264
- log.debug("RESOLVING BINDING FOR ", path.node);
265
- const name = path.node.name;
266
- if (name == undefined || typeof name != "string")
267
- return undefined;
268
- //const binding = path.scope.getBinding(name);
269
- const binding = (0, traverse_1.getBinding)(path.scopeId, name);
270
- if (!binding)
271
- return undefined;
272
- log.debug("THIS IS THE BINDING", binding);
273
- return binding.path;
274
- }
275
- function resolveFilterWithParent(node, path) {
276
- let startNode = node;
277
- let startPath = path;
278
- while (startNode.type == "parent") {
279
- if (!startNode.child)
280
- throw new Error("Parent filter must have child");
281
- if (!startPath.parentPath)
282
- return [];
283
- log.debug("STEP OUT", startNode, breadCrumb(startPath));
284
- startNode = startNode.child;
285
- startPath = startPath.parentPath;
249
+ function resolveFilterWithParent(node, path) {
250
+ let startNode = node;
251
+ let startPath = path;
252
+ while (startNode.type == "parent") {
253
+ if (!startNode.child)
254
+ throw new Error("Parent filter must have child");
255
+ if (!startPath.parentPath)
256
+ return [];
257
+ log.debug("STEP OUT", startNode, breadCrumb(startPath));
258
+ startNode = startNode.child;
259
+ startPath = startPath.parentPath;
260
+ }
261
+ return resolveDirectly(startNode, startPath);
286
262
  }
287
- return resolveDirectly(startNode, startPath);
288
- }
289
- const toArray = (value) => Array.isArray(value) ? value : [value];
290
- function isDefined(value) {
291
- return value != undefined && value != null;
292
- }
293
- let subQueryCounter = 0;
294
- function resolveDirectly(node, path) {
295
- let startNode = node;
296
- const startPath = path;
297
- let paths = [startPath];
298
- while (startNode.attribute && startNode.type == "child") {
299
- const lookup = startNode.value;
300
- if (!lookup)
301
- throw new Error("Selector must have a value");
302
- log.debug("STEP IN ", lookup, paths.map(p => breadCrumb(p)));
303
- const nodes = paths.map(n => (0, traverse_1.getChildren)(lookup, n)).map(toArray).flat().filter(n => n.node != undefined);
304
- log.debug("LOOKUP", lookup, path.node.type, nodes.map(n => n.node), nodes.filter(n => n.node == undefined));
305
- if (nodes.length == 0)
306
- return [];
307
- paths = nodes;
308
- if (startNode.resolve) {
309
- const resolved = paths.map(p => resolveBinding(p)).filter(isDefined).map(p => (0, traverse_1.getChildren)("init", p)).flatMap(toArray).filter(p => p.node != undefined).filter(isDefined);
310
- if (resolved.length > 0)
311
- paths = resolved;
263
+ const toArray = (value) => Array.isArray(value) ? value : [value];
264
+ function isDefined(value) {
265
+ return value != undefined && value != null;
266
+ }
267
+ let subQueryCounter = 0;
268
+ function resolveDirectly(node, path) {
269
+ let startNode = node;
270
+ const startPath = path;
271
+ let paths = [startPath];
272
+ while (startNode.attribute && startNode.type == "child") {
273
+ const lookup = startNode.value;
274
+ if (!lookup)
275
+ throw new Error("Selector must have a value");
276
+ log.debug("STEP IN ", lookup, paths.map(p => breadCrumb(p)));
277
+ const nodes = paths.map(n => getChildren(lookup, n)).map(toArray).flat().filter(n => n.node != undefined);
278
+ log.debug("LOOKUP", lookup, path.node.type, nodes.map(n => n.node), nodes.filter(n => n.node == undefined));
279
+ if (nodes.length == 0)
280
+ return [];
281
+ paths = nodes;
282
+ if (startNode.resolve) {
283
+ const resolved = paths.map(p => resolveBinding(p)).filter(isDefined).map(p => getChildren("init", p)).flatMap(toArray).filter(p => p.node != undefined).filter(isDefined);
284
+ if (resolved.length > 0)
285
+ paths = resolved;
286
+ }
287
+ else if (startNode.binding) {
288
+ paths = paths.map(p => resolveBinding(p)).filter(isDefined);
289
+ }
290
+ const filter = startNode.filter;
291
+ if (filter) {
292
+ paths = paths.filter(p => travHandle({ subquery: filter }, p).subquery.length > 0);
293
+ }
294
+ if (!startNode.child) {
295
+ return paths.map(p => p.node);
296
+ }
297
+ startNode = startNode.child;
312
298
  }
313
- else if (startNode.binding) {
314
- paths = paths.map(p => resolveBinding(p)).filter(isDefined);
299
+ log.debug("DIRECT TRAV RESOLVE", startNode, paths.map(p => breadCrumb(p)));
300
+ const result = paths.flatMap(path => {
301
+ const subQueryKey = "subquery-" + subQueryCounter++;
302
+ return travHandle({ [subQueryKey]: startNode }, path)[subQueryKey];
303
+ });
304
+ log.debug("DIRECT TRAV RESOLVE RESULT", result);
305
+ return result;
306
+ }
307
+ function addResultIfTokenMatch(fnode, path, state) {
308
+ const filters = state.filters[state.depth].filter(f => f.node == path.node && f.qNode == fnode.node);
309
+ const matchingFilters = filters.filter(f => evaluateFilter(f.filter, path).length > 0);
310
+ log.debug("RESULT MATCH", fnode.node.value, breadCrumb(path), filters.length, matchingFilters.length);
311
+ if (filters.length > 0 && matchingFilters.length == 0)
312
+ return;
313
+ if (fnode.node.resolve) {
314
+ const binding = resolveBinding(path);
315
+ const resolved = binding ? getChildren("init", binding)[0] : undefined;
316
+ if (fnode.node.child) {
317
+ const result = resolveDirectly(fnode.node.child, resolved ?? path);
318
+ fnode.result.push(...result);
319
+ }
320
+ else {
321
+ fnode.result.push(path.node);
322
+ }
315
323
  }
316
- const filter = startNode.filter;
317
- if (filter) {
318
- paths = paths.filter(p => travHandle({ subquery: filter }, p).subquery.length > 0);
324
+ else if (fnode.node.binding) {
325
+ const binding = resolveBinding(path);
326
+ if (binding) {
327
+ if (fnode.node.child) {
328
+ const result = resolveDirectly(fnode.node.child, binding);
329
+ fnode.result.push(...result);
330
+ }
331
+ else {
332
+ fnode.result.push(binding.node);
333
+ }
334
+ }
319
335
  }
320
- if (!startNode.child) {
321
- return paths.map(p => p.node);
336
+ else if (!fnode.node.child) {
337
+ fnode.result.push(path.node);
322
338
  }
323
- startNode = startNode.child;
324
- }
325
- log.debug("DIRECT TRAV RESOLVE", startNode, paths.map(p => breadCrumb(p)));
326
- const result = paths.flatMap(path => {
327
- const subQueryKey = "subquery-" + subQueryCounter++;
328
- return travHandle({ [subQueryKey]: startNode }, path)[subQueryKey];
329
- });
330
- log.debug("DIRECT TRAV RESOLVE RESULT", result);
331
- return result;
332
- }
333
- function addResultIfTokenMatch(fnode, path, state) {
334
- const filters = state.filters[state.depth].filter(f => f.node == path.node && f.qNode == fnode.node);
335
- const matchingFilters = filters.filter(f => evaluateFilter(f.filter, path).length > 0);
336
- log.debug("RESULT MATCH", fnode.node.value, breadCrumb(path), filters.length, matchingFilters.length);
337
- if (filters.length > 0 && matchingFilters.length == 0)
338
- return;
339
- if (fnode.node.resolve) {
340
- const binding = resolveBinding(path);
341
- const resolved = binding ? (0, traverse_1.getChildren)("init", binding)[0] : undefined;
342
- if (fnode.node.child) {
343
- const result = resolveDirectly(fnode.node.child, resolved ?? path);
344
- fnode.result.push(...result);
339
+ else if (fnode.node.child.type == "function") {
340
+ const functionCallResult = state.functionCalls[state.depth].find(f => f.node == fnode.node);
341
+ if (!functionCallResult)
342
+ throw new Error("Did not find expected function call for " + fnode.node.child.function);
343
+ resolveFunctionCalls(fnode, functionCallResult, path, state);
345
344
  }
346
- else {
347
- fnode.result.push(path.node);
345
+ else if (matchingFilters.length > 0) {
346
+ log.debug("HAS MATCHING FILTER", fnode.result.length, matchingFilters.length, breadCrumb(path));
347
+ fnode.result.push(...matchingFilters.flatMap(f => f.result));
348
348
  }
349
349
  }
350
- else if (fnode.node.binding) {
351
- const binding = resolveBinding(path);
352
- if (binding) {
353
- if (fnode.node.child) {
354
- const result = resolveDirectly(fnode.node.child, binding);
355
- fnode.result.push(...result);
350
+ function resolveFunctionCalls(fnode, functionCallResult, path, state) {
351
+ const parameterResults = [];
352
+ for (const p of functionCallResult.parameters) {
353
+ if ("parameters" in p) {
354
+ resolveFunctionCalls(p, p, path, state);
355
+ parameterResults.push(p.result);
356
356
  }
357
357
  else {
358
- fnode.result.push(binding.node);
358
+ parameterResults.push(p.result);
359
359
  }
360
360
  }
361
+ const functionResult = exports.functions[functionCallResult.functionCall.function].fn(parameterResults);
362
+ log.debug("PARAMETER RESULTS", functionCallResult.functionCall.function, parameterResults, functionResult);
363
+ fnode.result.push(...functionResult);
361
364
  }
362
- else if (!fnode.node.child) {
363
- fnode.result.push(path.node);
364
- }
365
- else if (fnode.node.child.type == "function") {
366
- const functionCallResult = state.functionCalls[state.depth].find(f => f.node == fnode.node);
367
- if (!functionCallResult)
368
- throw new Error("Did not find expected function call for " + fnode.node.child.function);
369
- resolveFunctionCalls(fnode, functionCallResult, path, state);
370
- }
371
- else if (matchingFilters.length > 0) {
372
- log.debug("HAS MATCHING FILTER", fnode.result.length, matchingFilters.length, breadCrumb(path));
373
- fnode.result.push(...matchingFilters.flatMap(f => f.result));
365
+ function travHandle(queries, root) {
366
+ const results = Object.fromEntries(Object.keys(queries).map(name => [name, []]));
367
+ const state = {
368
+ depth: 0,
369
+ child: [[], []],
370
+ descendant: [[], []],
371
+ filters: [[], []],
372
+ matches: [[]],
373
+ functionCalls: [[]]
374
+ };
375
+ Object.entries(queries).forEach(([name, node]) => {
376
+ createFNodeAndAddToState(node, results[name], state);
377
+ });
378
+ state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root));
379
+ state.descendant.slice(0, state.depth + 1).forEach(fnodes => fnodes.forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root)));
380
+ traverse(root.node, {
381
+ enter(path, state) {
382
+ log.debug("ENTER", breadCrumb(path));
383
+ state.depth++;
384
+ state.child.push([]);
385
+ state.descendant.push([]);
386
+ state.filters.push([]);
387
+ state.matches.push([]);
388
+ state.functionCalls.push([]);
389
+ state.child[state.depth].forEach(fnode => addIfTokenMatch(fnode, path, state));
390
+ state.descendant.slice(0, state.depth + 1).forEach(fnodes => fnodes.forEach(fnode => addIfTokenMatch(fnode, path, state)));
391
+ },
392
+ exit(path, state) {
393
+ log.debug("EXIT", breadCrumb(path));
394
+ // Check for attributes as not all attributes are visited
395
+ state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, path));
396
+ state.descendant.forEach(fnodes => fnodes.forEach(fnode => addPrimitiveAttributeIfMatch(fnode, path)));
397
+ state.matches[state.depth].forEach(([fNode, path]) => addResultIfTokenMatch(fNode, path, state));
398
+ state.depth--;
399
+ state.child.pop();
400
+ state.descendant.pop();
401
+ state.filters.pop();
402
+ state.matches.pop();
403
+ state.functionCalls.pop();
404
+ }
405
+ }, root.scopeId, state, root);
406
+ return results;
374
407
  }
375
- }
376
- function resolveFunctionCalls(fnode, functionCallResult, path, state) {
377
- const parameterResults = [];
378
- for (const p of functionCallResult.parameters) {
379
- if ("parameters" in p) {
380
- resolveFunctionCalls(p, p, path, state);
381
- parameterResults.push(p.result);
382
- }
383
- else {
384
- parameterResults.push(p.result);
385
- }
408
+ function beginHandle(queries, path) {
409
+ const rootPath = createNodePath(path, undefined, undefined, undefined);
410
+ return travHandle(queries, rootPath);
386
411
  }
387
- const functionResult = exports.functions[functionCallResult.functionCall.function].fn(parameterResults);
388
- log.debug("PARAMETER RESULTS", functionCallResult.functionCall.function, parameterResults, functionResult);
389
- fnode.result.push(...functionResult);
390
- }
391
- function travHandle(queries, root) {
392
- const results = Object.fromEntries(Object.keys(queries).map(name => [name, []]));
393
- const state = {
394
- depth: 0,
395
- child: [[], []],
396
- descendant: [[], []],
397
- filters: [[], []],
398
- matches: [[]],
399
- functionCalls: [[]]
412
+ return {
413
+ beginHandle
400
414
  };
401
- Object.entries(queries).forEach(([name, node]) => {
402
- createFNodeAndAddToState(node, results[name], state);
403
- });
404
- state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root));
405
- state.descendant.slice(0, state.depth + 1).forEach(fnodes => fnodes.forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root)));
406
- (0, traverse_1.default)(root.node, {
407
- enter(path, state) {
408
- log.debug("ENTER", breadCrumb(path));
409
- state.depth++;
410
- state.child.push([]);
411
- state.descendant.push([]);
412
- state.filters.push([]);
413
- state.matches.push([]);
414
- state.functionCalls.push([]);
415
- state.child[state.depth].forEach(fnode => addIfTokenMatch(fnode, path, state));
416
- state.descendant.slice(0, state.depth + 1).forEach(fnodes => fnodes.forEach(fnode => addIfTokenMatch(fnode, path, state)));
417
- },
418
- exit(path, state) {
419
- log.debug("EXIT", breadCrumb(path));
420
- // Check for attributes as not all attributes are visited
421
- state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, path));
422
- state.descendant.forEach(fnodes => fnodes.forEach(fnode => addPrimitiveAttributeIfMatch(fnode, path)));
423
- state.matches[state.depth].forEach(([fNode, path]) => addResultIfTokenMatch(fNode, path, state));
424
- state.depth--;
425
- state.child.pop();
426
- state.descendant.pop();
427
- state.filters.pop();
428
- state.matches.pop();
429
- state.functionCalls.pop();
430
- }
431
- }, root.scopeId, state, root);
432
- return results;
433
415
  }
434
416
  const defaultKey = "__default__";
435
- function query(code, query) {
436
- return multiQuery(code, { [defaultKey]: query })[defaultKey];
417
+ function query(code, query, returnAST) {
418
+ const result = multiQuery(code, { [defaultKey]: query }, returnAST);
419
+ if (returnAST) {
420
+ const r = result[defaultKey];
421
+ r.__AST = result.__AST;
422
+ return r;
423
+ }
424
+ return result[defaultKey];
437
425
  }
438
426
  exports.query = query;
439
- function multiQuery(code, namedQueries) {
427
+ function multiQuery(code, namedQueries, returnAST) {
440
428
  const start = Date.now();
441
429
  const ast = typeof code == "string" ? parseSource(code) : code;
442
430
  if (ast == null)
443
431
  throw new Error("Could not pase code");
444
432
  const queries = Object.fromEntries(Object.entries(namedQueries).map(([name, query]) => [name, (0, parseQuery_1.parse)(query)]));
445
- const result = beginHandle(queries, ast);
433
+ const querier = createQuerier();
434
+ const result = querier.beginHandle(queries, ast);
446
435
  log.debug("Query time: ", Date.now() - start);
436
+ if (returnAST) {
437
+ return { ...result, __AST: ast };
438
+ }
447
439
  return result;
448
440
  }
449
441
  exports.multiQuery = multiQuery;