superchris-rubyjs 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +131 -0
- data/Rakefile +65 -0
- data/bin/rubyjs +144 -0
- data/rubyjs.gemspec +112 -0
- data/src/rubyjs.rb +3 -0
- data/src/rubyjs/code_generator.rb +474 -0
- data/src/rubyjs/compiler.rb +2061 -0
- data/src/rubyjs/debug_name_generator.rb +95 -0
- data/src/rubyjs/encoder.rb +171 -0
- data/src/rubyjs/eval_into.rb +59 -0
- data/src/rubyjs/lib/core.rb +1016 -0
- data/src/rubyjs/lib/dom_element.rb +66 -0
- data/src/rubyjs/lib/json.rb +101 -0
- data/src/rubyjs/lib/microunit.rb +188 -0
- data/src/rubyjs/model.rb +293 -0
- data/src/rubyjs/name_generator.rb +71 -0
- data/src/rwt/AbsolutePanel.rb +161 -0
- data/src/rwt/DOM.Konqueror.rb +89 -0
- data/src/rwt/DOM.Opera.rb +65 -0
- data/src/rwt/DOM.rb +1044 -0
- data/src/rwt/Event.Opera.rb +35 -0
- data/src/rwt/Event.rb +429 -0
- data/src/rwt/HTTPRequest.IE6.rb +5 -0
- data/src/rwt/HTTPRequest.rb +74 -0
- data/src/rwt/Label.rb +164 -0
- data/src/rwt/Panel.rb +90 -0
- data/src/rwt/RootPanel.rb +16 -0
- data/src/rwt/UIObject.rb +495 -0
- data/src/rwt/Widget.rb +193 -0
- data/src/rwt/ported-from/AbsolutePanel.java +158 -0
- data/src/rwt/ported-from/DOM.java +571 -0
- data/src/rwt/ported-from/DOMImpl.java +426 -0
- data/src/rwt/ported-from/DOMImplOpera.java +82 -0
- data/src/rwt/ported-from/DOMImplStandard.java +234 -0
- data/src/rwt/ported-from/HTTPRequest.java +81 -0
- data/src/rwt/ported-from/HTTPRequestImpl.java +103 -0
- data/src/rwt/ported-from/Label.java +163 -0
- data/src/rwt/ported-from/Panel.java +99 -0
- data/src/rwt/ported-from/UIObject.java +614 -0
- data/src/rwt/ported-from/Widget.java +221 -0
- data/test/benchmark/bm_vm1_block.rb +15 -0
- data/test/benchmark/bm_vm1_const.rb +13 -0
- data/test/benchmark/bm_vm1_ensure.rb +15 -0
- data/test/benchmark/common.rb +5 -0
- data/test/benchmark/params.yaml +7 -0
- data/test/common.Browser.rb +13 -0
- data/test/common.rb +8 -0
- data/test/gen_browser_test_suite.rb +129 -0
- data/test/gen_test_suite.rb +41 -0
- data/test/run_benchs.rb +58 -0
- data/test/run_tests.rb +22 -0
- data/test/test_args.rb +24 -0
- data/test/test_array.rb +22 -0
- data/test/test_case.rb +35 -0
- data/test/test_class.rb +55 -0
- data/test/test_eql.rb +9 -0
- data/test/test_exception.rb +61 -0
- data/test/test_expr.rb +12 -0
- data/test/test_hash.rb +29 -0
- data/test/test_hot_ruby.rb +146 -0
- data/test/test_if.rb +28 -0
- data/test/test_insertion_sort.rb +25 -0
- data/test/test_inspect.rb +10 -0
- data/test/test_lebewesen.rb +39 -0
- data/test/test_massign.rb +66 -0
- data/test/test_new.rb +12 -0
- data/test/test_range.rb +70 -0
- data/test/test_regexp.rb +22 -0
- data/test/test_send.rb +65 -0
- data/test/test_simple_output.rb +5 -0
- data/test/test_splat.rb +21 -0
- data/test/test_string.rb +51 -0
- data/test/test_test.rb +17 -0
- data/test/test_yield.rb +154 -0
- data/utils/js/Makefile +9 -0
- data/utils/js/RunScript.class +0 -0
- data/utils/js/RunScript.java +73 -0
- data/utils/js/js.jar +0 -0
- data/utils/js/run.sh +3 -0
- data/utils/jsc/Makefile +7 -0
- data/utils/jsc/README +3 -0
- data/utils/jsc/RunScript.c +93 -0
- data/utils/jsc/run.sh +15 -0
- data/utils/yuicompressor/README +1 -0
- data/utils/yuicompressor/yuicompressor-2.2.5.jar +0 -0
- metadata +157 -0
data/src/rubyjs.rb
ADDED
@@ -0,0 +1,474 @@
|
|
1
|
+
#
|
2
|
+
# Generate Javascript code.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2007 by Michael Neumann (mneumann@ntecs.de).
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
|
8
|
+
require 'rubyjs/compiler'
|
9
|
+
require 'rubyjs/model'
|
10
|
+
require 'set'
|
11
|
+
|
12
|
+
RUNTIME_MM = <<EOS
|
13
|
+
//
|
14
|
+
// Generates a new method_missing function
|
15
|
+
// for the given symbol +sym+.
|
16
|
+
//
|
17
|
+
var #<globalattr:mm_fun_cache> = {};
|
18
|
+
function #<globalattr:mm_fun>(sym)
|
19
|
+
{
|
20
|
+
if (!#<globalattr:mm_fun_cache>[sym])
|
21
|
+
{
|
22
|
+
var fn = function() {
|
23
|
+
return #<globalattr:call_method_missing>(this, arguments, sym);
|
24
|
+
};
|
25
|
+
fn.#<attr:_mm> = true;
|
26
|
+
#<globalattr:mm_fun_cache>[sym] = fn;
|
27
|
+
}
|
28
|
+
|
29
|
+
return #<globalattr:mm_fun_cache>[sym];
|
30
|
+
}
|
31
|
+
|
32
|
+
function #<globalattr:call_method_missing>(obj, args, sym)
|
33
|
+
{
|
34
|
+
var i, a;
|
35
|
+
a = [];
|
36
|
+
if (args.length == 0)
|
37
|
+
a.push(#<nil>);
|
38
|
+
else
|
39
|
+
a.push(args[0]);
|
40
|
+
|
41
|
+
a.push(#<globalattr:mm>[sym] || #<nil>);
|
42
|
+
|
43
|
+
for (i=1; i<args.length; i++)
|
44
|
+
a.push(args[i]);
|
45
|
+
|
46
|
+
var m = obj.#<m:method_missing>;
|
47
|
+
|
48
|
+
if (m)
|
49
|
+
return m.apply(obj, a);
|
50
|
+
else
|
51
|
+
throw "FATAL: method_missing missing";
|
52
|
+
}
|
53
|
+
|
54
|
+
//
|
55
|
+
// assign method_missing stubs
|
56
|
+
//
|
57
|
+
function #<globalattr:mm_assign>(c)
|
58
|
+
{
|
59
|
+
var i;
|
60
|
+
|
61
|
+
for (i in #<globalattr:mm>)
|
62
|
+
{
|
63
|
+
if (c.#<attr:object_constructor>.prototype[i]===undefined)
|
64
|
+
{
|
65
|
+
c.#<attr:object_constructor>.prototype[i] = #<globalattr:mm_fun>(i);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
if (c.#<attr:superclass> != #<nil>)
|
70
|
+
{
|
71
|
+
for (i in c.#<attr:superclass>)
|
72
|
+
{
|
73
|
+
if (c[i]===undefined)
|
74
|
+
{
|
75
|
+
c[i] = #<globalattr:mm_fun>(i);
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
EOS
|
81
|
+
|
82
|
+
RUNTIME_INIT = <<EOS
|
83
|
+
// declare nil
|
84
|
+
function NilClass() {}
|
85
|
+
|
86
|
+
// FIXME: remove
|
87
|
+
NilClass.prototype.toString = function() { return "nil"; };
|
88
|
+
#<nil> = new NilClass();
|
89
|
+
|
90
|
+
//
|
91
|
+
// define a null-function (used by HTTPRequest)
|
92
|
+
//
|
93
|
+
function #<globalattr:null_func>()
|
94
|
+
{
|
95
|
+
}
|
96
|
+
|
97
|
+
//
|
98
|
+
// r: return value
|
99
|
+
// s: scope (method scope)
|
100
|
+
//
|
101
|
+
function #<globalattr:iter_jump>(r,s)
|
102
|
+
{
|
103
|
+
this.#<attr:return_value> = r;
|
104
|
+
this.#<attr:scope> = s;
|
105
|
+
return this;
|
106
|
+
}
|
107
|
+
|
108
|
+
//
|
109
|
+
// Throw in Javascript is a statement.
|
110
|
+
//
|
111
|
+
// This function can be used to overcome
|
112
|
+
// that limitation.
|
113
|
+
//
|
114
|
+
function #<globalattr:throw_expr>(x) { throw(x); }
|
115
|
+
|
116
|
+
function #<globalattr:to_splat>(a)
|
117
|
+
{
|
118
|
+
// TODO
|
119
|
+
return a;
|
120
|
+
}
|
121
|
+
|
122
|
+
//
|
123
|
+
// helper function for multiple assignment in
|
124
|
+
// iterator parameters.
|
125
|
+
//
|
126
|
+
// undefined -> []
|
127
|
+
// 1 -> [1]
|
128
|
+
// [1] -> [[1]]
|
129
|
+
// [] -> [[]]
|
130
|
+
// [1,2] -> [1,2]
|
131
|
+
//
|
132
|
+
function #<globalattr:masgn_iter>(a)
|
133
|
+
{
|
134
|
+
if (a===undefined) return [];
|
135
|
+
if (a.constructor!=Array || a.length<2) return [a];
|
136
|
+
return a;
|
137
|
+
}
|
138
|
+
|
139
|
+
//
|
140
|
+
// Call the method in the superclass.
|
141
|
+
//
|
142
|
+
// As super is used quite rarely, we dont optimize for it.
|
143
|
+
//
|
144
|
+
// object, method, iterator, arguments
|
145
|
+
//
|
146
|
+
function #<globalattr:supercall>(o, m, i, a)
|
147
|
+
{
|
148
|
+
var r = o[m]; // method in current class
|
149
|
+
var c = o.#<attr:_class>.#<attr:superclass>;
|
150
|
+
while (r === c.#<attr:object_constructor>.prototype[m])
|
151
|
+
c = c.#<attr:superclass>;
|
152
|
+
return c.#<attr:object_constructor>.prototype[m].apply(o, [i].concat(a));
|
153
|
+
}
|
154
|
+
|
155
|
+
function #<globalattr:zsupercall>(o, m, a)
|
156
|
+
{
|
157
|
+
var r = o[m]; // method in current class
|
158
|
+
var c = o.#<attr:_class>.#<attr:superclass>;
|
159
|
+
while (r === c.#<attr:object_constructor>.prototype[m])
|
160
|
+
c = c.#<attr:superclass>;
|
161
|
+
return c.#<attr:object_constructor>.prototype[m].apply(o, a);
|
162
|
+
}
|
163
|
+
|
164
|
+
//
|
165
|
+
// Whether o.kind_of?(c)
|
166
|
+
//
|
167
|
+
function #<globalattr:kind_of>(o, c)
|
168
|
+
{
|
169
|
+
var k,i,m;
|
170
|
+
|
171
|
+
k = o.#<attr:_class>;
|
172
|
+
|
173
|
+
while (k != #<nil>)
|
174
|
+
{
|
175
|
+
if (k === c) return true;
|
176
|
+
|
177
|
+
// check included modules
|
178
|
+
m = k.#<attr:modules>;
|
179
|
+
for (i=0; i<m.length; i++)
|
180
|
+
{
|
181
|
+
if (m[i] === c) return true;
|
182
|
+
}
|
183
|
+
|
184
|
+
k = k.#<attr:superclass>;
|
185
|
+
}
|
186
|
+
|
187
|
+
return false;
|
188
|
+
}
|
189
|
+
|
190
|
+
function #<globalattr:rebuild_classes>(c)
|
191
|
+
{
|
192
|
+
for (var i=0; i<c.length; i++)
|
193
|
+
#<globalattr:rebuild_class>(c[i]);
|
194
|
+
}
|
195
|
+
|
196
|
+
function #<globalattr:rebuild_class>(c)
|
197
|
+
{
|
198
|
+
var k,i;
|
199
|
+
|
200
|
+
//
|
201
|
+
// include modules
|
202
|
+
//
|
203
|
+
// do that before, because when assigning instance methods of
|
204
|
+
// the super class, a check for === undefined prevents this method
|
205
|
+
// from being overwritten.
|
206
|
+
//
|
207
|
+
for (i=0; i<c.#<attr:modules>.length; i++)
|
208
|
+
{
|
209
|
+
for (k in c.#<attr:modules>[i].#<attr:object_constructor>.prototype)
|
210
|
+
{
|
211
|
+
if (c.#<attr:object_constructor>.prototype[k]===undefined)
|
212
|
+
{
|
213
|
+
c.#<attr:object_constructor>.prototype[k] = c.#<attr:modules>[i].#<attr:object_constructor>.prototype[k];
|
214
|
+
}
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
// instance methods
|
219
|
+
if (c.#<attr:superclass> != #<nil>)
|
220
|
+
{
|
221
|
+
for (k in c.#<attr:superclass>.#<attr:object_constructor>.prototype)
|
222
|
+
{
|
223
|
+
if (c.#<attr:object_constructor>.prototype[k]===undefined)
|
224
|
+
{
|
225
|
+
c.#<attr:object_constructor>.prototype[k] = c.#<attr:superclass>.#<attr:object_constructor>.prototype[k];
|
226
|
+
}
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
230
|
+
// inherit class methods from superclass
|
231
|
+
if (c.#<attr:superclass> != #<nil>)
|
232
|
+
{
|
233
|
+
for (k in c.#<attr:superclass>)
|
234
|
+
{
|
235
|
+
if (c[k]===undefined)
|
236
|
+
{
|
237
|
+
c[k] = c.#<attr:superclass>[k];
|
238
|
+
}
|
239
|
+
}
|
240
|
+
}
|
241
|
+
|
242
|
+
// set class for instanciated objects
|
243
|
+
c.#<attr:object_constructor>.prototype.#<attr:_class> = c;
|
244
|
+
}
|
245
|
+
|
246
|
+
function #<globalattr:def_class>(h)
|
247
|
+
{
|
248
|
+
var c,k,i;
|
249
|
+
c = h.#<attr:_class> || #<Class>.#<m:new>(#<nil>, h.#<attr:superclass>, h.#<attr:classname>, h.#<attr:object_constructor>);
|
250
|
+
|
251
|
+
if (h.#<attr:instance_methods>)
|
252
|
+
{
|
253
|
+
for (k in h.#<attr:instance_methods>)
|
254
|
+
{
|
255
|
+
c.#<attr:object_constructor>.prototype[k] = h.#<attr:instance_methods>[k];
|
256
|
+
}
|
257
|
+
}
|
258
|
+
|
259
|
+
if (h.#<attr:methods>)
|
260
|
+
{
|
261
|
+
for (k in h.#<attr:methods>) c[k] = h.#<attr:methods>[k];
|
262
|
+
}
|
263
|
+
|
264
|
+
if (h.#<attr:modules>)
|
265
|
+
{
|
266
|
+
for (i=0; i<h.#<attr:modules>.length; i++)
|
267
|
+
{
|
268
|
+
c.#<attr:modules>.push(h.#<attr:modules>[i]);
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
return c;
|
273
|
+
}
|
274
|
+
|
275
|
+
function #<globalattr:MetaClass>(#<_class>, #<superclass>, #<classname>, #<object_constructor>)
|
276
|
+
{
|
277
|
+
this.#<attr:superclass> = #<superclass>;
|
278
|
+
this.#<attr:classname> = #<classname>;
|
279
|
+
this.#<attr:object_constructor> = #<object_constructor>;
|
280
|
+
this.#<attr:modules> = [];
|
281
|
+
this.#<attr:_class> = #<_class>;
|
282
|
+
return this;
|
283
|
+
}
|
284
|
+
|
285
|
+
#<globalattr:MetaClass>.#<m:name> = function() { return "MetaClass"; };
|
286
|
+
#<globalattr:MetaClass>.#<m:class> = function() { return this; };
|
287
|
+
EOS
|
288
|
+
|
289
|
+
|
290
|
+
|
291
|
+
|
292
|
+
class CodeGenerator
|
293
|
+
def initialize
|
294
|
+
@world = Model.new
|
295
|
+
end
|
296
|
+
|
297
|
+
def def_Class
|
298
|
+
m = @world.models[RubyJS::Environment::Class]
|
299
|
+
|
300
|
+
str = ""
|
301
|
+
str << generate_class_declaration(
|
302
|
+
m,
|
303
|
+
assign=true,
|
304
|
+
_class=ipol(%[new #<globalattr:MetaClass>(#<globalattr:MetaClass>, #<nil>, "Class", #<globalattr:MetaClass>)]),
|
305
|
+
obj_cons=nil,
|
306
|
+
use_superclass=false,
|
307
|
+
use_modules=false)
|
308
|
+
|
309
|
+
str << @world.encode_globalattr('rebuild_class') + "(" + @world.encode_constant(m[:name]) + ");"
|
310
|
+
|
311
|
+
str
|
312
|
+
end
|
313
|
+
|
314
|
+
def encode(code)
|
315
|
+
return ipol(code)
|
316
|
+
end
|
317
|
+
|
318
|
+
def gen_mm_stubs
|
319
|
+
# Method name mapping
|
320
|
+
|
321
|
+
mm_stubs = ""
|
322
|
+
mm_stubs << "// method map\n"
|
323
|
+
mm_stubs << "var #<globalattr:mm> = {"
|
324
|
+
i = []
|
325
|
+
# Javascript name -> Ruby name
|
326
|
+
@world.all_method_names do |k,v|
|
327
|
+
i << "#{v.inspect}:#{k.inspect}"
|
328
|
+
end
|
329
|
+
mm_stubs << i.join(",")
|
330
|
+
mm_stubs << "};\n"
|
331
|
+
mm_stubs << "var #<globalattr:mm_reverse> = {};\n"
|
332
|
+
mm_stubs << "for (var i in #<globalattr:mm>) #<globalattr:mm_reverse>[#<globalattr:mm>[i]] = i;\n"
|
333
|
+
|
334
|
+
ipol(mm_stubs)
|
335
|
+
end
|
336
|
+
|
337
|
+
def generate
|
338
|
+
str = ""
|
339
|
+
|
340
|
+
#
|
341
|
+
# Code for Class
|
342
|
+
#
|
343
|
+
# Required at the beginning because all other classes are created as
|
344
|
+
# objects from Class using Class.new.
|
345
|
+
#
|
346
|
+
str << def_Class()
|
347
|
+
|
348
|
+
#
|
349
|
+
# Now define all other classes/modules
|
350
|
+
#
|
351
|
+
|
352
|
+
@world.iterate_all(Set.new) do |m|
|
353
|
+
|
354
|
+
#
|
355
|
+
# We have to add the modules for class Class here.
|
356
|
+
#
|
357
|
+
if m[:for] == RubyJS::Environment::Class
|
358
|
+
h = { "_class" => @world.encode_constant(m[:name]) }
|
359
|
+
b_modules(m, h)
|
360
|
+
str << b_def_class(h)
|
361
|
+
next
|
362
|
+
end
|
363
|
+
|
364
|
+
begin
|
365
|
+
obj_cons = m[:for].const_get(:OBJECT_CONSTRUCTOR__)
|
366
|
+
rescue
|
367
|
+
obj_cons = nil
|
368
|
+
end
|
369
|
+
|
370
|
+
str << generate_class_declaration(m, assign=true, _class=nil, obj_cons)
|
371
|
+
end
|
372
|
+
|
373
|
+
#
|
374
|
+
# Class is a subclass of Object
|
375
|
+
#
|
376
|
+
str << ipol(<<-EOS)
|
377
|
+
#<Class>.#<attr:superclass> = #<Object>;
|
378
|
+
EOS
|
379
|
+
|
380
|
+
#
|
381
|
+
# rebuild all classes and modules
|
382
|
+
#
|
383
|
+
klasses = []
|
384
|
+
@world.iterate_all(Set.new) do |m|
|
385
|
+
klasses << @world.encode_constant(m[:name])
|
386
|
+
end
|
387
|
+
str << ipol("var #<globalattr:klasses> = [#{klasses.join(",")}];\n" +
|
388
|
+
"#<globalattr:rebuild_classes>(#<globalattr:klasses>);\n")
|
389
|
+
|
390
|
+
unless $RUBYJS__OPTS.include?('NoMethodMissing')
|
391
|
+
str << ipol("for (var i=0; i<#<globalattr:klasses>.length; i++) #<globalattr:mm_assign>(#<globalattr:klasses>[i]);\n")
|
392
|
+
end
|
393
|
+
|
394
|
+
#
|
395
|
+
# prepend
|
396
|
+
#
|
397
|
+
|
398
|
+
str_prep = ""
|
399
|
+
|
400
|
+
# Code of runtime
|
401
|
+
str_prep << ipol(RUNTIME_INIT)
|
402
|
+
|
403
|
+
unless $RUBYJS__OPTS.include?('NoMethodMissing')
|
404
|
+
str_prep << ipol(RUNTIME_MM)
|
405
|
+
str_prep << gen_mm_stubs()
|
406
|
+
end
|
407
|
+
|
408
|
+
return str_prep + str
|
409
|
+
end
|
410
|
+
|
411
|
+
def b_methods(kind, model, h)
|
412
|
+
m = {}
|
413
|
+
model[kind].each_pair do |name, pt|
|
414
|
+
@world.with_local do
|
415
|
+
m[name] = MethodCompiler.new(@world, @world.encode_method(name)).compile_method(pt)
|
416
|
+
end
|
417
|
+
end
|
418
|
+
unless m.empty?
|
419
|
+
h[kind.to_s] = "{" + m.map {|name, fn|
|
420
|
+
if $RUBYJS__OPTS.include?('PrettyPrint')
|
421
|
+
@world.encode_method(name) + ":\n" +
|
422
|
+
%[/* #{ model[:name] }#{kind.to_s == "methods" ? "." : "#"}#{ name } */\n#{fn}\n\n]
|
423
|
+
else
|
424
|
+
@world.encode_method(name) + ": #{fn}"
|
425
|
+
end
|
426
|
+
}.join(",") + "}"
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
def b_modules(model, h)
|
431
|
+
h["modules"] = "[" + model[:modules].map {|m|
|
432
|
+
@world.encode_constant(@world.namify(m))
|
433
|
+
}.join(",") + "]"
|
434
|
+
end
|
435
|
+
|
436
|
+
def b_def_class(h)
|
437
|
+
@world.encode_globalattr('def_class') + "({" +
|
438
|
+
h.map {|k, v| @world.encode_attr(k) + ": #{v}"}.join(",") + "});"
|
439
|
+
end
|
440
|
+
|
441
|
+
def generate_class_declaration(model, assign=true, _class=nil, object_constructor=nil, use_superclass=true, use_modules=true)
|
442
|
+
h = {}
|
443
|
+
h["_class"] = _class if _class
|
444
|
+
h["object_constructor"] = object_constructor if object_constructor
|
445
|
+
|
446
|
+
b_methods(:instance_methods, model, h)
|
447
|
+
b_methods(:methods, model, h)
|
448
|
+
|
449
|
+
h["classname"] = model[:name].inspect
|
450
|
+
|
451
|
+
if model[:superclass] and use_superclass
|
452
|
+
h["superclass"] = @world.old_encode_constant(@world.namify(model[:superclass]))
|
453
|
+
else
|
454
|
+
# we need this as def_class expects a nil value if no superclass
|
455
|
+
# is given!
|
456
|
+
h["superclass"] = @world.encode_nil
|
457
|
+
end
|
458
|
+
|
459
|
+
b_modules(model, h) if use_modules
|
460
|
+
|
461
|
+
str = ""
|
462
|
+
str << @world.encode_constant(model[:name]) + " = " if assign
|
463
|
+
str << b_def_class(h)
|
464
|
+
|
465
|
+
return str
|
466
|
+
end
|
467
|
+
|
468
|
+
private
|
469
|
+
|
470
|
+
# iterpolate strings
|
471
|
+
def ipol(str)
|
472
|
+
@world.interpolate(str)
|
473
|
+
end
|
474
|
+
end
|