baseConverter.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import {
  2. FunctionCall,
  3. Literal,
  4. UnaryApp,
  5. InfixApp,
  6. IntLiteral,
  7. RealLiteral,
  8. StringLiteral,
  9. VariableLiteral,
  10. ArrayAccess,
  11. BoolLiteral
  12. } from "./../ast/expressions";
  13. import { Types } from "./../typeSystem/types";
  14. import { ArrayType } from "./../typeSystem/array_type";
  15. import {
  16. resultTypeAfterInfixOp,
  17. resultTypeAfterUnaryOp
  18. } from "./../processor/compatibilityTable";
  19. import { LanguageDefinedFunction } from "./../processor/definedFunctions";
  20. export class BaseConverter {
  21. constructor (ivprogAST) {
  22. this.ivprogAST = ivprogAST;
  23. this.globalMap = new Map();
  24. this.symbolMap = [];
  25. this.symbolMap.push(this.globalMap);
  26. }
  27. popContext () {
  28. if (this.symbolMap.length > 1) {
  29. this.symbolMap.pop();
  30. }
  31. }
  32. pushContext (map) {
  33. this.symbolMap.push(map);
  34. }
  35. findFunction (name) {
  36. if (name.match(/^\$.+$/)) {
  37. const fun = LanguageDefinedFunction.getFunction(name);
  38. return fun;
  39. } else {
  40. const val = this.ivprogAST.functions.find(v => v.name === name);
  41. return val;
  42. }
  43. }
  44. findSymbol (id) {
  45. for (let i = this.symbolMap.length - 1; i >= 0; i -= 1) {
  46. const map = this.symbolMap[i];
  47. if (map.has(id)) {
  48. return map.get(id);
  49. }
  50. }
  51. return null;
  52. }
  53. insertGlobalSymbol (id, declaration) {
  54. this.globalMap.set(id, { id: id, type: declaration.type, global: true });
  55. }
  56. insertSymbol (id, declaration) {
  57. const map = this.symbolMap.slice(-1)[0];
  58. map.set(id, { id: id, type: declaration.type, global: false });
  59. }
  60. evaluateExpressionType (expression) {
  61. if (expression instanceof UnaryApp) {
  62. const op = expression.op;
  63. const resultType = this.evaluateExpressionType(expression.left);
  64. const finalResult = resultTypeAfterUnaryOp(op, resultType);
  65. return finalResult;
  66. } else if (expression instanceof InfixApp) {
  67. const op = expression.op;
  68. const resultTypeLeft = this.evaluateExpressionType(expression.left);
  69. const resultTypeRight = this.evaluateExpressionType(expression.right);
  70. const finalResult = resultTypeAfterInfixOp(
  71. op,
  72. resultTypeLeft,
  73. resultTypeRight
  74. );
  75. return finalResult;
  76. } else if (expression instanceof Literal) {
  77. return this.evaluateLiteralType(expression);
  78. } else if (expression instanceof FunctionCall) {
  79. const fun = this.findFunction(expression.id);
  80. return fun.returnType;
  81. } else if (expression instanceof ArrayAccess) {
  82. const arrayTypeInfo = this.findSymbol(expression.id);
  83. const arrType = arrayTypeInfo.type;
  84. if (expression.column !== null) {
  85. // indexing matrix
  86. return arrType.innerType;
  87. } else {
  88. if (arrayTypeInfo.columns === null) {
  89. return arrType.innerType;
  90. }
  91. return new ArrayType(arrType.innerType, 1);
  92. }
  93. }
  94. }
  95. evaluateLiteralType (literal) {
  96. if (literal instanceof IntLiteral) {
  97. return literal.type;
  98. } else if (literal instanceof RealLiteral) {
  99. return literal.type;
  100. } else if (literal instanceof StringLiteral) {
  101. return literal.type;
  102. } else if (literal instanceof BoolLiteral) {
  103. return literal.type;
  104. } else if (literal instanceof VariableLiteral) {
  105. const typeInfo = this.findSymbol(literal.id);
  106. return typeInfo.type;
  107. } else {
  108. console.warn("Evaluating type only for an array literal...");
  109. // This should never happen in this context and there is no use throwing execeptions!
  110. return new ArrayType(Types.INTEGER, 1);
  111. }
  112. }
  113. }