Added functions and ensured the context was being passed around correctly
This commit is contained in:
@@ -27,9 +27,9 @@ export default class AccessorNode extends ParseNode {
|
||||
}
|
||||
}
|
||||
reduce(scope, context){
|
||||
let result = this.compile(scope);
|
||||
let result = this.compile(scope, context);
|
||||
if (result instanceof AccessorNode){
|
||||
context.storeError({
|
||||
if (context) context.storeError({
|
||||
type: 'info',
|
||||
message: `${result.toString()} not found, set to 0`
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
||||
import ErrorNode from '/imports/parser/parseTree/ErrorNode.js';
|
||||
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
||||
import functions from '/imports/parser/functions.js';
|
||||
|
||||
export default class CallNode extends ParseNode {
|
||||
constructor({functionName, args}) {
|
||||
@@ -15,7 +16,7 @@ export default class CallNode extends ParseNode {
|
||||
error: `${this.functionName} is not a function`,
|
||||
context,
|
||||
});
|
||||
let args = castArgsToType({fn, scope, args: this.args, type: func.argumentType});
|
||||
let args = castArgsToType({fn, scope, context, args: this.args, type: func.argumentType});
|
||||
if (args.failed){
|
||||
if (fn === 'reduce'){
|
||||
return new ErrorNode({
|
||||
@@ -51,17 +52,8 @@ export default class CallNode extends ParseNode {
|
||||
}
|
||||
}
|
||||
|
||||
const functions = {
|
||||
'min': {
|
||||
comment: 'Returns the lowest of the given numbers',
|
||||
argumentType: 'number',
|
||||
resultType: 'number',
|
||||
fn: Math.min,
|
||||
},
|
||||
}
|
||||
|
||||
function castArgsToType({fn, scope, args, type}){
|
||||
let resolvedArgs = args.map(node => node[fn](scope))
|
||||
function castArgsToType({fn, scope, context, args, type}){
|
||||
let resolvedArgs = args.map(node => node[fn](scope, context))
|
||||
let result = [];
|
||||
if (type === 'number'){
|
||||
resolvedArgs.forEach(node => {
|
||||
|
||||
@@ -12,15 +12,15 @@ export default class IfNode extends ParseNode {
|
||||
let {condition, consequent, alternative} = this;
|
||||
return `${condition.toString()} ? ${consequent.toString()} : ${alternative.toString()}`
|
||||
}
|
||||
resolve(fn, scope){
|
||||
let condition = this.condition[fn](scope);
|
||||
resolve(fn, scope, context){
|
||||
let condition = this.condition[fn](scope, context);
|
||||
if (condition instanceof ConstantNode){
|
||||
if (condition.value){
|
||||
let consequent = this.consequent[fn](scope);
|
||||
let consequent = this.consequent[fn](scope, context);
|
||||
consequent.inheritDetails([condition, this]);
|
||||
return this.consequent[fn](scope);
|
||||
} else {
|
||||
let alternative = this.alternative[fn](scope);
|
||||
let alternative = this.alternative[fn](scope, context);
|
||||
alternative.inheritDetails([condition, this]);
|
||||
return alternative;
|
||||
}
|
||||
|
||||
@@ -6,19 +6,19 @@ export default class IndexNode extends ParseNode {
|
||||
this.array = array;
|
||||
this.index = index;
|
||||
}
|
||||
resolve(fn, scope){
|
||||
let index = this.index[fn](scope);
|
||||
resolve(fn, scope, context){
|
||||
let index = this.index[fn](scope, context);
|
||||
if (index.isInteger){
|
||||
let selection = this.array.values[index.value - 1];
|
||||
if (selection){
|
||||
let result = selection[fn](scope);
|
||||
let result = selection[fn](scope, context);
|
||||
result.inheritDetails([index, this]);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return new IndexNode({
|
||||
array: this.array[fn](scope),
|
||||
index: this.index[fn](scope),
|
||||
array: this.array[fn](scope, context),
|
||||
index: this.index[fn](scope, context),
|
||||
previousNodes: [this],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ export default class OperatorNode extends ParseNode {
|
||||
this.fn = fn;
|
||||
this.operator = operator;
|
||||
}
|
||||
resolve(fn, scope){
|
||||
let leftNode = this.left[fn](scope);
|
||||
let rightNode = this.right[fn](scope);
|
||||
resolve(fn, scope, context){
|
||||
let leftNode = this.left[fn](scope, context);
|
||||
let rightNode = this.right[fn](scope, context);
|
||||
let left, right;
|
||||
if (leftNode.type !== 'number' || rightNode.type !== 'number'){
|
||||
return new OperatorNode({
|
||||
|
||||
@@ -5,8 +5,8 @@ export default class ParenthesisNode extends ParseNode {
|
||||
super(...arguments);
|
||||
this.content = content;
|
||||
}
|
||||
resolve(fn, scope){
|
||||
let content = this.content[fn](scope);
|
||||
resolve(fn, scope, context){
|
||||
let content = this.content[fn](scope, context);
|
||||
if (
|
||||
content.constructor.name === 'IfNode' ||
|
||||
content.constructor.name === 'OperatorNode'
|
||||
|
||||
@@ -17,7 +17,6 @@ export default class RollArrayNode extends ParseNode {
|
||||
return new ConstantNode({
|
||||
value: total,
|
||||
type: 'number',
|
||||
previousNodes: [this],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ export default class RollNode extends ParseNode {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
compile(scope){
|
||||
let left = this.left.compile(scope);
|
||||
let right = this.right.compile(scope);
|
||||
compile(scope, context){
|
||||
let left = this.left.compile(scope, context);
|
||||
let right = this.right.compile(scope, context);
|
||||
return new RollNode({left, right, previousNodes: [this]});
|
||||
}
|
||||
toString(){
|
||||
@@ -23,8 +23,8 @@ export default class RollNode extends ParseNode {
|
||||
}
|
||||
}
|
||||
roll(scope, context){
|
||||
let left = this.left.reduce(scope);
|
||||
let right = this.right.reduce(scope);
|
||||
let left = this.left.reduce(scope, context);
|
||||
let right = this.right.reduce(scope, context);
|
||||
if (!left.isInteger){
|
||||
return new ErrorNode({
|
||||
node: this,
|
||||
@@ -56,7 +56,7 @@ export default class RollNode extends ParseNode {
|
||||
}
|
||||
return new RollArrayNode({values});
|
||||
}
|
||||
reduce(scope){
|
||||
return this.roll(scope).reduce(scope);
|
||||
reduce(scope, context){
|
||||
return this.roll(scope, context).reduce(scope, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
||||
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
||||
import ErrorNode from '/imports/parser/parseTree/ErrorNode.js';
|
||||
|
||||
export default class SymbolNode extends ParseNode {
|
||||
constructor({name}){
|
||||
@@ -19,23 +18,25 @@ export default class SymbolNode extends ParseNode {
|
||||
type = typeof value;
|
||||
}
|
||||
if (type === 'string' || type === 'number' || type === 'boolean'){
|
||||
return new ConstantNode({value, type, previousNodes: [this]});
|
||||
return new ConstantNode({value, type});
|
||||
} else if (type === 'undefined'){
|
||||
return new SymbolNode({
|
||||
name: this.name,
|
||||
previousNodes: [this],
|
||||
});
|
||||
} else {
|
||||
throw new Meteor.Error(`Unexpected case: ${this.name} resolved to ${value}`);
|
||||
}
|
||||
}
|
||||
reduce(scope){
|
||||
reduce(scope, context){
|
||||
let result = this.compile(scope);
|
||||
if (result instanceof SymbolNode){
|
||||
return new ErrorNode({
|
||||
node: result,
|
||||
error: `${this.toString()} could not be resolved`,
|
||||
previousNodes: [result],
|
||||
if (context) context.storeError({
|
||||
type: 'info',
|
||||
message: `${result.toString()} not found, set to 0`
|
||||
});
|
||||
return new ConstantNode({
|
||||
type: 'number',
|
||||
value: 0,
|
||||
});
|
||||
} else {
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user