Ver código fonte

Implement negative index error message

Implement endless loop error message

Implement logical operators translation

Implement array literal type, column and line erro messages
Lucas de Souza 6 anos atrás
pai
commit
39c6d44d1e

+ 23 - 10
i18n/pt/error.json

@@ -24,22 +24,25 @@
   "invalid_ref": "A expressão $0 fornecida como parâmetro para a função $1 não é válida para esta função. Use uma variável ou posição de vetor.",
   "invalid_parameter_type_full": "A expressão $0 fornecida como parâmetro para a função $1 na linha $2 não é compatível com o tipo esperado.",
   "invalid_parameter_type": "A expressão $0 fornecida como parâmetro para a função $1 não é compatível com o tipo esperado.",
-  "unknown_command": "Erro interno crítico: Comando desconhecido ($0) encontrado",
+  "unknown_command_full": "Erro interno crítico: comando desconhecido encontrado na linha $0",
+  "unknown_command": "Erro interno crítico: comando desconhecido encontrado!",
   "loop_condition_type_full": "Erro na linha: $0, coluna $1: a condição dos laços de repetição deve ser do tipo lógico",
   "loop_condition_type": "A condição dos laços de repetição deve ser do tipo lógico",
+  "endless_loop_full": "Possível laço infinito detectado no seu código. Verifique a linha $0",
+  "endless_loop": "Possível laço infinito detectado no seu código.",
   "for_condition_type_full": "Erro na linha: $0, coluna $1: a condição de parada do comando para(...) deve ser do tipo lógico",
   "for_condition_type": "A condição de parada do comando para(...) deve ser do tipo lógico",
   "if_condition_type_full": "Erro na linha: $0, coluna $1: a condição de um comando se...senao deve ser do tipo lógico",
   "if_condition_type": "A condição de um comando se...senao deve ser do tipo lógico",
-  "invalid_return_type_full": "Erro na linha $0: a expressão não produz um tipo compatível com o retorno de tipo $1.",
-  "invalid_return_type": "A expressão não produz um tipo compatível com o retorno de tipo $0.",
+  "invalid_return_type_full": "Erro na linha $0: a expressão não produz um tipo compatível com a função $1. Tipo esperado: $2.",
+  "invalid_return_type": "A expressão não produz um tipo compatível com a função $0. Tipo esperado: $1.",
   "invalid_void_return_full": "Erro na linha $0: a função $1 não pode retornar uma expressão vazia, use uma espressão do tipo $2",
   "invalid_void_return": "A função $0 não pode retornar uma expressão vazia, use uma espressão do tipo $1",
-  "unexpected_break_command": "Erro interno crítico: Comando pare encontrado fora do contexto de um laço/escolha..caso",
+  "unexpected_break_command_full": "Erro interno crítico: comando pare encontrado fora do contexto de um laço/escolha..caso na linha $0",
+  "unexpected_break_command": "Erro interno crítico: comando pare encontrado fora do contexto de um laço/escolha..caso",
   "invalid_dimension": "As dimensões de um vetor/matriz devem ser do tipo inteiro",
-  "void_in_expression_full": "Erro na linha: $0, coluna: $1: a função $2 não pode ser utilizada aqui pois seu tipo de retorno é vazio",
-  "void_in_expression": "A função $0 não pode ser utilizada aqui pois seu tipo de retorno é vazio",
-  "invalid_array": "Expressão literal de Vetor/Mariz inválida",
+  "void_in_expression_full": "Erro na linha: $0, coluna: $1: a função $2 não pode ser utilizada em uma expressão pois seu tipo de retorno é vazio",
+  "void_in_expression": "A função $0 não pode ser utilizada em uma expressão pois seu tipo de retorno é vazio",
   "invalid_array_access_full": "Identificador $0 na linha: $1, coluna: $2 não se refere a um vetor/matriz válido",
   "invalid_array_access": "Identificador $0 não se refere a um vetor/matriz válido",
   "invalid_matrix_access_full": "Identificador $0 na linha: $1, coluna: $2 não se refere a uma matriz válida",
@@ -48,11 +51,13 @@
   "matrix_column_outbounds": "Número de colunas $0 é inválido para a matriz $1 que possui $2 colunas",
   "matrix_line_outbounds_full": "Erro na linha $0: número de linhas $1 é inválido para a matriz $2 que possui $3 linhas",
   "matrix_line_outbounds": "Número de linhas $0 é inválido para a matriz $1 que possui $2 linhas",
-  "vector_column_outbounds_full": "Erro na linha $0: número de colunas $1 é inválido para a matriz $2 que possui $3 colunas",
-  "vector_column_outbounds": "Número de colunas $0 é inválido para a matriz $1 que possui $2 colunas",
   "vector_line_outbounds_full": "Erro na linha $0: número de linhas $1 é inválido para a matriz $2 que possui $3 linhas",
   "vector_line_outbounds": "Número de linhas $0 é inválido para a matriz $1 que possui $2 linhas",
+  "vector_not_matrix_full": "Erro na linha $0: $1 não é uma matriz",
+  "vector_not_matrix": "$1 não é uma matriz",
+  "invalid_infix_op_full": "Erro na linha $0: não é possível aplicar a operação $1 entre os tipos $2 e $3",
   "invalid_infix_op": "Não é possível aplicar a operação $0 entre os tipos $1 e $2",
+  "invalid_unary_op_full": "Erro na linha $0: não é possível aplicar a operação $1 ao tipo $2",
   "invalid_unary_op": "Não é possível aplicar a operação $0 ao tipo $1",
   "unknown_op": "Erro interno crítico: Operação $0 desconhecida",
   "duplicate_function": "A função $0 na linha: $1, coluna: $2 já foi definida anteriormente.",
@@ -62,11 +67,19 @@
   "symbol_not_found": "A variável $0 não foi declarada",
   "array_dimension_not_int_full": "As dimensões de um vetor/matriz na linha: $0 devem ser do tipo inteiro.",
   "array_dimension_not_int": "As dimensões de um vetor/matriz devem ser do tipo inteiro.",
+  "array_dimension_not_positive_full": "As dimensões de um vetor/matriz na linha: $0 devem ser valores positivos.",
+  "array_dimension_not_positive": "As dimensões de um vetor/matriz devem ser valores positivos.",
   "incompatible_types_full": "O tipo $0 não é compatível com o tipo resultante da expressão na linha $1",
   "incompatible_types": "O tipo $0 não é compatível com o tipo resultante da expressão fornecida.",
   "incompatible_types_array_full": "A expressão $0 é incompatível com o tipo $1 na linha: $2, coluna: $3.",
   "incompatible_types_array": "A expressão $0 é incompatível com o tipo $1.",
   "invalid_case_type_full": "O caso $0 na linha $1 é incompatível com o tipo $2.",
   "invalid_case_type": "O caso $0 é incompatível com o tipo $1.",
-  "function_no_return": "A função $0 não possui um retorno acessível. Toda função deve ter ao menos um retorno no seu corpo principal."
+  "function_no_return": "A função $0 não possui um retorno acessível. Toda função deve ter ao menos um retorno no seu corpo principal.",
+  "invalid_array_literal_type_full": "Erro na linha $0: a expressão $1 não resulta em um tipo compatível.",
+  "invalid_array_literal_type": "A expressão $0 não resulta em um tipo compatível.",
+  "invalid_array_literal_line_full": "Erro na linha $0: esperava-se $1 linhas mas encontrou $2.",
+  "invalid_array_literal_line": "Esperava-se $0 linhas mas encontrou $1.",
+  "invalid_array_literal_column_full": "Erro na linha $0: esperava-se $1 colunas mas encontrou $2.",
+  "invalid_array_literal_column": "Esperava-se $0 colunas mas encontrou $1."
 }

+ 3 - 0
i18n/pt/ui.json

@@ -4,6 +4,9 @@
   "start": "inicio",
   "void": "vazio",
   "integer": "inteiro",
+  "and": "E",
+  "or": "OU",
+  "not": "nao",
   "real": "real",
   "program": "programa",
   "text": "cadeia",

+ 147 - 27
js/processor/error/processorErrorFactory.js

@@ -1,6 +1,7 @@
 import { RuntimeError } from './runtimeError';
 import { SemanticError } from './semanticError';
 import { LocalizedStrings } from './../../services/localizedStringsService';
+import { Operators } from '../../ast/operators';
 
 function translateType (type, dim) {
   switch (dim) {
@@ -15,6 +16,17 @@ function translateType (type, dim) {
   }
 }
 
+function translateOp (op) {
+  switch(op.ord) {
+    case Operators.AND.ord:
+    case Operators.OR.ord:
+    case Operators.NOT.ord:
+      return LocalizedStrings.getUI(op.value);
+    default:
+      return op.value;
+  }
+}
+
 export const ProcessorErrorFactory  = Object.freeze({
   symbol_not_found_full: (id, sourceInfo) => {
     if(sourceInfo) {
@@ -42,7 +54,7 @@ export const ProcessorErrorFactory  = Object.freeze({
   },
   main_missing: () => {
     return new SemanticError(LocalizedStrings.getError("main_missing"));
-  },
+  },        // TODO: better urgent error message
   array_dimension_not_int_full: (sourceInfo) => {
     if(sourceInfo) {
       const context = [sourceInfo.line];
@@ -54,9 +66,17 @@ export const ProcessorErrorFactory  = Object.freeze({
   array_dimension_not_int: () => {
     return new SemanticError(LocalizedStrings.getError("array_dimension_not_int"));
   },
-  unknown_command: (id)=> {
-    const context = [id];
-    return new SemanticError(LocalizedStrings.getError("unknown_command", context));
+  unknown_command_full: (sourceInfo)=> {
+    if(sourceInfo) {
+      const context = [sourceInfo.line];
+      return new RuntimeError(LocalizedStrings.getError("unknown_command_full", context));
+    } else {
+      return ProcessorErrorFactory.unknown_command();
+    }
+    
+  },
+  unknown_command: ()=> {
+    return new RuntimeError(LocalizedStrings.getError("unknown_command"));
   },
   incompatible_types_full: (type, dim, sourceInfo) => {
     if(sourceInfo) {
@@ -93,6 +113,17 @@ export const ProcessorErrorFactory  = Object.freeze({
   loop_condition_type: () => {
     return new SemanticError(LocalizedStrings.getError("loop_condition_type"));
   },
+  endless_loop_full: (sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line];
+      return new SemanticError(LocalizedStrings.getError("endless_loop_full", context));
+    } else {
+      return ProcessorErrorFactory.endless_loop();
+    }
+  },
+  endless_loop: () => {
+    return new SemanticError(LocalizedStrings.getError("endless_loop"));
+  },
   for_condition_type_full: (sourceInfo) => {
     if(sourceInfo) {
       const context = [sourceInfo.line, sourceInfo.column];
@@ -115,6 +146,13 @@ export const ProcessorErrorFactory  = Object.freeze({
   if_condition_type: () => {
     return new SemanticError(LocalizedStrings.getError("if_condition_type"));
   },
+  invalid_global_var: () => {
+    return new RuntimeError(LocalizedStrings.getError("invalid_global_var"))
+  },
+  not_implemented: (id) => {
+    const context  = [id]
+    return new RuntimeError(LocalizedStrings.getError("not_implemented", context))
+  },
   invalid_case_type_full: (exp, type, dim, sourceInfo) => {
     if(sourceInfo) {
       const context = [exp, translateType(type, dim), sourceInfo.line, sourceInfo.column];
@@ -166,50 +204,50 @@ export const ProcessorErrorFactory  = Object.freeze({
   matrix_column_outbounds_full: (id, value, columns, sourceInfo) => {
     if(sourceInfo) {
       const context = [sourceInfo.line, value, id, columns];
-      return new SemanticError(LocalizedStrings.getError("matrix_column_outbounds_full", context));
+      return new RuntimeError(LocalizedStrings.getError("matrix_column_outbounds_full", context));
     } else {
       return ProcessorErrorFactory.matrix_column_outbounds(id, value, columns);
     }
   },
   matrix_column_outbounds: (id, value, columns) => {
     const context = [value, id, columns];
-    return new SemanticError(LocalizedStrings.getError("matrix_column_outbounds", context));
+    return new RuntimeError(LocalizedStrings.getError("matrix_column_outbounds", context));
   },
   matrix_line_outbounds_full: (id, value, lines, sourceInfo) => {
     if(sourceInfo) {
       const context = [sourceInfo.line, value, id, lines];
-      return new SemanticError(LocalizedStrings.getError("matrix_line_outbounds_full", context));
+      return new RuntimeError(LocalizedStrings.getError("matrix_line_outbounds_full", context));
     } else {
       return ProcessorErrorFactory.matrix_line_outbounds(id, value, lines);
     }
   },
   matrix_line_outbounds: (id, value, lines) => {
     const context = [value, id, lines];
-    return new SemanticError(LocalizedStrings.getError("matrix_line_outbounds", context));
-  },
-  vector_column_outbounds_full: (id, value, columns, sourceInfo) => {
-    if(sourceInfo) {
-      const context = [sourceInfo.line, value, id, columns];
-      return new SemanticError(LocalizedStrings.getError("vector_column_outbounds_full", context));
-    } else {
-      return ProcessorErrorFactory.vector_column_outbounds(id, value, columns);
-    }
-  },
-  vector_column_outbounds: (id, value, columns) => {
-    const context = [value, id, columns];
-    return new SemanticError(LocalizedStrings.getError("vector_column_outbounds", context));
+    return new RuntimeError(LocalizedStrings.getError("matrix_line_outbounds", context));
   },
   vector_line_outbounds_full: (id, value, lines, sourceInfo) => {
     if(sourceInfo) {
       const context = [sourceInfo.line, value, id, lines];
-      return new SemanticError(LocalizedStrings.getError("vector_line_outbounds_full", context));
+      return new RuntimeError(LocalizedStrings.getError("vector_line_outbounds_full", context));
     } else {
       return ProcessorErrorFactory.vector_line_outbounds(id, value, lines);
     }
   },
   vector_line_outbounds: (id, value, lines) => {
     const context = [value, id, lines];
-    return new SemanticError(LocalizedStrings.getError("vector_line_outbounds", context));
+    return new RuntimeError(LocalizedStrings.getError("vector_line_outbounds", context));
+  },
+  vector_not_matrix_full: (id, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, id];
+      return new RuntimeError(LocalizedStrings.getError("vector_not_matrix_full", context));
+    } else {
+      return ProcessorErrorFactory.vector_not_matrix(id);
+    }
+  },
+  vector_not_matrix: (id) => {
+    const context = [id];
+    return new RuntimeError(LocalizedStrings.getError("vector_not_matrix", context));
   },
   function_no_return: (id) => {
     const context = [id];
@@ -239,16 +277,16 @@ export const ProcessorErrorFactory  = Object.freeze({
     const context = [id, translateType(type, dim)];
     return new SemanticError(LocalizedStrings.getError("invalid_return_type", context));
   },
-  invalid_parameters_size_full: (id, value, count, sourceInfo) => {
+  invalid_parameters_size_full: (id, expected, actual, sourceInfo) => {
     if(sourceInfo) {
-      const context = [sourceInfo.line, id, value, count];
+      const context = [sourceInfo.line, id, expected, actual];
       return new SemanticError(LocalizedStrings.getError("invalid_parameters_size_full", context));
     } else {
-      return ProcessorErrorFactory.invalid_parameters_size(id, value, count);
+      return ProcessorErrorFactory.invalid_parameters_size(id, expected, actual);
     }
   },
-  invalid_parameters_size: (id, value, count) => {
-    const context = [id, value, count];
+  invalid_parameters_size: (id, expected, actual) => {
+    const context = [id, expected, actual];
     return new SemanticError(LocalizedStrings.getError("invalid_parameters_size", context));
   },
   invalid_parameter_type_full: (id, exp, sourceInfo) => {
@@ -274,5 +312,87 @@ export const ProcessorErrorFactory  = Object.freeze({
   invalid_ref: (id, exp) => {
     const context = [exp, id];
     return new SemanticError(LocalizedStrings.getError("invalid_ref", context));
+  },
+  unexpected_break_command_full: (sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line];
+      return new RuntimeError(LocalizedStrings.getError("unexpected_break_command_full", context));
+    } else {
+      return ProcessorErrorFactory.unexpected_break_command();
+    }
+  },
+  unexpected_break_command: () => {
+    return new RuntimeError(LocalizedStrings.getError("unexpected_break_command"));
+  },
+  invalid_array_literal_type_full: (exp, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, exp];
+      return new RuntimeError(LocalizedStrings.getError("invalid_array_literal_type_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_array_literal_type(exp);
+    }
+  },
+  invalid_array_literal_type: (exp) => {
+    const context = [exp];
+    return new RuntimeError(LocalizedStrings.getError("invalid_array_literal_type", context));
+  },
+  invalid_array_literal_line_full: (expected, actual, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, expected, actual];
+      return new RuntimeError(LocalizedStrings.getError("invalid_array_literal_line_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_array_literal_type(expected, actual);
+    }
+  },
+  invalid_array_literal_line: (expected, actual) => {
+    const context = [expected, actual];
+    return new RuntimeError(LocalizedStrings.getError("invalid_array_literal_line", context));
+  },
+  invalid_array_literal_column_full: (expected, actual, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, expected, actual];
+      return new RuntimeError(LocalizedStrings.getError("invalid_array_literal_column_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_array_literal_column(expected, actual);
+    }
+  },
+  invalid_array_literal_column: (expected, actual) => {
+    const context = [expected, actual];
+    return new RuntimeError(LocalizedStrings.getError("invalid_array_literal_column", context));
+  },
+  invalid_unary_op_full: (opName, type, dim, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, translateOp(opName), translateType(type, dim)];
+      return new RuntimeError(LocalizedStrings.getError("invalid_unary_op_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_unary_op(opName, type, dim);
+    }
+  },
+  invalid_unary_op: (opName, type, dim) => {
+    const context = [translateOp(opName), translateType(type, dim)];
+    return new RuntimeError(LocalizedStrings.getError("invalid_unary_op", context));
+  },
+  invalid_infix_op_full: (opName, typeLeft, dimLeft, typeRight, dimRight,  sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, translateOp(opName), translateType(typeLeft, dimLeft), translateType(typeRight, dimRight)];
+      return new RuntimeError(LocalizedStrings.getError("invalid_infix_op_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_infix_op(opName, typeLeft, dimLeft, typeRight, dimRight);
+    }
+  },
+  invalid_infix_op: (opName, typeLeft, dimLeft, typeRight, dimRight) => {
+    const context = [translateOp(opName), translateType(typeLeft, dimLeft), translateType(typeRight, dimRight)];
+    return new RuntimeError(LocalizedStrings.getError("invalid_infix_op", context));
+  },
+  array_dimension_not_positive_full: (sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line];
+      return new SemanticError(LocalizedStrings.getError("array_dimension_not_positive_full", context));
+    } else {
+      return ProcessorErrorFactory.array_dimension_not_positive();
+    }
+  },
+  array_dimension_not_positive: () => {
+    return new SemanticError(LocalizedStrings.getError("array_dimension_not_positive"));
   }
 });

+ 137 - 88
js/processor/ivprogProcessor.js

@@ -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) {
@@ -206,11 +214,12 @@ export class IVProgProcessor {
     } else if (cmd instanceof Commands.Switch) {
       return this.executeSwitch(store, cmd);
     } 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 {

+ 28 - 14
js/processor/semantic/semanticAnalyser.js

@@ -17,6 +17,7 @@ export class SemanticAnalyser {
     const lexer = new this.lexerClass(null);
     this.literalNames = lexer.literalNames;
     this.symbolMap = null;
+    this.currentFunction = null;
   }
 
   pushMap () {
@@ -57,7 +58,7 @@ export class SemanticAnalyser {
     if(name.match(/^\$.+$/)) {
       const fun = LanguageDefinedFunction.getFunction(name);
       if(!!!fun) {
-        throw ProcessorErrorFactory.unknown_command(name);
+        throw ProcessorErrorFactory.not_implemented(name);
       }
       return fun;
     } else {
@@ -243,12 +244,17 @@ export class SemanticAnalyser {
         if (!dimType.isCompatible(Types.INTEGER)) {
           throw ProcessorErrorFactory.array_dimension_not_int_full(literal.sourceInfo);
         }
-        if ((lines instanceof IntLiteral) && !lines.value.eq(literal.value.length)) {
-          if(type.dimensions > 1) {
-            throw ProcessorErrorFactory.matrix_line_outbounds_full(id, literal.value.length, lines.values.toNumber(), literal.sourceInfo)
-          } else {
-            throw ProcessorErrorFactory.vector_line_outbounds_full(id, literal.value.length, lines.values.toNumber(), literal.sourceInfo)
+        if ((lines instanceof IntLiteral)) {
+          if (!lines.value.eq(literal.value.length)) {
+            if(type.dimensions > 1) {
+              throw ProcessorErrorFactory.matrix_line_outbounds_full(id, literal.value.length, lines.values.toNumber(), literal.sourceInfo)
+            } else {
+              throw ProcessorErrorFactory.vector_line_outbounds_full(id, literal.value.length, lines.values.toNumber(), literal.sourceInfo)
+            }
+          } else if (line.value.isNeg()) {
+            throw ProcessorErrorFactory.array_dimension_not_positive_full(literal.sourceInfo);
           }
+          
         }
         literal.value.reduce((last, next) => {
           const eType = this.evaluateExpressionType(next);
@@ -264,13 +270,19 @@ export class SemanticAnalyser {
       } else {
         const dimType = this.evaluateExpressionType(columns);
         if (!dimType.isCompatible(Types.INTEGER)) {
-          throw ProcessorErrorFactory.array_dimension_not_int_full(literal.sourceInfo);        }
-        if ((columns instanceof IntLiteral) && !columns.value.eq(literal.value.length)) {
-          if(type.dimensions > 1) {
-            throw ProcessorErrorFactory.matrix_column_outbounds_full(id, literal.value.length, columns.values.toNumber(), literal.sourceInfo)
-          } else {
-            throw ProcessorErrorFactory.invalid_matrix_access_full(id, literal.sourceInfo);
+          throw ProcessorErrorFactory.array_dimension_not_int_full(literal.sourceInfo);
+        }
+        if ((columns instanceof IntLiteral)) {
+          if (!columns.value.eq(literal.value.length)) {
+            if(type.dimensions > 1) {
+              throw ProcessorErrorFactory.matrix_column_outbounds_full(id, literal.value.length, columns.values.toNumber(), literal.sourceInfo)
+            } else {
+              throw ProcessorErrorFactory.invalid_matrix_access_full(id, literal.sourceInfo);
+            }
+          } else if (columns.value.isNeg()) {
+            throw ProcessorErrorFactory.array_dimension_not_positive_full(literal.sourceInfo);
           }
+          
         }
         for (let i = 0; i < columns; i++) {
           const anotherArray = literal.value[i];
@@ -299,6 +311,7 @@ export class SemanticAnalyser {
 
   assertFunction (fun) {
     this.pushMap();
+    this.currentFunction = fun;
     fun.formalParameters.forEach(formalParam => {
       if(formalParam.type instanceof CompoundType) {
         if(formalParam.type.dimensions > 1) {
@@ -441,16 +454,17 @@ export class SemanticAnalyser {
       this.assertParameters(fun, cmd.actualParameters);
       return optional;
     } else if (cmd instanceof Return) {
+      const funcName = this.currentFunction.isMain ? LanguageDefinedFunction.getMainFunctionName() : this.currentFunction.name
       if (cmd.expression === null && !type.isCompatible(Types.VOID)) {
         const stringInfo = type.stringInfo();
         const info = stringInfo[0];
-        throw ProcessorErrorFactory.invalid_void_return_full(info.type, info.dim, cmd.sourceInfo);
+        throw ProcessorErrorFactory.invalid_void_return_full(funcName, info.type, info.dim, cmd.sourceInfo);
       } else if (cmd.expression !== null) {
         const resultType = this.evaluateExpressionType(cmd.expression);
         if (!type.isCompatible(resultType)) {
           const stringInfo = type.stringInfo();
           const info = stringInfo[0];
-          throw ProcessorErrorFactory.invalid_return_type_full(info.type, info.dim, cmd.sourceInfo);
+          throw ProcessorErrorFactory.invalid_return_type_full(funcName, info.type, info.dim, cmd.sourceInfo);
         } else {
           return true;
         }

+ 19 - 7
js/processor/store/storeObjectArray.js

@@ -2,6 +2,18 @@ import { StoreObject } from './storeObject';
 
 export class StoreObjectArray extends StoreObject {
 
+  static get WRONG_LINE_NUMBER () {
+    return 1;
+  }
+
+  static get WRONG_TYPE () {
+    return 2;
+  }
+
+  static get WRONG_COLUMN_NUMBER () {
+    return 3;
+  }
+
   constructor (type, lines, columns, value = null, readOnly = false) {
     super(type, value, readOnly);
     this._lines = lines;
@@ -37,31 +49,31 @@ export class StoreObjectArray extends StoreObject {
     if (this.value !== null) {
       if( this.isVector) {
         if(this.value.length !== this.lines) {
-          return false;
+          return [StoreObjectArray.WRONG_LINE_NUMBER, this.value.length];;
         }
         const mustBeNull = this.value.find(v => !this.type.canAccept(v.type) );
         if(!!mustBeNull) {
-          return false;
+          return [StoreObjectArray.WRONG_TYPE, this.value.indexOf(mustBeNull)];;
         }
       }
-      return true;
+      return [];
     } else {
     if(this.lines !== this.value.length) {
-      return false;
+      return [StoreObjectArray.WRONG_LINE_NUMBER, this.value.length];
     }
     for (let i = 0; i < this.lines; i++) {
       for (let j = 0; j < this.columns; j++) {
         const arr = this.value[i];
         if(arr.length !== this.columns) {
-          return false;
+          return [StoreObjectArray.WRONG_COLUMN_NUMBER, arr.length];
         }
         const mustBeNull = arr.find(v => !this.type.canAccept(v.type) );
         if(!!mustBeNull) {
-          return false;
+          return [StoreObjectArray.WRONG_TYPE, i, arr.indexOf(mustBeNull)];
         }            
       }
     }
-      return true;
+      return [];
     }
   }
 }

+ 15 - 0
js/processor/store/storeObjectArrayAddress.js

@@ -1,6 +1,7 @@
 import { StoreObject } from './storeObject';
 import { StoreObjectArray } from './storeObjectArray';
 import { CompoundType } from '../../typeSystem/compoundType';
+import { ProcessorErrorFactory } from '../error/processorErrorFactory';
 
 export class StoreObjectArrayAddress extends StoreObject {
 
@@ -22,8 +23,22 @@ export class StoreObjectArrayAddress extends StoreObject {
 
   get refValue () {
     const refLine = this.store.applyStore(this.refID).value[this.line];
+    if(!refLine) {
+      if(this.getArrayObject().isVector) {
+        throw ProcessorErrorFactory.vector_line_outbounds(this.refID, this.line, this.getArrayObject().lines);
+      } else {
+        throw ProcessorErrorFactory.matrix_line_outbounds(this.refID, this.line, this.getArrayObject().lines);
+      }
+    }
     if (this.column !== null) {
       const refColumn = refLine.value[this.column];
+      if(!refColumn) {
+        if(this.getArrayObject().isVector) {
+          throw ProcessorErrorFactory.vector_not_matrix(this.refID);
+        } else {
+          throw ProcessorErrorFactory.matrix_column_outbounds(this.refID, this.column, this.getArrayObject().columns);
+        }
+      }
       return refColumn;
     }
     return refLine;