rtl.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. "use strict";
  2. // support IE8
  3. if (!Array.prototype.indexOf)
  4. Array.prototype.indexOf = function(x){
  5. for(var i = 0; i < this.length; ++i)
  6. if (this[i] === x)
  7. return i;
  8. return -1;
  9. };
  10. function Class(){}
  11. Class.extend = function extend(methods){
  12. function Type(){
  13. for(var m in methods)
  14. this[m] = methods[m];
  15. }
  16. Type.prototype = this.prototype;
  17. var result = methods.init;
  18. result.prototype = new Type(); // inherit this.prototype
  19. result.prototype.constructor = result; // to see constructor name in diagnostic
  20. result.extend = extend;
  21. return result;
  22. };
  23. var impl = {
  24. extend: Class.extend,
  25. typeGuard: function(from, to){
  26. if (!(from instanceof to))
  27. throw new Error("typeguard assertion failed");
  28. return from;
  29. },
  30. makeArray: function(/*dimensions, initializer*/){
  31. var forward = Array.prototype.slice.call(arguments);
  32. var result = new Array(forward.shift());
  33. var i;
  34. if (forward.length == 1){
  35. var init = forward[0];
  36. if (typeof init == "function")
  37. for(i = 0; i < result.length; ++i)
  38. result[i] = init();
  39. else
  40. for(i = 0; i < result.length; ++i)
  41. result[i] = init;
  42. }
  43. else
  44. for(i = 0; i < result.length; ++i)
  45. result[i] = this.makeArray.apply(this, forward);
  46. return result;
  47. },
  48. makeSet: function(/*...*/){
  49. var result = 0;
  50. function checkBit(b){
  51. if (b < 0 || b > 31)
  52. throw new Error("integers between 0 and 31 expected, got " + b);
  53. }
  54. function setBit(b){
  55. checkBit(b);
  56. result |= 1 << b;
  57. }
  58. for(var i = 0; i < arguments.length; ++i){
  59. var b = arguments[i];
  60. if (b instanceof Array){
  61. var from = b[0];
  62. var to = b[1];
  63. if (from < to)
  64. throw new Error("invalid SET diapason: " + from + ".." + to);
  65. for(var bi = from; bi <= to; ++bi)
  66. setBit(bi);
  67. }
  68. else
  69. setBit(b);
  70. }
  71. return result;
  72. },
  73. makeRef: function(obj, prop){
  74. return {set: function(v){ obj[prop] = v; },
  75. get: function(){ return obj[prop]; }};
  76. },
  77. setInclL: function(l, r){return (l & r) == l;},
  78. setInclR: function(l, r){return (l & r) == r;},
  79. assignArrayFromString: function(a, s){
  80. var i;
  81. for(i = 0; i < s.length; ++i)
  82. a[i] = s.charCodeAt(i);
  83. for(i = s.length; i < a.length; ++i)
  84. a[i] = 0;
  85. },
  86. strToArray: function(s){
  87. var result = new Array(s.length);
  88. for(var i = 0; i < s.length; ++i)
  89. result[i] = s.charCodeAt(i);
  90. return result;
  91. },
  92. copy: function(from, to){
  93. for(var prop in to){
  94. if (to.hasOwnProperty(prop)){
  95. var v = from[prop];
  96. if (v !== null && typeof v == "object")
  97. this.copy(v, to[prop]);
  98. else
  99. to[prop] = v;
  100. }
  101. }
  102. },
  103. assert: function(condition, code){
  104. if (!condition)
  105. throw new Error("assertion failed"
  106. + ((code !== undefined) ? " with code " + code : ""));
  107. }
  108. };
  109. var Code = Class.extend({
  110. init: function RTL$Code(){
  111. var names = [];
  112. for(var f in impl)
  113. names.push(f);
  114. this.__functions = names;
  115. },
  116. functions: function(){return this.__functions;},
  117. get: function(func){return impl[func];}
  118. });
  119. var defaultCode = new Code();
  120. exports.Class = Class;
  121. exports.RTL = Class.extend({
  122. init: function RTL(code){
  123. this.__entries = {};
  124. this.__code = code || defaultCode;
  125. var names = this.__code.functions();
  126. for(var i = 0; i < names.length; ++i){
  127. var name = names[i];
  128. this[name] = this.__makeOnDemand(name);
  129. this[name + "Id"] = this.__makeIdOnDemand(name);
  130. }
  131. },
  132. name: function(){return "RTL$";},
  133. generate: function(){
  134. var result = "var " + this.name() + " = {\n";
  135. var firstEntry = true;
  136. for (var name in this.__entries){
  137. if (!firstEntry)
  138. result += ",\n";
  139. else
  140. firstEntry = false;
  141. result += " " + name + ": " + this.__entries[name].toString();
  142. }
  143. if (!firstEntry)
  144. result += "\n};\n";
  145. else
  146. result = undefined;
  147. return result;
  148. },
  149. __makeIdOnDemand: function(name){
  150. return function(){
  151. if (!this.__entries[name])
  152. this.__entries[name] = this.__code.get(name);
  153. return this.name() + "." + name;
  154. };
  155. },
  156. __makeOnDemand: function(name){
  157. return function(){
  158. var result = this[name +"Id"]() + "(";
  159. if (arguments.length){
  160. result += arguments[0];
  161. for(var a = 1; a < arguments.length; ++a)
  162. result += ", " + arguments[a];
  163. }
  164. result += ")";
  165. return result;
  166. };
  167. }
  168. });
  169. exports.Code = Code;