72 lines
2.2 KiB
JavaScript
72 lines
2.2 KiB
JavaScript
import ParseNode from '/imports/parser/parseTree/ParseNode.js';
|
|
import ConstantNode from '/imports/parser/parseTree/ConstantNode.js';
|
|
|
|
export default class OperatorNode extends ParseNode {
|
|
constructor({left, right, operator, fn}) {
|
|
super(...arguments);
|
|
this.left = left;
|
|
this.right = right;
|
|
this.fn = fn;
|
|
this.operator = operator;
|
|
}
|
|
resolve(fn, scope, context){
|
|
let leftNode = this.left[fn](scope, context);
|
|
let rightNode = this.right[fn](scope, context);
|
|
let left, right;
|
|
if (!(leftNode instanceof ConstantNode) || !(rightNode instanceof ConstantNode)){
|
|
return new OperatorNode({
|
|
left: leftNode,
|
|
right: rightNode,
|
|
operator: this.operator,
|
|
fn: this.fn,
|
|
});
|
|
} else {
|
|
left = leftNode.value;
|
|
right = rightNode.value;
|
|
}
|
|
let result;
|
|
switch(this.operator){
|
|
case '+': result = left + right; break;
|
|
case '-': result = left - right; break;
|
|
case '*': result = left * right; break;
|
|
case '/': result = left / right; break;
|
|
case '^': result = Math.pow(left, right); break;
|
|
case '%': result = left % right; break;
|
|
case '&':
|
|
case '&&': result = left && right; break;
|
|
case '|':
|
|
case '||': result = left || right; break;
|
|
case '=':
|
|
case '==': result = left == right; break;
|
|
case '===': result = left === right; break;
|
|
case '!=': result = left != right; break;
|
|
case '!==': result = left !== right; break;
|
|
case '>': result = left > right; break;
|
|
case '<': result = left < right; break;
|
|
case '>=': result = left >= right; break;
|
|
case '<=': result = left <= right; break;
|
|
}
|
|
return new ConstantNode({
|
|
value: result,
|
|
type: typeof result,
|
|
});
|
|
}
|
|
toString(){
|
|
let {left, right, operator} = this;
|
|
// special case of adding a negative number
|
|
if (operator === '+' && right.isNumber && right.value < 0){
|
|
return `${left.toString()} - ${-right.value}`
|
|
}
|
|
return `${left.toString()} ${operator} ${right.toString()}`;
|
|
}
|
|
traverse(fn){
|
|
fn(this);
|
|
this.left.traverse(fn);
|
|
this.right.traverse(fn);
|
|
}
|
|
replaceChildren(fn){
|
|
this.left = this.left.replaceNodes(fn);
|
|
this.right = this.right.replaceNodes(fn);
|
|
}
|
|
}
|