| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 | 
							- import { Types } from './../typeSystem/types';
 
- import { Operators } from './../ast/operators';
 
- import { MultiType } from '../typeSystem/multiType';
 
- import { Config } from '../util/config';
 
- function buildInfixAddTable () {
 
-   const table = [[], [], [], []];
 
-   table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.INTEGER;
 
-   table[Types.INTEGER.ord][Types.REAL.ord] = Types.REAL;
 
-   table[Types.INTEGER.ord][Types.STRING.ord] = Types.STRING;
 
-   table[Types.REAL.ord][Types.INTEGER.ord] = Types.REAL;
 
-   table[Types.REAL.ord][Types.REAL.ord] = Types.REAL;
 
-   table[Types.REAL.ord][Types.STRING.ord] = Types.STRING;
 
-   table[Types.STRING.ord][Types.INTEGER.ord] = Types.STRING;
 
-   table[Types.STRING.ord][Types.REAL.ord] = Types.STRING;
 
-   table[Types.STRING.ord][Types.STRING.ord] = Types.STRING;
 
-   table[Types.STRING.ord][Types.BOOLEAN.ord] = Types.STRING;
 
-   return table;
 
- }
 
- function buildInfixMultiDivSubTable () {
 
-   const table = [[], [], [], []];
 
-   table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.INTEGER;
 
-   table[Types.INTEGER.ord][Types.REAL.ord] = Types.REAL;
 
-   table[Types.REAL.ord][Types.INTEGER.ord] = Types.REAL;
 
-   table[Types.REAL.ord][Types.REAL.ord] = Types.REAL;
 
-   return table;
 
- }
 
- function buildInfixEqualityInequalityTable () {
 
-   const table = [[], [], [], []];
 
-   table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.BOOLEAN;
 
-   table[Types.REAL.ord][Types.REAL.ord] = Types.BOOLEAN;
 
-   table[Types.BOOLEAN.ord][Types.BOOLEAN.ord] = Types.BOOLEAN;
 
-   table[Types.STRING.ord][Types.STRING.ord] = Types.BOOLEAN;
 
-   return table;
 
- }
 
- function buildInfixRelationalTable () {
 
-   const table = [[], [], [], []];
 
-   table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.BOOLEAN;
 
-   table[Types.REAL.ord][Types.REAL.ord] = Types.BOOLEAN;
 
-   table[Types.STRING.ord][Types.STRING.ord] = Types.BOOLEAN;
 
-   return table;
 
- }
 
- function buildInfixAndOrTable () {
 
-   const table = [[], [], [], []];
 
-   table[Types.BOOLEAN.ord][Types.BOOLEAN.ord] = Types.BOOLEAN;
 
-   return table;
 
- }
 
- function buildInfixModTable () {
 
-   const table = [[], [], [], []];
 
-   table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.INTEGER;
 
-   return table;
 
- }
 
- function buildUnarySumSubList () {
 
-   const list = [];
 
-   list[Types.INTEGER.ord] = Types.INTEGER;
 
-   list[Types.REAL.ord] = Types.REAL;
 
-   return list;
 
- }
 
- function buildUnaryNegList () {
 
-   const list = [];
 
-   list[Types.BOOLEAN.ord] = Types.BOOLEAN;
 
-   return list;
 
- }
 
- function buildInfixCompatibilityTable () {
 
-   const compatibilityMap = new WeakMap();
 
-   compatibilityMap.set(Operators.ADD, buildInfixAddTable());
 
-   compatibilityMap.set(Operators.SUB, buildInfixMultiDivSubTable());
 
-   compatibilityMap.set(Operators.MULT, buildInfixMultiDivSubTable());
 
-   compatibilityMap.set(Operators.DIV, buildInfixMultiDivSubTable());
 
-   compatibilityMap.set(Operators.EQ, buildInfixEqualityInequalityTable());
 
-   compatibilityMap.set(Operators.NEQ, buildInfixEqualityInequalityTable());
 
-   compatibilityMap.set(Operators.GE, buildInfixRelationalTable());
 
-   compatibilityMap.set(Operators.GT, buildInfixRelationalTable());
 
-   compatibilityMap.set(Operators.LE, buildInfixRelationalTable());
 
-   compatibilityMap.set(Operators.LT, buildInfixRelationalTable());
 
-   compatibilityMap.set(Operators.OR, buildInfixAndOrTable());
 
-   compatibilityMap.set(Operators.AND, buildInfixAndOrTable());
 
-   compatibilityMap.set(Operators.MOD, buildInfixModTable());
 
-   return compatibilityMap;
 
- }
 
- function buildUnaryCompatibilityTable () {
 
-   const compatibilityMap = new WeakMap();
 
-   compatibilityMap.set(Operators.ADD, buildUnarySumSubList());
 
-   compatibilityMap.set(Operators.SUB, buildUnarySumSubList());
 
-   compatibilityMap.set(Operators.NOT, buildUnaryNegList());
 
-   return compatibilityMap;
 
- }
 
- const infixMap = buildInfixCompatibilityTable();
 
- const unaryMap = buildUnaryCompatibilityTable();
 
- export function resultTypeAfterInfixOp (operator, leftExpressionType, rightExpressionType) {
 
-   try {
 
-     if(leftExpressionType instanceof MultiType && rightExpressionType instanceof MultiType) {
 
-       let newMulti = [];
 
-       for (let i = 0; i < leftExpressionType.types.length; ++i) {
 
-         const typeA = leftExpressionType.types[i];
 
-         for(let j = 0; j < rightExpressionType.types.length; ++i) {
 
-           const typeB = rightExpressionType.types[j];
 
-           newMulti.push(resultTypeAfterInfixOp(operator, typeA, typeB));
 
-         }
 
-       }
 
-       newMulti = newMulti.filter(x => !x.isCompatible(Types.UNDEFINED));
 
-       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)
 
-       }
 
-     } else if(leftExpressionType instanceof MultiType) {
 
-       if(leftExpressionType.isCompatible(rightExpressionType)) {
 
-         return resultTypeAfterInfixOp(operator, rightExpressionType, 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 resultTypeAfterInfixOp(operator, leftExpressionType, 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;
 
-   } catch (e) {
 
-     if (e instanceof TypeError) {
 
-       return Types.UNDEFINED;
 
-     } else {
 
-       throw e;
 
-     }
 
-   }
 
- }
 
- export function resultTypeAfterUnaryOp (operator, leftExpressionType) {
 
-   try {
 
-     if(leftExpressionType instanceof MultiType){
 
-       return leftExpressionType;
 
-     }
 
-     const resultType = unaryMap.get(operator)[leftExpressionType.ord];
 
-     if (resultType == null) {
 
-       return Types.UNDEFINED;
 
-     }
 
-     return resultType;
 
-   } catch (e) {
 
-     if (e instanceof TypeError) {
 
-       return Types.UNDEFINED;
 
-     } else {
 
-       throw e;
 
-     } 
 
-   }
 
- }
 
 
  |