astronomical 1.0.0-beta.12 → 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,349 +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 = path.get(fnode.node.value);
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);
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);
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);
239
229
  }
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);
230
+ if (filter.node.type == "parent") {
231
+ return resolveFilterWithParent(filter.node, path);
245
232
  }
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));
233
+ return filter.result;
234
+ }
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;
248
+ }
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;
250
260
  }
251
- throw new Error("Unknown filter type: " + filter.type);
261
+ return resolveDirectly(startNode, startPath);
252
262
  }
253
- if (filter.node.type == "parent") {
254
- return resolveFilterWithParent(filter.node, path);
263
+ const toArray = (value) => Array.isArray(value) ? value : [value];
264
+ function isDefined(value) {
265
+ return value != undefined && value != null;
255
266
  }
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;
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;
298
+ }
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;
286
306
  }
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) {
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 => n.get(lookup)).map(toArray).flat().filter(n => n.node != undefined);
304
- log.debug("LOOKUP", lookup, 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 => p.get("init")).flatMap(toArray).filter(p => p.node != undefined).filter(isDefined);
310
- if (resolved.length > 0)
311
- paths = resolved;
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
+ }
312
323
  }
313
- else if (startNode.binding) {
314
- paths = paths.map(p => resolveBinding(p)).filter(isDefined);
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
+ }
315
335
  }
316
- if (!startNode.child) {
317
- return paths.map(p => p.node);
336
+ else if (!fnode.node.child) {
337
+ fnode.result.push(path.node);
318
338
  }
319
- startNode = startNode.child;
320
- }
321
- log.debug("DIRECT TRAV RESOLVE", startNode, paths.map(p => breadCrumb(p)));
322
- const result = paths.flatMap(path => {
323
- const subQueryKey = "subquery-" + subQueryCounter++;
324
- return travHandle({ [subQueryKey]: startNode }, path)[subQueryKey];
325
- });
326
- log.debug("DIRECT TRAV RESOLVE RESULT", result);
327
- return result;
328
- }
329
- function addResultIfTokenMatch(fnode, path, state) {
330
- const filters = state.filters[state.depth].filter(f => f.node == path.node && f.qNode == fnode.node);
331
- const matchingFilters = filters.filter(f => evaluateFilter(f.filter, path).length > 0);
332
- log.debug("RESULT MATCH", fnode.node.value, breadCrumb(path), filters.length, matchingFilters.length);
333
- if (filters.length > 0 && matchingFilters.length == 0)
334
- return;
335
- if (fnode.node.resolve) {
336
- const [resolved] = toArray(resolveBinding(path)?.get("init")).filter(isDefined).filter(p => p.node != undefined);
337
- if (fnode.node.child) {
338
- const result = resolveDirectly(fnode.node.child, resolved ?? path);
339
- 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);
340
344
  }
341
- else {
342
- 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));
343
348
  }
344
349
  }
345
- else if (fnode.node.binding) {
346
- const binding = resolveBinding(path);
347
- if (binding) {
348
- if (fnode.node.child) {
349
- const result = resolveDirectly(fnode.node.child, binding);
350
- 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);
351
356
  }
352
357
  else {
353
- fnode.result.push(binding.node);
358
+ parameterResults.push(p.result);
354
359
  }
355
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);
356
364
  }
357
- else if (!fnode.node.child) {
358
- fnode.result.push(path.node);
359
- }
360
- else if (fnode.node.child.type == "function") {
361
- const functionCallResult = state.functionCalls[state.depth].find(f => f.node == fnode.node);
362
- if (!functionCallResult)
363
- throw new Error("Did not find expected function call for " + fnode.node.child.function);
364
- resolveFunctionCalls(fnode, functionCallResult, path, state);
365
- }
366
- else if (matchingFilters.length > 0) {
367
- log.debug("HAS MATCHING FILTER", fnode.result.length, matchingFilters.length, breadCrumb(path));
368
- 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;
369
407
  }
370
- }
371
- function resolveFunctionCalls(fnode, functionCallResult, path, state) {
372
- const parameterResults = [];
373
- for (const p of functionCallResult.parameters) {
374
- if ("parameters" in p) {
375
- resolveFunctionCalls(p, p, path, state);
376
- parameterResults.push(p.result);
377
- }
378
- else {
379
- parameterResults.push(p.result);
380
- }
408
+ function beginHandle(queries, path) {
409
+ const rootPath = createNodePath(path, undefined, undefined, undefined);
410
+ return travHandle(queries, rootPath);
381
411
  }
382
- const functionResult = exports.functions[functionCallResult.functionCall.function].fn(parameterResults);
383
- log.debug("PARAMETER RESULTS", functionCallResult.functionCall.function, parameterResults, functionResult);
384
- fnode.result.push(...functionResult);
385
- }
386
- function travHandle(queries, root) {
387
- const results = Object.fromEntries(Object.keys(queries).map(name => [name, []]));
388
- const state = {
389
- depth: 0,
390
- child: [[], []],
391
- descendant: [[], []],
392
- filters: [[], []],
393
- matches: [[]],
394
- functionCalls: [[]]
412
+ return {
413
+ beginHandle
395
414
  };
396
- Object.entries(queries).forEach(([name, node]) => {
397
- createFNodeAndAddToState(node, results[name], state);
398
- });
399
- state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root));
400
- state.descendant.slice(0, state.depth + 1).forEach(fnodes => fnodes.forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root)));
401
- (0, traverse_1.default)(root.node, {
402
- enter(path, state) {
403
- log.debug("ENTER", breadCrumb(path));
404
- state.depth++;
405
- state.child.push([]);
406
- state.descendant.push([]);
407
- state.filters.push([]);
408
- state.matches.push([]);
409
- state.functionCalls.push([]);
410
- state.child[state.depth].forEach(fnode => addIfTokenMatch(fnode, path, state));
411
- state.descendant.slice(0, state.depth + 1).forEach(fnodes => fnodes.forEach(fnode => addIfTokenMatch(fnode, path, state)));
412
- },
413
- exit(path, state) {
414
- log.debug("EXIT", breadCrumb(path));
415
- // Check for attributes as not all attributes are visited
416
- state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, path));
417
- state.descendant.forEach(fnodes => fnodes.forEach(fnode => addPrimitiveAttributeIfMatch(fnode, path)));
418
- state.matches[state.depth].forEach(([fNode, path]) => addResultIfTokenMatch(fNode, path, state));
419
- state.depth--;
420
- state.child.pop();
421
- state.descendant.pop();
422
- state.filters.pop();
423
- state.matches.pop();
424
- state.functionCalls.pop();
425
- }
426
- }, root.scopeId, state, root);
427
- return results;
428
415
  }
429
416
  const defaultKey = "__default__";
430
- function query(code, query) {
431
- 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];
432
425
  }
433
426
  exports.query = query;
434
- function multiQuery(code, namedQueries) {
427
+ function multiQuery(code, namedQueries, returnAST) {
435
428
  const start = Date.now();
436
429
  const ast = typeof code == "string" ? parseSource(code) : code;
437
430
  if (ast == null)
438
431
  throw new Error("Could not pase code");
439
432
  const queries = Object.fromEntries(Object.entries(namedQueries).map(([name, query]) => [name, (0, parseQuery_1.parse)(query)]));
440
- const result = beginHandle(queries, ast);
433
+ const querier = createQuerier();
434
+ const result = querier.beginHandle(queries, ast);
441
435
  log.debug("Query time: ", Date.now() - start);
436
+ if (returnAST) {
437
+ return { ...result, __AST: ast };
438
+ }
442
439
  return result;
443
440
  }
444
441
  exports.multiQuery = multiQuery;