Преглед изворни кода

Caso de teste ok, cor dos comandos atualizada e escrever modificado

Douglas Lima пре 5 година
родитељ
комит
cdc48b4689
100 измењених фајлова са 1864 додато и 435 уклоњено
  1. 0 0
      css/ivprog-term (cópia).css
  2. 82 10
      css/ivprog-visual-1.0 (cópia).css
  3. 82 5
      css/ivprog-visual-1.0.css
  4. 0 0
      grammar/en/ivprog.g4
  5. 0 0
      grammar/en/langFunctions.js
  6. 0 0
      grammar/en/langLibs.js
  7. 0 0
      grammar/es/ivprog.g4
  8. 0 0
      grammar/es/langFunctions.js
  9. 0 0
      grammar/es/langLibs.js
  10. 0 0
      grammar/index.js
  11. 0 0
      grammar/pt/ivprog.g4
  12. 0 0
      grammar/pt/langFunctions.js
  13. 0 0
      grammar/pt/langLibs.js
  14. 0 0
      i18n/en/error.json
  15. 0 0
      i18n/en/index.js
  16. 0 0
      i18n/en/message.json
  17. 11 3
      i18n/en/ui.json
  18. 0 0
      i18n/es/error.json
  19. 0 0
      i18n/es/index.js
  20. 0 0
      i18n/es/message.json
  21. 11 3
      i18n/es/ui.json
  22. 0 0
      i18n/i18n-database.json
  23. 0 39
      i18n/i18n-engine.js
  24. 0 0
      i18n/index.js
  25. 0 0
      i18n/pt/error.json
  26. 0 0
      i18n/pt/index.js
  27. 0 0
      i18n/pt/message.json
  28. 11 3
      i18n/pt/ui.json
  29. 1 2
      index.html
  30. 56 56
      js/assessment/ivprogAssessment.js
  31. 0 0
      js/ast/ASA.txt
  32. 0 0
      js/ast/commands/arrayAssign.js
  33. 0 0
      js/ast/commands/arrayDeclaration.js
  34. 0 0
      js/ast/commands/assign.js
  35. 0 0
      js/ast/commands/break.js
  36. 0 0
      js/ast/commands/case.js
  37. 0 0
      js/ast/commands/command.js
  38. 0 0
      js/ast/commands/commandBlock.js
  39. 0 0
      js/ast/commands/declaration.js
  40. 0 0
      js/ast/commands/doWhile.js
  41. 0 0
      js/ast/commands/for.js
  42. 0 0
      js/ast/commands/formalParameter.js
  43. 0 0
      js/ast/commands/function.js
  44. 0 0
      js/ast/commands/ifThenElse.js
  45. 0 0
      js/ast/commands/index.js
  46. 0 0
      js/ast/commands/return.js
  47. 0 0
      js/ast/commands/switch.js
  48. 0 0
      js/ast/commands/sysCall.js
  49. 0 0
      js/ast/commands/while.js
  50. 0 0
      js/ast/error/syntaxError.js
  51. 12 1
      js/ast/error/syntaxErrorFactory.js
  52. 13 0
      js/ast/expressions/arrayAccess.js
  53. 6 1
      js/ast/expressions/arrayLiteral.js
  54. 5 0
      js/ast/expressions/boolLiteral.js
  55. 0 0
      js/ast/expressions/expression.js
  56. 22 0
      js/ast/expressions/functionCall.js
  57. 0 0
      js/ast/expressions/index.js
  58. 7 0
      js/ast/expressions/infixApp.js
  59. 5 0
      js/ast/expressions/intLiteral.js
  60. 0 0
      js/ast/expressions/literal.js
  61. 5 0
      js/ast/expressions/realLiteral.js
  62. 4 0
      js/ast/expressions/stringLiteral.js
  63. 6 0
      js/ast/expressions/unaryApp.js
  64. 4 0
      js/ast/expressions/variableLiteral.js
  65. 0 7
      js/ast/index.js
  66. 45 6
      js/ast/ivprogParser.js
  67. 0 0
      js/ast/operators.js
  68. 0 0
      js/ast/sourceInfo.js
  69. 0 37
      js/ast/types.js
  70. 435 11
      js/iassign-integration-functions.js
  71. 25 7
      js/io/domConsole.js
  72. 0 0
      js/io/domInput.js
  73. 0 0
      js/io/domOutput.js
  74. 0 0
      js/io/input.js
  75. 0 0
      js/io/output.js
  76. 3 0
      js/jquery.json-editor.min.js
  77. 6 3
      js/main.js
  78. 33 0
      js/processor/compatibilityTable.js
  79. 0 0
      js/processor/context.js
  80. 12 0
      js/processor/definedFunctions.js
  81. 392 1
      js/processor/error/processorErrorFactory.js
  82. 0 0
      js/processor/error/runtimeError.js
  83. 0 0
      js/processor/error/semanticError.js
  84. 288 138
      js/processor/ivprogProcessor.js
  85. 0 0
      js/processor/lib/arrays.js
  86. 2 12
      js/processor/lib/io.js
  87. 0 0
      js/processor/lib/lang.js
  88. 52 7
      js/processor/lib/math.js
  89. 0 0
      js/processor/lib/strings.js
  90. 0 0
      js/processor/modes.js
  91. 165 72
      js/processor/semantic/semanticAnalyser.js
  92. 24 2
      js/processor/store/store.js
  93. 0 0
      js/processor/store/storeObject.js
  94. 19 7
      js/processor/store/storeObjectArray.js
  95. 15 0
      js/processor/store/storeObjectArrayAddress.js
  96. 0 0
      js/processor/store/storeObjectArrayAddressRef.js
  97. 0 0
      js/processor/store/storeObjectRef.js
  98. 5 2
      js/runner.js
  99. 0 0
      js/semantic/.versions
  100. 0 0
      js/semantic/LICENSE

+ 0 - 0
css/ivprog-term (cópia).css


+ 82 - 10
css/ivprog-visual-1.0 (cópia).css

@@ -29,6 +29,7 @@ body {
 
 .main_title h2 {
 	margin: 0;
+	color: white;
 }
 .main_title span {
 	font-size: 80%;
@@ -153,7 +154,7 @@ body {
 .expression_operand_1, .expression_operand_2, .operator, .div_comment_text, .value_rendered, .parameters_function_called, .parameters_function_called div, .expression_elements,
 .expression_element, .var_rendered, .menu_add_item, .component_element, .component_element, .conditional_expression, .variable_attribution, .attribution_expression, .var_value_expression,
 .incrementation_field, .incrementation_variable, .first_operand, .operator, .second_operand, .variable_to_switch, .variable_case, .button_remove_case, .editing_name_var, .parameter_div_edit,
-.all_elements_write, .container_var_element_control, .inline_add_command {
+.all_elements_write, .container_var_element_control, .inline_add_command, .restart_expression, .div_parent_handler, .div_drag_writer {
 	display: inline;
 }
 
@@ -279,11 +280,12 @@ div.buttons_manage_columns {
 }
 .ui.comment, .ui.reader, .ui.writer, .ui.attribution, .ui.iftrue, .ui.repeatNtimes, .ui.whiletrue, .ui.dowhiletrue, .ui.switch, .ui.functioncall,
 .ui.return {
-	border: 1px solid gray;
 	padding: 5px;
-	border-radius: 5px;
 	margin: 5px;
-	background: #f9f9f9;
+	background: #f7f2c9;
+    border: 2px solid #4d4be3;
+    border-radius: 0.25em;
+    box-shadow: 1px 1px;
 }
 .ui.repeatNtimes .separator_character {
 	margin-right: 10px;
@@ -353,7 +355,10 @@ div.buttons_manage_columns {
 
 .ui.icon.red.exclamation.triangle.error_icon {
 	float: left;
-    margin-left: -30px;
+    margin-left: -1.6em;
+    z-index: 10;
+    position: absolute;
+    font-size: 1.5em;
 }
 
 .height_100 {
@@ -768,11 +773,6 @@ div.function_name_div_updated:active,
 	opacity: 1 !important;
 }
 
-.command_container {
-    background: #e9dede !important;
-	border: 2px solid #e76060 !important;
-    border-radius: 0.25em !important;
-}
 .command_drag {
 	cursor: move;
 }
@@ -783,4 +783,76 @@ div.function_name_div_updated:active,
 .commands_list_div.over_command_drag {
 	border: 3px dotted blue !important;
 	padding: 0.2em !important;
+}
+.ui.segment:first-child {
+	margin-top: 1em !important;
+}
+div.ui.checkbox.transition.visible {
+	margin-bottom: 1em;
+}
+.var_menu_select_content_error {
+	background: #ff0000;
+    color: white !important;
+    border: 2px solid #3125ee;
+}
+.ui.comment:hover, .ui.reader:hover, .ui.writer:hover, .ui.attribution:hover, .ui.functioncall:hover,
+.ui.return:hover {
+    background: #f2e67f;
+}
+
+.ui.iftrue:hover, .ui.repeatNtimes:hover, .ui.whiletrue:hover, .ui.dowhiletrue:hover, .ui.switch:hover {
+	background: #c6c8f2;
+}
+
+.ui.iftrue, .ui.repeatNtimes, .ui.whiletrue, .ui.dowhiletrue, .ui.switch {
+    background: #787fe721;
+}
+.ui.popup.invalid-identifier {
+	background: #ff3232;
+    color: white;
+    font-weight: bold;
+    border: 1px solid black;
+}
+.ui.popup.invalid-identifier:before {
+	background: #ff3232;
+	border-right: 1px solid black;
+    border-bottom: 1px solid black;
+}
+.ui.popup.invalid-identifier i.ui.icon.inverted.exclamation.triangle.yellow {
+	margin-left: -.5em;
+    margin-right: .4em;
+}
+.ui.repeatNtimes.command_container .ui.block_commands, 
+.ui.whiletrue.command_container .ui.block_commands {
+	margin-top: .8em;
+}
+
+.ui.restart_expression {
+	margin-left: .4em;
+    cursor: pointer;
+    color: brown;
+}
+
+.div_parent_handler {
+	padding-top: 5px;
+    padding-bottom: 6px;
+    background: #7a7acf;
+    border-radius: 4px;
+}
+
+.div_parent_handler i.times {
+	margin-left: .3em;
+	cursor: pointer;
+}
+
+.div_parent_handler i.ellipsis {
+	cursor: move;
+}
+
+.div_parent_handler i.handler {
+	opacity: 0;
+}
+
+.div_parent_handler:hover i.handler {
+	opacity: 1;
 }

+ 82 - 5
css/ivprog-visual-1.0.css

@@ -160,7 +160,7 @@ body {
 .expression_operand_1, .expression_operand_2, .operator, .div_comment_text, .value_rendered, .parameters_function_called, .parameters_function_called div, .expression_elements,
 .expression_element, .var_rendered, .menu_add_item, .component_element, .component_element, .conditional_expression, .variable_attribution, .attribution_expression, .var_value_expression,
 .incrementation_field, .incrementation_variable, .first_operand, .operator, .second_operand, .variable_to_switch, .variable_case, .button_remove_case, .editing_name_var, .parameter_div_edit,
-.all_elements_write, .container_var_element_control, .inline_add_command {
+.all_elements_write, .container_var_element_control, .inline_add_command, .restart_expression, .div_parent_handler, .div_drag_writer {
 	display: inline;
 }
 
@@ -290,7 +290,10 @@ div.buttons_manage_columns {
 	padding: 5px;
 	border-radius: 5px;
 	margin: 5px;
-	background: #f9f9f9;
+	background: #f7f2c9;
+	border: 2px solid #4d4be3;
+	border-radius: 0.25em;
+	box-shadow: 1px 1px;
 }
 .ui.repeatNtimes .separator_character {
 	margin-right: 10px;
@@ -360,7 +363,10 @@ div.buttons_manage_columns {
 
 .ui.icon.red.exclamation.triangle.error_icon {
 	float: left;
-    margin-left: -30px;
+	margin-left: -1.6em;
+	z-index: 10;
+	position: absolute;
+	font-size: 1.5em;
 }
 
 .height_100 {
@@ -795,12 +801,12 @@ button.ui.segment, .global_container.ui {
 .ui.label.function_name_parameter:hover > .ellipsis {
 	opacity: 1 !important;
 }
-
+/*
 .command_container {
     background: #e9dede !important;
 	border: 2px solid #e76060 !important;
     border-radius: 0.25em !important;
-}
+}*/
 .command_drag {
 	cursor: move;
 }
@@ -812,7 +818,78 @@ button.ui.segment, .global_container.ui {
 	border: 3px dotted blue !important;
 	padding: 0.2em !important;
 }
+.ui.segment:first-child {
+	margin-top: 1em !important;
+}
+div.ui.checkbox.transition.visible {
+	margin-bottom: 1em;
+}
+.var_menu_select_content_error {
+	background: #ff0000;
+    color: white !important;
+    border: 2px solid #3125ee;
+}
+.ui.comment:hover, .ui.reader:hover, .ui.writer:hover, .ui.attribution:hover, .ui.functioncall:hover,
+.ui.return:hover {
+    background: #f2e67f;
+}
+
+.ui.iftrue:hover, .ui.repeatNtimes:hover, .ui.whiletrue:hover, .ui.dowhiletrue:hover, .ui.switch:hover {
+	background: #c6c8f2;
+}
+
+.ui.iftrue, .ui.repeatNtimes, .ui.whiletrue, .ui.dowhiletrue, .ui.switch {
+    background: #787fe721;
+}
+.ui.popup.invalid-identifier {
+	background: #ff3232;
+    color: white;
+    font-weight: bold;
+    border: 1px solid black;
+}
+.ui.popup.invalid-identifier:before {
+	background: #ff3232;
+	border-right: 1px solid black;
+    border-bottom: 1px solid black;
+}
+.ui.popup.invalid-identifier i.ui.icon.inverted.exclamation.triangle.yellow {
+	margin-left: -.5em;
+    margin-right: .4em;
+}
+.ui.repeatNtimes.command_container .ui.block_commands, 
+.ui.whiletrue.command_container .ui.block_commands {
+	margin-top: .8em;
+}
 
+.ui.restart_expression {
+	margin-left: .4em;
+    cursor: pointer;
+    color: brown;
+}
+
+.div_parent_handler {
+	padding-top: 5px;
+    padding-bottom: 6px;
+    background: #7a7acf;
+    border-radius: 4px;
+}
+
+.div_parent_handler i.times {
+	margin-left: .3em;
+	cursor: pointer;
+}
+
+.div_parent_handler i.ellipsis {
+	cursor: move;
+}
+
+.div_parent_handler i.handler {
+	opacity: 0;
+}
+
+.div_parent_handler:hover i.handler {
+	opacity: 1;
+}
 .tabular > .item:not(.active) {
 	color: white !important;
 }

+ 0 - 0
grammar/en/ivprog.g4


+ 0 - 0
grammar/en/langFunctions.js


+ 0 - 0
grammar/en/langLibs.js


+ 0 - 0
grammar/es/ivprog.g4


+ 0 - 0
grammar/es/langFunctions.js


+ 0 - 0
grammar/es/langLibs.js


+ 0 - 0
grammar/index.js


+ 0 - 0
grammar/pt/ivprog.g4


+ 0 - 0
grammar/pt/langFunctions.js


+ 0 - 0
grammar/pt/langLibs.js


+ 0 - 0
i18n/en/error.json


+ 0 - 0
i18n/en/index.js


+ 0 - 0
i18n/en/message.json


+ 11 - 3
i18n/en/ui.json

@@ -44,7 +44,7 @@
   "text_code_switch": "switch",
   "text_code_case": "case",
   "text_logic_expression": "Logic Expression",
-  "text_arithmetic_expression": "Arithmetic Expression",
+  "text_arithmetic_expression": "Relational Expression",
   "text_iftrue": "If true then",
   "text_receives": "receives",
   "text_repeatNtimes": "Repeat N times",
@@ -78,6 +78,7 @@
   "text_menu_functions_conversion":"Conversion",
   "text_none_variable":"There is no declared variable",
   "text_none_variable_instruction":"Create a new variable to use it",
+  "text_ivprog_description":"Interactive Visual Programming on the Internet",
   "tooltip_visual": "Visual programming",
   "tooltip_textual": "Textual programming",
   "tooltip_upload": "Upload code file",
@@ -93,9 +94,15 @@
   "var_menu_select_var": "Select a var",
   "var_menu_select_all": "Select",
   "var_menu_select_function": "Select a function",
-  "expression_menu_select": "Select an expression",
+  "expression_menu_select": "Construct any logical condition",
   "math": "Mathematic",
   "text_t": "Text",
+  "inform_valid_name": "Inform a valid name!",
+  "inform_valid_content": "Enter some content!",
+  "inform_valid_expression": "Construct the logical condition!",
+  "inform_valid_name_duplicated": "This name is already in use by other function.",
+  "inform_valid_global_duplicated": "A global variable with this name already exists.",
+  "inform_valid_variable_duplicated" : "A local variable with this name already exists.",
   "arrangement": "Arrangement",
   "conversion": "Conversion",
   "$sin": "sin",
@@ -123,5 +130,6 @@
   "$castReal": "to_real",
   "$castInt": "to_integer",
   "$castBool": "to_logic",
-  "$castString": "to_string"
+  "$castString": "to_string",
+  "text_ivprog_version":"Version 2018_12_19 Build 13_18"
 }

+ 0 - 0
i18n/es/error.json


+ 0 - 0
i18n/es/index.js


+ 0 - 0
i18n/es/message.json


+ 11 - 3
i18n/es/ui.json

@@ -46,7 +46,7 @@
   "text_code_switch": "switch",
   "text_code_case": "case",
   "text_logic_expression": "Logic Expression",
-  "text_arithmetic_expression": "Arithmetic Expression",
+  "text_arithmetic_expression": "Relational Expression",
   "text_iftrue": "If true then",
   "text_repeatNtimes": "Repeat N times",
   "text_receives": "receives",
@@ -78,6 +78,7 @@
   "text_menu_functions_conversion":"Conversion",
   "text_none_variable":"There is no declared variable",
   "text_none_variable_instruction":"Create a new variable to use it",
+  "text_ivprog_description":"Interactive Visual Programming on the Internet",
   "tooltip_visual": "Visual programming",
   "tooltip_textual": "Textual programming",
   "tooltip_upload": "Upload code file",
@@ -93,13 +94,19 @@
   "var_menu_select_var": "Select a var",
   "var_menu_select_all": "Select",
   "var_menu_select_function": "Select a function",
-  "expression_menu_select": "Select an expression",
+  "expression_menu_select": "Construct any logical condition",
   "$sin": "sen",
   "math": "Mathematic",
   "text": "Text",
   "arrangement": "Arrangement",
   "conversion": "Conversion",
   "math": "Mathematic",
+  "inform_valid_name": "Inform a valid name!",
+  "inform_valid_content": "Enter some content!",
+  "inform_valid_expression": "Construct the logical condition!",
+  "inform_valid_name_duplicated": "This name is already in use by other function.",
+  "inform_valid_global_duplicated": "A global variable with this name already exists.",
+  "inform_valid_variable_duplicated" : "A local variable with this name already exists.",
   "text_t": "Text",
   "arrangement": "Arrangement",
   "conversion": "Conversion",
@@ -128,5 +135,6 @@
   "$castReal": "to_real",
   "$castInt": "to_integer",
   "$castBool": "to_logic",
-  "$castString": "to_string"
+  "$castString": "to_string",
+  "text_ivprog_version":"Version 2018_12_19 Build 13_18"
 }

+ 0 - 0
i18n/i18n-database.json


+ 0 - 39
i18n/i18n-engine.js

@@ -1,39 +0,0 @@
-
-var LocalizedStrings = ivprogCore.LocalizedStrings;
-var StringTypes = ivprogCore.StringTypes;
-
-function i18n(identifier) {
-  var opts = identifier.split(':');
-  var type = opts[0].toLowerCase();
-  var id = opts[1];
-  if (StringTypes.ERROR === type) {
-    return LocalizedStrings.getError(id);
-  } else if (StringTypes.MESSAGE === type) {
-    return LocalizedStrings.getMessage(id); 
-  } else if (StringTypes.UI === type) {
-    return LocalizedStrings.getUI(id);
-  } else {
-    console.warn(" A string has been passed to the i18n helper function that was not in the form type:id -> " + identifier);
-    return LocalizedStrings.getString(id, type);
-  }
-}
-
-i18n.set = function(locale, identifier, translate) {
-  if (!i18n.db[locale]) {
-    i18n.db[locale] = {};
-  }
-  i18n.db[locale][identifier] = translate;
-}
-
-i18n.updateLocale = function(new_locale) {
-  localStorage.setItem('ivprog.lang', new_locale);
-  $( "data.i18n" ).each(function() {
-    $( this ).text(i18n($( this ).val()));
-  });
-}
-
-$( document ).ready(function() {
-  $( "data.i18n" ).each(function() {
-    $( this ).text(i18n($( this ).val()));
-  });
-});

+ 0 - 0
i18n/index.js


+ 0 - 0
i18n/pt/error.json


+ 0 - 0
i18n/pt/index.js


+ 0 - 0
i18n/pt/message.json


+ 11 - 3
i18n/pt/ui.json

@@ -52,7 +52,7 @@
   "text_code_switch": "escolha",
   "text_code_case": "caso",
   "text_logic_expression": "Expressão Lógica",
-  "text_arithmetic_expression": "Expressão Aritmética",
+  "text_arithmetic_expression": "Expressão Relacional",
   "text_iftrue": "Se verdadeiro então",
   "text_repeatNtimes": "Repita N vezes",
   "text_receives": "recebe",
@@ -84,6 +84,7 @@
   "text_menu_functions_conversion":"Conversão",
   "text_none_variable":"Nenhuma variável declarada",
   "text_none_variable_instruction":"Antes de utilizar uma variável, é necessário criá-la",
+  "text_ivprog_description":"Programação Visual interativa na Internet",
   "tooltip_visual": "Programação visual",
   "tooltip_textual": "Programação textual",
   "tooltip_upload": "Upload de código fonte",
@@ -99,10 +100,16 @@
   "var_menu_select_var": "Selecione uma variável",
   "var_menu_select_all": "Selecione",
   "var_menu_select_function": "Selecione uma função",
-  "expression_menu_select": "Selecione uma expressão",
+  "expression_menu_select": "Construir uma expressão lógica",
   "$sin": "sen",
   "math": "Matematica",
   "text_t": "Texto",
+  "inform_valid_name": "Informe um nome válido!",
+  "inform_valid_content": "Informe o conteúdo!",
+  "inform_valid_expression": "Construa uma expressão lógica!",
+  "inform_valid_name_duplicated": "Este nome já está em uso por outra função!",
+  "inform_valid_global_duplicated": "Já existe uma variável global com o nome informado.",
+  "inform_valid_variable_duplicated" : "Já existe uma variável local com o nome informado.",
   "arrangement": "Arranjo",
   "conversion": "Conversao",
   "$sin": "seno",
@@ -130,5 +137,6 @@
   "$castReal": "como_real",
   "$castInt": "como_inteiro",
   "$castBool": "como_logico",
-  "$castString": "como_cadeia"
+  "$castString": "como_cadeia",
+  "text_ivprog_version":"Versão 2018_12_19 Build 13_18"
 }

+ 1 - 2
index.html

@@ -21,7 +21,6 @@
 
   <script src="js/jquery-ui.js"></script>
   <script src="js/Sortable.js"></script>
-  <script src="i18n/i18n-engine.js"></script>
 
 </head>
 
@@ -201,4 +200,4 @@
 
 </body>
 
-</html>
+</html>

+ 56 - 56
js/assessment/ivprogAssessment.js

@@ -13,69 +13,69 @@ export class IVProgAssessment {
   }
 
   runTest () {
-    const outerRef = this;
-    return new Promise((resolve, _) => {
-      try {
-        // try and show error messages through domconsole
-        const parser = IVProgParser.createParser(outerRef.textCode);
-        const semantic = new SemanticAnalyser(parser.parseTree());
-        const validTree = semantic.analyseTree();
-        // loop test cases and show messages through domconsole
-        const tests = outerRef.testCases.map( (t, name) => {
-          return outerRef.evaluateTestCase(new IVProgProcessor(validTree), t.input, t.output, name);
-        });
-        Promise.all(tests).then(results => {
-          const count = results.reduce((lastValue, nextValue) =>  lastValue + nextValue, 0);
-          resolve(count / outerRef.testCases.length);
-        }).catch(err => {
-          outerRef.domConsole.err("Erro durante a execução do programa");// try and show error messages through domconsole
-          outerRef.domConsole.err(err.message);
-          resolve(0);
-        })
-      } catch (error) {
-        outerRef.domConsole.err("Erro durante a execução do programa");// try and show error messages through domconsole
-        outerRef.domConsole.err(error.message);
-        resolve(0);
-      }
-    });
+    try {
+      // try and show error messages through domconsole
+      const parser = IVProgParser.createParser(this.textCode);
+      const semantic = new SemanticAnalyser(parser.parseTree());
+      const validTree = semantic.analyseTree();
+      // loop test cases and show messages through domconsole
+      const partialTests = this.testCases.map( (t, name) => {
+        return this.partialEvaluateTestCase(new IVProgProcessor(validTree), t.input, t.output, name);
+      });
+      const testResult = partialTests.reduce((acc, curr) => acc.then(curr), Promise.resolve(0));
+      return testResult.then(total => Promise.resolve(total / this.testCases.length))
+        .catch(err => {
+          this.domConsole.err("Erro durante a execução do programa");// try and show error messages through domconsole
+          this.domConsole.err(err.message);
+          return Promise.resolve(0);
+      });
+    } catch (error) {
+      this.domConsole.err("Erro durante a execução do programa");// try and show error messages through domconsole
+      this.domConsole.err(error.message);
+      return Promise.resolve(0);
+    }
   }
 
-  evaluateTestCase (prog, inputList, outputList, name) {
+  evaluateTestCase (prog, inputList, outputList, name, accumulator) {
     const outerThis = this;
-    return new Promise((resolve, reject) => {
-      const input = new InputTest(inputList);
-      const output = new OutputTest();
-      prog.registerInput(input);
-      prog.registerOutput(output);
-      const startTime = Date.now()
-      prog.interpretAST().then( _ => {
-        const millis = Date.now() - startTime;
-        if (input.inputList.length !== input.index) {
-          outerThis.domConsole.err(`Caso de teste ${name + 1}: Falhou, ainda restam entradas!`);
-          outerThis.domConsole.info(`Levou ${millis}ms`);
-          resolve(1 * (input.index/inputList.length));
-        } else if (output.list.length < outputList.length) {
-          outerThis.domConsole.err(`Caso de teste ${name + 1}: Falhou <${inputList.join(", ")};${outputList.join(", ")};${output.list.join(", ")}>`);
-          outerThis.domConsole.info(`Levou ${millis}ms`);
-          resolve(1 * (output.list.length/outputList.length));
-        } else if (output.list.length > outputList.length) {
+    const input = new InputTest(inputList);
+    const output = new OutputTest();
+    prog.registerInput(input);
+    prog.registerOutput(output);
+    const startTime = Date.now()
+    return prog.interpretAST().then( _ => {
+      const millis = Date.now() - startTime;
+      if (input.inputList.length !== input.index) {
+        outerThis.domConsole.err(`Caso de teste ${name + 1}: Falhou, ainda restam entradas!`);
+        outerThis.domConsole.info(`Levou ${millis}ms`);
+        return Promise.resolve(accumulator + 1 * (input.index/inputList.length));
+      } else if (output.list.length < outputList.length) {
+        outerThis.domConsole.err(`Caso de teste ${name + 1}: Falhou <${inputList.join(", ")};${outputList.join(", ")};${output.list.join(", ")}>`);
+        outerThis.domConsole.info(`Levou ${millis}ms`);
+        return Promise.resolve(accumulator + 1 * (output.list.length/outputList.length));
+      } else if (output.list.length > outputList.length) {
+        outerThis.domConsole.err(`Caso de teste ${name + 1}: Falhou <${inputList.join(", ")};${outputList.join(", ")};${output.list.join(", ")}>`);
+        outerThis.domConsole.info(`Levou ${millis}ms`);
+        return Promise.resolve(accumulator + 1 * (outputList.length/output.list.length));
+      } else {
+        const isOk = outerThis.checkOutput(output.list, outputList);
+        if(!isOk) {
           outerThis.domConsole.err(`Caso de teste ${name + 1}: Falhou <${inputList.join(", ")};${outputList.join(", ")};${output.list.join(", ")}>`);
           outerThis.domConsole.info(`Levou ${millis}ms`);
-          resolve(1 * (outputList.length/output.list.length));
+          return Promise.resolve(accumulator);
         } else {
-          const isOk = outerThis.checkOutput(output.list, outputList);
-          if(!isOk) {
-            outerThis.domConsole.err(`Caso de teste ${name + 1}: Falhou <${inputList.join(", ")};${outputList.join(", ")};${output.list.join(", ")}>`);
-            outerThis.domConsole.info(`Levou ${millis}ms`);
-            resolve(0);
-          } else {
-            outerThis.domConsole.info(`Caso de teste ${name + 1}: OK!`);
-            outerThis.domConsole.info(`Levou ${millis}ms`);
-            resolve(1);
-          }
+          outerThis.domConsole.info(`Caso de teste ${name + 1}: OK!`);
+          outerThis.domConsole.info(`Levou ${millis}ms`);
+          return Promise.resolve(accumulator + 1);
         }
-      }).catch( _ => resolve(0));
-    })
+      }
+    }).catch( _ => Promise.resolve(accumulator));
+  }
+
+  partialEvaluateTestCase (prog, inputList, outputList, name) {
+    let partial = (accumulator) => this.evaluateTestCase(prog, inputList, outputList, name, accumulator)
+    partial = partial.bind(this);
+    return partial;
   }
 
   checkOutput (aList, bList) {

+ 0 - 0
js/ast/ASA.txt


+ 0 - 0
js/ast/commands/arrayAssign.js


+ 0 - 0
js/ast/commands/arrayDeclaration.js


+ 0 - 0
js/ast/commands/assign.js


+ 0 - 0
js/ast/commands/break.js


+ 0 - 0
js/ast/commands/case.js


+ 0 - 0
js/ast/commands/command.js


+ 0 - 0
js/ast/commands/commandBlock.js


+ 0 - 0
js/ast/commands/declaration.js


+ 0 - 0
js/ast/commands/doWhile.js


+ 0 - 0
js/ast/commands/for.js


+ 0 - 0
js/ast/commands/formalParameter.js


+ 0 - 0
js/ast/commands/function.js


+ 0 - 0
js/ast/commands/ifThenElse.js


+ 0 - 0
js/ast/commands/index.js


+ 0 - 0
js/ast/commands/return.js


+ 0 - 0
js/ast/commands/switch.js


+ 0 - 0
js/ast/commands/sysCall.js


+ 0 - 0
js/ast/commands/while.js


+ 0 - 0
js/ast/error/syntaxError.js


+ 12 - 1
js/ast/error/syntaxErrorFactory.js

@@ -39,7 +39,7 @@ export const SyntaxErrorFactory = Object.freeze({
     const context = [token.line, cmdName];
     return new SyntaxError(LocalizedStrings.getError("invalid_break_command", context));
   },
-  invalid_terminal: () => {
+  invalid_terminal: (token) => {
     const context = [token.text, token.line, token.column];
     return new SyntaxError(LocalizedStrings.getError('invalid_terminal', context));
   },
@@ -55,5 +55,16 @@ export const SyntaxErrorFactory = Object.freeze({
   invalid_id_format: (token) => {
     const context = [token.text, token.line, token.column];
     return new SyntaxError(LocalizedStrings.getError("invalid_id_format", context));
+  },
+  duplicate_function: (token) => {
+    const context = [token.text, token.line, token.column];
+    return new SyntaxError(LocalizedStrings.getError("duplicate_function", context));
+  },
+  main_parameters: () => {
+    return new SyntaxError(LocalizedStrings.getError("main_parameters"));
+  },
+  duplicate_variable: (token) => {
+    const context = [token.text, token.line, token.column];
+    return new SyntaxError(LocalizedStrings.getError("duplicate_variable", context));
   }
 });

+ 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}]`;
+		}
+	}
 }

+ 6 - 1
js/ast/expressions/arrayLiteral.js

@@ -25,7 +25,7 @@ export class ArrayLiteral extends Literal {
     if (!(element instanceof ArrayLiteral)){
       return null;
     } else {
-      return element.value[0].value.length;
+      return element.value[0].length;
     }
   }
 
@@ -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);
+  }
 }

+ 0 - 0
js/ast/expressions/expression.js


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

@@ -1,4 +1,5 @@
 import { Expression } from './expression';
+import { LanguageDefinedFunction } from '../../processor/definedFunctions';
 
 export class FunctionCall extends Expression {
 
@@ -8,7 +9,28 @@ export class FunctionCall extends Expression {
 		this.actualParameters = actualParameters;
 	}
 
+	get isMainCall () {
+		return this.id === null;
+	}
+
 	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;
+	}
 }

+ 0 - 0
js/ast/expressions/index.js


+ 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);
+  }
 }

+ 0 - 0
js/ast/expressions/literal.js


+ 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;
+  }
 }

+ 0 - 7
js/ast/index.js

@@ -1,7 +0,0 @@
-import { ASA } from './ASA';
-import { NoGlobal } from './NoGlobal';
-import { NoDeclaracao } from './NoDeclaracao';
-
-exports.ASA = ASA;
-exports.NoGlobal = NoGlobal;
-exports.NoDeclaracao = NoDeclaracao;

+ 45 - 6
js/ast/ivprogParser.js

@@ -47,6 +47,8 @@ export class IVProgParser {
     this.parsingArrayDimension = 0;
     this.scope = [];
     this.langFuncs = LanguageService.getCurrentLangFuncs();
+    this.definedFuncsNameList = [];
+    this.definedVariablesStack = [];
   }
 
   parseTree () {
@@ -71,10 +73,22 @@ export class IVProgParser {
     this.scope.push(scope);
   }
 
+  pushVariableStack () {
+    this.definedVariablesStack.push([]);
+  }
+
   popScope () {
     return this.scope.pop();
   }
 
+  popVariableStack () {
+    return this.definedVariablesStack.pop();
+  }
+
+  getCurrentVariableStack () {
+    return this.definedVariablesStack[this.definedVariablesStack.length - 1];
+  }
+
   isEOF () {
     this.getToken(this.pos);
     return this.tokenStream.fetchedEOF;
@@ -90,13 +104,16 @@ export class IVProgParser {
       this.consumeNewLines();
       this.checkOpenCurly();
       this.pos++;
+      this.pushVariableStack();
       while(true) {
         this.consumeNewLines();
         const token = this.getToken();
         if (token.type === this.lexerClass.RK_CONST || this.isVariableType(token)) {
           globalVars = globalVars.concat(this.parseGlobalVariables());
         } else if (token.type === this.lexerClass.RK_FUNCTION) {
+          this.pushVariableStack();
           functions = functions.concat(this.parseFunction());
+          this.popVariableStack();
         } else {
           break;
         }
@@ -108,6 +125,7 @@ export class IVProgParser {
       if(!this.isEOF()) {
         throw SyntaxErrorFactory.extra_lines();
       }
+      this.popVariableStack();
       return {global: globalVars, functions: functions};
     } else {
       throw SyntaxErrorFactory.token_missing_one(this.lexer.literalNames[this.lexerClass.RK_PROGRAM], token);
@@ -203,6 +221,23 @@ export class IVProgParser {
     return true;
   }
 
+  checkFunctionDuplicate (functionID, funcIDToken) {
+    const id = functionID === null ? "$main" : functionID;
+    const index = this.definedFuncsNameList.indexOf(id);
+    if(index !== -1) {
+      throw SyntaxErrorFactory.duplicate_function(funcIDToken);
+    }
+    this.definedFuncsNameList.push(id);
+  }
+
+  checkVariableDuplicate (variableID, variableIDToken) {
+    const index = this.getCurrentVariableStack().indexOf(variableID);
+    if(index !== -1) {
+      throw SyntaxErrorFactory.duplicate_variable(variableIDToken);
+    }
+    this.getCurrentVariableStack().push(variableID);
+  }
+
   consumeForSemiColon () {
     const eosToken = this.getToken();
     if (eosToken.type === this.lexerClass.EOS && eosToken.text.match(';')) {
@@ -250,7 +285,7 @@ export class IVProgParser {
     let dim2 = null;
     const idToken = this.getToken();
     const idString = this.parseID();
-    
+    this.checkVariableDuplicate(idString,idToken);
     // Check for array or vector
     // ID[int/IDi][int/IDj]
     if (this.checkOpenBrace(true)) {
@@ -372,7 +407,6 @@ export class IVProgParser {
     this.checkOpenCurly();
     const beginArray = this.getToken();
     if (this.parsingArrayDimension >= 2) {
-      // TODO: better error message
       throw SyntaxErrorFactory.token_missing_list(`Array dimensions exceed maximum size of 2 at line ${beginArray.line}`);
     }
     this.pos++;
@@ -441,7 +475,9 @@ export class IVProgParser {
         dimensions++;
       }
     }
+    const funcIDToken = this.getToken();
     const functionID = this.parseID();
+    this.checkFunctionDuplicate(functionID, funcIDToken);
     this.checkOpenParenthesis();
     this.pos++;
     this.consumeNewLines();
@@ -461,10 +497,11 @@ export class IVProgParser {
     }
     const func = new Commands.Function(functionID, returnType, formalParams, commandsBlock);
     if (functionID === null && !func.isMain) {
-      // TODO: better error message
       throw SyntaxErrorFactory.invalid_main_return(LanguageDefinedFunction.getMainFunctionName(),
         this.lexer.literalNames[this.lexerClass.RK_VOID],
         token.line);
+    } else if (func.isMain && formalParams.length !== 0) {
+      throw SyntaxErrorFactory.main_parameters();
     }
     this.popScope();
     return func;
@@ -479,7 +516,9 @@ export class IVProgParser {
     while(true) {
       let dimensions = 0;
       const typeString = this.parseType();
+      const idToken = this.getToken();
       const idString = this.parseID();
+      this.checkVariableDuplicate(idString, idToken);
       if (this.checkOpenBrace(true)) {
         this.pos++;
         dimensions++;
@@ -592,7 +631,6 @@ export class IVProgParser {
     const token = this.getToken();
     if (this.isVariableType(token)) {
       if(!this.insideScope(IVProgParser.FUNCTION)) {
-        // TODO better error message
         throw SyntaxErrorFactory.invalid_var_declaration(token.line);
       }
       this.pushScope(IVProgParser.BASE);
@@ -614,7 +652,6 @@ export class IVProgParser {
       return this.parseFor();
     } else if (token.type === this.lexerClass.RK_BREAK ) {
       if(!this.insideScope(IVProgParser.BREAKABLE)) {
-        // TODO better error message
         throw SyntaxErrorFactory.invalid_break_command(
           this.lexer.literalNames[this.lexerClass.RK_BREAK],
           token
@@ -710,7 +747,6 @@ export class IVProgParser {
       } else if(maybeIf.type === this.lexerClass.RK_IF) {
         elseBlock = this.parseIfThenElse();
       } else {
-        // TODO better error message
         throw SyntaxErrorFactory.token_missing_list([this.lexer.literalNames[this.lexerClass.RK_IF], '{'], maybeIf);
       }
       return new Commands.IfThenElse(logicalExpression, cmdBlocks, elseBlock);
@@ -1069,6 +1105,9 @@ export class IVProgParser {
   getFunctionName (id) {
     const name = LanguageDefinedFunction.getInternalName(id);
     if (name === null) {
+      if (id === LanguageDefinedFunction.getMainFunctionName()) {
+        return null;
+      }
       return id;
     } else {
       return name;

+ 0 - 0
js/ast/operators.js


+ 0 - 0
js/ast/sourceInfo.js


+ 0 - 37
js/ast/types.js

@@ -1,37 +0,0 @@
-export const Types = Object.freeze({
-  INTEGER: {value: "int", ord: 0},
-  REAL: {value: "real", ord: 1},
-  STRING: {value: "string", ord: 2},
-  BOOLEAN: {value: "bool", ord: 3},
-  VOID: {value: "void", ord: 4},
-  ARRAY: {value: 'array', ord: 5},
-  UNDEFINED: {value: 'undefined', ord: 6},
-  ALL: {value: 'all', ord: 7}
-});
-
-export function toInt (str) {
-  if(str.match('^0b|^0B')) {
-    return parseInt(str.substring(2), 2);
-  } else if (str.match('^0x|^0X')) {
-    return parseInt(str.substring(2), 16);
-  } else {
-    return parseInt(str);
-  }
-}
-
-export function toString (str) {
-  let value = str.replace(/^"/, '');
-  value = value.replace(/"$/, '');
-  value = value.replace(/\\b/g, "\b");
-  value = value.replace(/\\t/g, "\t");
-  value = value.replace(/\\n/g, "\n");
-  value = value.replace(/\\r/g, "\r");
-  value = value.replace(/\\\"/g, "\"");
-  value = value.replace(/\\\'/g, "\'");
-  value = value.replace(/\\\\/g, "\\");
-  return value;
-}
-
-export function toBool (str) {
-  return true;
-}

+ 435 - 11
js/iassign-integration-functions.js

@@ -1,6 +1,6 @@
 // Função para ler parâmetros informados pelo iTarefa via URL
 // Apesar de não ser obrigatório, será muito útil para capturar os parâmetros
-function getParameterByName(name, defaultReturn = null) {
+function getParameterByName (name, defaultReturn = null) {
     var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
     return match ? decodeURIComponent(match[1].replace(/\+/g, ' ')) : defaultReturn;
 }
@@ -17,42 +17,466 @@ var iLMparameters = {
 
 // Set the lang parameter to the localStorage for easy access
 // and no dependency to the global scope, avoind future 'strict mode' problems
-localStorage.setItem('ivprog.lang', iLMparameters.lang);
+//localStorage.setItem('ivprog.lang', iLMparameters.lang);
 
 // Função chamada pelo iTarefa quando o professor finaliza a criação da atividade
 // ou quando o aluno finaliza a resolução do exercício
 // O retorno é um JSON com os dados do exercício ou da resolução
 // Esse retorno será armazenado no banco de dados do Moodle, pelo iTarefa
-function getAnswer() {
+function getAnswer () {
     // Se o parâmetro "iLM_PARAM_SendAnswer" for false,
     // então trata-se de resolução de atividade
     if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
-        // Montar o retorno da resposta do aluno
-        
+        // Montar o retorno com a resposta do aluno
+        var contentToSend = previousContent.split("\n::algorithm::")[0];
+        contentToSend += '\n::algorithm::\n';
+        contentToSend += JSON.stringify(window.program_obj);
+
+        contentToSend += '\n::logs::';
+        contentToSend += getTrackingLogs();
+
+        return contentToSend;
+
     } else {
-        
+        // Montar o retorno com a criação da atividade do professor
+        var ret = ' { ' + prepareTestCases() 
+            + ',\n"settings_data_types": \n' + JSON.stringify($('form[name="settings_data_types"]').serializeArray()) 
+            + ',\n"settings_commands": \n' + JSON.stringify($('form[name="settings_commands"]').serializeArray()) 
+            + ',\n"settings_functions": \n' + JSON.stringify($('form[name="settings_functions"]').serializeArray()) 
+            + ' } ';
+
+        if ($("input[name='include_algo']").is(':checked')) {
+            ret += '\n::algorithm::\n';
+            ret += JSON.stringify(window.program_obj);
+        }
+
+        return ret;
     }
 }
 
+function prepareTestCases () {
+    var ret = ' \n "testcases" : [ '
+    var test_cases_array = $('form[name="test_cases"]').serializeArray();
+    for (var i = 0; i < test_cases_array.length; i = i + 2) {
+        ret += '\n{ ';
+        ret += '\n "input": [';
+        var inps = test_cases_array[i].value.match(/[^\r\n]+/g);
+        if (inps) {
+            for (var j = 0; j < inps.length; j++) {
+                ret += '"' + inps[j] + '"';
+                if ((j + 1) < inps.length) {
+                    ret += ', ';
+                }
+            }
+        }
+        ret += '], \n "output": [';
+        var outs = test_cases_array[i+1].value.match(/[^\r\n]+/g);
+        if (outs) {
+            for (var j = 0; j < outs.length; j++) {
+                ret += '"' + outs[j] + '"';
+                if ((j + 1) < outs.length) {
+                    ret += ', ';
+                }
+            }
+        }
+        ret += ']';
+        ret += '\n}'
+        if ((i + 2) < test_cases_array.length) {
+            ret += ',';
+        }
+    }
+    ret += '\n] ';
+    return ret;
+}
+
 // Função chamada pelo iTarefa para receber a nota do aluno na atividade
 // O retorno é um valor entre 0.0 e 1.0
-function getEvaluation() {
+function getEvaluation () {
     if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
-        // Calcula a nota do aluno:
-
         // A chamada do método abaixo é obrigatória!
         // Observe que a chamada parte do iLM para o iTarefa
-        parent.getEvaluationCallback(0);
+        //parent.getEvaluationCallback(window.studentGrade);
+
+        runCodeAssessment();
     }
 }
 
 
+var testCases = null;
+var settingsDataTypes = null;
+var settingsCommands = null;
+var settingsFunctions = null;
+var algorithm_in_ilm = null;
+var previousContent = null;
+
 // Função para que o iMA leia os dados da atividade fornecidos pelo iTarefa
-function getiLMContent() {
+function getiLMContent () {
 
     // O parâmetro "iLM_PARAM_Assignment" fornece o URL do endereço que deve ser
     // requisitado via AJAX para a captura dos dados da atividade
     $.get(iLMparameters.iLM_PARAM_Assignment, function (data) {
+        // Aluno está trabalhando em alguma atividade:
+        if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+            previousContent = data;
+            prepareActivityToStudent(data);
+        } else { // Professor está editando uma atividade:
+            previousContent = data;
+            prepareActivityToEdit(data);
+        }
+    });
+}
+
+function prepareActivityToEdit (ilm_cont) {
+    var content = JSON.parse(ilm_cont.split('\n::algorithm::')[0]);
+    testCases = content.testcases;
+    settingsDataTypes = content.settings_data_types;
+    settingsCommands = content.settings_commands;
+    settingsFunctions = content.settings_functions;
+
+    for (var i = 0; i < testCases.length; i++) {
+        addTestCase(testCases[i]);
+    }
+
+    if (ilm_cont.split('\n::algorithm::')[1]) {
+        algorithm_in_ilm = ilm_cont.split('\n::algorithm::')[1].split('\n::logs::')[0];
+        $("input[name='include_algo']").prop('checked', true);
+        includePreviousAlgorithm();
+        renderAlgorithm();
+    }
+}
+
+function includePreviousAlgorithm () {
+    window.program_obj.functions = JSON.parse(algorithm_in_ilm).functions;
+    window.program_obj.globals = JSON.parse(algorithm_in_ilm).globals;
+
+    window.watchW.watch(window.program_obj.globals, function(){
+      if (window.insertContext) {
+        setTimeout(function(){ renderAlgorithm(); }, 300);
+        window.insertContext = false;
+      } else {
+        renderAlgorithm();
+      }
+    }, 1);
+
+    for (var i = 0; i < window.program_obj.functions.length; i ++) {
+        window.watchW.watch(window.program_obj.functions[i].parameters_list, function(){
+          if (window.insertContext) {
+            setTimeout(function(){ renderAlgorithm(); }, 300);
+            window.insertContext = false;
+          } else {
+            renderAlgorithm();
+          }
+        }, 1);
+
+        window.watchW.watch(window.program_obj.functions[i].variables_list, function(){
+          if (window.insertContext) {
+            setTimeout(function(){ renderAlgorithm(); }, 300);
+            window.insertContext = false;
+          } else {
+            renderAlgorithm();
+          }
+        }, 1);
+
+        if (window.program_obj.functions[i].is_main) {
+            window.program_obj.functions[i].name = LocalizedStrings.getUI("start");
+        }
+    }
+    window.watchW.watch(window.program_obj.functions, function(){
+      if (window.insertContext) {
+        setTimeout(function(){ renderAlgorithm(); }, 300);
+        window.insertContext = false;
+      } else {
+        renderAlgorithm();
+      }
+    }, 1);
+}
+
+function prepareActivityToStudent (ilm_cont) {
+    var content = JSON.parse(ilm_cont.split('\n::algorithm::')[0]);
+    testCases = content.testcases;
+    settingsDataTypes = content.settings_data_types;
+    settingsCommands = content.settings_commands;
+    settingsFunctions = content.settings_functions;
+
+    if (ilm_cont.split('\n::algorithm::')[1]) {
+        algorithm_in_ilm = ilm_cont.split('\n::algorithm::')[1].split('\n::logs::')[0];
+        includePreviousAlgorithm();
+    }
+    $('.assessment_button').removeClass('disabled');
+    renderAlgorithm();
+}
+
+// Função para organizar se para criação, visualização ou resolução de atividade
+function prepareEnvironment () {
+    if ((iLMparameters.iLM_PARAM_AssignmentURL == "true") && (iLMparameters.iLM_PARAM_SendAnswer == "true")) {
+        prepareActivityCreation();
+    }
+}
+
+$(document).ready(function() {
+
+    // Se iLM_PARAM_SendAnswer for false, então trata-se de resolução de atividade,
+    // portanto, a "DIV" de resolução é liberada
+    if (iLMparameters.iLM_PARAM_SendAnswer == 'false') {
+        //$('.resolucao').css("display","block");
+        getiLMContent();
+
+
+        $( document ).ready(function() {
+            $('.div_to_body').mousemove(function(e) {
+                trackingMatrix.push(adCoords(e, 0));
+            });
+
+            $('.div_to_body').click(function(e) {
+                trackingMatrix.push(adCoords(e, 1));                    
+            });
+
+        });
+
+    } else {
+        // Caso não esteja em modo de resolução de atividade, a visualização no momento
+        // é para a elaboração de atividade:
+        //$('.elaboracao').css("display","block");
+
+        // Se possuir o parâmetro iLMparameters.iLM_PARAM_Assignment, o professor
+        // está editando uma atividade:
+        if (iLMparameters.iLM_PARAM_Assignment) {
+            getiLMContent();
+        }
+    }
+
+    if (!testCases) {
+        $('.assessment_button').addClass('disabled');
+    }
+
+});
+
+// Função para preparar a interface para o professor criar atividade:
+function prepareActivityCreation () {
+
+    $('.add_accordion').addClass('accordion');
+
+    $('.default_visual_title').toggle();
+    $('.default_visual_title').append('<span>'+LocalizedStrings.getUI('text_teacher_algorithm')+'</span>');
+    $('.height_100').removeClass('height_100');
+    $('.main_title').remove();
+    $('.ui.accordion').addClass('styled');
+    
+    $('<div class="content_margin"></div>').insertBefore($('.add_accordion').find('.content').find('.div_to_body'));
+
+    $('<div class="ui checkbox"><input type="checkbox" name="include_algo" class="include_algo" tabindex="0" class="hidden"><label>'+LocalizedStrings.getUI('text_teacher_algorithm_include')+'</label></div>').insertAfter('.content_margin');
+    
+    var cases_test_div = $('<div class="ui accordion styled"><div class="active title"><i class="dropdown icon"></i>'+LocalizedStrings.getUI('text_teacher_test_case')+'</div><div class="active content"></div></div>');
+
+    cases_test_div.insertBefore('.accordion');
+
+    var config_div = $('<div class="ui accordion styled"><div class="title"><i class="dropdown icon"></i>'+LocalizedStrings.getUI('text_teacher_config')+'</div><div class="content"></div></div>');
+
+    config_div.insertAfter(cases_test_div);
+
+    $('.ui.accordion').accordion();
+
+    $('.ui.checkbox').checkbox();
+
+    prepareTableSettings(config_div.find('.content'));
+
+    prepareTableTestCases(cases_test_div.find('.content'));
+}
+
+function prepareTableTestCases (div_el) {
+
+    var table_el = '<form name="test_cases"><table class="ui blue table"><thead><tr><th width="30px">#</th><th>'+LocalizedStrings.getUI('text_teacher_test_case_input')+'</th><th>'+LocalizedStrings.getUI('text_teacher_test_case_output')+'</th><th width="80px">'+LocalizedStrings.getUI('text_teacher_test_case_actions')+'</th></tr></thead>'
+            + '<tbody class="content_cases"></tbody></table></form>';
+
+    div_el.append(table_el);
+
+    div_el.append('<button class="ui teal labeled icon button button_add_case"><i class="plus icon"></i>'+LocalizedStrings.getUI('text_teacher_test_case_add')+'</button>');
+
+    $('.button_add_case').on('click', function(e) {
+        addTestCase();
+    });
+}
+
+var hist = false;
+
+function addTestCase (test_case = null) {
+    var new_row = null;
+    if (test_case) {
+        var text_row = '';
+
+        text_row += '<tr><td class="counter"></td><td class="expandingArea"><textarea rows="'+test_case.input.length+'" name="input" class="text_area_input">';
+
+        for (var i = 0; i < test_case.input.length; i ++) {
+            text_row += test_case.input[i];
+            if ((i + 1) < test_case.input.length) {
+                text_row += '\n';
+            }
+        }
         
+        text_row += '</textarea></td><td class="expandingArea"><textarea rows="'+test_case.output.length+'" name="output" class="text_area_output">';
+
+        for (var i = 0; i < test_case.output.length; i ++) {
+            text_row += test_case.output[i];
+            if ((i + 1) < test_case.output.length) {
+                text_row += '\n';
+            }
+        }
+
+        text_row += '</textarea></td><td class="btn_actions"><div class="ui button_remove_case"><i class="red icon times large"></i></div></td></tr>';
+
+        new_row = $(text_row);
+    } else {
+        new_row = $('<tr><td class="counter"></td><td class="expandingArea"><textarea rows="1" name="input" class="text_area_input"></textarea></td><td class="expandingArea"><textarea rows="1" name="output" class="text_area_output"></textarea></td><td class="btn_actions"><div class="ui button_remove_case"><i class="red icon times large"></i></div></td></tr>');
+    }
+    $('.content_cases').append(new_row);
+
+    new_row.find('.button_remove_case').click(function(e) {
+        new_row.remove();
+        updateTestCaseCounter();
+    });
+
+    new_row.find('textarea').on('input', function(e) {
+        var lines = $(this).val().split('\n').length;
+        $(this).attr('rows', lines);
     });
+    
+    updateTestCaseCounter();
+
+     $('.text_area_output').keydown(function(e) {
+        var code = e.keyCode || e.which;
+        if (code == 9 && $(this).closest("tr").is(":last-child")) {
+            hist = true;
+            addTestCase();
+        }
+     });
+     if (test_case == null) {
+        if (!hist) {
+            $( ".content_cases tr:last" ).find('.text_area_input').focus();
+         } else {
+            hist = false;
+         }
+     }
+}
+
+function updateTestCaseCounter () {
+    var i = 1;
+    $( ".content_cases" ).find('tr').each(function() {
+      $( this ).find('.counter').text(i);
+      i ++;
+    });
+}
+
+function prepareTableSettings (div_el) {
+    div_el.append('<h4 class="ui header">'+LocalizedStrings.getUI('text_teacher_data_types')+'</h4>');
+    div_el.append('<form name="settings_data_types"><div class="ui stackable five column grid">'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="integer_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('integer')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="real_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('real')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="text_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="boolean_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('boolean')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="void_data_type" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('void')+'</label></div></div>'
+        +'</div></form>');
+
+
+    div_el.append('<h4 class="ui header">'+LocalizedStrings.getUI('text_teacher_commands')+'</h4>');
+    div_el.append('<form name="settings_commands"><div class="ui stackable three column grid">'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_read" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_read_var')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_write" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_write_var')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_comment" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_comment')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_attribution" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_attribution')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_functioncall" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_functioncall')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_iftrue" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_iftrue')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_repeatNtimes" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_repeatNtimes')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_while" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_whiletrue')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_dowhile" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_dowhiletrue')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="commands_switch" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_switch')+'</label></div></div>'
+        +'</div></form>');
+
+    div_el.append('<h4 class="ui header">'+LocalizedStrings.getUI('text_teacher_functions')+'</h4>');
+    div_el.append('<form name="settings_functions"><div class="ui stackable one column grid">'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="functions_creation" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_teacher_create_functions')+'</label></div></div>'
+        +'<div class="column"><div class="ui checkbox"><input type="checkbox" name="functions_move" checked tabindex="0" class="hidden small"><label>'+LocalizedStrings.getUI('text_teacher_create_movement_functions')+'</label></div></div>'
+        +'</div></form>');
+
+    $('.ui.checkbox').checkbox();
+
+
+}
+
+function getTrackingLogs () {
+    var ret = "";
+    for (var i = 0; i < trackingMatrix.length; i++) {
+        ret += "\n" + trackingMatrix[i][0] + "," + trackingMatrix[i][1] + "," + trackingMatrix[i][2];
+        if (trackingMatrix[i][2] === 1) {
+            ret += ',"' + trackingMatrix[i][3] + '"';
+        }
+    }
+    return ret;
 }
+
+// Tracking mouse movements
+var trackingMatrix = [];
+
+function adCoords(e, code){
+    var x = e.pageX; 
+    var y = e.pageY;
+    if (code === 1) {
+        return [x, y, code, e.target.classList['value']];
+    } else {
+        return [x, y, code];
+    }
+}
+
+$( document ).ready(function() {
+
+    if (inIframe()) {
+        orderIcons();
+        orderWidth();
+    }
+
+});
+
+function orderWidth() {
+    $('.ui.raised.container.segment.div_to_body').css('width', '100%');
+    $('.ui.one.column.container.segment.ivprog_visual_panel').css('width', '100%');
+}
+
+function orderIcons() {
+    $('.ui.one.column.doubling.stackable.grid.container').css('display', 'none');
+    $('.only_in_frame').css('display', 'block');
+    
+}
+
+
+function inIframe () {
+    try {
+        return window.self !== window.top;
+    } catch (e) {
+        return true;
+    }
+}
+
+
+function full_screen() {
+    // check if user allows full screen of elements. This can be enabled or disabled in browser config. By default its enabled.
+    //its also used to check if browser supports full screen api.
+    if("fullscreenEnabled" in document || "webkitFullscreenEnabled" in document || "mozFullScreenEnabled" in document || "msFullscreenEnabled" in document) {
+        if(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled) {
+            var element = document.getElementById("ui_main_div");
+            //requestFullscreen is used to display an element in full screen mode.
+            if("requestFullscreen" in element) {
+                element.requestFullscreen();
+            } 
+            else if ("webkitRequestFullscreen" in element) {
+                element.webkitRequestFullscreen();
+            } 
+            else if ("mozRequestFullScreen" in element) {
+                element.mozRequestFullScreen();
+            } 
+            else if ("msRequestFullscreen" in element) {
+                element.msRequestFullscreen();
+            }
+        }
+    } else {
+        $('.expand_button').addClass('disabled');
+    }
+}

+ 25 - 7
js/io/domConsole.js

@@ -17,6 +17,7 @@ export class DOMConsole {
   constructor (elementID) {
     this.input = null;
     this.needInput = false;
+    this.termDiv = null;
     this.anyKey = false;
     this.parent = $(elementID);
     this.setup();
@@ -46,18 +47,18 @@ export class DOMConsole {
   }
 
   _setupDom () {
-    const termDiv = $("<div></div>");
-    termDiv.addClass("ivprog-term-div");
+    this.termDiv = $("<div></div>");
+    this.termDiv.addClass("ivprog-term-div");
     this.input = $('<input text="type">')
     this.input.addClass("ivprog-term-input");
-    termDiv.append(this.input);
-    this.parent.append(termDiv);
+    this.termDiv.append(this.input);
+    this.parent.append(this.termDiv);
   }
 
   notifyListeners (text) {
     this.inputListeners.forEach(resolve => resolve(text));
     this.inputListeners.splice(0, this.inputListeners.length);
-    this.needInput = false;
+    this.hideInput();
     this.anyKey = false;
   }
 
@@ -79,6 +80,13 @@ export class DOMConsole {
     textDiv.addClass(divClass);
     textDiv.append(text);
     textDiv.insertBefore(this.input);
+    this.scrollTerm();
+  }
+
+  scrollTerm () {
+    this.termDiv.animate({
+      scrollTop: this.termDiv.prop('scrollHeight')
+    }, 0);
   }
 
   getClassForType (type) {
@@ -99,11 +107,21 @@ export class DOMConsole {
     this.parent.empty();
   }
 
+  showInput () {
+    this.needInput = true;
+    this.input.show();
+    this.input.focus();
+  }
+
+  hideInput () {
+    this.needInput = false;
+    this.input.hide();
+  }
+
   requestInput (callback, anyKey = false) {
     this.inputListeners.push(callback);
     this.anyKey = anyKey;
-    this.input.focus();
-    this.needInput = true;
+    this.showInput();
   }
 
   sendOutput (text) {

+ 0 - 0
js/io/domInput.js


+ 0 - 0
js/io/domOutput.js


+ 0 - 0
js/io/input.js


+ 0 - 0
js/io/output.js


+ 3 - 0
js/jquery.json-editor.min.js

@@ -35,6 +35,9 @@ function(e) {
               s += "</ol>]"
           } else s += "[]";
       else if ("object" == typeof e) {
+          if (e['_type'] && (e['_type'].value === 'real' || e['_type'].value === 'int')) {
+            e._value = e._value.toNumber();
+          }
           var a = Object.keys(e).length;
           if (a > 0) {
               s += '{<ul class="json-dict">';

+ 6 - 3
js/main.js

@@ -1,10 +1,13 @@
 import { runner } from './runner';
 import { initVisualUI } from './visualUI/functions';
-import { LocalizedStrings, StringTypes } from './services/localizedStringsService';
+import { LocalizedStrings} from './services/localizedStringsService';
+import { i18nHelper } from "./services/i18nHelper";
+
+const i18n = i18nHelper.i18n
 
 export {
   runner,
   initVisualUI,
   LocalizedStrings,
-  StringTypes
-}
+  i18n
+}

+ 33 - 0
js/processor/compatibilityTable.js

@@ -1,6 +1,7 @@
 import { Types } from './../typeSystem/types';
 import { Operators } from './../ast/operators';
 import { MultiType } from '../typeSystem/multiType';
+import { Config } from '../util/config';
 
 function buildInfixAddTable () {
   const table = [[], [], [], []];
@@ -133,6 +134,13 @@ export function resultTypeAfterInfixOp (operator, leftExpressionType, rightExpre
         }
       }
       if(newMulti.length <= 0) {
+        if(Config.enable_type_casting) {
+          if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
+            if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
+              return new MultiType([Types.INTEGER, Types.REAL]);
+            }
+          }
+        }
         return Types.UNDEFINED;
       } else {
         return new MultiType(newMulti)
@@ -141,17 +149,42 @@ export function resultTypeAfterInfixOp (operator, leftExpressionType, rightExpre
       if(leftExpressionType.isCompatible(rightExpressionType)) {
         return rightExpressionType;
       } else {
+        if(Config.enable_type_casting) {
+          if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
+            if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
+              return rightExpressionType;
+            }
+          }
+        }
         return Types.UNDEFINED;
       }
     } else if(rightExpressionType instanceof MultiType) {
       if(rightExpressionType.isCompatible(leftExpressionType)) {
         return leftExpressionType;
       } else {
+        if(Config.enable_type_casting) {
+          if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
+            if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
+              return leftExpressionType;
+            }
+          }
+        }
         return Types.UNDEFINED;
       }
     }
     const resultType = infixMap.get(operator)[leftExpressionType.ord][rightExpressionType.ord];
     if (resultType === null || resultType === undefined) {
+      if(Config.enable_type_casting) {
+        if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
+          if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
+            if(operator === Operators.MOD) {
+              return Types.INTEGER;
+            } else if (operator.ord >= 5 && operator.ord <= 10){
+              return Types.BOOLEAN;
+            }
+          }
+        }
+      }
       return Types.UNDEFINED
     }
     return resultType;

+ 0 - 0
js/processor/context.js


+ 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
+    }
+  }
 });

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

@@ -1,7 +1,398 @@
 import { RuntimeError } from './runtimeError';
 import { SemanticError } from './semanticError';
 import { LocalizedStrings } from './../../services/localizedStringsService';
+import { Operators } from '../../ast/operators';
+
+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])
+  }
+}
+
+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) {
+      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"));
+  },        // TODO: better urgent error message
+  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_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) {
+      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"));
+  },
+  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];
+      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_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];
+      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));
+  },
+  void_in_expression_full: (id, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, sourceInfo.column, id];
+      return new SemanticError(LocalizedStrings.getError("void_in_expression_full", context));
+    } else {
+      return ProcessorErrorFactory.void_in_expression(id);
+    }
+  },
+  void_in_expression: (id) => {
+    const context = [id];
+    return new SemanticError(LocalizedStrings.getError("void_in_expression", context));
+  },
+  invalid_array_access_full: (id, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [id, sourceInfo.line, sourceInfo.column];
+      return new SemanticError(LocalizedStrings.getError("invalid_array_access_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_array_access(id);
+    }
+  },
+  invalid_array_access: (id) => {
+    const context = [id];
+    return new SemanticError(LocalizedStrings.getError("invalid_array_access", context));
+  },
+  invalid_matrix_access_full: (id, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [id, sourceInfo.line, sourceInfo.column];
+      return new SemanticError(LocalizedStrings.getError("invalid_matrix_access_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_matrix_access(id);
+    }
+  },
+  invalid_matrix_access: (id) => {
+    const context = [id];
+    return new SemanticError(LocalizedStrings.getError("invalid_matrix_access", context));
+  },
+  matrix_column_outbounds_full: (id, value, columns, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, value, id, columns];
+      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 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 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 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 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 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];
+    return new SemanticError(LocalizedStrings.getError("function_no_return", context));
+  },
+  invalid_void_return_full: (id, type, dim, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, id, translateType(type, dim)];
+      return new SemanticError(LocalizedStrings.getError("invalid_void_return_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_void_return(id, type, dim);
+    }
+  },
+  invalid_void_return: (id, type, dim) => {
+    const context = [id, translateType(type, dim)];
+    return new SemanticError(LocalizedStrings.getError("invalid_void_return_full", context));
+  },
+  invalid_return_type_full: (id, type, dim, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, id, translateType(type, dim)];
+      return new SemanticError(LocalizedStrings.getError("invalid_return_type_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_return_type(id, type, dim);
+    }
+  },
+  invalid_return_type: (id, type, dim) => {
+    const context = [id, translateType(type, dim)];
+    return new SemanticError(LocalizedStrings.getError("invalid_return_type", context));
+  },
+  invalid_parameters_size_full: (id, expected, actual, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [sourceInfo.line, id, expected, actual];
+      return new SemanticError(LocalizedStrings.getError("invalid_parameters_size_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_parameters_size(id, expected, actual);
+    }
+  },
+  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) => {
+    if(sourceInfo) {
+      const context = [exp, id, sourceInfo.line];
+      return new SemanticError(LocalizedStrings.getError("invalid_parameter_type_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_parameter_type(id, exp);
+    }
+  },
+  invalid_parameter_type: (id, exp) => {
+    const context = [exp, id];
+    return new SemanticError(LocalizedStrings.getError("invalid_parameter_type_full", context));
+  },
+  invalid_ref_full: (id, exp, sourceInfo) => {
+    if(sourceInfo) {
+      const context = [exp, id , sourceInfo.line];
+      return new SemanticError(LocalizedStrings.getError("invalid_ref_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_ref(id, exp);
+    }
+  },
+  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"));
+  }
 });

+ 0 - 0
js/processor/error/runtimeError.js


+ 0 - 0
js/processor/error/semanticError.js


+ 288 - 138
js/processor/ivprogProcessor.js

@@ -14,24 +14,30 @@ import { StoreObjectArrayAddress } from './store/storeObjectArrayAddress';
 import { StoreObjectArrayAddressRef } from './store/storeObjectArrayAddressRef';
 import { CompoundType } from './../typeSystem/compoundType';
 import { convertToString } from '../typeSystem/parsers';
-
-let loopTimeoutMs = 10000
+import { Config } from '../util/config';
+import Decimal from 'decimal.js';
+import { ProcessorErrorFactory } from './error/processorErrorFactory';
+import { RuntimeError } from './error/runtimeError';
 
 export class IVProgProcessor {
 
   static get LOOP_TIMEOUT () {
-    return loopTimeoutMs;
+    return Config.loopTimeout;
   }
 
   static set LOOP_TIMEOUT (ms) {
-    loopTimeoutMs = ms;
+    Config.setConfig({loopTimeout: ms});
+  }
+
+  static get MAIN_INTERNAL_ID () {
+    return "$main";
   }
 
   constructor (ast) {
     this.ast = ast;
-    this.globalStore = null;
-    this.stores = null;
-    this.context = null;
+    this.globalStore = new Store("$global");
+    this.stores = [this.globalStore];
+    this.context = [Context.BASE];
     this.input = null;
     this.forceKill = false;
     this.loopTimers = [];
@@ -73,29 +79,27 @@ export class IVProgProcessor {
     }
     if(this.globalStore !== null)
       this.globalStore = null;
-    this.globalStore = new Store();
+    this.globalStore = new Store("$global");
     this.stores = [this.globalStore];
     this.context = [Context.BASE];
   }
 
   interpretAST () {
     this.prepareState();
-    this.initGlobal();
-    const mainFunc = this.findMainFunction();
-    if(mainFunc === null) {
-      // TODO: Better error message
-      throw new Error("Missing main funciton.");
-    }
-    return this.runFunction(mainFunc, [], this.globalStore);
+    return this.initGlobal().then( _ => {
+      const mainFunc = this.findMainFunction();
+      if(mainFunc === null) {
+        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);
-    });
+    return this.executeCommands(this.globalStore, this.ast.global);
   }
 
   findMainFunction () {
@@ -106,21 +110,22 @@ 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) {
-    let funcStore = new Store();
+    const funcName = func.isMain ? IVProgProcessor.MAIN_INTERNAL_ID : func.name;
+    let funcStore = new Store(funcName);
     funcStore.extendStore(this.globalStore);
     let returnStoreObject = null;
     if(func.returnType instanceof CompoundType) {
@@ -132,10 +137,7 @@ export class IVProgProcessor {
     } else {
       returnStoreObject = new StoreObject(func.returnType, null);
     }
-    const funcName = func.isMain ? 'main' : func.name;
-    const funcNameStoreObject = new StoreObject(Types.STRING, funcName, true);
     funcStore.insertStore('$', returnStoreObject);
-    funcStore.insertStore('$name', funcNameStoreObject);
     const newFuncStore$ = this.associateParameters(func.formalParameters, actualParameters, store, funcStore);
     return newFuncStore$.then(sto => {
       this.context.push(Context.FUNCTION);
@@ -150,34 +152,46 @@ 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];
+        let shouldTypeCast = false;
         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');
+        if(!formalParameter.type.isCompatible(stoObj.type)) {
+          if (Config.enable_type_casting && !formalParameter.byRef
+            && Store.canImplicitTypeCast(formalParameter.type, stoObj.type)) {
+              shouldTypeCast =  true;
+          } else {
+            throw ProcessorErrorFactory.invalid_parameter_type(funcName, exp.toString());
           }
+        }
 
-          if(formalParameter.byRef) {
-            let ref = null;
-            if (stoObj instanceof StoreObjectArrayAddress) {
-              ref = new StoreObjectArrayAddressRef(stoObj);
-            } else {
-              ref = new StoreObjectRef(stoObj.id, callerStore);
-            }
-            calleeStore.insertStore(formalParameter.id, ref);
+        if(formalParameter.byRef && !stoObj.inStore) {
+          throw ProcessorErrorFactory.invalid_ref(funcName, exp.toString());
+        }
+
+        if(formalParameter.byRef) {
+          let ref = null;
+          if (stoObj instanceof StoreObjectArrayAddress) {
+            ref = new StoreObjectArrayAddressRef(stoObj);
           } else {
-            let realValue = this.parseStoreObjectValue(stoObj);
-            calleeStore.insertStore(formalParameter.id, realValue);
+            ref = new StoreObjectRef(stoObj.id, callerStore);
           }
+          calleeStore.insertStore(formalParameter.id, ref);
         } else {
-          throw new Error(`Parameter ${formalParameter.id} is not compatible with the value given.`);
+          let realValue = this.parseStoreObjectValue(stoObj);
+          if (shouldTypeCast) {
+            realValue = Store.doImplicitCasting(formalParameter.type, realValue);
+          }
+          calleeStore.insertStore(formalParameter.id, realValue);
         }
       }
       return calleeStore;
@@ -197,7 +211,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) {
@@ -226,12 +240,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);
     }
   }
 
@@ -241,12 +256,18 @@ export class IVProgProcessor {
   }
 
   executeFunctionCall (store, cmd) {
-    const func = this.findFunction(cmd.id);
+    let func = null;
+    if(cmd.isMainCall) {
+      func = this.findMainFunction();
+    } else {
+      func = this.findFunction(cmd.id);
+    }
     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;
         }
@@ -311,6 +332,7 @@ export class IVProgProcessor {
       const whileBlock = new Commands.CommandBlock([],
         cmd.commands.concat(increment));
       const forAsWhile = new Commands.While(condition, whileBlock);
+      forAsWhile.sourceInfo = cmd.sourceInfo;
       //END for -> while rewrite
       const newCmdList = [initCmd,forAsWhile];
       return this.executeCommands(store, newCmdList);
@@ -335,25 +357,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;
           }
         })
@@ -383,9 +401,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);
@@ -393,13 +410,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));
         }
       })
       
@@ -425,9 +439,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) {
@@ -437,19 +449,20 @@ export class IVProgProcessor {
 
   executeReturn (store, cmd) {
     try {
-      const funcType = store.applyStore('$');
+      const funcType = store.applyStore('$').type;
       const $value = this.evaluateExpression(store, cmd.expression);
-      const funcName = store.applyStore('$name');
+      const funcName = store.name === IVProgProcessor.MAIN_INTERNAL_ID ? 
+        LanguageDefinedFunction.getMainFunctionName() : store.name;
       return $value.then(vl => {
 
         if(vl === null && funcType.isCompatible(Types.VOID)) {
           return Promise.resolve(store);
         }
 
-        if (vl === null || !funcType.type.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.value} must return ${funcType.type} instead of ${vl.type}.`));
+        if (vl === null || !funcType.isCompatible(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);
@@ -462,20 +475,31 @@ 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));
     }
   }
 
   executeAssign (store, cmd) {
     try {
+      const inStore = store.applyStore(cmd.id);
       const $value = this.evaluateExpression(store, cmd.expression);
       return $value.then( vl => {
         let realValue = this.parseStoreObjectValue(vl);
+        if(!inStore.type.isCompatible(realValue.type)) {
+          if(Config.enable_type_casting && Store.canImplicitTypeCast(inStore.type, vl.type)) {
+            realValue = Store.doImplicitCasting(inStore.type, realValue);
+          } else {
+            const stringInfo = inStore.type.stringInfo()
+            const info = stringInfo[0]
+            return Promise.reject(ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, cmd.sourceInfo));
+          }
+        }
+        
         store.updateStore(cmd.id, realValue) 
         return store;
       });
@@ -487,7 +511,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);
@@ -495,45 +519,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));
+        if (value.type instanceof CompoundType || !newArray.type.canAccept(value.type)) {
+          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));
+        if((mustBeArray.columns !== null && value.type instanceof CompoundType) || !newArray.type.canAccept(value.type)) {
+          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);
@@ -551,20 +585,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);
@@ -597,15 +633,24 @@ export class IVProgProcessor {
         return $value.then(vl => {
           let realValue = vl;
           if (vl !== null) {
+            if(!vl.type.isCompatible(cmd.type)) {
+              if(Config.enable_type_casting && Store.canImplicitTypeCast(cmd.type, vl.type)) {
+                realValue = Store.doImplicitCasting(cmd.type, realValue);
+              } else {
+                const stringInfo = typeInfo.type.stringInfo();
+                const info = stringInfo[0];
+                return Promise.reject(ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, cmd.sourceInfo));
+              }
+            }
             if(vl instanceof StoreObjectArrayAddress) {
               if(vl.type instanceof CompoundType) {
-                realValue = Object.assign(new StoreObjectArray(null,null,null), vl.refValue);
+                return Promise.reject(new Error("!!!Critical Error: Compatibility check failed, a Type accepts a CompoundType"))
               } else {
                 realValue = Object.assign(new StoreObject(null,null), vl.refValue);
               }
             }
           } else {
-            realValue = new StoreObject(cmd.type,0);
+            realValue = new StoreObject(cmd.type, 0);
           }
           realValue.readOnly = cmd.isConst;
           store.updateStore(cmd.id, realValue);
@@ -644,10 +689,13 @@ export class IVProgProcessor {
   }
 
   evaluateFunctionCall (store, exp) {
+    if(exp.isMainCall) {
+      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 => {
@@ -664,24 +712,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);
+        }
       });
     }
   }
@@ -720,9 +797,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);
@@ -730,32 +805,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));
     });
@@ -766,8 +845,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:
@@ -777,7 +857,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));
       }
     });
   }
@@ -786,12 +866,21 @@ export class IVProgProcessor {
     const $left = this.evaluateExpression(store, infixApp.left);
     const $right = this.evaluateExpression(store, infixApp.right);
     return Promise.all([$left, $right]).then(values => {
+      let shouldImplicitCast = false;
       const left = values[0];
       const right = values[1];
-      const resultType = resultTypeAfterInfixOp(infixApp.op, left.type, right.type);
+      let 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}`));
+        if (Config.enable_type_casting && Store.canImplicitTypeCast(left.type, right.type)) {
+          shouldImplicitCast = true;
+        } else {
+          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) {
@@ -808,61 +897,122 @@ export class IVProgProcessor {
         }
         case Operators.SUB.ord:
           return new StoreObject(resultType, left.value.minus(right.value));
-        case Operators.MULT.ord:
-          return new StoreObject(resultType, left.value.times(right.value));
+        case Operators.MULT.ord: {
+          result = left.value.times(right.value);
+          if(result.dp() > Config.decimalPlaces) {
+            result = new Decimal(result.toFixed(Config.decimalPlaces));
+          }
+          return new StoreObject(resultType, result);
+        }
         case Operators.DIV.ord: {
-          result = left.value / right.value;
           if (Types.INTEGER.isCompatible(resultType))
             result = left.value.divToInt(right.value);
           else
             result = left.value.div(right.value);
+          if(result.dp() > Config.decimalPlaces) {
+            result = new Decimal(result.toFixed(Config.decimalPlaces));
+          }
           return new StoreObject(resultType, result);
         }
-        case Operators.MOD.ord:
-          return new StoreObject(resultType, left.value.modulo(right.value));
+        case Operators.MOD.ord: {
+          let leftValue = left.value;
+          let rightValue = right.value;
+          if(shouldImplicitCast) {
+            resultType = Types.INTEGER;
+            leftValue = leftValue.trunc();
+            rightValue = rightValue.trunc();
+          }
+          result = leftValue.modulo(rightValue);
+          if(result.dp() > Config.decimalPlaces) {
+            result = new Decimal(result.toFixed(Config.decimalPlaces));
+          }
+          return new StoreObject(resultType, result);
+        }          
         case Operators.GT.ord: {
+          let leftValue = left.value;
+          let rightValue = right.value;
           if (Types.STRING.isCompatible(left.type)) {
             result = left.value.length > right.value.length;
           } else {
-            result = left.value.gt(right.value);
+            if (shouldImplicitCast) {
+              resultType = Types.BOOLEAN;
+              leftValue = leftValue.trunc();
+              rightValue = rightValue.trunc();
+            }
+            result = leftValue.gt(rightValue);
           }
           return new StoreObject(resultType, result);
         }
         case Operators.GE.ord: {
+          let leftValue = left.value;
+          let rightValue = right.value;
           if (Types.STRING.isCompatible(left.type)) {
             result = left.value.length >= right.value.length;
           } else {
-            result = left.value.gte(right.value);
+            if (shouldImplicitCast) {
+              resultType = Types.BOOLEAN;
+              leftValue = leftValue.trunc();
+              rightValue = rightValue.trunc();
+            }
+            result = leftValue.gte(rightValue);
           }
           return new StoreObject(resultType, result);
         }
         case Operators.LT.ord: {
+          let leftValue = left.value;
+          let rightValue = right.value;
           if (Types.STRING.isCompatible(left.type)) {
             result = left.value.length < right.value.length;
           } else {
-            result = left.value.lt(right.value);
+            if (shouldImplicitCast) {
+              resultType = Types.BOOLEAN;
+              leftValue = leftValue.trunc();
+              rightValue = rightValue.trunc();
+            }
+            result = leftValue.lt(rightValue);
           }
           return new StoreObject(resultType, result);
         }
         case Operators.LE.ord: {
+          let leftValue = left.value;
+          let rightValue = right.value;
           if (Types.STRING.isCompatible(left.type)) {
             result = left.value.length <= right.value.length;
           } else {
-            result = left.value.lte(right.value);
+            if (shouldImplicitCast) {
+              resultType = Types.BOOLEAN;
+              leftValue = leftValue.trunc();
+              rightValue = rightValue.trunc();
+            }
+            result = leftValue.lte(rightValue);
           }
           return new StoreObject(resultType, result);
         }
         case Operators.EQ.ord: {
+          let leftValue = left.value;
+          let rightValue = right.value;
           if (Types.INTEGER.isCompatible(left.type) || Types.REAL.isCompatible(left.type)) {
-            result = left.value.eq(right.value);
+            if (shouldImplicitCast) {
+              resultType = Types.BOOLEAN;
+              leftValue = leftValue.trunc();
+              rightValue = rightValue.trunc();
+            }
+            result = leftValue.eq(rightValue);
           } else {
             result = left.value === right.value;
           }
           return new StoreObject(resultType, result);
         }
         case Operators.NEQ.ord: {
+          let leftValue = left.value;
+          let rightValue = right.value;
           if (Types.INTEGER.isCompatible(left.type) || Types.REAL.isCompatible(left.type)) {
-            result = !left.value.eq(right.value);
+            if (shouldImplicitCast) {
+              resultType = Types.BOOLEAN;
+              leftValue = leftValue.trunc();
+              rightValue = rightValue.trunc();
+            }
+            result = !leftValue.eq(rightValue);
           } else {
             result = left.value !== right.value;
           }
@@ -873,7 +1023,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));
       }
     });
   }
@@ -888,7 +1038,7 @@ export class IVProgProcessor {
             break;
           }
           default: {
-            throw new Error("Three dimensional array address...");
+            throw new RuntimeError("Three dimensional array address...");
           }
         }
       } else {

+ 0 - 0
js/processor/lib/arrays.js


+ 2 - 12
js/processor/lib/io.js

@@ -1,22 +1,12 @@
 import { StoreObject } from './../store/storeObject';
 import * as Commands from './../../ast/commands';
-import {toInt, toString, toBool, toReal} from './../../typeSystem/parsers';
+import {toInt, toString, toBool, toReal, convertToString} from './../../typeSystem/parsers';
 import { Types } from './../../typeSystem/types';
 
 export function createOutputFun () {
   const writeFunction = function (store, _) {
     const val = store.applyStore('p1');
-    if(val.type.isCompatible(Types.INTEGER)) {
-      this.output.sendOutput(val.value.toString());
-    } else if (val.type.isCompatible(Types.REAL)) {
-      if (val.value.dp() <= 0) {
-        this.output.sendOutput(val.value.toFixed(1));  
-      } else {
-        this.output.sendOutput(val.value.toString());
-      }
-    } else {
-      this.output.sendOutput(val.value);
-    }
+    this.output.sendOutput(convertToString(val.value, val.type));
     return Promise.resolve(store);
   }
   const block = new Commands.CommandBlock([], [new Commands.SysCall(writeFunction)]);

+ 0 - 0
js/processor/lib/lang.js


+ 52 - 7
js/processor/lib/math.js

@@ -6,6 +6,7 @@ import { Decimal } from 'decimal.js';
 import { MultiType } from '../../typeSystem/multiType';
 import { CompoundType } from '../../typeSystem/compoundType';
 import { Modes } from '../modes';
+import { Config } from '../../util/config';
 
 /**
  * sin
@@ -28,7 +29,20 @@ function convertToRadians (degrees) {
 export function createSinFun () {
    const sinFun = (sto, _) => {
      const x = sto.applyStore('x');
-     const result = Decimal.sin(convertToRadians(x.value));
+     const angle = x.value.mod(360);
+     let result = null;
+     if(angle.eq(90)) {
+       result = new Decimal(1);
+     } else if (angle.eq(180)) {
+      result = new Decimal(0);
+     } else if (angle.eq(270)) {
+       result = new Decimal(-1);
+     } else {
+       result = Decimal.sin(convertToRadians(angle));
+     }
+     if(result.dp() > Config.decimalPlaces) {
+      result = new Decimal(result.toFixed(Config.decimalPlaces));
+    }
      const temp = new StoreObject(Types.REAL, result);
      sto.mode = Modes.RETURN;
      return Promise.resolve(sto.updateStore('$', temp));
@@ -44,7 +58,19 @@ export function createSinFun () {
 export function createCosFun () {
   const cosFun = (sto, _) => {
     const x = sto.applyStore('x');
-    const result = Decimal.cos(convertToRadians(x.value));
+    const angle = x.value.mod(360);
+    let result = null;
+    if(angle.eq(90)) {
+      result = new Decimal(0);
+    } else if (angle.eq(180)) {
+      result = new Decimal(-1);
+    } else if (angle.eq(270)) {
+      result = new Decimal(0)
+    }
+    result = Decimal.cos(convertToRadians(angle));
+    if(result.dp() > Config.decimalPlaces) {
+      result = new Decimal(result.toFixed(Config.decimalPlaces));
+    }
     const temp = new StoreObject(Types.REAL, result);
     sto.mode = Modes.RETURN;
     return Promise.resolve(sto.updateStore('$', temp));
@@ -60,7 +86,14 @@ export function createCosFun () {
 export function createTanFun () {
   const tanFun = (sto, _) => {
     const x = sto.applyStore('x');
-    const result = Decimal.tan(convertToRadians(x.value));
+    const angle = x.value.mod(360);
+    if(angle.eq(90) || angle.eq(270)) {
+      return Promise.reject("Tangent of "+x.value.toNumber()+"° is undefined.");
+    }
+    let result = Decimal.tan(convertToRadians(angle));
+    if(result.dp() > Config.decimalPlaces) {
+      result = new Decimal(result.toFixed(Config.decimalPlaces));
+    }
     const temp = new StoreObject(Types.REAL, result);
     sto.mode = Modes.RETURN;
     return Promise.resolve(sto.updateStore('$', temp));
@@ -76,7 +109,10 @@ export function createTanFun () {
 export function createSqrtFun () {
   const sqrtFun = (sto, _) => {
     const x = sto.applyStore('x');
-    const result = x.value.sqrt();
+    let result = x.value.sqrt();
+    if(result.dp() > Config.decimalPlaces) {
+      result = new Decimal(result.toFixed(Config.decimalPlaces));
+    }
     const temp = new StoreObject(Types.REAL, result);
     sto.mode = Modes.RETURN;
     return Promise.resolve(sto.updateStore('$', temp));
@@ -93,7 +129,10 @@ export function createPowFun () {
   const powFun = (sto, _) => {
     const x = sto.applyStore('x');
     const y = sto.applyStore('y');
-    const result = x.value.pow(y.value);
+    let result = x.value.pow(y.value);
+    if(result.dp() > Config.decimalPlaces) {
+      result = new Decimal(result.toFixed(Config.decimalPlaces));
+    }
     const temp = new StoreObject(Types.REAL, result);
     sto.mode = Modes.RETURN;
     return Promise.resolve(sto.updateStore('$', temp));
@@ -113,7 +152,10 @@ export function createLogFun () {
     if (x.value.isNegative()) {
       return Promise.reject("the value passed to log function cannot be negative");
     }
-    const result = Decimal.log10(x.value);
+    let result = Decimal.log10(x.value);
+    if(result.dp() > Config.decimalPlaces) {
+      result = new Decimal(result.toFixed(Config.decimalPlaces));
+    }
     const temp = new StoreObject(Types.REAL, result);
     sto.mode = Modes.RETURN;
     return Promise.resolve(sto.updateStore('$', temp));
@@ -161,7 +203,10 @@ export function createNegateFun () {
 export function createInvertFun () {
   const invertFun = (sto, _) => {
     const x = sto.applyStore('x');
-    const result = toReal(1).dividedBy(x.value);
+    let result = toReal(1).dividedBy(x.value);
+    if(result.dp() > Config.decimalPlaces) {
+      result = new Decimal(result.toFixed(Config.decimalPlaces));
+    }
     const temp = new StoreObject(Types.REAL, result);
     sto.mode = Modes.RETURN;
     return Promise.resolve(sto.updateStore('$', temp));

+ 0 - 0
js/processor/lib/strings.js


+ 0 - 0
js/processor/modes.js


+ 165 - 72
js/processor/semantic/semanticAnalyser.js

@@ -1,13 +1,15 @@
 import { ProcessorErrorFactory } from './../error/processorErrorFactory';
 import { LanguageDefinedFunction } from './../definedFunctions';
 import { LanguageService } from './../../services/languageService';
-import { ArrayDeclaration, While, For, Switch, Case, Declaration, Assign, Break, IfThenElse, Return, ArrayIndexAssign } from '../../ast/commands';
+import { ArrayDeclaration, While, For, Switch, Assign, Break, IfThenElse, Return, ArrayIndexAssign } from '../../ast/commands';
 import { InfixApp, UnaryApp, FunctionCall, IntLiteral, RealLiteral, StringLiteral, BoolLiteral, VariableLiteral, ArrayLiteral, ArrayAccess } from '../../ast/expressions';
 import { Literal } from '../../ast/expressions/literal';
 import { resultTypeAfterInfixOp, resultTypeAfterUnaryOp } from '../compatibilityTable';
 import { Types } from '../../typeSystem/types';
 import { CompoundType } from '../../typeSystem/compoundType';
 import { MultiType } from '../../typeSystem/multiType';
+import { Config } from '../../util/config';
+import { Store } from '../store/store';
 
 export class SemanticAnalyser {
 
@@ -17,6 +19,7 @@ export class SemanticAnalyser {
     const lexer = new this.lexerClass(null);
     this.literalNames = lexer.literalNames;
     this.symbolMap = null;
+    this.currentFunction = null;
   }
 
   pushMap () {
@@ -43,24 +46,28 @@ 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];
     }
   }
 
+  getMainFunction () {
+    return this.ast.functions.find(v => v.isMain);
+  }
+
   findFunction (name) {
+    console.log(name);
     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.`);
+        return null;
       }
       return val;
     }
@@ -73,12 +80,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);
     }
@@ -96,18 +100,18 @@ 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});
         return;
       }
-      this.evaluateArrayLiteral(declaration.lines, declaration.columns, declaration.type, declaration.initial);
+      this.evaluateArrayLiteral(declaration.id, declaration.lines, declaration.columns, declaration.type, declaration.initial);
       this.insertSymbol(declaration.id, {id: declaration.id, lines: declaration.lines, columns: declaration.columns, type: declaration.type});
 
     } else {
@@ -118,13 +122,19 @@ 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');
+      } else if((!declaration.type.isCompatible(resultType) && !Config.enable_type_casting)
+        || (!declaration.type.isCompatible(resultType) && Config.enable_type_casting
+        && !Store.canImplicitTypeCast(declaration.type, resultType))) {
+        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})
+        this.insertSymbol(declaration.id, {id: declaration.id, type: declaration.type});
       }
     }
   }
@@ -142,28 +152,37 @@ export class SemanticAnalyser {
     } else if (expression instanceof Literal) {
       return this.evaluateLiteralType(expression);
     } else if (expression instanceof FunctionCall) {
+      if (expression.isMainCall) {
+        throw ProcessorErrorFactory.void_in_expression_full(LanguageDefinedFunction.getMainFunctionName(), expression.sourceInfo);
+      }
       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");
+        throw ProcessorErrorFactory.void_in_expression_full(expression.id, expression.sourceInfo);
       }
       this.assertParameters(fun, expression.actualParameters);
       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");
+        throw ProcessorErrorFactory.invalid_array_access_full(expression.id, expression.sourceInfo);
       }
       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) {
-          throw new Error("it's not a matrix");
+          throw ProcessorErrorFactory.invalid_matrix_access_full(expression.id, expression.sourceInfo);
         }
         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;
@@ -190,6 +209,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;
       }
@@ -205,9 +227,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);
           }
         }
       }
@@ -218,21 +241,32 @@ export class SemanticAnalyser {
     }
   }
 
-  evaluateArrayLiteral (lines, columns, type, literal) {
-    if (literal instanceof ArrayLiteral) {
+  evaluateArrayLiteral (id, lines, columns, type, literal) {
+    /* if (literal instanceof ArrayLiteral) {
+      const dimType = this.evaluateExpressionType(lines);
+      if (!dimType.isCompatible(Types.INTEGER)) {
+        throw ProcessorErrorFactory.array_dimension_not_int_full(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.value.toNumber(), literal.sourceInfo)
+          } else {
+            throw ProcessorErrorFactory.vector_line_outbounds_full(id, literal.value.length, lines.value.toNumber(), literal.sourceInfo)
+          }
+        } else if (lines.value.isNeg()) {
+          throw ProcessorErrorFactory.array_dimension_not_positive_full(literal.sourceInfo);
+        }
+      }
       if (columns === null) {
         // it's a vector...
-        const dimType = this.evaluateExpressionType(lines);
-        if (!dimType.isCompatible(Types.INTEGER)) {
-          throw new Error("dim must be int");
-        }
-        if ((lines instanceof IntLiteral) && !lines.value.eq(literal.value.length)) {
-          throw new Error("invalid array size");
-        }
         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);
@@ -240,14 +274,23 @@ 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");
-        }
-        for (let i = 0; i < columns; i++) {
-          const anotherArray = literal.value[i];
-          this.evaluateArrayLiteral(lines, null, type, anotherArray)
+        if ((columns instanceof IntLiteral)) {
+          const columnValue = literal.value[0].value.length;
+          if (!columns.value.eq(columnValue)) {
+            if(type.dimensions > 1) {
+              throw ProcessorErrorFactory.matrix_column_outbounds_full(id, literal.value.length, columns.value.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];
+            this.evaluateArrayLiteral(id, columns, null, type, anotherArray)
+          }
         }
       }
 
@@ -255,18 +298,25 @@ 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;
-
-    }
+    } */
+    return true;
   }
 
   assertFunction (fun) {
     this.pushMap();
+    this.currentFunction = fun;
     fun.formalParameters.forEach(formalParam => {
       if(formalParam.type instanceof CompoundType) {
         if(formalParam.type.dimensions > 1) {
@@ -282,7 +332,7 @@ export class SemanticAnalyser {
     const optional = fun.returnType.isCompatible(Types.VOID);
     const valid = this.assertReturn(fun, optional);
     if (!valid) {
-      throw new Error("function has no accessible return");
+      throw ProcessorErrorFactory.function_no_return(fun.name);
     }
     this.popMap();
   }
@@ -297,7 +347,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;
@@ -305,7 +355,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);
@@ -319,7 +369,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;
@@ -330,43 +383,55 @@ 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.");
+        throw ProcessorErrorFactory.invalid_array_access_full(cmd.id, cmd.sourceInfo);
       }
       const exp = cmd.expression;
       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) {
-        throw new Error(cmd.id + " is not a matrix");
+        throw ProcessorErrorFactory.invalid_matrix_access_full(cmd.id, cmd.sourceInfo);
       } 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
       if(exp instanceof ArrayLiteral) {
-        this.evaluateArrayLiteral(typeInfo.lines, (columnExp ? typeInfo.columns : null), typeInfo.type, exp);
+        this.evaluateArrayLiteral(cmd.id, typeInfo.lines, (columnExp ? typeInfo.columns : null), typeInfo.type, exp);
       } else {
         // cannot properly evaluate since type system is poorly constructed
       }
       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);
+        this.evaluateArrayLiteral(cmd.id, typeInfo.lines, typeInfo.columns, typeInfo.type, exp);
       } else {
         const resultType = this.evaluateExpressionType(exp);
-        if(!resultType.isCompatible(typeInfo.type)) {
-          throw new Error("type not compatible");
+        if((!resultType.isCompatible(typeInfo.type) && !Config.enable_type_casting)
+          || (!resultType.isCompatible(typeInfo.type) && Config.enable_type_casting
+          && !Store.canImplicitTypeCast(typeInfo.type, resultType))) {
+          const stringInfo = typeInfo.type.stringInfo();
+          const info = stringInfo[0];
+          throw ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, cmd.sourceInfo);
         }
       }
       return optional;
@@ -375,7 +440,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);
@@ -384,17 +449,29 @@ export class SemanticAnalyser {
       }
 
     } else if (cmd instanceof FunctionCall) {
-      const fun = this.findFunction(cmd.id);
+      let fun = null;
+      if (cmd.isMainCall) {
+        fun = this.getMainFunction();
+      } 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) {
+      const funcName = this.currentFunction.isMain ? LanguageDefinedFunction.getMainFunctionName() : this.currentFunction.name
       if (cmd.expression === null && !type.isCompatible(Types.VOID)) {
-        throw new Error('invalid return type');
+        const stringInfo = type.stringInfo();
+        const info = stringInfo[0];
+        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)) {
-          console.log(resultType);
-          throw new Error('invalid return type');
+          const stringInfo = type.stringInfo();
+          const info = stringInfo[0];
+          throw ProcessorErrorFactory.invalid_return_type_full(funcName, info.type, info.dim, cmd.sourceInfo);
         } else {
           return true;
         }
@@ -412,14 +489,15 @@ export class SemanticAnalyser {
 
   assertParameters (fun, actualParametersList) {
     if (fun.formalParameters.length !== actualParametersList.length) {
-      throw new Error("wrong number of parameters...");
+      throw ProcessorErrorFactory.invalid_parameters_size_full(fun.name, actualParametersList.length, fun.formalParameters.length, null);
     }
     for (let i = 0; i < actualParametersList.length; i++) {
       const param = actualParametersList[i];
       const formalParam = fun.formalParameters[i];
+      const id = formalParam.id;
       if(formalParam.byRef) {
         if (!(param instanceof VariableLiteral || param instanceof ArrayAccess)) {
-          throw new Error("Invalid param type for ref");
+          throw ProcessorErrorFactory.invalid_parameter_type_full(id, param.toString(), param.sourceInfo);
         }
       }
       const resultType = this.evaluateExpressionType(param);
@@ -432,18 +510,33 @@ export class SemanticAnalyser {
           }
         }
         if(shared <= 0) {
-          throw new Error(`Parameter ${formalParam.id} is not compatible with the value given.`);
+          if(Config.enable_type_casting && !formalParam.byRef) {
+            if(resultType.isCompatible(Types.INTEGER) || resultType.isCompatible(Types.REAL)) {
+              if(formalParam.type.isCompatible(Types.INTEGER) || formalParam.type.isCompatible(Types.REAL)) {
+                continue;
+              }
+            }
+          }
+          throw ProcessorErrorFactory.invalid_parameter_type_full(id, param.toString(), param.sourceInfo);
         }
       } else if (resultType instanceof MultiType) {
         if(!resultType.isCompatible(formalParam.type)) {
-          throw new Error(`Parameter ${formalParam.id} is not compatible with the value given.`);
+          if(Config.enable_type_casting && !formalParam.byRef) {
+            if(resultType.isCompatible(Types.INTEGER) || resultType.isCompatible(Types.REAL)) {
+              if(formalParam.type.isCompatible(Types.INTEGER) || formalParam.type.isCompatible(Types.REAL)) {
+                continue;
+              }
+            }
+          }
+          throw ProcessorErrorFactory.invalid_parameter_type_full(id, param.toString(), param.sourceInfo);
         }
       } 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.`);
+        if(Config.enable_type_casting && !formalParam.byRef) {
+          if (Store.canImplicitTypeCast(formalParam.type, resultType)) {
+            continue;
+          }
+        }
+        throw ProcessorErrorFactory.invalid_parameter_type_full(id, param.toString(), param.sourceInfo);
       }
 
     }

+ 24 - 2
js/processor/store/store.js

@@ -1,8 +1,31 @@
 import { Modes } from './../modes';
+import { Types } from "./../../typeSystem/types";
+import { StoreObject } from './storeObject';
 
 export class Store {
 
-  constructor() {
+  static canImplicitTypeCast (castType, sourceType) {
+    if (castType.isCompatible(Types.INTEGER) || castType.isCompatible(Types.REAL)) {
+      if (sourceType.isCompatible(Types.INTEGER) || sourceType.isCompatible(Types.REAL)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static doImplicitCasting (castType, stoObj) {
+    if(!Store.canImplicitTypeCast(castType, stoObj.type)) {
+      throw new Error("!!!Critical error: attempted to type cast invalid types");
+    }
+    if(Types.INTEGER.isCompatible(castType)) {
+      return new StoreObject(castType, stoObj.value.trunc());
+    } else {
+      return new StoreObject(castType, stoObj.value);
+    }
+  }
+
+  constructor(name) {
+    this.name = name;
     this.store = {};
     this.nextStore = null;
     this.mode = Modes.RUN; 
@@ -17,7 +40,6 @@ export class Store {
       if (this.nextStore !== null) {
         return this.nextStore.applyStore(id);
       } else {
-        // TODO: better error message
         throw new Error(`Variable ${id} not found.`);
       }
     }

+ 0 - 0
js/processor/store/storeObject.js


+ 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;

+ 0 - 0
js/processor/store/storeObjectArrayAddressRef.js


+ 0 - 0
js/processor/store/storeObjectRef.js


+ 5 - 2
js/runner.js

@@ -2,6 +2,7 @@ import { IVProgParser } from './ast/ivprogParser';
 import { IVProgProcessor } from './processor/ivprogProcessor';
 import {DOMConsole} from './io/domConsole';
 import { LanguageService } from './services/languageService';
+import { SemanticAnalyser } from './processor/semantic/semanticAnalyser';
 
 export function runner () {
 const ivprogLexer = LanguageService.getCurrentLexer();
@@ -29,14 +30,16 @@ 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(domConsole);
       domConsole.clear();
       proc.registerOutput(domConsole);
       proc.interpretAST().then(sto => editor.load(sto.store))
-        .catch( e => alert(e));
+        .catch( e => {alert(e); console.log(e)});
     } catch (error) {
       alert(error);
+      console.log(error);
     }
     
   });

+ 0 - 0
js/semantic/.versions


+ 0 - 0
js/semantic/LICENSE


Неке датотеке нису приказане због велике количине промена