Bladeren bron

Implement the ProcessorErrorFactory methods for semantic errors

-Change expresion subclasses toString impementation

-Implement a helper function stringInfo in the Type classes
Lucas de Souza 5 jaren geleden
bovenliggende
commit
52ec99c738

+ 19 - 4
i18n/pt/error.json

@@ -17,24 +17,39 @@
   "invalid_global_var": "Erro crítico: Chamada inválida da função initGlobal fora do contexto BASE",
   "not_implemented": "Erro interno crítico: A função definida pelo sistema $0 não foi implementada.",
   "function_missing": "A função $0 não foi encontrada",
+  "function_missing_full": "A função $0 na linha: $1, coluna: $2 não foi encontrada",
   "invalid_parameters_size": "A quantidade de parâmetros fornecidos está incorreta. Esperava-se $0, encontrou-se $1",
   "invalid_ref": "Você deve fornecer apenas um identificador como parâmetro",
   "invalid_parameter_type": "O valor fornecido como parâmetro é do tipo $0, mas o tipo esperado é $1",
-  "unknown_command": "Erro interno crítico: Comando desconhecido encontrado",
+  "unknown_command": "Erro interno crítico: Comando desconhecido ($0) 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",
+  "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": "A função $0 deve retornar um tipo $1, ao invés de $1",
+  "invalid_return_type": "A função $0 deve retornar um tipo $1, ao invés de $2",
   "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": "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",
   "invalid_array_access": "Identificador $0 não se refere a um vetor/matriz válido",
   "column_outbounds": "Número de colunas $0 é inválido para a matriz $1 que possui $2 colunas",
-  "line_outbounds": "Número de linhas $0 é invaálido para a matriz $1 que possui $2 linhas",
+  "line_outbounds": "Número de linhas $0 é inválido para a matriz $1 que possui $2 linhas",
   "invalid_infix_op": "Não é possível aplicar a operação $0 entre os tipos $1 e $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.",
   "duplicate_variable": "A variável $0 na linha: $1, coluna: $2 já foi declarada anteriormente.",
-  "main_parameters": "A função inicio não pode ter parâmetros."
+  "main_parameters": "A função inicio não pode ter parâmetros.",
+  "symbol_not_found_full": "A variável $0 na linha: $1, coluna: $2 não foi declarada",
+  "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.",
+  "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."
 }

+ 3 - 1
i18n/pt/ui.json

@@ -22,5 +22,7 @@
   "text_read_var": "Leitura de dados",
   "text_write_var": "Escrita de dados",
   "text_comment": "Comentário",
-  "join_or": "ou"
+  "join_or": "ou",
+  "matrix_string": "matriz de $0",
+  "vector_string": "vetor de $0"
 }

+ 13 - 0
js/ast/expressions/arrayAccess.js

@@ -8,4 +8,17 @@ export class ArrayAccess extends Expression {
 		this.line = line;
 		this.column = column;
 	}
+
+	toString () {
+		const strLine = this.line.toString();
+		let strColumn = null;
+		if(this.column) {
+			strColumn = this.column.toString();
+		}
+		if(strColumn) {
+			return `${this.id}[${strLine}][${strColumn}]`;
+		} else {
+			return `${this.id}[${strLine}]`;
+		}
+	}
 }

+ 5 - 0
js/ast/expressions/arrayLiteral.js

@@ -79,4 +79,9 @@ export class ArrayLiteral extends Literal {
     }
     return valid;
   }
+
+  toString () {
+    const strList = this.value.map(arrayLiteral => arrayLiteral.toString());
+    return "{" + strList.join(',') + "}";
+  }
 }

+ 5 - 0
js/ast/expressions/boolLiteral.js

@@ -1,5 +1,6 @@
 import { Literal } from './literal';
 import { Types } from './../../typeSystem/types';
+import { convertBoolToString } from "./../../typeSystem/parsers";
 
 export class BoolLiteral extends Literal {
   
@@ -7,4 +8,8 @@ export class BoolLiteral extends Literal {
     super(Types.BOOLEAN);
     this.value = value;
   }
+
+  toString () {
+    return convertBoolToString(this.value);
+  }
 }

+ 18 - 0
js/ast/expressions/functionCall.js

@@ -1,4 +1,5 @@
 import { Expression } from './expression';
+import { LanguageDefinedFunction } from '../../processor/definedFunctions';
 
 export class FunctionCall extends Expression {
 
@@ -15,4 +16,21 @@ export class FunctionCall extends Expression {
 	get parametersSize () {
 		return this.actualParameters.length;
 	}
+
+	toString () {
+		let name = null;
+		if(this.isMainCall) {
+			name = LanguageDefinedFunction.getMainFunctionName();
+		} else {
+			name = LanguageDefinedFunction.getLocalName(this.id);
+		}
+		let params = null;
+		if(this.actualParameters.length == 0) {
+			params = "()";
+		} else {
+			const strParams = this.actualParameters.map(v => v.toString());
+			params = "(" + strParams.join(",") + ")";
+		}
+		return name + params;
+	}
 }

+ 7 - 0
js/ast/expressions/infixApp.js

@@ -8,4 +8,11 @@ export class InfixApp extends Expression {
     this.left = left;
     this.right = right;
   }
+
+  toString () {
+    const l = this.left.toString();
+    const op = this.op.value;
+    const r = this.right.toString();
+    return l + op + r;
+  }
 }

+ 5 - 0
js/ast/expressions/intLiteral.js

@@ -1,5 +1,6 @@
 import { Literal } from './literal';
 import { Types } from './../../typeSystem/types';
+import { convertToString } from './../../typeSystem/parsers';
 
 export class IntLiteral extends Literal {
   
@@ -7,4 +8,8 @@ export class IntLiteral extends Literal {
     super(Types.INTEGER);
     this.value = value;
   }
+
+  toString() {
+    return convertToString(this.value, this.type);
+  }
 }

+ 5 - 0
js/ast/expressions/realLiteral.js

@@ -1,5 +1,6 @@
 import { Literal } from './literal';
 import { Types } from './../../typeSystem/types';
+import { convertToString } from './../../typeSystem/parsers';
 
 export class RealLiteral extends Literal {
   
@@ -7,4 +8,8 @@ export class RealLiteral extends Literal {
     super(Types.REAL);
     this.value = value;
   }
+
+  toString() {
+    return convertToString(this.value, this.type);
+  }
 }

+ 4 - 0
js/ast/expressions/stringLiteral.js

@@ -7,4 +7,8 @@ export class StringLiteral extends Literal {
     super(Types.STRING);
     this.value = value;
   }
+
+  toString() {
+    return this.value;
+  }
 }

+ 6 - 0
js/ast/expressions/unaryApp.js

@@ -5,4 +5,10 @@ export class UnaryApp extends InfixApp {
   constructor (op, left) {
     super(op, left, null);
   }
+
+  toString () {
+    const l = this.left.toString();
+    const op = this.op.value;
+    return op + l;
+  }
 }

+ 4 - 0
js/ast/expressions/variableLiteral.js

@@ -7,4 +7,8 @@ export class VariableLiteral extends Literal {
     super(Types.UNDEFINED);
     this.id = id;
   }
+
+  toString () {
+    return this.id;
+  }
 }

+ 3 - 1
js/main.js

@@ -1,5 +1,6 @@
 import { IVProgParser } from './ast/ivprogParser';
 import { IVProgProcessor } from './processor/ivprogProcessor';
+import { SemanticAnalyser } from "./processor/semantic/semanticAnalyser";
 import {DOMInput} from './io/domInput';
 import {DOMOutput} from './io/domOutput';
 import { LanguageService } from './services/languageService';
@@ -31,7 +32,8 @@ try {
     const analiser = new IVProgParser(input, ivprogLexer);
     try {
       const data = analiser.parseTree();
-      const proc = new IVProgProcessor(data);
+      const semAna = new SemanticAnalyser(data);
+      const proc = new IVProgProcessor(semAna.analyseTree());
       proc.registerInput(domIn);
       domOut.clear();
       proc.registerOutput(domOut);

+ 12 - 0
js/processor/definedFunctions.js

@@ -113,4 +113,16 @@ export const LanguageDefinedFunction = Object.freeze({
     }
     return funcsObject[internalName];
   },
+  getLocalName: (internalName) => {
+    if (internalName.indexOf(".") !== -1) {
+      const names = internalName.split(".");
+      const libName = LanguageService.getCurrentLangLibs()[names[0]];
+      const funName = LanguageService.getCurrentLangFuncs()[names[1]];
+      return `${libName}.${funName}`;
+    } else if (LanguageService.getCurrentLangFuncs()[internalName]) {
+      return LanguageService.getCurrentLangFuncs()[internalName];
+    } else { 
+      return internalName
+    }
+  }
 });

+ 124 - 1
js/processor/error/processorErrorFactory.js

@@ -2,6 +2,129 @@ import { RuntimeError } from './runtimeError';
 import { SemanticError } from './semanticError';
 import { LocalizedStrings } from './../../services/localizedStringsService';
 
+function translateType (type, dim) {
+  switch (dim) {
+    case 0:
+      return LocalizedStrings.getUI(type);
+    default:
+      const transType = LocalizedStrings.getUI(type);
+      if(dim === 1)
+        return LocalizedStrings.getUI("vector_string", [transType])
+      else
+        return LocalizedStrings.getUI("matrix_string", [transType])
+  }
+}
+
 export const ProcessorErrorFactory  = Object.freeze({
-  
+  symbol_not_found_full: (id, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [id, sourceInfo.line, sourceInfo.column];
+      return new SemanticError(LocalizedStrings.getError("symbol_not_found_full", context));
+    } else {
+      return ProcessorErrorFactory.symbol_not_found(id);
+    }
+  },
+  symbol_not_found: (id) => {
+    const context = [id];
+    return new SemanticError(LocalizedStrings.getError("symbol_not_found", context));
+  },
+  function_missing_full: (id, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [id, sourceInfo.line, sourceInfo.column];
+      return new SemanticError(LocalizedStrings.getError("function_missing_full", context));
+    } else {
+      return ProcessorErrorFactory.function_missing(id);
+    }
+  },
+  function_missing: (id) => {
+    const context = [id];
+    return new SemanticError(LocalizedStrings.getError("function_missing", context));
+  },
+  main_missing: () => {
+    return new SemanticError(LocalizedStrings.getError("main_missing"));
+  },
+  array_dimension_not_int_full: (sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line];
+      return new SemanticError(LocalizedStrings.getError("array_dimension_not_int_full", context));
+    } else {
+      return ProcessorErrorFactory.array_dimension_not_int();
+    }
+  },
+  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));
+  },
+  incompatible_types_full: (type, dim, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [translateType(type, dim), sourceInfo.line, sourceInfo.column];
+      return new SemanticError(LocalizedStrings.getError("incompatible_types_full", context));
+    } else {
+      return ProcessorErrorFactory.incompatible_types(type, dim);
+    }
+  },
+  incompatible_types: (type, dim) => {
+    const context = [translateType(type, dim)];
+    return new SemanticError(LocalizedStrings.getError("incompatible_types", context));
+  },
+  incompatible_types_array_full: (exp, type, dim, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [exp, translateType(type, dim), sourceInfo.line, sourceInfo.column];
+      return new SemanticError(LocalizedStrings.getError("incompatible_types_array_full", context));
+    } else {
+      return ProcessorErrorFactory.incompatible_types_array(exp, type, dim);
+    }
+  },
+  incompatible_types_array: (exp, type, dim) => {
+    const context = [exp, translateType(type, dim)];
+    return new SemanticError(LocalizedStrings.getError("incompatible_types_array", context));
+  },
+  loop_condition_type_full: (sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, sourceInfo.column];
+      return new SemanticError(LocalizedStrings.getError("loop_condition_type_full", context));
+    } else {
+      return ProcessorErrorFactory.loop_condition_type();
+    }
+  },
+  loop_condition_type: () => {
+    return new SemanticError(LocalizedStrings.getError("loop_condition_type"));
+  },
+  for_condition_type_full: (sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, sourceInfo.column];
+      return new SemanticError(LocalizedStrings.getError("for_condition_type_full", context));
+    } else {
+      return ProcessorErrorFactory.for_condition_type();
+    }
+  },
+  for_condition_type: () => {
+    return new SemanticError(LocalizedStrings.getError("for_condition_type"));
+  },
+  if_condition_type_full: (sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, sourceInfo.column];
+      return new SemanticError(LocalizedStrings.getError("if_condition_type_full", context));
+    } else {
+      return ProcessorErrorFactory.if_condition_type();
+    }
+  },
+  if_condition_type: () => {
+    return new SemanticError(LocalizedStrings.getError("if_condition_type"));
+  },
+  invalid_case_type_full: (exp, type, dim, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [exp, translateType(type, dim), sourceInfo.line, sourceInfo.column];
+      return new SemanticError(LocalizedStrings.getError("invalid_case_type_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_case_type(exp, type, dim);
+    }
+  },
+  invalid_case_type: (exp, type, dim) => {
+    const context = [exp, translateType(type, dim)];
+    return new SemanticError(LocalizedStrings.getError("invalid_case_type", context));
+  }
 });

+ 1 - 1
js/processor/ivprogProcessor.js

@@ -205,7 +205,7 @@ 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);

+ 65 - 36
js/processor/semantic/semanticAnalyser.js

@@ -43,7 +43,7 @@ export class SemanticAnalyser {
       if(symMap.next) {
         return this.findSymbol(id, symMap.next);
       }
-      throw new Error("variable not defined "+id);
+      return null;
     } else {
       return symMap.map[id];
     }
@@ -57,14 +57,13 @@ export class SemanticAnalyser {
     if(name.match(/^\$.+$/)) {
       const fun = LanguageDefinedFunction.getFunction(name);
       if(!!!fun) {
-        throw new Error("!!!Internal Error. Language defined function not implemented -> " + name + "!!!");
+        throw ProcessorErrorFactory.unknown_command(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.`);
+        return null;
       }
       return val;
     }
@@ -77,12 +76,9 @@ export class SemanticAnalyser {
     const functions = this.ast.functions;
     const mainFunc = functions.filter((f) => f.name === null);
     if (mainFunc.length <= 0) {
-      throw new Error("no main func...");
-    } else if (mainFunc.length > 1) {
-      throw new Error("only one main func...");
+      throw ProcessorErrorFactory.main_missing();
     }
     for (let i = 0; i < functions.length; i++) {
-
       const fun = functions[i];
       this.assertFunction(fun);
     }
@@ -100,12 +96,12 @@ export class SemanticAnalyser {
       if(declaration.initial === null) {
         const lineType = this.evaluateExpressionType(declaration.lines);
         if (!lineType.isCompatible(Types.INTEGER)) {
-          throw new Error("dim must be int");
+          throw ProcessorErrorFactory.array_dimension_not_int_full(declaration.sourceInfo);
         }
         if (declaration.columns !== null) {
           const columnType = this.evaluateExpressionType(declaration.columns);
           if (!columnType.isCompatible(Types.INTEGER)) {
-            throw new Error("dim must be int");
+            throw ProcessorErrorFactory.array_dimension_not_int_full(declaration.sourceInfo);
           }
         }
         this.insertSymbol(declaration.id, {id: declaration.id, lines: declaration.lines, columns: declaration.columns, type: declaration.type});
@@ -122,11 +118,15 @@ export class SemanticAnalyser {
       const resultType = this.evaluateExpressionType(declaration.initial);
       if(resultType instanceof MultiType) {
         if(!resultType.isCompatible(declaration.type)) {
-          throw new Error('Invalid type');  
+          const stringInfo = declaration.type.stringInfo();
+          const info = stringInfo[0];
+          throw ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, declaration.sourceInfo);
         }
         this.insertSymbol(declaration.id, {id: declaration.id, type: declaration.type})
       } else if(!declaration.type.isCompatible(resultType)) {
-        throw new Error('Invalid type');
+        const stringInfo = declaration.type.stringInfo();
+        const info = stringInfo[0];
+        throw ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, declaration.sourceInfo);
       } else {
         this.insertSymbol(declaration.id, {id: declaration.id, type: declaration.type})
       }
@@ -150,6 +150,9 @@ export class SemanticAnalyser {
         throw new Error("void return used in expression");
       }
       const fun = this.findFunction(expression.id);
+      if(fun === null) {
+        throw ProcessorErrorFactory.function_missing_full(expression.id, expression.sourceInfo);
+      }
       if (fun.returnType.isCompatible(Types.VOID)) {
         throw new Error("void return used in expression");
       }
@@ -157,12 +160,15 @@ export class SemanticAnalyser {
       return fun.returnType;
     } else if (expression instanceof ArrayAccess) {
       const arrayTypeInfo = this.findSymbol(expression.id, this.symbolMap);
+      if(arrayTypeInfo === null) {
+        throw ProcessorErrorFactory.symbol_not_found_full(expression.id, expression.sourceInfo);
+      }
       if (!(arrayTypeInfo.type instanceof CompoundType)) {
         throw new Error("it's not an array");
       }
       const lineType = this.evaluateExpressionType(expression.line);
       if (!lineType.isCompatible(Types.INTEGER)) {
-        throw new Error("line must be integer");
+        throw ProcessorErrorFactory.array_dimension_not_int_full(expression.sourceInfo);
       }
       if (expression.column !== null) {
         if (arrayTypeInfo.columns === null) {
@@ -170,7 +176,7 @@ export class SemanticAnalyser {
         }
         const columnType = this.evaluateExpressionType(expression.column);
         if(!columnType.isCompatible(Types.INTEGER)) {
-          throw new Error("column must be integer");
+          throw ProcessorErrorFactory.array_dimension_not_int_full(expression.sourceInfo);
         }
       }
       const arrType = arrayTypeInfo.type;
@@ -197,6 +203,9 @@ export class SemanticAnalyser {
       return literal.type;
     } else if (literal instanceof VariableLiteral) {
       const typeInfo = this.findSymbol(literal.id, this.symbolMap);
+      if(typeInfo === null) {
+        throw ProcessorErrorFactory.symbol_not_found_full(literal.id, literal.sourceInfo);
+      }
       if (typeInfo.type instanceof CompoundType) {
         return typeInfo.type;
       }
@@ -212,9 +221,10 @@ export class SemanticAnalyser {
           if(last === null) {
             last = e;
           } else if(!last.isCompatible(e)) {
-            throw new Error("invalid value type for array");
-          } else {
-            last = e;
+            const strInfo = last.stringInfo();
+            const info = strInfo[0];
+            const strExp = literal.toString();
+            throw ProcessorErrorFactory.incompatible_types_array_full(strExp,info.type, info.dim, literal.sourceInfo);
           }
         }
       }
@@ -231,7 +241,7 @@ export class SemanticAnalyser {
         // it's a vector...
         const dimType = this.evaluateExpressionType(lines);
         if (!dimType.isCompatible(Types.INTEGER)) {
-          throw new Error("dim must be int");
+          throw ProcessorErrorFactory.array_dimension_not_int_full(literal.sourceInfo);
         }
         if ((lines instanceof IntLiteral) && !lines.value.eq(literal.value.length)) {
           throw new Error("invalid array size");
@@ -239,7 +249,10 @@ export class SemanticAnalyser {
         literal.value.reduce((last, next) => {
           const eType = this.evaluateExpressionType(next);
           if (!last.canAccept(eType)) {
-            throw new Error("invalid value type for array");
+            const strInfo = last.stringInfo();
+            const info = strInfo[0];
+            const strExp = literal.toString();
+            throw ProcessorErrorFactory.incompatible_types_array_full(strExp,info.type, info.dim, literal.sourceInfo);
           }
           return last;
         }, type);
@@ -247,8 +260,7 @@ export class SemanticAnalyser {
       } else {
         const dimType = this.evaluateExpressionType(columns);
         if (!dimType.isCompatible(Types.INTEGER)) {
-          throw new Error("dim must be int");
-        }
+          throw ProcessorErrorFactory.array_dimension_not_int_full(literal.sourceInfo);        }
         if ((columns instanceof IntLiteral) && !columns.value.eq(literal.value.length)) {
           throw new Error("invalid array size");
         }
@@ -262,13 +274,18 @@ export class SemanticAnalyser {
 
       const resultType = this.evaluateExpressionType(literal);
       if (!(resultType instanceof CompoundType)) {
-        throw new Error("initial must be of type array");
+        const strInfo = type.stringInfo();
+        const info = strInfo[0];
+        const strExp = literal.toString();
+        throw ProcessorErrorFactory.incompatible_types_array_full(strExp,info.type, info.dim, literal.sourceInfo);
       }
       if (!type.isCompatible(resultType)) {
-        throw new Error("invalid array type");
+        const strInfo = type.stringInfo();
+        const info = strInfo[0];
+        const strExp = literal.toString();
+        throw ProcessorErrorFactory.incompatible_types_array_full(strExp,info.type, info.dim, literal.sourceInfo);
       }
       return true;
-
     }
   }
 
@@ -304,7 +321,7 @@ export class SemanticAnalyser {
     if (cmd instanceof While) {
       const resultType = this.evaluateExpressionType(cmd.expression);
       if (!resultType.isCompatible(Types.BOOLEAN)) {
-        throw new Error("condition not boolean");
+        throw ProcessorErrorFactory.loop_condition_type_full(cmd.sourceInfo);
       }
       this.checkCommands(type, cmd.commands, optional);
       return false;
@@ -312,7 +329,7 @@ export class SemanticAnalyser {
       this.checkCommand(type, cmd.assignment, optional);
       const resultType = this.evaluateExpressionType(cmd.condition);
       if (!resultType.isCompatible(Types.BOOLEAN)) {
-        throw new Error("condition not boolean");
+        throw ProcessorErrorFactory.for_condition_type_full(cmd.sourceInfo);
       }
       this.checkCommand(type, cmd.increment, optional);
       this.checkCommands(type, cmd.commands, optional);
@@ -326,7 +343,10 @@ export class SemanticAnalyser {
         if (aCase.expression !== null) {
           const caseType = this.evaluateExpressionType(aCase.expression);
           if (!sType.isCompatible(caseType)) {
-            throw new Error("invalid type in case");
+            const strInfo = sType.stringInfo();
+            const info = strInfo[0];
+            const strExp = aCase.expression.toString();
+            throw ProcessorErrorFactory.invalid_case_type_full(strExp, info.type, info.dim, aCase.sourceInfo);
           }
         } else {
           hasDefault = true;
@@ -337,6 +357,9 @@ export class SemanticAnalyser {
 
     } else if (cmd instanceof ArrayIndexAssign) {
       const typeInfo = this.findSymbol(cmd.id, this.symbolMap);
+      if(typeInfo === null) {
+        throw ProcessorErrorFactory.symbol_not_found_full(cmd.id, cmd.sourceInfo);
+      }
       if(!(typeInfo.type instanceof CompoundType)) {
         throw new Error(cmd.id + " is not an array.");
       }
@@ -344,7 +367,7 @@ export class SemanticAnalyser {
       const lineExp = cmd.line;
       const lineType = this.evaluateExpressionType(lineExp);
       if (!lineType.isCompatible(Types.INTEGER)) {
-        throw new Error("array dimension must be of type int");
+        throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
       }
       const columnExp = cmd.column;
       if (typeInfo.columns === null && columnExp !== null) {
@@ -352,7 +375,7 @@ export class SemanticAnalyser {
       } else if (columnExp !== null) {
         const columnType = this.evaluateExpressionType(columnExp);
         if (!columnType.isCompatible(Types.INTEGER)) {
-          throw new Error("array dimension must be of type int");
+          throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
         }
       }
       // exp can be a arrayLiteral, a single value exp or an array access
@@ -364,16 +387,23 @@ export class SemanticAnalyser {
       return optional;
     } else if (cmd instanceof Assign) {
       const typeInfo = this.findSymbol(cmd.id, this.symbolMap);
+      if(typeInfo === null) {
+        throw ProcessorErrorFactory.symbol_not_found_full(cmd.id, cmd.sourceInfo);
+      }
       const exp = cmd.expression;
       if(exp instanceof ArrayLiteral) {
         if(!(typeInfo.type instanceof CompoundType)) {
-          throw new Error("type not compatible");
+          const stringInfo = typeInfo.type.stringInfo();
+          const info = stringInfo[0];
+          throw ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, cmd.sourceInfo);
         }
         this.evaluateArrayLiteral(typeInfo.lines, typeInfo.columns, typeInfo.type, exp);
       } else {
         const resultType = this.evaluateExpressionType(exp);
         if(!resultType.isCompatible(typeInfo.type)) {
-          throw new Error("type not compatible");
+          const stringInfo = typeInfo.type.stringInfo();
+          const info = stringInfo[0];
+          throw ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, cmd.sourceInfo);
         }
       }
       return optional;
@@ -382,7 +412,7 @@ export class SemanticAnalyser {
     } else if (cmd instanceof IfThenElse) {
       const resultType = this.evaluateExpressionType(cmd.condition);
       if (!resultType.isCompatible(Types.BOOLEAN)) {
-        throw new Error("condition not boolean");
+        throw ProcessorErrorFactory.if_condition_type_full(cmd.sourceInfo);
       }
       if(cmd.ifFalse instanceof IfThenElse) {
         return this.checkCommands(type, cmd.ifTrue.commands, optional) && this.checkCommand(type, cmd.ifFalse, optional);
@@ -397,6 +427,9 @@ export class SemanticAnalyser {
       } else {
         fun = this.findFunction(cmd.id);
       }
+      if(fun === null) {
+        throw ProcessorErrorFactory.function_missing_full(cmd.id, cmd.sourceInfo);
+      }
       this.assertParameters(fun, cmd.actualParameters);
       return optional;
     } else if (cmd instanceof Return) {
@@ -451,10 +484,6 @@ export class SemanticAnalyser {
           throw new Error(`Parameter ${formalParam.id} is not compatible with the value given.`);
         }
       } else if(!formalParam.type.isCompatible(resultType)) {
-        console.log("####");
-        console.log(resultType);
-        console.log("####");
-        console.log(formalParam.type);
         throw new Error(`Parameter ${formalParam.id} is not compatible with the value given.`);
       }
 

+ 4 - 3
js/typeSystem/baseTypes.js

@@ -16,11 +16,12 @@ class BaseType {
   }
 }
 
+// Base types names are the same as i18n ui type keys
 export const BaseTypes = Object.freeze({
-  INTEGER: new BaseType("int", 0),
+  INTEGER: new BaseType("integer", 0),
   REAL: new BaseType("real", 1),
-  STRING: new BaseType("string", 2),
-  BOOLEAN: new BaseType("bool", 3),
+  STRING: new BaseType("text", 2),
+  BOOLEAN: new BaseType("boolean", 3),
   VOID: new BaseType("void", 4),
   UNDEFINED: new BaseType("undefined", 5)
 })

+ 8 - 0
js/typeSystem/compoundType.js

@@ -18,6 +18,14 @@ export class CompoundType extends Type {
     return false;
   }
 
+  stringInfo () {
+    const list = this.innerType.stringInfo();
+    list.forEach(v => {
+      v.dim = this.dimensions;
+    });
+    return list;
+  }
+
   canAccept (another) {
     if(another instanceof CompoundType) {
       return this.dimensions > another.dimensions && this.innerType.isCompatible(another.innerType);

+ 9 - 0
js/typeSystem/multiType.js

@@ -15,6 +15,15 @@ export class MultiType extends Type {
     return null;
   }
 
+  stringInfo () {
+    let list = [];
+    for (let i = 0; i < this.types.length; i++) {
+      const t = this.types[i];
+      list = list.concat(t.stringInfo());
+    }
+    return list;
+  }
+
   isCompatible (another) {
     if(another instanceof Type) {
       for (let i = 0; i < this.types.length; i++) {

+ 4 - 0
js/typeSystem/type.js

@@ -12,6 +12,10 @@ export class Type {
     return this.baseType.ord;
   }
 
+  stringInfo () {
+    return [{type: this.baseType.name, dim: 0}];
+  }
+
   isCompatible (another) {
     if(another instanceof Type) {
       return this.baseType.isCompatible(another.baseType);