|
@@ -16,6 +16,8 @@ import { CompoundType } from './../typeSystem/compoundType';
|
|
|
import { convertToString } from '../typeSystem/parsers';
|
|
|
import { Config } from '../util/config';
|
|
|
import Decimal from 'decimal.js';
|
|
|
+import { ProcessorErrorFactory } from './error/processorErrorFactory';
|
|
|
+import { RuntimeError } from './error/runtimeError';
|
|
|
|
|
|
export class IVProgProcessor {
|
|
|
|
|
@@ -27,6 +29,10 @@ export class IVProgProcessor {
|
|
|
Config.setConfig({loopTimeout: ms});
|
|
|
}
|
|
|
|
|
|
+ static get MAIN_INTERNAL_ID () {
|
|
|
+ return "$main";
|
|
|
+ }
|
|
|
+
|
|
|
constructor (ast) {
|
|
|
this.ast = ast;
|
|
|
this.globalStore = new Store("$global");
|
|
@@ -64,15 +70,14 @@ export class IVProgProcessor {
|
|
|
this.initGlobal();
|
|
|
const mainFunc = this.findMainFunction();
|
|
|
if(mainFunc === null) {
|
|
|
- // TODO: Better error message
|
|
|
- throw new Error("Missing main funciton.");
|
|
|
+ throw ProcessorErrorFactory.main_missing();
|
|
|
}
|
|
|
return this.runFunction(mainFunc, [], this.globalStore);
|
|
|
}
|
|
|
|
|
|
initGlobal () {
|
|
|
if(!this.checkContext(Context.BASE)) {
|
|
|
- throw new Error("!!!CRITICAL: Invalid call to initGlobal outside BASE context!!!");
|
|
|
+ throw ProcessorErrorFactory.invalid_global_var();
|
|
|
}
|
|
|
this.ast.global.forEach(decl => {
|
|
|
this.executeCommand(this.globalStore, decl).then(sto => this.globalStore = sto);
|
|
@@ -87,21 +92,21 @@ export class IVProgProcessor {
|
|
|
if(name.match(/^\$.+$/)) {
|
|
|
const fun = LanguageDefinedFunction.getFunction(name);
|
|
|
if(!!!fun) {
|
|
|
- throw new Error("!!!Internal Error. Language defined function not implemented -> " + name + "!!!");
|
|
|
+ throw ProcessorErrorFactory.not_implemented(name);
|
|
|
}
|
|
|
return fun;
|
|
|
} else {
|
|
|
const val = this.ast.functions.find( v => v.name === name);
|
|
|
if (!!!val) {
|
|
|
// TODO: better error message;
|
|
|
- throw new Error(`Function ${name} is not defined.`);
|
|
|
+ throw ProcessorErrorFactory.function_missing(name);
|
|
|
}
|
|
|
return val;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
runFunction (func, actualParameters, store) {
|
|
|
- const funcName = func.isMain ? 'main' : func.name;
|
|
|
+ const funcName = func.isMain ? IVProgProcessor.MAIN_INTERNAL_ID : func.name;
|
|
|
let funcStore = new Store(funcName);
|
|
|
funcStore.extendStore(this.globalStore);
|
|
|
let returnStoreObject = null;
|
|
@@ -129,18 +134,21 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
|
|
|
associateParameters (formalList, actualList, callerStore, calleeStore) {
|
|
|
+ const funcName = calleeStore.name === IVProgProcessor.MAIN_INTERNAL_ID ?
|
|
|
+ LanguageDefinedFunction.getMainFunctionName() : calleeStore.name;
|
|
|
+
|
|
|
if (formalList.length != actualList.length) {
|
|
|
- // TODO: Better error message
|
|
|
- throw new Error("Numbers of parameters doesn't match");
|
|
|
+ throw ProcessorErrorFactory.invalid_parameters_size(funcName, formalList.length, actualList.length);
|
|
|
}
|
|
|
const promises$ = actualList.map(actualParameter => this.evaluateExpression(callerStore, actualParameter));
|
|
|
return Promise.all(promises$).then(values => {
|
|
|
for (let i = 0; i < values.length; i++) {
|
|
|
const stoObj = values[i];
|
|
|
+ const exp = actualList[i]
|
|
|
const formalParameter = formalList[i];
|
|
|
if(formalParameter.type.isCompatible(stoObj.type)) {
|
|
|
if(formalParameter.byRef && !stoObj.inStore) {
|
|
|
- throw new Error('You must inform a variable as parameter');
|
|
|
+ throw ProcessorErrorFactory.invalid_ref(funcName, exp.toString());
|
|
|
}
|
|
|
|
|
|
if(formalParameter.byRef) {
|
|
@@ -156,7 +164,7 @@ export class IVProgProcessor {
|
|
|
calleeStore.insertStore(formalParameter.id, realValue);
|
|
|
}
|
|
|
} else {
|
|
|
- throw new Error(`Parameter ${formalParameter.id} is not compatible with the value given.`);
|
|
|
+ throw ProcessorErrorFactory.invalid_parameter_type(funcName, exp.toString());
|
|
|
}
|
|
|
}
|
|
|
return calleeStore;
|
|
@@ -176,7 +184,7 @@ export class IVProgProcessor {
|
|
|
executeCommand (store, cmd) {
|
|
|
|
|
|
if(this.forceKill) {
|
|
|
- return Promise.reject("Interrupção forçada do programa!");
|
|
|
+ return Promise.reject("FORCED_KILL!");
|
|
|
} else if (store.mode === Modes.PAUSE) {
|
|
|
return Promise.resolve(this.executeCommand(store, cmd));
|
|
|
} else if(store.mode === Modes.RETURN) {
|
|
@@ -205,12 +213,13 @@ export class IVProgProcessor {
|
|
|
return this.executeFor(store, cmd);
|
|
|
} else if (cmd instanceof Commands.Switch) {
|
|
|
return this.executeSwitch(store, cmd);
|
|
|
- } else if (cmd instanceof Commands.FunctionCall) {
|
|
|
+ } else if (cmd instanceof Expressions.FunctionCall) {
|
|
|
+
|
|
|
return this.executeFunctionCall(store, cmd);
|
|
|
} else if (cmd instanceof Commands.SysCall) {
|
|
|
return this.executeSysCall(store, cmd);
|
|
|
} else {
|
|
|
- throw new Error("!!!CRITICAL A unknown command was found!!!\n" + cmd);
|
|
|
+ throw ProcessorErrorFactory.unknown_command(cmd.sourceInfo);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -229,8 +238,9 @@ export class IVProgProcessor {
|
|
|
return this.runFunction(func, cmd.actualParameters, store)
|
|
|
.then(sto => {
|
|
|
if(!Types.VOID.isCompatible(func.returnType) && sto.mode !== Modes.RETURN) {
|
|
|
- // TODO: better error message
|
|
|
- return Promise.reject(new Error(`Function ${func.name} must have a return command`));
|
|
|
+ const funcName = func.name === IVProgProcessor.MAIN_INTERNAL_ID ?
|
|
|
+ LanguageDefinedFunction.getMainFunctionName() : func.name;
|
|
|
+ return Promise.reject(ProcessorErrorFactory.function_no_return(funcName));
|
|
|
} else {
|
|
|
return store;
|
|
|
}
|
|
@@ -319,25 +329,21 @@ export class IVProgProcessor {
|
|
|
const $value = outerRef.evaluateExpression(sto, cmd.expression);
|
|
|
return $value.then(vl => {
|
|
|
if (!vl.type.isCompatible(Types.BOOLEAN)) {
|
|
|
- // TODO: Better error message -- Inform line and column from token!!!!
|
|
|
- // THIS IF SHOULD BE IN A SEMANTIC ANALYSER
|
|
|
- return Promise.reject(new Error(`DoWhile expression must be of type boolean`));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.loop_condition_type_full(cmd.sourceInfo));
|
|
|
}
|
|
|
if (vl.value) {
|
|
|
outerRef.context.pop();
|
|
|
for (let i = 0; i < outerRef.loopTimers.length; i++) {
|
|
|
const time = outerRef.loopTimers[i];
|
|
|
if(Date.now() - time >= IVProgProcessor.LOOP_TIMEOUT) {
|
|
|
- console.log("Kill by Timeout...");
|
|
|
outerRef.forceKill = true;
|
|
|
- return Promise.reject(new Error("Potential endless loop detected."));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.endless_loop_full(cmd.sourceInfo));
|
|
|
}
|
|
|
}
|
|
|
return outerRef.executeCommand(sto, cmd);
|
|
|
} else {
|
|
|
outerRef.context.pop();
|
|
|
outerRef.loopTimers.pop();
|
|
|
- console.log("Clear Timeout...");
|
|
|
return sto;
|
|
|
}
|
|
|
})
|
|
@@ -367,9 +373,8 @@ export class IVProgProcessor {
|
|
|
for (let i = 0; i < outerRef.loopTimers.length; i++) {
|
|
|
const time = outerRef.loopTimers[i];
|
|
|
if(Date.now() - time >= IVProgProcessor.LOOP_TIMEOUT) {
|
|
|
- console.log("Kill by Timeout...");
|
|
|
outerRef.forceKill = true;
|
|
|
- return Promise.reject(new Error("Potential endless loop detected."));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.endless_loop_full(cmd.sourceInfo));
|
|
|
}
|
|
|
}
|
|
|
return outerRef.executeCommand(sto, cmd);
|
|
@@ -377,13 +382,10 @@ export class IVProgProcessor {
|
|
|
} else {
|
|
|
outerRef.context.pop();
|
|
|
outerRef.loopTimers.pop();
|
|
|
- console.log("Clear Timeout...");
|
|
|
return store;
|
|
|
}
|
|
|
} else {
|
|
|
- // TODO: Better error message -- Inform line and column from token!!!!
|
|
|
- // THIS IF SHOULD BE IN A SEMANTIC ANALYSER
|
|
|
- return Promise.reject(new Error(`Loop condition must be of type boolean`));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.loop_condition_type_full(cmd.sourceInfo));
|
|
|
}
|
|
|
})
|
|
|
|
|
@@ -409,9 +411,7 @@ export class IVProgProcessor {
|
|
|
return Promise.resolve(store);
|
|
|
}
|
|
|
} else {
|
|
|
- // TODO: Better error message -- Inform line and column from token!!!!
|
|
|
- // THIS IF SHOULD BE IN A SEMANTIC ANALYSER
|
|
|
- return Promise.reject(new Error(`If expression must be of type boolean`));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.if_condition_type_full(cmd.sourceInfo));
|
|
|
}
|
|
|
});
|
|
|
} catch (error) {
|
|
@@ -423,7 +423,8 @@ export class IVProgProcessor {
|
|
|
try {
|
|
|
const funcType = store.applyStore('$').type;
|
|
|
const $value = this.evaluateExpression(store, cmd.expression);
|
|
|
- const funcName = store.name;
|
|
|
+ const funcName = store.name === IVProgProcessor.MAIN_INTERNAL_ID ?
|
|
|
+ LanguageDefinedFunction.getMainFunctionName() : store.name;
|
|
|
return $value.then(vl => {
|
|
|
|
|
|
if(vl === null && funcType.isCompatible(Types.VOID)) {
|
|
@@ -431,9 +432,9 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
|
|
|
if (vl === null || !funcType.isCompatible(vl.type)) {
|
|
|
- // TODO: Better error message -- Inform line and column from token!!!!
|
|
|
- // THIS IF SHOULD BE IN A SEMANTIC ANALYSER
|
|
|
- return Promise.reject(new Error(`Function ${funcName} must return ${funcType.type} instead of ${vl.type}.`));
|
|
|
+ const stringInfo = funcType.stringInfo();
|
|
|
+ const info = stringInfo[0];
|
|
|
+ return Promise.reject(ProcessorErrorFactory.invalid_return_type_full(funcName, info.type, info.dim, cmd.sourceInfo));
|
|
|
} else {
|
|
|
let realValue = this.parseStoreObjectValue(vl);
|
|
|
store.updateStore('$', realValue);
|
|
@@ -446,12 +447,12 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- executeBreak (store, _) {
|
|
|
+ executeBreak (store, cmd) {
|
|
|
if(this.checkContext(Context.BREAKABLE)) {
|
|
|
store.mode = Modes.BREAK;
|
|
|
return Promise.resolve(store);
|
|
|
} else {
|
|
|
- return Promise.reject(new Error("!!!CRITIAL: Break command outside Loop/Switch scope!!!"));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.unexpected_break_command_full(cmd.sourceInfo));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -471,7 +472,7 @@ export class IVProgProcessor {
|
|
|
executeArrayIndexAssign (store, cmd) {
|
|
|
const mustBeArray = store.applyStore(cmd.id);
|
|
|
if(!(mustBeArray.type instanceof CompoundType)) {
|
|
|
- return Promise.reject(new Error(cmd.id + " is not a vector/matrix"));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.invalid_array_access_full(cmd.id, cmd.sourceInfo));
|
|
|
}
|
|
|
const line$ = this.evaluateExpression(store, cmd.line);
|
|
|
const column$ = this.evaluateExpression(store, cmd.column);
|
|
@@ -479,45 +480,55 @@ export class IVProgProcessor {
|
|
|
return Promise.all([line$, column$, value$]).then(results => {
|
|
|
const lineSO = results[0];
|
|
|
if(!Types.INTEGER.isCompatible(lineSO.type)) {
|
|
|
- // TODO: better error message
|
|
|
- //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS
|
|
|
- return Promise.reject(new Error("Array dimension must be of type int"));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
|
|
|
}
|
|
|
const line = lineSO.number;
|
|
|
const columnSO = results[1];
|
|
|
let column = null
|
|
|
if (columnSO !== null) {
|
|
|
if(!Types.INTEGER.isCompatible(columnSO.type)) {
|
|
|
- // TODO: better error message
|
|
|
- //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS
|
|
|
- return Promise.reject(new Error("Array dimension must be of type int"));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
|
|
|
}
|
|
|
column = columnSO.number;
|
|
|
}
|
|
|
const value = this.parseStoreObjectValue(results[2]);
|
|
|
if (line >= mustBeArray.lines) {
|
|
|
- // TODO: better error message
|
|
|
- return Promise.reject(new Error(`${exp.id}: index out of bounds: ${lines}`));
|
|
|
+ if(mustBeArray.isVector) {
|
|
|
+ return Promise.reject(ProcessorErrorFactory.vector_line_outbounds_full(cmd.id, line, mustBeArray.lines, cmd.sourceInfo));
|
|
|
+ } else {
|
|
|
+ return Promise.reject(ProcessorErrorFactory.matrix_line_outbounds_full(cmd.id, line, mustBeArray.lines, cmd.sourceInfo));
|
|
|
+ }
|
|
|
+ } else if (line < 0) {
|
|
|
+ throw ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo);
|
|
|
}
|
|
|
if (column !== null && mustBeArray.columns === null ){
|
|
|
- // TODO: better error message
|
|
|
- return Promise.reject(new Error(`${exp.id}: index out of bounds: ${column}`));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.vector_not_matrix_full(cmd.id, cmd.sourceInfo));
|
|
|
}
|
|
|
- if(column !== null && column >= mustBeArray.columns) {
|
|
|
- // TODO: better error message
|
|
|
- return Promise.reject(new Error(`${exp.id}: index out of bounds: ${column}`));
|
|
|
+ if(column !== null ) {
|
|
|
+ if (column >= mustBeArray.columns) {
|
|
|
+ return Promise.reject(ProcessorErrorFactory.matrix_column_outbounds_full(cmd.id, column,mustBeArray.columns, cmd.sourceInfo));
|
|
|
+ } else if (column < 0) {
|
|
|
+ throw ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
const newArray = Object.assign(new StoreObjectArray(null,null,null), mustBeArray);
|
|
|
if (column !== null) {
|
|
|
if (value.type instanceof CompoundType) {
|
|
|
- return Promise.reject(new Error("Invalid operation. This must be a value: line "+cmd.sourceInfo.line));
|
|
|
+ const type = mustBeArray.type.innerType;
|
|
|
+ const stringInfo = type.stringInfo()
|
|
|
+ const info = stringInfo[0]
|
|
|
+ return Promise.reject(ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, cmd.sourceInfo));
|
|
|
}
|
|
|
newArray.value[line].value[column] = value;
|
|
|
store.updateStore(cmd.id, newArray);
|
|
|
} else {
|
|
|
if(mustBeArray.columns !== null && value.type instanceof CompoundType) {
|
|
|
- return Promise.reject(new Error("Invalid operation. This must be a vector: line "+cmd.sourceInfo.line));
|
|
|
+ const type = mustBeArray.type;
|
|
|
+ const stringInfo = type.stringInfo()
|
|
|
+ const info = stringInfo[0]
|
|
|
+ const exp = cmd.expression.toString()
|
|
|
+ return Promise.reject(ProcessorErrorFactory.incompatible_types_array_full(exp,info.type, info.dim-1, cmd.sourceInfo));
|
|
|
}
|
|
|
newArray.value[line] = value;
|
|
|
store.updateStore(cmd.id, newArray);
|
|
@@ -535,20 +546,22 @@ export class IVProgProcessor {
|
|
|
return Promise.all([$lines, $columns, $value]).then(values => {
|
|
|
const lineSO = values[0];
|
|
|
if(!Types.INTEGER.isCompatible(lineSO.type)) {
|
|
|
- // TODO: better error message
|
|
|
- //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS
|
|
|
- return Promise.reject(new Error("Array dimension must be of type int"));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
|
|
|
}
|
|
|
const line = lineSO.number;
|
|
|
+ if(line < 0) {
|
|
|
+ throw ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo);
|
|
|
+ }
|
|
|
const columnSO = values[1];
|
|
|
let column = null
|
|
|
if (columnSO !== null) {
|
|
|
if(!Types.INTEGER.isCompatible(columnSO.type)) {
|
|
|
- // TODO: better error message
|
|
|
- //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS
|
|
|
- return Promise.reject(new Error("Array dimension must be of type int"));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
|
|
|
}
|
|
|
column = columnSO.number;
|
|
|
+ if(column < 0) {
|
|
|
+ throw ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo);
|
|
|
+ }
|
|
|
}
|
|
|
const value = values[2];
|
|
|
const temp = new StoreObjectArray(cmd.type, line, column, null);
|
|
@@ -629,12 +642,12 @@ export class IVProgProcessor {
|
|
|
|
|
|
evaluateFunctionCall (store, exp) {
|
|
|
if(exp.isMainCall) {
|
|
|
- return Promise.reject(new Error(`Main function cannot be used inside an expression`));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.void_in_expression_full(LanguageDefinedFunction.getMainFunctionName(), exp.sourceInfo));
|
|
|
}
|
|
|
const func = this.findFunction(exp.id);
|
|
|
if(Types.VOID.isCompatible(func.returnType)) {
|
|
|
// TODO: better error message
|
|
|
- return Promise.reject(new Error(`Function ${exp.id} cannot be used inside an expression`));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.void_in_expression_full(exp.id, exp.sourceInfo));
|
|
|
}
|
|
|
const $newStore = this.runFunction(func, exp.actualParameters, store);
|
|
|
return $newStore.then( sto => {
|
|
@@ -651,24 +664,53 @@ export class IVProgProcessor {
|
|
|
}
|
|
|
|
|
|
evaluateArrayLiteral (store, exp) {
|
|
|
+ const errorHelperFunction = (validationResult, exp) => {
|
|
|
+ const errorCode = validationResult[0];
|
|
|
+ switch(errorCode) {
|
|
|
+ case StoreObjectArray.WRONG_COLUMN_NUMBER: {
|
|
|
+ const columnValue = validationResult[1];
|
|
|
+ return Promise.reject(ProcessorErrorFactory.invalid_array_literal_column_full(arr.columns, columnValue, exp.sourceInfo));
|
|
|
+ }
|
|
|
+ case StoreObjectArray.WRONG_LINE_NUMBER: {
|
|
|
+ const lineValue = validationResult[1];
|
|
|
+ return Promise.reject(ProcessorErrorFactory.invalid_array_literal_line_full(arr.lines, lineValue, exp.sourceInfo));
|
|
|
+ }
|
|
|
+ case StoreObjectArray.WRONG_TYPE: {
|
|
|
+ let line = null;
|
|
|
+ let strExp = null;
|
|
|
+ if (validationResult.length > 2) {
|
|
|
+ line = validationResult[1];
|
|
|
+ const column = validationResult[2];
|
|
|
+ strExp = exp.value[line].value[column].toString()
|
|
|
+ } else {
|
|
|
+ line = validationResult[1];
|
|
|
+ strExp = exp.value[line].toString()
|
|
|
+ }
|
|
|
+ return Promise.reject(ProcessorErrorFactory.invalid_array_literal_type_full(strExp, exp.sourceInfo)); }
|
|
|
+ }
|
|
|
+ };
|
|
|
if(!exp.isVector) {
|
|
|
const $matrix = this.evaluateMatrix(store, exp.value);
|
|
|
return $matrix.then(list => {
|
|
|
const type = new CompoundType(list[0].type.innerType, 2);
|
|
|
const arr = new StoreObjectArray(type, list.length, list[0].lines, list);
|
|
|
- if(arr.isValid)
|
|
|
+ const checkResult = arr.isValid;
|
|
|
+ if(checkResult.length == 0)
|
|
|
return Promise.resolve(arr);
|
|
|
- else
|
|
|
- return Promise.reject(new Error(`Invalid array`))
|
|
|
+ else {
|
|
|
+ return errorHelperFunction(checkResult, exp);
|
|
|
+ }
|
|
|
});
|
|
|
} else {
|
|
|
return this.evaluateVector(store, exp.value).then(list => {
|
|
|
const type = new CompoundType(list[0].type, 1);
|
|
|
const stoArray = new StoreObjectArray(type, list.length, null, list);
|
|
|
- if(stoArray.isValid)
|
|
|
+ const checkResult = stoArray.isValid;
|
|
|
+ if(checkResult.length == 0)
|
|
|
return Promise.resolve(stoArray);
|
|
|
- else
|
|
|
- return Promise.reject(new Error(`Invalid array`))
|
|
|
+ else {
|
|
|
+ return errorHelperFunction(checkResult, exp);
|
|
|
+ }
|
|
|
});
|
|
|
}
|
|
|
}
|
|
@@ -707,9 +749,7 @@ export class IVProgProcessor {
|
|
|
evaluateArrayAccess (store, exp) {
|
|
|
const mustBeArray = store.applyStore(exp.id);
|
|
|
if (!(mustBeArray.type instanceof CompoundType)) {
|
|
|
- // TODO: better error message
|
|
|
- console.log(mustBeArray.type);
|
|
|
- return Promise.reject(new Error(`${exp.id} is not of type array`));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.invalid_array_access_full(exp.id, exp.sourceInfo));
|
|
|
}
|
|
|
const $line = this.evaluateExpression(store, exp.line);
|
|
|
const $column = this.evaluateExpression(store, exp.column);
|
|
@@ -717,32 +757,36 @@ export class IVProgProcessor {
|
|
|
const lineSO = values[0];
|
|
|
const columnSO = values[1];
|
|
|
if(!Types.INTEGER.isCompatible(lineSO.type)) {
|
|
|
- // TODO: better error message
|
|
|
- //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS
|
|
|
- return Promise.reject(new Error("Array dimension must be of type int"));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(exp.sourceInfo));
|
|
|
}
|
|
|
const line = lineSO.number;
|
|
|
let column = null;
|
|
|
if(columnSO !== null) {
|
|
|
if(!Types.INTEGER.isCompatible(columnSO.type)) {
|
|
|
- // TODO: better error message
|
|
|
- //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS
|
|
|
- return Promise.reject(new Error("Array dimension must be of type int"));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(exp.sourceInfo));
|
|
|
}
|
|
|
column = columnSO.number;
|
|
|
}
|
|
|
|
|
|
if (line >= mustBeArray.lines) {
|
|
|
- // TODO: better error message
|
|
|
- return Promise.reject(new Error(`${exp.id}: index out of bounds: ${lines}`));
|
|
|
+ if(mustBeArray.isVector) {
|
|
|
+ return Promise.reject(ProcessorErrorFactory.vector_line_outbounds_full(exp.id, line, mustBeArray.lines, exp.sourceInfo));
|
|
|
+ } else {
|
|
|
+ return Promise.reject(ProcessorErrorFactory.matrix_line_outbounds_full(exp.id, line, mustBeArray.lines, exp.sourceInfo));
|
|
|
+ }
|
|
|
+ } else if (line < 0) {
|
|
|
+ throw ProcessorErrorFactory.array_dimension_not_positive_full(exp.sourceInfo);
|
|
|
}
|
|
|
if (column !== null && mustBeArray.columns === null ){
|
|
|
- // TODO: better error message
|
|
|
- return Promise.reject(new Error(`${exp.id}: index out of bounds: ${column}`));
|
|
|
+ return Promise.reject(ProcessorErrorFactory.vector_not_matrix_full(exp.id, exp.sourceInfo));
|
|
|
}
|
|
|
- if(column !== null && column >= mustBeArray.columns) {
|
|
|
- // TODO: better error message
|
|
|
- return Promise.reject(new Error(`${exp.id}: index out of bounds: ${column}`));
|
|
|
+ if(column !== null ) {
|
|
|
+ if (column >= mustBeArray.columns) {
|
|
|
+ return Promise.reject(ProcessorErrorFactory.matrix_column_outbounds_full(exp.id, column,mustBeArray.columns, exp.sourceInfo));
|
|
|
+ } else if (column < 0) {
|
|
|
+ throw ProcessorErrorFactory.array_dimension_not_positive_full(exp.sourceInfo);
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
return Promise.resolve(new StoreObjectArrayAddress(mustBeArray.id, line, column, store));
|
|
|
});
|
|
@@ -753,8 +797,9 @@ export class IVProgProcessor {
|
|
|
return $left.then( left => {
|
|
|
const resultType = resultTypeAfterUnaryOp(unaryApp.op, left.type);
|
|
|
if (Types.UNDEFINED.isCompatible(resultType)) {
|
|
|
- // TODO: better urgent error message
|
|
|
- return Promise.reject(new Error(`Cannot use this op to ${left.type}`));
|
|
|
+ const stringInfo = left.type.stringInfo();
|
|
|
+ const info = stringInfo[0];
|
|
|
+ return Promise.reject(ProcessorErrorFactory.invalid_unary_op_full(unaryApp.op, info.type, info.dim, unaryApp.sourceInfo));
|
|
|
}
|
|
|
switch (unaryApp.op.ord) {
|
|
|
case Operators.ADD.ord:
|
|
@@ -764,7 +809,7 @@ export class IVProgProcessor {
|
|
|
case Operators.NOT.ord:
|
|
|
return new StoreObject(resultType, !left.value);
|
|
|
default:
|
|
|
- return Promise.reject(new Error('!!!Critical Invalid UnaryApp '+ unaryApp.op));
|
|
|
+ return Promise.reject(new RuntimeError('!!!Critical Invalid UnaryApp '+ unaryApp.op));
|
|
|
}
|
|
|
});
|
|
|
}
|
|
@@ -777,8 +822,12 @@ export class IVProgProcessor {
|
|
|
const right = values[1];
|
|
|
const resultType = resultTypeAfterInfixOp(infixApp.op, left.type, right.type);
|
|
|
if (Types.UNDEFINED.isCompatible(resultType)) {
|
|
|
- // TODO: better urgent error message
|
|
|
- return Promise.reject(new Error(`Cannot use this ${infixApp.op} to ${left.type} and ${right.type}`));
|
|
|
+ const stringInfoLeft = left.type.stringInfo();
|
|
|
+ const infoLeft = stringInfoLeft[0];
|
|
|
+ const stringInfoRight = right.type.stringInfo();
|
|
|
+ const infoRight = stringInfoRight[0];
|
|
|
+ return Promise.reject(ProcessorErrorFactory.invalid_infix_op_full(infixApp.op, infoLeft.type, infoLeft.dim,
|
|
|
+ infoRight.type,infoRight.dim,infixApp.sourceInfo));
|
|
|
}
|
|
|
let result = null;
|
|
|
switch (infixApp.op.ord) {
|
|
@@ -872,7 +921,7 @@ export class IVProgProcessor {
|
|
|
case Operators.OR.ord:
|
|
|
return new StoreObject(resultType, left.value || right.value);
|
|
|
default:
|
|
|
- return Promise.reject(new Error('!!!Critical Invalid InfixApp '+ infixApp.op));
|
|
|
+ return Promise.reject(new RuntimeError('!!!Critical Invalid InfixApp '+ infixApp.op));
|
|
|
}
|
|
|
});
|
|
|
}
|
|
@@ -887,7 +936,7 @@ export class IVProgProcessor {
|
|
|
break;
|
|
|
}
|
|
|
default: {
|
|
|
- throw new Error("Three dimensional array address...");
|
|
|
+ throw new RuntimeError("Three dimensional array address...");
|
|
|
}
|
|
|
}
|
|
|
} else {
|