type.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. var Class = require("rtl.js").Class;
  2. var Errors = require("errors.js");
  3. var Id = Class.extend({
  4. init: function Id(){},
  5. });
  6. var Type = Id.extend({
  7. init: function Type(){
  8. Id.prototype.init.bind(this)();
  9. },
  10. idType: function(){return "type";},
  11. isProcedure: function(){return false;}
  12. });
  13. exports.Type = Type;
  14. exports.String = Type.extend({
  15. init: function TypeString(s){
  16. Type.prototype.init.bind(this)();
  17. this.__s = s;
  18. },
  19. idType: function(){return "string";},
  20. description: function(){return (this.__s.length == 1 ? "single-" : "multi-") + "character string";},
  21. value: function(){return this.__s;},
  22. asChar: function (){return this.__s.length == 1 ? this.__s.charCodeAt(0) : undefined;}
  23. });
  24. var BasicType = Type.extend({
  25. init: function BasicType(name, initValue){
  26. Type.prototype.init.bind(this)();
  27. this.__name = name;
  28. this.__initValue = initValue;
  29. },
  30. name: function() {return this.__name;},
  31. description: function(){return this.name();},
  32. initializer: function() {return this.__initValue;}
  33. });
  34. exports.Basic = BasicType;
  35. exports.Array = BasicType.extend({
  36. init: function ArrayType(name, initializer, elementsType, size){
  37. BasicType.prototype.init.bind(this)(name, initializer);
  38. this.__elementsType = elementsType;
  39. this.__size = size;
  40. },
  41. elementsType: function(){return this.__elementsType;},
  42. arraySize: function(){return this.__size;}
  43. });
  44. exports.Pointer = BasicType.extend({
  45. init: function PointerType(name, base){
  46. BasicType.prototype.init.bind(this)(name, "null");
  47. this.__base = base;
  48. },
  49. description: function(){
  50. var name = this.name();
  51. if (name.indexOf("$") != -1)
  52. return "POINTER TO " + this.baseType().description();
  53. return name;
  54. },
  55. baseType: function(){
  56. if (this.__base instanceof exports.ForwardRecord)
  57. this.__base = this.__base.resolve();
  58. return this.__base;
  59. }
  60. });
  61. exports.ForwardRecord = Type.extend({
  62. init: function(resolve){
  63. Type.prototype.init.bind(this)();
  64. this.__resolve = resolve;
  65. },
  66. resolve: function(){return this.__resolve();}
  67. });
  68. exports.Record = BasicType.extend({
  69. init: function RecordType(name){
  70. BasicType.prototype.init.bind(this)(name, "new " + name + "()");
  71. this.__fields = {};
  72. this.__base = undefined;
  73. this.__finalized = false;
  74. },
  75. addField: function(field, type){
  76. if (this.__fields.hasOwnProperty(field))
  77. throw new Errors.Error("duplicated field: '" + field + "'");
  78. if (this.__base && this.__base.findSymbol(field))
  79. throw new Errors.Error("base record already has field: '" + field + "'");
  80. this.__fields[field] = type;
  81. },
  82. ownFields: function() {return this.__fields;},
  83. findSymbol: function(field){
  84. var result = this.__fields[field];
  85. if ( !result && this.__base)
  86. result = this.__base.findSymbol(field);
  87. return result;
  88. },
  89. baseType: function() {return this.__base;},
  90. setBaseType: function(type) {this.__base = type;},
  91. finalize: function(){this.__finalized = true;},
  92. description: function(){
  93. var name = this.name();
  94. if (name.indexOf("$") != -1)
  95. return "anonymous RECORD";
  96. return name;
  97. }
  98. });
  99. var NilType = Type.extend({
  100. init: function NilType(){Type.prototype.init.bind(this)();},
  101. idType: function(){return "NIL";},
  102. description: function(){return "NIL";}
  103. });
  104. exports.basic = {
  105. bool: new BasicType("BOOLEAN", false),
  106. char: new BasicType("CHAR", 0),
  107. int: new BasicType("INTEGER", 0),
  108. real: new BasicType("REAL", 0),
  109. set: new BasicType("SET", 0)
  110. };
  111. exports.nil = new NilType();
  112. exports.Const = Id.extend({
  113. init: function Const(type, value){
  114. Id.prototype.init.bind(this)();
  115. this.__type = type;
  116. this.__value = value;
  117. },
  118. idType: function(){return "constant";},
  119. type: function(){return this.__type;},
  120. value: function(){return this.__value;}
  121. });
  122. exports.Variable = Id.extend({
  123. init: function Variable(type, isVar, isReadOnly){
  124. Id.prototype.init.bind(this)();
  125. this.__type = type;
  126. this.__isVar = isVar;
  127. this.__isReadOnly = isReadOnly;
  128. },
  129. idType: function(){return this.__isReadOnly ? "read-only variable" : "variable";},
  130. type: function(){return this.__type;},
  131. isVar: function(){return this.__isVar;},
  132. isReadOnly: function(){return this.__isReadOnly;}
  133. });
  134. exports.Procedure = Id.extend({
  135. init: function Procedure(type){
  136. Id.prototype.init.bind(this)();
  137. this.__type = type;
  138. },
  139. idType: function(){return "procedure";},
  140. type: function(){return this.__type;}
  141. });
  142. var Symbol = Class.extend({
  143. init: function Symbol(id, info){
  144. this.__id = id;
  145. this.__info = info;
  146. },
  147. id: function(){return this.__id;},
  148. info: function(){return this.__info;},
  149. isVariable: function(){return this.__info instanceof exports.Variable;},
  150. isConst: function(){return this.__info instanceof exports.Const;},
  151. isType: function(){return this.__info instanceof Type;},
  152. isProcedure: function(){return this.__info instanceof exports.Procedure;},
  153. });
  154. exports.Symbol = Symbol;