Files
DiceCloud/app/imports/parser/resolve.js
Stefan Zermatten 1a14393031 Parsed calculations are now cached between calculations
Parsing is one of the more expensive computations done to characters, so 
the parser results are now stored on the DB and only updated if they are 
dirty. A hash is used to determine if the calculation has changed since 
the last computation
2021-10-03 20:59:04 +02:00

67 lines
1.7 KiB
JavaScript

import nodeTypeIndex from './parseTree/_index.js';
// Takes a parse ndoe and computes it to a set detail level
// returns {result, context}
export default function resolve(fn, node, scope, context = new Context()){
if (!node) return {result: undefined, context};
let type = nodeTypeIndex[node.parseType];
if (!type){
throw new Meteor.Error(`Parse node type: ${node.parseType} not implemented`);
}
if (type.resolve){
return type.resolve(fn, node, scope, context);
} else if (type[fn]) {
return type[fn](node, scope, context);
} else if (fn === 'reduce' && type.roll) {
return type.roll(node, scope, context)
} else if (type.compile){
return type.compile(node, scope, context)
} else {
throw new Meteor.Error('Compile not implemented on ' + node.parseType);
}
}
export function toString(node){
if (!node) return '';
let type = nodeTypeIndex[node.parseType];
if (!type.toString){
throw new Meteor.Error('toString not implemented on ' + node.parseType);
}
return type.toString(node);
}
export function traverse(node, fn){
if (!node) return;
let type = nodeTypeIndex[node.parseType];
if (!type){
console.error(node);
throw new Meteor.Error('Not valid parse node');
}
if (type.traverse){
return type.traverse(node, fn);
}
return fn(node);
}
export class Context {
constructor({errors = [], rolls = [], doubleRolls} = {}){
this.errors = errors;
this.rolls = rolls;
this.doubleRolls = doubleRolls;
}
error(e){
if (!e) return;
if (typeof e === 'string'){
this.errors.push({
type: 'error',
message: e,
});
} else {
this.errors.push(e);
}
}
roll(r){
this.rolls.push(r);
}
}