Browse Source

Refactor all ivprogProcessor.js execute* functions using async/await pattern

Implement type information in the jsdoc of the execute* function and the ast file case.js and switch.js

Fix a bug regarding return command not properly perfomring the implicit cast
Lucas de Souza 4 years ago
parent
commit
ce802e476b

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

@@ -5,9 +5,16 @@ export class Case extends Command {
   constructor (expression) {
     super();
     this.expression = expression;
+    /**
+     * @type {Command[]}
+     */
     this.commands = [];
   }
 
+  /**
+   * 
+   * @param {Command[]} commands 
+   */
   setCommands (commands) {
     this.commands = commands;
   }

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

@@ -1,7 +1,16 @@
 import { Command } from './command';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { Expression } from '../expressions/expression';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { Case } from '.';
 
 export class Switch extends Command {
   
+  /**
+   * 
+   * @param {Expression} expression 
+   * @param {Case[]} cases 
+   */
   constructor (expression, cases) {
     super();
     this.expression = expression;

+ 335 - 327
js/processor/ivprogProcessor.js

@@ -9,6 +9,8 @@ import * as Commands from './../ast/commands/';
 // eslint-disable-next-line @typescript-eslint/no-unused-vars
 import { Command } from './../ast/commands/command'
 import * as Expressions from './../ast/expressions/';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { Expression } from './../ast/expressions/expression'
 import * as Utils from './../util/utils';
 import { ArrayType } from './../typeSystem/array_type';
 import { convertToString, toInt } from '../typeSystem/parsers';
@@ -205,7 +207,9 @@ export class IVProgProcessor {
   /**
    * 
    * @param {Store} store 
-   * @param {Command[]} cmds 
+   * @param {Command[]} cmds
+   * 
+   * @returns {Promise<Store>} 
    */
   async executeCommands (store, cmds) {
     // helper to partially apply a function, in this case executeCommand
@@ -219,7 +223,9 @@ export class IVProgProcessor {
   /**
    * 
    * @param {Store} store 
-   * @param {Command} cmd
+   * @param {Command} cmd 
+   * 
+   * @returns {Promise<Store>}
    */
   async executeCommand (store, cmd) {
     this.instruction_count += 1;
@@ -272,11 +278,25 @@ export class IVProgProcessor {
     }
   }
 
+  /**
+   * 
+   * @param {Store} store 
+   * @param {Commands.SysCall} cmd 
+   * 
+   * @returns {Promise<Store>}
+   */
   executeSysCall (store, cmd) {
     const func = cmd.langFunc.bind(this);
     return func(store, cmd);
   }
 
+  /**
+   * 
+   * @param {Store} store 
+   * @param {Commands.FunctionCall} cmd 
+   * 
+   * @returns {Promise<Store>}
+   */
   async executeFunctionCall (store, cmd) {
     let func = null;
     if(cmd.isMainCall) {
@@ -297,384 +317,375 @@ export class IVProgProcessor {
     }
   }
 
-  executeSwitch (store, cmd) {
+  /**
+   * 
+   * @param {Store} store 
+   * @param {Commands.Switch} cmd 
+   * 
+   * @returns {Promise<Store>}
+   */
+  async executeSwitch (store, cmd) {
     this.context.push(Context.BREAKABLE);
-    const caseSequence = cmd.cases.reduce( (prev,next) => {
-      return prev.then( tuple => {
-        if(this.ignoreSwitchCases(tuple[1])) {
-          return Promise.resolve(tuple);
-        } else if(tuple[0] || next.isDefault) {
-          return this.executeCommands(tuple[1], next.commands)
-            .then(nSto => Promise.resolve([true, nSto]));
-        } else {
-          const equalityInfixApp = new Expressions.InfixApp(Operators.EQ, cmd.expression, next.expression);
-          equalityInfixApp.sourceInfo = next.sourceInfo;
-          return this.evaluateExpression(tuple[1],equalityInfixApp).then(stoObj => stoObj.get())
-            .then(isEqual => {
-              if (isEqual) {
-                return this.executeCommands(tuple[1], next.commands)
-                  .then(nSto => Promise.resolve([true, nSto]));
-              } else {
-                return Promise.resolve(tuple);
-              }
-          });
+    const switchCases = cmd.cases;
+    let lastStore = store;
+    let lastCaseCheckResult = false;
+    for (let i = 0; i < switchCases.length && !this.ignoreSwitchCases(lastStore); i += 1) {
+      const switchCase = switchCases[i];
+      if (lastCaseCheckResult || switchCase.isDefault) {
+        lastStore = await this.executeCommands(lastStore, switchCase.commands);
+      } else {
+        const equalityInfixApp = new Expressions.InfixApp(Operators.EQ, cmd.expression, switchCase.expression);
+        equalityInfixApp.sourceInfo = switchCase.sourceInfo;
+        const result = await this.evaluateExpression(lastStore, equalityInfixApp);
+        if (result.get()) {
+          lastStore = await this.executeCommands(lastStore, switchCase.commands);
         }
-      });
-    }, Promise.resolve([false, store]));
-    return caseSequence.then(tuple => {
-      this.context.pop();
-      const newStore = tuple[1];
-      if (newStore.mode === Modes.BREAK) {
-        newStore.mode = Modes.RUN;
+        lastCaseCheckResult = result.get();
       }
-      return newStore;
-    });
+    }
+    this.context.pop();
+    if (lastStore.mode === Modes.BREAK) {
+      lastStore.mode = Modes.RUN;
+    }
+    return lastStore;
   }
 
   /**
    *
    * @param {Store} store
    * @param {Commands.For} cmd
+   * 
+   * @returns {Promise<Store>}
    */
-  executeFor (store, cmd) {
+  async executeFor (store, cmd) {
     //BEGIN for -> while rewrite
     const initCmd = new Commands.Assign(cmd.for_id.id, cmd.for_from);
     initCmd.sourceInfo = cmd.sourceInfo;
-    const expression_tuple = []; //(for conditional, is for increasing)
+    // Assume for is iterating forward and that pass is not missing
+    let passValue = cmd.for_pass;
+    let condition = new Expressions.InfixApp(Operators.LE, cmd.for_id, cmd.for_to);
+
     if(cmd.for_pass == null) {
-      expression_tuple.push(Promise.resolve(null));
-      expression_tuple.push(this.evaluateExpression(store, new Expressions.InfixApp(Operators.GE, cmd.for_to, cmd.for_from)));
+      passValue = new Expressions.IntLiteral(toInt(1));
+      const checkEndGTBegin = await this.evaluateExpression(store,
+        new Expressions.InfixApp(Operators.GE, cmd.for_to, cmd.for_from));
+      if (!checkEndGTBegin.get()) {
+        passValue = new Expressions.IntLiteral(toInt(-1));
+        condition = new Expressions.InfixApp(Operators.GE, cmd.for_id, cmd.for_to);
+      }
     } else {
-      expression_tuple.push(this.evaluateExpression(store, new Expressions.InfixApp(Operators.GE, cmd.for_pass, new Expressions.IntLiteral(toInt(0)))));
-      expression_tuple.push(Promise.resolve(null));
-    }
-
-    return Promise.all(expression_tuple).then (results => {
-      // console.log(results);
-      let is_forward = true;
-      let is_end_gt_init = undefined;
-      let condition = null;
-      let pass_value = cmd.for_pass;
-      if (results[0] == null) {
-        // pass is null, we need to deduce a value for it
-        is_end_gt_init = results[1].value;
-      } else {
-        is_forward = results[0].value
+      const isForward = await this.evaluateExpression(store, new Expressions.InfixApp(Operators.GE,
+        cmd.for_pass, new Expressions.IntLiteral(toInt(0))));
+      if (!isForward.get()) {
+        condition = new Expressions.InfixApp(Operators.GE, cmd.for_id, cmd.for_to)
       }
+    }
 
-      if(is_end_gt_init == null) {
-        // console.log("pass is not null and is forward? ", is_forward);
-        if(is_forward) {
-          condition = new Expressions.InfixApp(Operators.LE, cmd.for_id, cmd.for_to);
-        } else {
-          condition = new Expressions.InfixApp(Operators.GE, cmd.for_id, cmd.for_to);
-        }
-        // console.log("Cond", condition);
-      } else if(is_end_gt_init) {
-        pass_value = new Expressions.IntLiteral(toInt(1));
-        condition = new Expressions.InfixApp(Operators.LE, cmd.for_id, cmd.for_to);
-      } else {
-        pass_value = new Expressions.IntLiteral(toInt(-1));
-        condition = new Expressions.InfixApp(Operators.GE, cmd.for_id, cmd.for_to);
-      }
-      condition.sourceInfo = cmd.sourceInfo;
-      const increment = new Commands.Assign(cmd.for_id.id,
-        new Expressions.InfixApp(Operators.ADD, cmd.for_id, pass_value));
-        increment.sourceInfo = cmd.sourceInfo;
-      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);
-    }).catch(error => Promise.reject(error));
+    condition.sourceInfo = cmd.sourceInfo;
+    const increment = new Commands.Assign(cmd.for_id.id,
+      new Expressions.InfixApp(Operators.ADD, cmd.for_id, passValue));
+      increment.sourceInfo = cmd.sourceInfo;
+    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);
   }
 
-  executeRepeatUntil (store, cmd) {
-    try {
-      this.context.push(Context.BREAKABLE);
-      const $newStore = this.executeCommands(store, cmd.commands);
-      return $newStore.then(sto => {
-        if(sto.mode === Modes.BREAK) {
-          this.context.pop();
-          sto.mode = Modes.RUN;
-          return sto;
-        }
-        const $value = this.evaluateExpression(sto, cmd.expression);
-        return $value.then(vl => {
-          if (!vl.type.isCompatible(Types.BOOLEAN)) {
-            return Promise.reject(ProcessorErrorFactory.loop_condition_type_full(cmd.sourceInfo));
-          }
-          if (!vl.get()) {
-            this.context.pop();
-            return this.executeCommand(sto, cmd);
-          } else {
-            this.context.pop();
-            return sto;
-          }
-        })
-      })
-    } catch (error) {
-      return Promise.reject(error);
+  /**
+   *
+   * @param {Store} store
+   * @param {Commands.RepeatUntil} cmd
+   * 
+   * @returns {Promise<Store>}
+   */
+  async executeRepeatUntil (store, cmd) {
+    this.context.push(Context.BREAKABLE);
+    const sto = await this.executeCommands(store, cmd.commands);
+    if(sto.mode === Modes.BREAK) {
+      this.context.pop();
+      sto.mode = Modes.RUN;
+      return sto;
+    }
+    const checkCondition = await this.evaluateExpression(sto, cmd.expression);
+    if (!checkCondition.type.isCompatible(Types.BOOLEAN)) {
+      throw ProcessorErrorFactory.loop_condition_type_full(cmd.sourceInfo);
+    }
+    this.context.pop();
+    if (checkCondition.get()) {
+      return sto;
+    } else {
+      return this.executeCommand(sto, cmd);
     }
   }
 
-  executeWhile (store, cmd) {
-    try {
-      this.context.push(Context.BREAKABLE);
-      const $value = this.evaluateExpression(store, cmd.expression);
-      return $value.then(vl => {
-        if(vl.type.isCompatible(Types.BOOLEAN)) {
-          if(vl.get()) {
-            const $newStore = this.executeCommands(store, cmd.commands);
-            return $newStore.then(sto => {
-              this.context.pop();
-              if (sto.mode === Modes.BREAK) {
-                sto.mode = Modes.RUN;
-                return sto;
-              }
-              return this.executeCommand(sto, cmd);
-            });
-          } else {
-            this.context.pop();
-            return store;
-          }
-        } else {
-          return Promise.reject(ProcessorErrorFactory.loop_condition_type_full(cmd.expression.toString(), cmd.sourceInfo));
-        }
-      })
-
-    } catch (error) {
-      return Promise.reject(error);
+  /**
+   *
+   * @param {Store} store
+   * @param {Commands.While} cmd
+   * 
+   * @returns {Promise<Store>}
+   */
+  async executeWhile (store, cmd) {
+    this.context.push(Context.BREAKABLE);
+    const checkCondition = await this.evaluateExpression(store, cmd.expression);
+    if(!checkCondition.type.isCompatible(Types.BOOLEAN)) {
+      throw ProcessorErrorFactory.loop_condition_type_full(cmd.expression.toString(), cmd.sourceInfo);
+    }
+    if(checkCondition.get()) {
+      const sto = await this.executeCommands(store, cmd.commands);
+      this.context.pop();
+      if (sto.mode === Modes.BREAK) {
+        sto.mode = Modes.RUN;
+        return sto;
+      }
+      return this.executeCommand(sto, cmd);
+    } else {
+      this.context.pop();
+      return store;
     }
   }
 
-  executeIfThenElse (store, cmd) {
-    try {
-      const $value = this.evaluateExpression(store, cmd.condition);
-      return $value.then(vl => {
-        if(vl.type.isCompatible(Types.BOOLEAN)) {
-          if(vl.get()) {
-            return this.executeCommands(store, cmd.ifTrue.commands);
-          } else if( cmd.ifFalse !== null){
-            if(cmd.ifFalse instanceof Commands.IfThenElse) {
-              return this.executeCommand(store, cmd.ifFalse);
-            } else {
-              return this.executeCommands(store, cmd.ifFalse.commands);
-            }
-          } else {
-            return Promise.resolve(store);
-          }
-        } else {
-          return Promise.reject(ProcessorErrorFactory.if_condition_type_full(cmd.condition.toString(), cmd.sourceInfo));
-        }
-      });
-    } catch (error) {
-      return Promise.reject(error);
+  /**
+   *
+   * @param {Store} store
+   * @param {Commands.IfThenElse} cmd
+   * 
+   * @returns {Promise<Store>}
+   */
+  async executeIfThenElse (store, cmd) {
+    const isTrue = await this.evaluateExpression(store, cmd.condition);
+    if (!isTrue.type.isCompatible(Types.BOOLEAN)) {
+      throw ProcessorErrorFactory.if_condition_type_full(cmd.condition.toString(), cmd.sourceInfo);
+    }
+    if (isTrue.get()) {
+      return this.executeCommands(store, cmd.ifTrue.commands);
+    } else if (cmd.ifFalse !== null) {
+      if (cmd.ifFalse instanceof Commands.IfThenElse) {
+        return this.executeCommand(store, cmd.ifFalse);
+      } else {
+        return this.executeCommands(store, cmd.ifFalse.commands);
+      }
+    } else {
+      return store;
     }
   }
 
-  executeReturn (store, cmd) {
-    try {
-      const funcName = store.name === IVProgProcessor.MAIN_INTERNAL_ID ?
-        LanguageDefinedFunction.getMainFunctionName() : store.name;
-      // console.log(funcName,  store.name === IVProgProcessor.MAIN_INTERNAL_ID);
-      const func = this.findFunction(store.name);
-      const funcType = func.returnType;
-      const $value = this.evaluateExpression(store, cmd.expression);
-
-      return $value.then(value => {
-
-        let real_value = value;
-        if(value === null && funcType.isCompatible(Types.VOID)) {
-          store.mode = Modes.RETURN;
-          return Promise.resolve(store);
-        }
+  /**
+   *
+   * @param {Store} store
+   * @param {Commands.Return} cmd
+   * 
+   * @returns {Promise<Store>}
+   */
+  async executeReturn (store, cmd) {
+    const funcName = store.name === IVProgProcessor.MAIN_INTERNAL_ID ?
+      LanguageDefinedFunction.getMainFunctionName() : store.name;
+    // console.log(funcName,  store.name === IVProgProcessor.MAIN_INTERNAL_ID);
+    const func = this.findFunction(store.name);
+    const funcType = func.returnType;
+    const value = await this.evaluateExpression(store, cmd.expression);
+    if(value === null && funcType.isCompatible(Types.VOID)) {
+      store.mode = Modes.RETURN;
+      return store;
+    }
 
-        if (value === null || !funcType.isCompatible(value.type)) {
-          if(!Config.enable_type_casting || !Store.canImplicitTypeCast(funcType, value.type)) {
-            const stringInfo = funcType.stringInfo();
-          const info = stringInfo[0];
-          return Promise.reject(ProcessorErrorFactory.invalid_return_type_full(funcName, info.type, info.dim, cmd.sourceInfo));
-          }
-          real_value = Store.doImplicitCasting(funcType, value);
-        } else {
-          store.insertStore('$', real_value);
-          store.mode = Modes.RETURN;
-          return Promise.resolve(store);
-        }
-      });
-    } catch (error) {
-      return Promise.reject(error);
+    let real_value = value;
+    if (value === null || !funcType.isCompatible(value.type)) {
+      if (!Config.enable_type_casting || !Store.canImplicitTypeCast(funcType, value.type)) {
+        const stringInfo = funcType.stringInfo();
+        const info = stringInfo[0];
+        throw ProcessorErrorFactory.invalid_return_type_full(funcName, info.type, info.dim,
+          cmd.sourceInfo);
+      }
+      real_value = Store.doImplicitCasting(funcType, value);
     }
+
+    store.insertStore('$', real_value);
+    store.mode = Modes.RETURN;
+    return store;
   }
 
-  executeBreak (store, cmd) {
+  /**
+   *
+   * @param {Store} store
+   * @param {Commands.Break} cmd
+   * 
+   * @returns {Promise<Store>}
+   */
+  async executeBreak (store, cmd) {
     if(this.checkContext(Context.BREAKABLE)) {
       store.mode = Modes.BREAK;
-      return Promise.resolve(store);
+      return store;
     } else {
-      return Promise.reject(ProcessorErrorFactory.unexpected_break_command_full(cmd.sourceInfo));
+      throw ProcessorErrorFactory.unexpected_break_command_full(cmd.sourceInfo);
     }
   }
 
-  executeAssign (store, cmd) {
-    try {
-      const inStore = store.applyStore(cmd.id);
-      if(inStore.isConst) {
-        return Promise.reject(ProcessorErrorFactory.invalid_const_assignment_full(cmd.id, cmd.sourceInfo))
+  /**
+   *
+   * @param {Store} store
+   * @param {Commands.Assign} cmd
+   * 
+   * @returns {Promise<Store>}
+   */
+  async executeAssign (store, cmd) {
+    const inStore = store.applyStore(cmd.id);
+    if (inStore.isConst) {
+      throw ProcessorErrorFactory.invalid_const_assignment_full(cmd.id, cmd.sourceInfo);
+    }
+    const value = await this.evaluateExpression(store, cmd.expression);
+    let realValue = value;
+    if (!inStore.type.isCompatible(realValue.type)) {
+      if (Config.enable_type_casting && Store.canImplicitTypeCast(inStore.type, value.type)) {
+        realValue = Store.doImplicitCasting(inStore.type, realValue);
+      } else {
+        const stringInfo = inStore.type.stringInfo()
+        const info = stringInfo[0]
+        const exp_type_string_info = value.type.stringInfo();
+        const exp_type_info = exp_type_string_info[0];
+        const exp = cmd.expression.toString();
+        throw ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, exp_type_info.type,
+          exp_type_info.dim,  exp, cmd.sourceInfo);
       }
-      const $value = this.evaluateExpression(store, cmd.expression);
-      return $value.then( vl => {
-        let realValue = 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]
-            const exp_type_string_info = vl.type.stringInfo();
-            const exp_type_info = exp_type_string_info[0];
-            const exp = cmd.expression.toString();
-            return Promise.reject(ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, exp_type_info.type, exp_type_info.dim,  exp, cmd.sourceInfo));
-          }
-        }
+    }
 
-        if(inStore instanceof ArrayStoreValue) {
-          const columns = realValue.columns == null ? 0 : realValue.columns;
-          if(inStore.lines !== realValue.lines || inStore.columns !== columns){
-            const exp = cmd.expression.toString();
-            if(inStore.isVector()) {
-              return Promise.reject(ProcessorErrorFactory.invalid_vector_assignment_full(cmd.id, inStore.lines, exp, realValue.lines, cmd.sourceInfo));
-            } else {
-              return Promise.reject(ProcessorErrorFactory.invalid_matrix_assignment_full(cmd.id, inStore.lines, inStore.columns, exp, realValue.lines, realValue.columns, cmd.sourceInfo));
-            }
-          }
+    if (inStore instanceof ArrayStoreValue) {
+      const columns = realValue.columns == null ? 0 : realValue.columns;
+      if (inStore.lines !== realValue.lines || inStore.columns !== columns){
+        const exp = cmd.expression.toString();
+        if (inStore.isVector()) {
+          throw ProcessorErrorFactory.invalid_vector_assignment_full(cmd.id, inStore.lines, exp,
+            realValue.lines, cmd.sourceInfo);
+        } else {
+          throw ProcessorErrorFactory.invalid_matrix_assignment_full(cmd.id, inStore.lines,
+            inStore.columns, exp, realValue.lines, realValue.columns, cmd.sourceInfo);
         }
-
-        store.updateStore(cmd.id, realValue)
-        return store;
-      });
-    } catch (error) {
-      return Promise.reject(error);
+      }
     }
+
+    store.updateStore(cmd.id, realValue)
+    return store;
   }
 
-  executeArrayIndexAssign (store, cmd) {
+  /**
+   *
+   * @param {Store} store
+   * @param {Commands.ArrayIndexAssign} cmd
+   * 
+   * @returns {Promise<Store>}
+   */
+  async executeArrayIndexAssign (store, cmd) {
     const mustBeArray = store.applyStore(cmd.id);
     let used_dims = 0;
-    if(mustBeArray.isConst) {
-      return Promise.reject(ProcessorErrorFactory.invalid_const_assignment_full(cmd.id, cmd.sourceInfo))
+    if (mustBeArray.isConst) {
+      throw ProcessorErrorFactory.invalid_const_assignment_full(cmd.id, cmd.sourceInfo);
     }
-    if(!(mustBeArray.type instanceof ArrayType)) {
-      return Promise.reject(ProcessorErrorFactory.invalid_array_access_full(cmd.id, cmd.sourceInfo));
+    if (!(mustBeArray.type instanceof ArrayType)) {
+      throw ProcessorErrorFactory.invalid_array_access_full(cmd.id, cmd.sourceInfo);
     }
-    const line$ = this.evaluateExpression(store, cmd.line);
-    const column$ = this.evaluateExpression(store, cmd.column);
-    const value$ =  this.evaluateExpression(store, cmd.expression);
-    return Promise.all([line$, column$, value$]).then(([line_sv, column_sv, value]) => {
-      if(!Types.INTEGER.isCompatible(line_sv.type)) {
-        return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
+    const lineSV = await this.evaluateExpression(store, cmd.line);
+    if (!Types.INTEGER.isCompatible(lineSV.type)) {
+      throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
+    }
+    used_dims += 1;
+    const line = lineSV.get().toNumber();
+    const columnSV = await this.evaluateExpression(store, cmd.column);
+    let column = null;
+    if (columnSV != null) {
+      if(!Types.INTEGER.isCompatible(columnSV.type)) {
+        throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
       }
-      const line = line_sv.get().toNumber();
+      column = columnSV.get().toNumber();
       used_dims += 1;
-      let column = undefined;
-      if (column_sv != null) {
-        if(!Types.INTEGER.isCompatible(column_sv.type)) {
-          return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
-        }
-        column = column_sv.get().toNumber();
-        used_dims += 1;
-      }
-      let actualValue = value;
+    }
+    const value =  await this.evaluateExpression(store, cmd.expression);
+    let actualValue = value;
       if (line >= mustBeArray.lines) {
-        if(mustBeArray.isVector) {
-          return Promise.reject(ProcessorErrorFactory.vector_line_outbounds_full(cmd.id, line, mustBeArray.lines, cmd.sourceInfo));
+        if (mustBeArray.isVector) {
+          throw 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));
+          throw ProcessorErrorFactory.matrix_line_outbounds_full(cmd.id, line, mustBeArray.lines,
+            cmd.sourceInfo);
         }
       } else if (line < 0) {
-        return Promise.reject(ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo))
+        throw ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo);
       }
       if (column != null && mustBeArray.columns === 0 ){
-        return Promise.reject(ProcessorErrorFactory.vector_not_matrix_full(cmd.id, cmd.sourceInfo));
+        throw ProcessorErrorFactory.vector_not_matrix_full(cmd.id, cmd.sourceInfo);
       }
-      if(column != null ) {
+      if (column != null) {
         if (column >= mustBeArray.columns) {
-          return Promise.reject(ProcessorErrorFactory.matrix_column_outbounds_full(cmd.id, column,mustBeArray.columns, cmd.sourceInfo));
+          throw ProcessorErrorFactory.matrix_column_outbounds_full(cmd.id, column,mustBeArray.columns,
+            cmd.sourceInfo);
         } else if (column < 0) {
-          return Promise.reject(ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo))
+          throw ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo);
         }
       }
 
       if (!mustBeArray.type.canAccept(value.type, used_dims)) {
-        if(!Config.enable_type_casting || !Store.canImplicitTypeCast(mustBeArray.type.innerType, value.type)) {
+        if (!Config.enable_type_casting || !Store.canImplicitTypeCast(mustBeArray.type.innerType,
+          value.type)) {
+
           const type = mustBeArray.type.innerType;
           const stringInfo = type.stringInfo();
           const info = stringInfo[0];
           const exp_type_string_info = value.type.stringInfo();
           const exp_type_info = exp_type_string_info[0];
           const exp = cmd.expression.toString();
-          return Promise.reject(ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, exp_type_info.type, exp_type_info.dim,  exp, cmd.sourceInfo));
+          throw ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, exp_type_info.type,
+            exp_type_info.dim,  exp, cmd.sourceInfo);
         }
         actualValue = Store.doImplicitCasting(mustBeArray.type.innerType, value);
       }
 
       const current_value = mustBeArray.getAt(line, column);
-      if(current_value instanceof ArrayStoreValue) {
-        if(current_value.lines !== actualValue.lines || current_value.columns !== actualValue.columns){
+      if (current_value instanceof ArrayStoreValue) {
+        if (current_value.lines !== actualValue.lines || current_value.columns !== actualValue.columns){
           const exp = cmd.expression.toString();
-          return Promise.reject(ProcessorErrorFactory.invalid_matrix_index_assign_full(cmd.id, line, current_value.lines, exp, actualValue.lines, cmd.sourceInfo))
+          throw ProcessorErrorFactory.invalid_matrix_index_assign_full(cmd.id, line, current_value.lines,
+            exp, actualValue.lines, cmd.sourceInfo);
         }
       }
 
-      // mustBeArray.setAt(actualValue, line, column);
-      // store.updateStore(cmd.id, mustBeArray);
-      return store.updateStoreArray(cmd.id, actualValue, line, column);
-    });
+    return store.updateStoreArray(cmd.id, actualValue, line, column);
   }
 
   /**
    *
    * @param {Store} store
    * @param {Commands.Declaration} cmd
+   * 
+   * @returns {Promise<Store>}
    */
-  executeDeclaration (store, cmd) {
-    try {
-      let $value = Promise.resolve(null);
-      if(cmd instanceof Commands.ArrayDeclaration) {
-        return this.executeArrayDeclaration(store, cmd);
-      } else {
-        if(cmd.initial !== null) {
-          $value = this.evaluateExpression(store, cmd.initial);
-        }
-        return $value.then(vl => {
-          let realValue = vl;
-          let temp = null;
-          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 = vl.type.stringInfo();
-                const info = stringInfo[0];
-                const exp_type_string_info = vl.type.stringInfo();
-                const exp_type_info = exp_type_string_info[0];
-                const exp = cmd.expression.toString();
-                return Promise.reject(ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, exp_type_info.type, exp_type_info.dim,  exp, cmd.sourceInfo));
-              }
-            }
-            temp = new StoreValue(cmd.type, realValue.get(), null, cmd.isConst);
+  async executeDeclaration (store, cmd) {
+    if (cmd instanceof Commands.ArrayDeclaration) {
+      return this.executeArrayDeclaration(store, cmd);
+    } else {
+      let temp = new StoreValue(cmd.type, null, null, cmd.isConst);
+      if(cmd.initial !== null) {
+        const value = await this.evaluateExpression(store, cmd.initial);
+        let realValue = value;
+        if (!value.type.isCompatible(cmd.type)) {
+          if(Config.enable_type_casting && Store.canImplicitTypeCast(cmd.type, value.type)) {
+            realValue = Store.doImplicitCasting(cmd.type, realValue);
           } else {
-            temp = new StoreValue(cmd.type, null, null, cmd.isConst);
+            const stringInfo = value.type.stringInfo();
+            const info = stringInfo[0];
+            const exp_type_string_info = value.type.stringInfo();
+            const exp_type_info = exp_type_string_info[0];
+            const exp = cmd.expression.toString();
+            throw ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, exp_type_info.type,
+              exp_type_info.dim,  exp, cmd.sourceInfo);
           }
-          store.insertStore(cmd.id, temp);
-          return store;
-        });
+        }
+        temp = new StoreValue(cmd.type, realValue.get(), null, cmd.isConst);
       }
-    } catch (e) {
-      return Promise.reject(e);
+      store.insertStore(cmd.id, temp);
+      return store;
     }
   }
 
@@ -682,46 +693,43 @@ export class IVProgProcessor {
    *
    * @param {Store} store
    * @param {Commands.ArrayDeclaration} cmd
+   * 
+   * @returns {Promise<Store>}
    */
-  executeArrayDeclaration (store, cmd) {
-    const $lines = this.evaluateExpression(store, cmd.lines);
-    const $columns = cmd.columns === null ? null: this.evaluateExpression(store, cmd.columns);
-    return Promise.all([$lines, $columns]).then(([line_sv, column_sv]) => {
-      if(!Types.INTEGER.isCompatible(line_sv.type)) {
-        return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
-      }
-      const line = line_sv.get().toNumber();
-      if(line < 0) {
-        return Promise.reject(ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo));
-      }
-      let column = null
-      if (column_sv !== null) {
-        if(!Types.INTEGER.isCompatible(column_sv.type)) {
-          return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
-        }
-        column = column_sv.get().toNumber();
-        if(column < 0) {
-          return Promise.reject(ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo));
-        }
+  async executeArrayDeclaration (store, cmd) {
+    const linesSV = await this.evaluateExpression(store, cmd.lines);
+    if (!Types.INTEGER.isCompatible(linesSV.type)) {
+      throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
+    }
+    const line = linesSV.get().toNumber();
+    const columnsSV = await this.evaluateExpression(store, cmd.columns);
+    let column = null
+    if (columnsSV !== null) {
+      if (!Types.INTEGER.isCompatible(columnsSV.type)) {
+        throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
       }
-      let $value = Promise.resolve(null);
-      if(cmd.initial !== null) {
-        // array can only be initialized by a literal....
-        $value = this.evaluateArrayLiteral(store, cmd.initial, cmd.type, line, column);
+      column = columnsSV.get().toNumber();
+      if(column < 0) {
+        throw ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo);
       }
-      return $value.then(vector_list => {
-        let temp = null;
-        if (vector_list !== null) {
-          temp = new ArrayStoreValue(cmd.type, vector_list, line, column, null, cmd.isConst);
-        } else {
-          temp = new ArrayStoreValue(cmd.type, [], line, column, null, cmd.isConst);
-        }
-        store.insertStore(cmd.id, temp);
-        return store;
-      })
-    });
+    }
+    let temp = new ArrayStoreValue(cmd.type, [], line, column, null, cmd.isConst);
+    if (cmd.initial !== null) {
+      // array can only be initialized by a literal....
+      const valueList = await this.evaluateArrayLiteral(store, cmd.initial, cmd.type, line, column);
+      temp = new ArrayStoreValue(cmd.type, valueList, line, column, null, cmd.isConst);
+    }
+    store.insertStore(cmd.id, temp);
+    return store;
   }
 
+  /**
+   * 
+   * @param {Store} store 
+   * @param {Expression} exp
+   * 
+   * @returns {Promise<import('./store/value/istore_value').IStoreValue>} 
+   */
   async evaluateExpression (store, exp) {
     this.instruction_count += 1;
     if(this.instruction_count % Config.suspend_threshold == 0) {

+ 6 - 5
js/processor/semantic/semanticAnalyser.js

@@ -511,12 +511,13 @@ export class SemanticAnalyser {
       } else if (cmd.expression !== null) {
         const resultType = this.evaluateExpressionType(cmd.expression);
         if (!type.isCompatible(resultType)) {
-          const stringInfo = type.stringInfo();
-          const info = stringInfo[0];
-          throw ProcessorErrorFactory.invalid_return_type_full(funcName, info.type, info.dim, cmd.sourceInfo);
-        } else {
-          return true;
+          if (!Config.enable_type_casting || !Store.canImplicitTypeCast(type, resultType)) {
+            const stringInfo = type.stringInfo();
+            const info = stringInfo[0];
+            throw ProcessorErrorFactory.invalid_return_type_full(funcName, info.type, info.dim, cmd.sourceInfo);
+          }
         }
+        return true;
       } else {
         return true;
       }