浏览代码

Rework all ivprogProcessor.js evaluate* functions using async/await pattern

Add type information in jsdoc of ast file arrayLiteral.js

Add type information for all evaluate* functions
Lucas de Souza 4 年之前
父节点
当前提交
bac03046c5
共有 2 个文件被更改,包括 279 次插入247 次删除
  1. 5 0
      js/ast/expressions/arrayLiteral.js
  2. 274 247
      js/processor/ivprogProcessor.js

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

@@ -2,6 +2,11 @@ import { Literal } from './literal';
 
 export class ArrayLiteral extends Literal {
   
+  /**
+   * 
+   * @param {import('../../typeSystem/itype').IType} type 
+   * @param {import('./expression').Expression[]} value 
+   */
   constructor(type, value) {
     super(type);
     this.value = value;

+ 274 - 247
js/processor/ivprogProcessor.js

@@ -285,7 +285,7 @@ export class IVProgProcessor {
    * 
    * @returns {Promise<Store>}
    */
-  executeSysCall (store, cmd) {
+  async executeSysCall (store, cmd) {
     const func = cmd.langFunc.bind(this);
     return func(store, cmd);
   }
@@ -793,24 +793,21 @@ export class IVProgProcessor {
    * @param {Store} store
    * @param {Expressions.ArrayLiteral} exp
    * @param {ArrayType} type
+   * 
+   * @returns {Promise<StoreValue[]>}
    */
-  evaluateArrayLiteral (store, exp, type, lines, columns) {
-    if(!exp.isVector) {
+  async evaluateArrayLiteral (store, exp, type, lines, columns) {
+    if (!exp.isVector) {
       if(columns == null) {
-        return Promise.reject(new Error("This should never happen: Vector cannot be initialized by a matrix"));
+        throw new Error("This should never happen: Vector cannot be initialized by a matrix");
       }
-      const $matrix = this.evaluateMatrix(store, exp, type, lines, columns);
-      return Promise.all($matrix).then(vectorList => {
-        const values = vectorList.reduce((prev, next) =>  prev.concat(next), []);
-        return Promise.resolve(values);
-      });
+      const storeValueMatrix = await this.evaluateMatrix(store, exp, type, lines, columns);
+      return storeValueMatrix.reduce( (prev, next) => prev.concat(next), []);
     } else {
       if(columns != null) {
-        return Promise.reject(new Error("This should never happen: Matrix cannot be initialized by a vector"));
+        throw new Error("This should never happen: Matrix cannot be initialized by a vector");
       }
-      return this.evaluateVector(store, exp, type, lines).then(list => {
-        return Promise.resolve(list);
-      });
+      return this.evaluateVector(store, exp, type, lines)
     }
   }
 
@@ -820,29 +817,29 @@ export class IVProgProcessor {
    * @param {Expressions.ArrayLiteral} exps
    * @param {ArrayType} type
    * @param {number} n_elements
+   * 
    * @returns {Promise<StoreValue[]>} store object list
    */
-  evaluateVector (store, exps, type, n_elements) {
+  async evaluateVector (store, exps, type, n_elements) {
     const values =  exps.value;
-    if(n_elements !== values.length) {
-      return Promise.reject(ProcessorErrorFactory.invalid_number_elements_vector(n_elements, exps.toString(), values.length, exps.sourceInfo));
+    if (n_elements !== values.length) {
+      throw ProcessorErrorFactory.invalid_number_elements_vector(n_elements, exps.toString(),
+        values.length, exps.sourceInfo);
     }
-    const actual_values = Promise.all(values.map( exp => this.evaluateExpression(store, exp)));
-    return actual_values.then( values => {
-      return values.map((v, index) => {
-        if(!type.canAccept(v.type, 1)) {
-          if (!Config.enable_type_casting || !Store.canImplicitTypeCast(type.innerType, v.type)) {
-            // const stringInfo = v.type.stringInfo();
-            // const info = stringInfo[0];
-            const exp_str = values[index].toString();
-            // TODO - fix error message
-            return Promise.reject(ProcessorErrorFactory.invalid_array_literal_type_full(exp_str, values[index].sourceInfo));
-          }
-          const new_value = Store.doImplicitCasting(type.innerType, v);
-          return new_value;
+    const actualValues = await Promise.all(values.map( exp => this.evaluateExpression(store, exp)));
+    return actualValues.map( (v, index) => {
+      if(!type.canAccept(v.type, 1)) {
+        if (!Config.enable_type_casting || !Store.canImplicitTypeCast(type.innerType, v.type)) {
+          // const stringInfo = v.type.stringInfo();
+          // const info = stringInfo[0];
+          const exp_str = values[index].toString();
+          // TODO - fix error message
+          throw ProcessorErrorFactory.invalid_array_literal_type_full(exp_str, values[index].sourceInfo);
         }
-        return v;
-      });
+        const newValue = Store.doImplicitCasting(type.innerType, v);
+        return newValue;
+      }
+      return v;
     });
   }
 
@@ -851,265 +848,295 @@ export class IVProgProcessor {
    * @param {Store} store
    * @param {Expressions.ArrayLiteral} exps
    * @param {ArrayType} type
-   * @returns {Promise<StoreValue[]>[]}
+   * 
+   * @returns {Promise<StoreValue[][]>}
    */
-  evaluateMatrix (store, exps, type, lines, columns) {
+  async evaluateMatrix (store, exps, type, lines, columns) {
     const values = exps.value;
     if(values.length !== lines) {
-      return Promise.reject(ProcessorErrorFactory.invalid_number_lines_matrix(lines,exps.toString(),values.length, exps.sourceInfo));
+      throw ProcessorErrorFactory.invalid_number_lines_matrix(lines, exps.toString(), values.length,
+        exps.sourceInfo);
     }
-    return values.map( vector => {
+    const vectors = values.map( vector => {
       const vec_type = new ArrayType(type.innerType, 1);
       return this.evaluateVector(store, vector, vec_type, columns);
     });
+    return await Promise.all(vectors);
   }
 
-  evaluateLiteral (_, exp) {
-    return Promise.resolve(new StoreValue(exp.type, exp.value));
+  /**
+   * 
+   * @param {Store} _ 
+   * @param {import('../ast/expressions/literal').Literal} exp
+   * 
+   * @returns {import('./store/value/istore_value').IStoreValue}
+   */
+  async evaluateLiteral (_, exp) {
+    return new StoreValue(exp.type, exp.value);
   }
 
-  evaluateVariableLiteral (store, exp) {
-    try {
-      const val = store.applyStore(exp.id);
-      return Promise.resolve(val);
-    } catch (error) {
-      return Promise.reject(error);
-    }
+
+  /**
+   * 
+   * @param {Store} store 
+   * @param {Expressions.VariableLiteral} exp
+   * 
+   * @returns {import('./store/value/istore_value').IStoreValue}
+   */
+  async evaluateVariableLiteral (store, exp) {
+    const val = store.applyStore(exp.id);
+    return val;
   }
 
-  evaluateArrayAccess (store, exp) {
+  /**
+   * 
+   * @param {Store} store 
+   * @param {Expressions.ArrayAccess} exp
+   * 
+   * @returns {import('./store/value/istore_value').IStoreValue}
+   */
+  async evaluateArrayAccess (store, exp) {
     const mustBeArray = store.getStoreObject(exp.id);
     if (!(mustBeArray.type instanceof ArrayType)) {
-      return Promise.reject(ProcessorErrorFactory.invalid_array_access_full(exp.id, exp.sourceInfo));
+      throw ProcessorErrorFactory.invalid_array_access_full(exp.id, exp.sourceInfo);
     }
-    const $line = this.evaluateExpression(store, exp.line);
-    const $column = this.evaluateExpression(store, exp.column);
-    return Promise.all([$line, $column]).then(([line_sv, column_sv]) => {
-      if(!Types.INTEGER.isCompatible(line_sv.type)) {
-        return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(exp.sourceInfo));
-      }
-      const line = line_sv.get().toNumber();
-      let column = null;
-      if(column_sv !== null) {
-        if(!Types.INTEGER.isCompatible(column_sv.type)) {
-          return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(exp.sourceInfo));
-        }
-        column = column_sv.get().toNumber();
-      }
-
-      if (line >= mustBeArray.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) {
-        return Promise.reject(ProcessorErrorFactory.array_dimension_not_positive_full(exp.sourceInfo));
-      }
-      if (column !== null && mustBeArray.columns === 0 ){
-        return Promise.reject(ProcessorErrorFactory.vector_not_matrix_full(exp.id, exp.sourceInfo));
-      }
-      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) {
-          return Promise.reject(ProcessorErrorFactory.array_dimension_not_positive_full(exp.sourceInfo));
-        }
+    const lineSV = await this.evaluateExpression(store, exp.line);
+    if(!Types.INTEGER.isCompatible(lineSV.type)) {
+      throw ProcessorErrorFactory.array_dimension_not_int_full(exp.sourceInfo);
+    }
+    const line = lineSV.get().toNumber();
+    const columnSV = await this.evaluateExpression(store, exp.column);
+    let column = null;
+    if(columnSV !== null) {
+      if(!Types.INTEGER.isCompatible(columnSV.type)) {
+        throw ProcessorErrorFactory.array_dimension_not_int_full(exp.sourceInfo);
       }
-      const result = mustBeArray.getAt(line, column);
-      const type = mustBeArray.type.innerType;
-      if(Array.isArray(result)) {
-        const values = result.map((v, c) => {
-          return new StoreValueAddress(type, v, line, c, mustBeArray.id, mustBeArray.readOnly);
-        });
-        return Promise.resolve(new ArrayStoreValue(new ArrayType(type, 1),
-          values, mustBeArray.columns, null, mustBeArray.id, mustBeArray.readOnly))
+      column = columnSV.get().toNumber();
+    }
+    if (line >= mustBeArray.lines) {
+      if (mustBeArray.isVector) {
+        throw ProcessorErrorFactory.vector_line_outbounds_full(exp.id, line, mustBeArray.lines,
+          exp.sourceInfo);
       } else {
-        return Promise.resolve(new StoreValueAddress(type, result, line, column, mustBeArray.id, mustBeArray.readOnly));
+        throw 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 === 0 ){
+      throw ProcessorErrorFactory.vector_not_matrix_full(exp.id, exp.sourceInfo);
+    }
+    if (column !== null ) {
+      if (column >= mustBeArray.columns) {
+        throw 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);
+      }
+    }
+    const result = mustBeArray.getAt(line, column);
+    const type = mustBeArray.type.innerType;
+    if (Array.isArray(result)) {
+      const values = result.map((val, col) => {
+        return new StoreValueAddress(type, val, line, col, mustBeArray.id, mustBeArray.readOnly);
+      });
+      return new ArrayStoreValue(new ArrayType(type, 1),
+        values, mustBeArray.columns, null, mustBeArray.id, mustBeArray.readOnly);
+    } else {
+      return new StoreValueAddress(type, result, line, column, mustBeArray.id, mustBeArray.readOnly);
+    }
   }
 
-  evaluateUnaryApp (store, unaryApp) {
-    const $left = this.evaluateExpression(store, unaryApp.left);
-    return $left.then( left => {
-      const resultType = resultTypeAfterUnaryOp(unaryApp.op, left.type);
-      if (Types.UNDEFINED.isCompatible(resultType)) {
-        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:
-          return new StoreValue(resultType, left.get());
-        case Operators.SUB.ord:
-          return new StoreValue(resultType, left.get().negated());
-        case Operators.NOT.ord:
-          return new StoreValue(resultType, !left.get());
-        default:
-          return Promise.reject(new RuntimeError('!!!Critical Invalid UnaryApp '+ unaryApp.op));
-      }
-    });
+  /**
+   * 
+   * @param {Store} store 
+   * @param {Expressions.UnaryApp} unaryApp
+   * 
+   * @returns {import('./store/value/istore_value').IStoreValue}
+   */
+  async evaluateUnaryApp (store, unaryApp) {
+    const left = await this.evaluateExpression(store, unaryApp.left);
+    const resultType = resultTypeAfterUnaryOp(unaryApp.op, left.type);
+    if (Types.UNDEFINED.isCompatible(resultType)) {
+      const stringInfo = left.type.stringInfo();
+      const info = stringInfo[0];
+      throw ProcessorErrorFactory.invalid_unary_op_full(unaryApp.op, info.type, info.dim,
+        unaryApp.sourceInfo);
+    }
+    switch (unaryApp.op.ord) {
+      case Operators.ADD.ord:
+        return new StoreValue(resultType, left.get());
+      case Operators.SUB.ord:
+        return new StoreValue(resultType, left.get().negated());
+      case Operators.NOT.ord:
+        return new StoreValue(resultType, !left.get());
+      default:
+        throw new RuntimeError('!!!Critical Invalid UnaryApp '+ unaryApp.op);
+    }
   }
 
-  evaluateInfixApp (store, infixApp) {
-    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];
-      let resultType = resultTypeAfterInfixOp(infixApp.op, left.type, right.type);
-      if (Types.UNDEFINED.isCompatible(resultType)) {
-        if (Config.enable_type_casting && Store.canImplicitTypeCast(left.type, right.type)) {
-          shouldImplicitCast = true;
+  /**
+   * 
+   * @param {Store} store 
+   * @param {Expressions.InfixApp} infixApp
+   * 
+   * @returns {import('./store/value/istore_value').IStoreValue}
+   */
+  async evaluateInfixApp (store, infixApp) {
+    const left = await this.evaluateExpression(store, infixApp.left);
+    const right = await this.evaluateExpression(store, infixApp.right);
+    let shouldImplicitCast = false;
+    let resultType = resultTypeAfterInfixOp(infixApp.op, left.type, right.type);
+    if (Types.UNDEFINED.isCompatible(resultType)) {
+      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];
+        throw ProcessorErrorFactory.invalid_infix_op_full(infixApp.op, infoLeft.type, infoLeft.dim,
+          infoRight.type,infoRight.dim,infixApp.sourceInfo);
+      }
+    }
+    let result = null;
+    switch (infixApp.op.ord) {
+      case Operators.ADD.ord: {
+        if (Types.STRING.isCompatible(left.type)) {
+          const rightStr = convertToString(right.get(), right.type);
+          return new StoreValue(resultType, (left.get() + rightStr));
+        } else if (Types.STRING.isCompatible(right.type)) {
+          const leftStr = convertToString(left.get(), left.type);
+          return new StoreValue(resultType, (leftStr + right.get()));
         } 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));
+          return new StoreValue(resultType, (left.get().plus(right.get())));
         }
       }
-      let result = null;
-      switch (infixApp.op.ord) {
-        case Operators.ADD.ord: {
-          if(Types.STRING.isCompatible(left.type)) {
-            const rightStr = convertToString(right.get(), right.type);
-            return new StoreValue(resultType, (left.get() + rightStr));
-          } else if (Types.STRING.isCompatible(right.type)) {
-            const leftStr = convertToString(left.get(), left.type);
-            return new StoreValue(resultType, (leftStr + right.get()));
-          } else {
-            return new StoreValue(resultType, (left.get().plus(right.get())));
-          }
-        }
-        case Operators.SUB.ord:
-          return new StoreValue(resultType, (left.get().minus(right.get())));
-        case Operators.MULT.ord: {
-          result = left.get().times(right.get());
-          return new StoreValue(resultType, result);
+      case Operators.SUB.ord:
+        return new StoreValue(resultType, (left.get().minus(right.get())));
+      case Operators.MULT.ord: {
+        result = left.get().times(right.get());
+        return new StoreValue(resultType, result);
+      }
+      case Operators.DIV.ord: {
+        if(right.get() == 0) {
+          throw ProcessorErrorFactory.divsion_by_zero_full(infixApp.toString(), infixApp.sourceInfo);
         }
-        case Operators.DIV.ord: {
-          if(right.get() == 0) {
-            return Promise.reject(ProcessorErrorFactory.divsion_by_zero_full(infixApp.toString(), infixApp.sourceInfo));
-          }
-          if (Types.INTEGER.isCompatible(resultType))
-            result = left.get().divToInt(right.get());
-          else
-            result = left.get().div(right.get());
-          return new StoreValue(resultType, (result));
+        if (Types.INTEGER.isCompatible(resultType))
+          result = left.get().divToInt(right.get());
+        else
+          result = left.get().div(right.get());
+        return new StoreValue(resultType, (result));
+      }
+      case Operators.MOD.ord: {
+        let leftValue = left.get();
+        let rightValue = right.get();
+        if(shouldImplicitCast) {
+          resultType = Types.INTEGER;
+          leftValue = leftValue.trunc();
+          rightValue = rightValue.trunc();
         }
-        case Operators.MOD.ord: {
-          let leftValue = left.get();
-          let rightValue = right.get();
-          if(shouldImplicitCast) {
-            resultType = Types.INTEGER;
+        result = leftValue.modulo(rightValue);
+        return new StoreValue(resultType, (result));
+      }
+      case Operators.GT.ord: {
+        let leftValue = left.get();
+        let rightValue = right.get();
+        if (Types.STRING.isCompatible(left.type)) {
+          result = leftValue.length > rightValue.length;
+        } else {
+          if (shouldImplicitCast) {
+            resultType = Types.BOOLEAN;
             leftValue = leftValue.trunc();
             rightValue = rightValue.trunc();
           }
-          result = leftValue.modulo(rightValue);
-          return new StoreValue(resultType, (result));
-        }
-        case Operators.GT.ord: {
-          let leftValue = left.get();
-          let rightValue = right.get();
-          if (Types.STRING.isCompatible(left.type)) {
-            result = leftValue.length > rightValue.length;
-          } else {
-            if (shouldImplicitCast) {
-              resultType = Types.BOOLEAN;
-              leftValue = leftValue.trunc();
-              rightValue = rightValue.trunc();
-            }
-            result = leftValue.gt(rightValue);
-          }
-          return new StoreValue(resultType, result);
+          result = leftValue.gt(rightValue);
         }
-        case Operators.GE.ord: {
-          let leftValue = left.get();
-          let rightValue = right.get();
-          if (Types.STRING.isCompatible(left.type)) {
-            result = leftValue.length >= rightValue.length;
-          } else {
-            if (shouldImplicitCast) {
-              resultType = Types.BOOLEAN;
-              leftValue = leftValue.trunc();
-              rightValue = rightValue.trunc();
-            }
-            result = leftValue.gte(rightValue);
+        return new StoreValue(resultType, result);
+      }
+      case Operators.GE.ord: {
+        let leftValue = left.get();
+        let rightValue = right.get();
+        if (Types.STRING.isCompatible(left.type)) {
+          result = leftValue.length >= rightValue.length;
+        } else {
+          if (shouldImplicitCast) {
+            resultType = Types.BOOLEAN;
+            leftValue = leftValue.trunc();
+            rightValue = rightValue.trunc();
           }
-          return new StoreValue(resultType, result);
+          result = leftValue.gte(rightValue);
         }
-        case Operators.LT.ord: {
-          let leftValue = left.get();
-          let rightValue = right.get();
-          if (Types.STRING.isCompatible(left.type)) {
-            result = leftValue.length < rightValue.length;
-          } else {
-            if (shouldImplicitCast) {
-              resultType = Types.BOOLEAN;
-              leftValue = leftValue.trunc();
-              rightValue = rightValue.trunc();
-            }
-            result = leftValue.lt(rightValue);
+        return new StoreValue(resultType, result);
+      }
+      case Operators.LT.ord: {
+        let leftValue = left.get();
+        let rightValue = right.get();
+        if (Types.STRING.isCompatible(left.type)) {
+          result = leftValue.length < rightValue.length;
+        } else {
+          if (shouldImplicitCast) {
+            resultType = Types.BOOLEAN;
+            leftValue = leftValue.trunc();
+            rightValue = rightValue.trunc();
           }
-          return new StoreValue(resultType, (result));
+          result = leftValue.lt(rightValue);
         }
-        case Operators.LE.ord: {
-          let leftValue = left.get();
-          let rightValue = right.get();
-          if (Types.STRING.isCompatible(left.type)) {
-            result = leftValue.length <= rightValue.length;
-          } else {
-            if (shouldImplicitCast) {
-              resultType = Types.BOOLEAN;
-              leftValue = leftValue.trunc();
-              rightValue = rightValue.trunc();
-            }
-            result = leftValue.lte(rightValue);
+        return new StoreValue(resultType, (result));
+      }
+      case Operators.LE.ord: {
+        let leftValue = left.get();
+        let rightValue = right.get();
+        if (Types.STRING.isCompatible(left.type)) {
+          result = leftValue.length <= rightValue.length;
+        } else {
+          if (shouldImplicitCast) {
+            resultType = Types.BOOLEAN;
+            leftValue = leftValue.trunc();
+            rightValue = rightValue.trunc();
           }
-          return new StoreValue(resultType, result);
+          result = leftValue.lte(rightValue);
         }
-        case Operators.EQ.ord: {
-          let leftValue = left.get();
-          let rightValue = right.get();
-          if (Types.INTEGER.isCompatible(left.type) || Types.REAL.isCompatible(left.type)) {
-            if (shouldImplicitCast) {
-              resultType = Types.BOOLEAN;
-              leftValue = leftValue.trunc();
-              rightValue = rightValue.trunc();
-            }
-            result = leftValue.eq(rightValue);
-          } else {
-            result = leftValue === rightValue;
+        return new StoreValue(resultType, result);
+      }
+      case Operators.EQ.ord: {
+        let leftValue = left.get();
+        let rightValue = right.get();
+        if (Types.INTEGER.isCompatible(left.type) || Types.REAL.isCompatible(left.type)) {
+          if (shouldImplicitCast) {
+            resultType = Types.BOOLEAN;
+            leftValue = leftValue.trunc();
+            rightValue = rightValue.trunc();
           }
-          return new StoreValue(resultType, result);
+          result = leftValue.eq(rightValue);
+        } else {
+          result = leftValue === rightValue;
         }
-        case Operators.NEQ.ord: {
-          let leftValue = left.get();
-          let rightValue = right.get();
-          if (Types.INTEGER.isCompatible(left.type) || Types.REAL.isCompatible(left.type)) {
-            if (shouldImplicitCast) {
-              resultType = Types.BOOLEAN;
-              leftValue = leftValue.trunc();
-              rightValue = rightValue.trunc();
-            }
-            result = !leftValue.eq(rightValue);
-          } else {
-            result = leftValue !== rightValue;
+        return new StoreValue(resultType, result);
+      }
+      case Operators.NEQ.ord: {
+        let leftValue = left.get();
+        let rightValue = right.get();
+        if (Types.INTEGER.isCompatible(left.type) || Types.REAL.isCompatible(left.type)) {
+          if (shouldImplicitCast) {
+            resultType = Types.BOOLEAN;
+            leftValue = leftValue.trunc();
+            rightValue = rightValue.trunc();
           }
-          return new StoreValue(resultType, result);
+          result = !leftValue.eq(rightValue);
+        } else {
+          result = leftValue !== rightValue;
         }
-        case Operators.AND.ord:
-          return new StoreValue(resultType, (left.get() && right.get()));
-        case Operators.OR.ord:
-          return new StoreValue(resultType, (left.get() || right.get()));
-        default:
-          return Promise.reject(new RuntimeError('!!!Critical Invalid InfixApp '+ infixApp.op));
+        return new StoreValue(resultType, result);
       }
-    });
+      case Operators.AND.ord:
+        return new StoreValue(resultType, (left.get() && right.get()));
+      case Operators.OR.ord:
+        return new StoreValue(resultType, (left.get() || right.get()));
+      default:
+        throw new RuntimeError('!!!Critical Invalid InfixApp '+ infixApp.op);
+    }
   }
 
 }