compatibilityTable.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import { Types } from './../typeSystem/types';
  2. import { Operators } from './../ast/operators';
  3. import { MultiType } from '../typeSystem/multiType';
  4. import { Config } from '../util/config';
  5. function buildInfixAddTable () {
  6. const table = [[], [], [], []];
  7. table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.INTEGER;
  8. table[Types.INTEGER.ord][Types.REAL.ord] = Types.REAL;
  9. table[Types.INTEGER.ord][Types.STRING.ord] = Types.STRING;
  10. table[Types.REAL.ord][Types.INTEGER.ord] = Types.REAL;
  11. table[Types.REAL.ord][Types.REAL.ord] = Types.REAL;
  12. table[Types.REAL.ord][Types.STRING.ord] = Types.STRING;
  13. table[Types.STRING.ord][Types.INTEGER.ord] = Types.STRING;
  14. table[Types.STRING.ord][Types.REAL.ord] = Types.STRING;
  15. table[Types.STRING.ord][Types.STRING.ord] = Types.STRING;
  16. table[Types.STRING.ord][Types.BOOLEAN.ord] = Types.STRING;
  17. return table;
  18. }
  19. function buildInfixMultiDivSubTable () {
  20. const table = [[], [], [], []];
  21. table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.INTEGER;
  22. table[Types.INTEGER.ord][Types.REAL.ord] = Types.REAL;
  23. table[Types.REAL.ord][Types.INTEGER.ord] = Types.REAL;
  24. table[Types.REAL.ord][Types.REAL.ord] = Types.REAL;
  25. return table;
  26. }
  27. function buildInfixEqualityInequalityTable () {
  28. const table = [[], [], [], []];
  29. table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.BOOLEAN;
  30. table[Types.REAL.ord][Types.REAL.ord] = Types.BOOLEAN;
  31. table[Types.BOOLEAN.ord][Types.BOOLEAN.ord] = Types.BOOLEAN;
  32. table[Types.STRING.ord][Types.STRING.ord] = Types.BOOLEAN;
  33. return table;
  34. }
  35. function buildInfixRelationalTable () {
  36. const table = [[], [], [], []];
  37. table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.BOOLEAN;
  38. table[Types.REAL.ord][Types.REAL.ord] = Types.BOOLEAN;
  39. table[Types.STRING.ord][Types.STRING.ord] = Types.BOOLEAN;
  40. return table;
  41. }
  42. function buildInfixAndOrTable () {
  43. const table = [[], [], [], []];
  44. table[Types.BOOLEAN.ord][Types.BOOLEAN.ord] = Types.BOOLEAN;
  45. return table;
  46. }
  47. function buildInfixModTable () {
  48. const table = [[], [], [], []];
  49. table[Types.INTEGER.ord][Types.INTEGER.ord] = Types.INTEGER;
  50. return table;
  51. }
  52. function buildUnarySumSubList () {
  53. const list = [];
  54. list[Types.INTEGER.ord] = Types.INTEGER;
  55. list[Types.REAL.ord] = Types.REAL;
  56. return list;
  57. }
  58. function buildUnaryNegList () {
  59. const list = [];
  60. list[Types.BOOLEAN.ord] = Types.BOOLEAN;
  61. return list;
  62. }
  63. function buildInfixCompatibilityTable () {
  64. const compatibilityMap = new WeakMap();
  65. compatibilityMap.set(Operators.ADD, buildInfixAddTable());
  66. compatibilityMap.set(Operators.SUB, buildInfixMultiDivSubTable());
  67. compatibilityMap.set(Operators.MULT, buildInfixMultiDivSubTable());
  68. compatibilityMap.set(Operators.DIV, buildInfixMultiDivSubTable());
  69. compatibilityMap.set(Operators.EQ, buildInfixEqualityInequalityTable());
  70. compatibilityMap.set(Operators.NEQ, buildInfixEqualityInequalityTable());
  71. compatibilityMap.set(Operators.GE, buildInfixRelationalTable());
  72. compatibilityMap.set(Operators.GT, buildInfixRelationalTable());
  73. compatibilityMap.set(Operators.LE, buildInfixRelationalTable());
  74. compatibilityMap.set(Operators.LT, buildInfixRelationalTable());
  75. compatibilityMap.set(Operators.OR, buildInfixAndOrTable());
  76. compatibilityMap.set(Operators.AND, buildInfixAndOrTable());
  77. compatibilityMap.set(Operators.MOD, buildInfixModTable());
  78. return compatibilityMap;
  79. }
  80. function buildUnaryCompatibilityTable () {
  81. const compatibilityMap = new WeakMap();
  82. compatibilityMap.set(Operators.ADD, buildUnarySumSubList());
  83. compatibilityMap.set(Operators.SUB, buildUnarySumSubList());
  84. compatibilityMap.set(Operators.NOT, buildUnaryNegList());
  85. return compatibilityMap;
  86. }
  87. const infixMap = buildInfixCompatibilityTable();
  88. const unaryMap = buildUnaryCompatibilityTable();
  89. export function resultTypeAfterInfixOp (operator, leftExpressionType, rightExpressionType) {
  90. try {
  91. if(leftExpressionType instanceof MultiType && rightExpressionType instanceof MultiType) {
  92. let newMulti = [];
  93. for (let i = 0; i < leftExpressionType.types.length; ++i) {
  94. const typeA = leftExpressionType.types[i];
  95. for(let j = 0; j < rightExpressionType.types.length; ++i) {
  96. const typeB = rightExpressionType.types[j];
  97. newMulti.push(resultTypeAfterInfixOp(operator, typeA, typeB));
  98. }
  99. }
  100. newMulti = newMulti.filter(x => !x.isCompatible(Types.UNDEFINED));
  101. if(newMulti.length <= 0) {
  102. if(Config.enable_type_casting) {
  103. if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
  104. if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
  105. return new MultiType([Types.INTEGER, Types.REAL]);
  106. }
  107. }
  108. }
  109. return Types.UNDEFINED;
  110. } else {
  111. return new MultiType(newMulti)
  112. }
  113. } else if(leftExpressionType instanceof MultiType) {
  114. if(leftExpressionType.isCompatible(rightExpressionType)) {
  115. return resultTypeAfterInfixOp(operator, rightExpressionType, rightExpressionType);
  116. } else {
  117. if(Config.enable_type_casting) {
  118. if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
  119. if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
  120. return rightExpressionType;
  121. }
  122. }
  123. }
  124. return Types.UNDEFINED;
  125. }
  126. } else if(rightExpressionType instanceof MultiType) {
  127. if(rightExpressionType.isCompatible(leftExpressionType)) {
  128. return resultTypeAfterInfixOp(operator, leftExpressionType, leftExpressionType);
  129. } else {
  130. if(Config.enable_type_casting) {
  131. if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
  132. if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
  133. return leftExpressionType;
  134. }
  135. }
  136. }
  137. return Types.UNDEFINED;
  138. }
  139. }
  140. const resultType = infixMap.get(operator)[leftExpressionType.ord][rightExpressionType.ord];
  141. if (resultType === null || resultType === undefined) {
  142. if(Config.enable_type_casting) {
  143. if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
  144. if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
  145. if(operator === Operators.MOD) {
  146. return Types.INTEGER;
  147. } else if (operator.ord >= 5 && operator.ord <= 10){
  148. return Types.BOOLEAN;
  149. }
  150. }
  151. }
  152. }
  153. return Types.UNDEFINED
  154. }
  155. return resultType;
  156. } catch (e) {
  157. if (e instanceof TypeError) {
  158. return Types.UNDEFINED;
  159. } else {
  160. throw e;
  161. }
  162. }
  163. }
  164. export function resultTypeAfterUnaryOp (operator, leftExpressionType) {
  165. try {
  166. if(leftExpressionType instanceof MultiType){
  167. return leftExpressionType;
  168. }
  169. const resultType = unaryMap.get(operator)[leftExpressionType.ord];
  170. if (resultType == null) {
  171. return Types.UNDEFINED;
  172. }
  173. return resultType;
  174. } catch (e) {
  175. if (e instanceof TypeError) {
  176. return Types.UNDEFINED;
  177. } else {
  178. throw e;
  179. }
  180. }
  181. }