Settling on a data structure to balance compatibility

with not being wrong
This commit is contained in:
Thaum Rystra
2023-11-09 16:08:04 +02:00
parent 6ce7542c4b
commit 9e5b6b11e1
22 changed files with 312 additions and 338 deletions

View File

@@ -1,16 +1,16 @@
const error = {
create({node, error}) {
create({ node, error }) {
return {
parseType: 'error',
node,
error,
}
},
compile(node, scope, context){
return {result: node, context};
compile(node, scope, context) {
return { result: node, context };
},
toString(node){
return node.error.toString();
toString(node) {
return `${node.error.type} error: ${node.error.message}`;
},
}

View File

@@ -2,69 +2,76 @@ 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};
export default function resolve(fn, node, scope, context = new Context()) {
if (!node) return { result: undefined, context };
let type = nodeTypeIndex[node.parseType];
if (!type){
if (!type) {
throw new Meteor.Error(`Parse node type: ${node.parseType} not implemented`);
}
if (type.resolve){
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){
} 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){
export function toString(node) {
if (!node) return '';
let type = nodeTypeIndex[node.parseType];
if (!type.toString){
if (!type.toString) {
throw new Meteor.Error('toString not implemented on ' + node.parseType);
}
return type.toString(node);
}
export function traverse(node, fn){
export function toPrimitiveOrString(node) {
if (!node) return '';
if (node.parseType === 'constant') return node.value;
if (node.parseType === 'error') return null;
return toString(node);
}
export function traverse(node, fn) {
if (!node) return;
let type = nodeTypeIndex[node.parseType];
if (!type){
if (!type) {
console.error(node);
throw new Meteor.Error('Not valid parse node');
}
if (type.traverse){
if (type.traverse) {
return type.traverse(node, fn);
}
return fn(node);
}
export function map(node, fn){
export function map(node, fn) {
if (!node) return;
let type = nodeTypeIndex[node.parseType];
if (!type){
if (!type) {
console.error(node);
throw new Meteor.Error('Not valid parse node');
}
if (type.map){
if (type.map) {
return type.map(node, fn);
}
return fn(node);
}
export class Context {
constructor({errors = [], rolls = [], options = {}} = {}){
constructor({ errors = [], rolls = [], options = {} } = {}) {
this.errors = errors;
this.rolls = rolls;
this.options = options;
}
error(e){
error(e) {
if (!e) return;
if (typeof e === 'string'){
if (typeof e === 'string') {
this.errors.push({
type: 'error',
message: e,
@@ -73,7 +80,7 @@ export class Context {
this.errors.push(e);
}
}
roll(r){
roll(r) {
this.rolls.push(r);
}
}