scope.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. "use strict";
  2. var Class = require("rtl.js").Class;
  3. var Errors = require("errors.js");
  4. var Procedure = require("procedure.js");
  5. var Symbol = require("symbol.js");
  6. var Type = require("type.js");
  7. var stdSymbols = function(){
  8. var symbols = {};
  9. for(var t in Type.basic){
  10. var type = Type.basic[t];
  11. symbols[type.name()] = new Symbol.Symbol(type.name(), new Type.TypeId(type));
  12. }
  13. symbols["LONGREAL"] = new Symbol.Symbol("LONGREAL", new Type.TypeId(Type.basic.real));
  14. var predefined = Procedure.predefined;
  15. for(var i = 0; i < predefined.length; ++i){
  16. var s = predefined[i];
  17. symbols[s.id()] = s;
  18. }
  19. return symbols;
  20. }();
  21. var Scope = Class.extend({
  22. init: function Scope(id){
  23. this.__id = id;
  24. this.__symbols = {};
  25. for(var p in stdSymbols)
  26. this.__symbols[p] = stdSymbols[p];
  27. this.__unresolved = [];
  28. },
  29. id: function(){return this.__id;},
  30. addSymbol: function(symbol){
  31. var id = symbol.id();
  32. if (this.findSymbol(id))
  33. throw new Errors.Error( "'" + id + "' already declared");
  34. this.__symbols[id] = symbol;
  35. },
  36. addType: function(type, id){
  37. if (!id)
  38. return undefined;
  39. var symbol = new Symbol.Symbol(id.id(), type);
  40. this.addSymbol(symbol, id.exported());
  41. return symbol;
  42. },
  43. resolve: function(symbol){
  44. var id = symbol.id();
  45. var i = this.__unresolved.indexOf(id);
  46. if (i != -1){
  47. var info = symbol.info();
  48. var type = info.type();
  49. if (type !== undefined && !(type instanceof Type.Record))
  50. throw new Errors.Error(
  51. "'" + id + "' must be of RECORD type because it was used before in the declation of POINTER");
  52. this.__unresolved.splice(i, 1);
  53. }
  54. },
  55. findSymbol: function(ident){return this.__symbols[ident];},
  56. addUnresolved: function(id){
  57. if (this.__unresolved.indexOf(id) == -1)
  58. this.__unresolved.push(id);
  59. },
  60. unresolved: function(){return this.__unresolved;}
  61. });
  62. var ProcedureScope = Scope.extend({
  63. init: function ProcedureScope(){
  64. Scope.prototype.init.call(this, "procedure");
  65. },
  66. addSymbol: function(symbol, exported){
  67. if (exported)
  68. throw new Errors.Error("cannot export from within procedure: "
  69. + symbol.info().idType() + " '" + symbol.id() + "'");
  70. Scope.prototype.addSymbol.call(this, symbol, exported);
  71. }
  72. });
  73. var CompiledModule = Type.Module.extend({
  74. init: function Scope$CompiledModule(id){
  75. Type.Module.prototype.init.call(this, id);
  76. this.__exports = {};
  77. },
  78. defineExports: function(exports){
  79. for(var id in exports){
  80. var symbol = exports[id];
  81. if (symbol.isVariable())
  82. symbol = new Symbol.Symbol(
  83. id,
  84. new Type.ExportedVariable(symbol.info()));
  85. this.__exports[id] = symbol;
  86. }
  87. },
  88. findSymbol: function(id){
  89. var s = this.__exports[id];
  90. if (!s)
  91. return undefined;
  92. return new Symbol.Found(s);
  93. }
  94. });
  95. var Module = Scope.extend({
  96. init: function Scope$Module(name){
  97. Scope.prototype.init.call(this, "module");
  98. this.__name = name;
  99. this.__exports = {};
  100. this.__stripTypes = [];
  101. this.__symbol = new Symbol.Symbol(name, new CompiledModule(name));
  102. this.addSymbol(this.__symbol);
  103. },
  104. module: function(){return this.__symbol;},
  105. addSymbol: function(symbol, exported){
  106. Scope.prototype.addSymbol.call(this, symbol, exported);
  107. if (exported)
  108. this.__exports[symbol.id()] = symbol;
  109. },
  110. addType: function(type, id){
  111. var result = Scope.prototype.addType.call(this, type, id);
  112. if (!id || !id.exported())
  113. this.__stripTypes.push(type);
  114. return result;
  115. },
  116. exports: function(){return this.__exports;},
  117. strip: function(){
  118. for(var i = 0; i < this.__stripTypes.length; ++i)
  119. this.__stripTypes[i].strip();
  120. }
  121. });
  122. exports.Procedure = ProcedureScope;
  123. exports.Module = Module;