diff --git a/app/imports/parser/parseTree/IndexNode.js b/app/imports/parser/parseTree/IndexNode.js index 850ff088..fdd6c6c6 100644 --- a/app/imports/parser/parseTree/IndexNode.js +++ b/app/imports/parser/parseTree/IndexNode.js @@ -1,4 +1,6 @@ import ParseNode from '/imports/parser/parseTree/ParseNode.js'; +import ArrayNode from '/imports/parser/parseTree/ArrayNode.js'; +import ErrorNode from '/imports/parser/parseTree/ErrorNode.js'; export default class IndexNode extends ParseNode { constructor({array, index}) { @@ -8,16 +10,42 @@ export default class IndexNode extends ParseNode { } resolve(fn, scope, context){ let index = this.index[fn](scope, context); - if (index.isInteger){ - let selection = this.array.values[index.value - 1]; + let array = this.array[fn](scope, context); + + if (index.isInteger && array instanceof ArrayNode){ + if (index.value < 1 || index.value > array.values.length){ + if (context){ + context.storeError({ + type: 'warning', + message: `Index of ${index.value} is out of range for an array` + + ` of length ${array.values.length}`, + }); + } + } + let selection = array.values[index.value - 1]; if (selection){ let result = selection[fn](scope, context); return result; } + } else if (fn === 'reduce'){ + if (!(array instanceof ArrayNode)){ + return new ErrorNode({ + node: this, + error: 'Can not get the index of a non-array node: ' + + this.array.toString() + ' = ' + array.toString(), + context, + }); + } else if (!index.isInteger){ + return new ErrorNode({ + node: this, + error: array.toString() + ' is not an integer index of the array', + context, + }); + } } return new IndexNode({ index, - array: this.array[fn](scope, context), + array, previousNodes: [this], }); } diff --git a/app/imports/parser/parseTree/ParenthesisNode.js b/app/imports/parser/parseTree/ParenthesisNode.js index eda6038f..db6b5e14 100644 --- a/app/imports/parser/parseTree/ParenthesisNode.js +++ b/app/imports/parser/parseTree/ParenthesisNode.js @@ -8,6 +8,7 @@ export default class ParenthesisNode extends ParseNode { resolve(fn, scope, context){ let content = this.content[fn](scope, context); if ( + fn === 'reduce' || content.constructor.name === 'ConstantNode' || content.constructor.name === 'ErrorNode' ){