compatibilityTable.js 5.3 KB

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