Handle set! predicate function in queries
This commit is contained in:
parent
ff9a2c1f53
commit
b15e90bd26
5 changed files with 140 additions and 25 deletions
|
|
@ -719,6 +719,7 @@ class Language {
|
|||
stringValues[i] = UTF8ToString(valueAddress, nameLength);
|
||||
}
|
||||
|
||||
const properties = new Array(patternCount);
|
||||
const predicates = new Array(patternCount);
|
||||
for (let i = 0; i < patternCount; i++) {
|
||||
const predicatesAddress = C._ts_query_predicates_for_pattern(
|
||||
|
|
@ -729,6 +730,8 @@ class Language {
|
|||
const stepCount = getValue(TRANSFER_BUFFER, 'i32');
|
||||
|
||||
predicates[i] = [];
|
||||
properties[i] = null;
|
||||
|
||||
const steps = [];
|
||||
let stepAddress = predicatesAddress;
|
||||
for (let j = 0; j < stepCount; j++) {
|
||||
|
|
@ -741,14 +744,28 @@ class Language {
|
|||
} else if (stepType === PREDICATE_STEP_TYPE_STRING) {
|
||||
steps.push({type: 'string', value: stringValues[stepValueId]});
|
||||
} else if (steps.length > 0) {
|
||||
predicates[i].push(buildQueryPredicate(steps));
|
||||
const predicate = buildQueryPredicate(steps);
|
||||
if (typeof predicate === 'function') {
|
||||
predicates[i].push(predicate);
|
||||
} else {
|
||||
if (!properties[i]) properties[i] = {};
|
||||
properties[i][predicate.key] = predicate.value;
|
||||
}
|
||||
steps.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Object.freeze(properties[i]);
|
||||
}
|
||||
|
||||
C._free(sourceAddress);
|
||||
return new Query(INTERNAL, address, captureNames, predicates);
|
||||
return new Query(
|
||||
INTERNAL,
|
||||
address,
|
||||
captureNames,
|
||||
predicates,
|
||||
Object.freeze(properties)
|
||||
);
|
||||
}
|
||||
|
||||
static load(url) {
|
||||
|
|
@ -784,11 +801,12 @@ class Language {
|
|||
}
|
||||
|
||||
class Query {
|
||||
constructor(internal, address, captureNames, predicates) {
|
||||
constructor(internal, address, captureNames, predicates, properties) {
|
||||
assertInternal(internal);
|
||||
this[0] = address;
|
||||
this.captureNames = captureNames;
|
||||
this.predicates = predicates;
|
||||
this.patternProperties = properties;
|
||||
}
|
||||
|
||||
delete() {
|
||||
|
|
@ -826,6 +844,9 @@ class Query {
|
|||
if (this.predicates[pattern].every(p => p(captures))) {
|
||||
result[i] = {pattern, captures};
|
||||
}
|
||||
|
||||
const properties = this.patternProperties[pattern];
|
||||
if (properties) result[i].properties = properties;
|
||||
}
|
||||
|
||||
C._free(startAddress);
|
||||
|
|
@ -851,6 +872,7 @@ class Query {
|
|||
const startAddress = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
|
||||
const result = [];
|
||||
|
||||
const captures = [];
|
||||
let address = startAddress;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const pattern = getValue(address, 'i32');
|
||||
|
|
@ -860,11 +882,14 @@ class Query {
|
|||
const captureIndex = getValue(address, 'i32');
|
||||
address += SIZE_OF_INT;
|
||||
|
||||
const captures = new Array(captureCount);
|
||||
captures.length = captureCount
|
||||
address = unmarshalCaptures(this, node.tree, address, captures);
|
||||
|
||||
if (this.predicates[pattern].every(p => p(captures))) {
|
||||
result.push(captures[captureIndex]);
|
||||
const capture = captures[captureIndex];
|
||||
const properties = this.patternProperties[pattern];
|
||||
if (properties) capture.properties = properties;
|
||||
result.push(capture);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -927,6 +952,18 @@ function buildQueryPredicate(steps) {
|
|||
return false;
|
||||
}
|
||||
|
||||
case 'set!':
|
||||
if (steps.length !== 3) throw new Error(
|
||||
`Wrong number of arguments to \`set!\` predicate. Expected 2, got ${steps.length - 1}.`
|
||||
);
|
||||
if (steps[1].type !== 'string' || steps[2].type !== 'string') throw new Error(
|
||||
`Arguments to \`set!\` predicate must be a strings.".`
|
||||
);
|
||||
return {
|
||||
key: steps[1].value,
|
||||
value: steps[2].value,
|
||||
};
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown query predicate \`${steps[0].value}\``);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue