|  | @@ -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 {
 |