Handle set! predicate function in queries

This commit is contained in:
Max Brunsfeld 2019-09-18 17:35:47 -07:00
parent ff9a2c1f53
commit b15e90bd26
5 changed files with 140 additions and 25 deletions

View file

@ -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}\``);
}