compatibilityTable.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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 element = leftExpressionType.types[i];
  95. if(rightExpressionType.types.indexOf(element) !== -1) {
  96. newMulti.push(element);
  97. }
  98. }
  99. if(newMulti.length <= 0) {
  100. if(Config.enable_type_casting) {
  101. if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
  102. if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
  103. return new MultiType([Types.INTEGER, Types.REAL]);
  104. }
  105. }
  106. }
  107. return Types.UNDEFINED;
  108. } else {
  109. return new MultiType(newMulti)
  110. }
  111. } else if(leftExpressionType instanceof MultiType) {
  112. if(leftExpressionType.isCompatible(rightExpressionType)) {
  113. return rightExpressionType;
  114. } else {
  115. if(Config.enable_type_casting) {
  116. if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
  117. if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
  118. return rightExpressionType;
  119. }
  120. }
  121. }
  122. return Types.UNDEFINED;
  123. }
  124. } else if(rightExpressionType instanceof MultiType) {
  125. if(rightExpressionType.isCompatible(leftExpressionType)) {
  126. return leftExpressionType;
  127. } else {
  128. if(Config.enable_type_casting) {
  129. if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
  130. if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
  131. return leftExpressionType;
  132. }
  133. }
  134. }
  135. return Types.UNDEFINED;
  136. }
  137. }
  138. const resultType = infixMap.get(operator)[leftExpressionType.ord][rightExpressionType.ord];
  139. if (resultType === null || resultType === undefined) {
  140. if(Config.enable_type_casting) {
  141. if(leftExpressionType.isCompatible(Types.INTEGER) || leftExpressionType.isCompatible(Types.REAL)) {
  142. if(rightExpressionType.isCompatible(Types.INTEGER) || rightExpressionType.isCompatible(Types.REAL)) {
  143. if(operator === Operators.MOD) {
  144. return Types.INTEGER;
  145. } else if (operator.ord >= 5 && operator.ord <= 10){
  146. return Types.BOOLEAN;
  147. }
  148. }
  149. }
  150. }
  151. return Types.UNDEFINED
  152. }
  153. return resultType;
  154. } catch (e) {
  155. if (e instanceof TypeError) {
  156. return Types.UNDEFINED;
  157. } else {
  158. throw e;
  159. }
  160. }
  161. }
  162. export function resultTypeAfterUnaryOp (operator, leftExpressionType) {
  163. try {
  164. if(leftExpressionType instanceof MultiType){
  165. return leftExpressionType;
  166. }
  167. return unaryMap.get(operator)[leftExpressionType.ord];
  168. } catch (e) {
  169. if (e instanceof TypeError) {
  170. return Types.UNDEFINED;
  171. } else {
  172. throw e;
  173. }
  174. }
  175. }