rubyjs 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +128 -0
- data/Rakefile +9 -0
- data/bin/rubyjs +140 -0
- data/examples/ex1/Rakefile +7 -0
- data/examples/ex1/ex1.js +771 -0
- data/examples/ex1/ex1.rb +42 -0
- data/examples/ex1/index.html +7 -0
- data/examples/hw/Rakefile +9 -0
- data/examples/hw/hw.js +635 -0
- data/examples/hw/hw.rb +7 -0
- data/examples/hw/index.html +7 -0
- data/patches/parse_tree.rb.diff +34 -0
- data/rubyjs.gemspec +24 -0
- data/src/rubyjs.rb +4 -0
- data/src/rubyjs/code_generator.rb +474 -0
- data/src/rubyjs/compiler.rb +2007 -0
- data/src/rubyjs/debug_name_generator.rb +75 -0
- data/src/rubyjs/encoder.rb +171 -0
- data/src/rubyjs/eval_into.rb +59 -0
- data/src/rubyjs/lib/core.rb +1008 -0
- data/src/rubyjs/lib/json.rb +101 -0
- data/src/rubyjs/model.rb +287 -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_call_conv1.js +16 -0
- data/test/benchmark/bm_call_conv2.js +14 -0
- data/test/benchmark/bm_var_acc1.js +13 -0
- data/test/benchmark/bm_var_acc2.js +11 -0
- data/test/benchmark/bm_vm1_block.js +15 -0
- data/test/benchmark/bm_vm1_block.rb +15 -0
- data/test/benchmark/bm_vm1_const.js +13 -0
- data/test/benchmark/bm_vm1_const.rb +13 -0
- data/test/benchmark/bm_vm1_ensure.js +17 -0
- data/test/benchmark/bm_vm1_ensure.rb +15 -0
- data/test/benchmark/common.js +4 -0
- data/test/benchmark/common.rb +5 -0
- data/test/benchmark/params.yaml +7 -0
- data/test/browser.test.html +4059 -0
- data/test/browser.test.js +3225 -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 +26 -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_if.rb +28 -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 +53 -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_yield.rb +152 -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
- data/vendor/ParseTree-1.7.1-patched/History.txt +217 -0
- data/vendor/ParseTree-1.7.1-patched/Manifest.txt +22 -0
- data/vendor/ParseTree-1.7.1-patched/README.txt +110 -0
- data/vendor/ParseTree-1.7.1-patched/Rakefile +41 -0
- data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_abc +89 -0
- data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_audit +28 -0
- data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_deps +62 -0
- data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_show +49 -0
- data/vendor/ParseTree-1.7.1-patched/demo/printer.rb +20 -0
- data/vendor/ParseTree-1.7.1-patched/lib/composite_sexp_processor.rb +49 -0
- data/vendor/ParseTree-1.7.1-patched/lib/parse_tree.rb +1013 -0
- data/vendor/ParseTree-1.7.1-patched/lib/sexp.rb +235 -0
- data/vendor/ParseTree-1.7.1-patched/lib/sexp_processor.rb +330 -0
- data/vendor/ParseTree-1.7.1-patched/lib/unique.rb +15 -0
- data/vendor/ParseTree-1.7.1-patched/test/pt_testcase.rb +1221 -0
- data/vendor/ParseTree-1.7.1-patched/test/something.rb +53 -0
- data/vendor/ParseTree-1.7.1-patched/test/test_all.rb +13 -0
- data/vendor/ParseTree-1.7.1-patched/test/test_composite_sexp_processor.rb +69 -0
- data/vendor/ParseTree-1.7.1-patched/test/test_parse_tree.rb +216 -0
- data/vendor/ParseTree-1.7.1-patched/test/test_sexp.rb +291 -0
- data/vendor/ParseTree-1.7.1-patched/test/test_sexp_processor.rb +244 -0
- data/vendor/ParseTree-1.7.1-patched/validate.sh +31 -0
- data/vendor/ParseTree-1.7.1/History.txt +217 -0
- data/vendor/ParseTree-1.7.1/Manifest.txt +22 -0
- data/vendor/ParseTree-1.7.1/README.txt +110 -0
- data/vendor/ParseTree-1.7.1/Rakefile +41 -0
- data/vendor/ParseTree-1.7.1/bin/parse_tree_abc +89 -0
- data/vendor/ParseTree-1.7.1/bin/parse_tree_audit +28 -0
- data/vendor/ParseTree-1.7.1/bin/parse_tree_deps +62 -0
- data/vendor/ParseTree-1.7.1/bin/parse_tree_show +49 -0
- data/vendor/ParseTree-1.7.1/demo/printer.rb +20 -0
- data/vendor/ParseTree-1.7.1/lib/composite_sexp_processor.rb +49 -0
- data/vendor/ParseTree-1.7.1/lib/parse_tree.rb +1004 -0
- data/vendor/ParseTree-1.7.1/lib/sexp.rb +235 -0
- data/vendor/ParseTree-1.7.1/lib/sexp_processor.rb +330 -0
- data/vendor/ParseTree-1.7.1/lib/unique.rb +15 -0
- data/vendor/ParseTree-1.7.1/test/pt_testcase.rb +1221 -0
- data/vendor/ParseTree-1.7.1/test/something.rb +53 -0
- data/vendor/ParseTree-1.7.1/test/test_all.rb +13 -0
- data/vendor/ParseTree-1.7.1/test/test_composite_sexp_processor.rb +69 -0
- data/vendor/ParseTree-1.7.1/test/test_parse_tree.rb +216 -0
- data/vendor/ParseTree-1.7.1/test/test_sexp.rb +291 -0
- data/vendor/ParseTree-1.7.1/test/test_sexp_processor.rb +244 -0
- data/vendor/ParseTree-1.7.1/validate.sh +31 -0
- metadata +230 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#
|
|
2
|
+
# JSON loading/dumping
|
|
3
|
+
#
|
|
4
|
+
# Parser code taken from http://www.json.org/json.js
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
class JSON
|
|
8
|
+
class SyntaxError < RuntimeError; end
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# Parsing happens in three stages. In the first stage, we run the text against
|
|
12
|
+
# a regular expression which looks for non-JSON characters. We are especially
|
|
13
|
+
# concerned with '()' and 'new' because they can cause invocation, and '='
|
|
14
|
+
# because it can cause mutation. But just to be safe, we will reject all
|
|
15
|
+
# unexpected characters.
|
|
16
|
+
#
|
|
17
|
+
# We split the first stage into 4 regexp operations in order to work around
|
|
18
|
+
# crippling deficiencies in IE's and Safari's regexp engines. First we replace
|
|
19
|
+
# all backslash pairs with '@' (a non-JSON character). Second, we replace all
|
|
20
|
+
# simple value tokens with ']' characters. Third, we delete all open brackets
|
|
21
|
+
# that follow a colon or comma or that begin the text. Finally, we look to see
|
|
22
|
+
# that the remaining characters are only whitespace or ']' or ',' or ':' or '{'
|
|
23
|
+
# or '}'. If that is so, then the text is safe for eval.
|
|
24
|
+
#
|
|
25
|
+
# In the second stage we use the eval function to compile the text into a
|
|
26
|
+
# JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
|
27
|
+
# in JavaScript: it can begin a block or an object literal. We wrap the text
|
|
28
|
+
# in parens to eliminate the ambiguity.
|
|
29
|
+
#
|
|
30
|
+
def self._parse(str)
|
|
31
|
+
RubyJS::inline <<-'endjs'
|
|
32
|
+
if (/^[\],:{}\s]*$/.test(#<str>.replace(/\\./g, '@').
|
|
33
|
+
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']').
|
|
34
|
+
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
|
35
|
+
return eval('(' + #<str> + ')');
|
|
36
|
+
}
|
|
37
|
+
endjs
|
|
38
|
+
|
|
39
|
+
raise SyntaxError, str
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.load(str)
|
|
43
|
+
obj = _parse(str)
|
|
44
|
+
`
|
|
45
|
+
var conv = function(obj) {
|
|
46
|
+
if (obj==null) return #<nil>;
|
|
47
|
+
else if (obj instanceof Array) {
|
|
48
|
+
for (var i=0; i<obj.length; i++) obj[i] = conv(obj[i]);
|
|
49
|
+
}
|
|
50
|
+
else if (typeof(obj) == 'object') {
|
|
51
|
+
var nobj = #<Hash>.#<m:new>();
|
|
52
|
+
for (var i in obj) {
|
|
53
|
+
nobj.#<m:[]=>(#<nil>, conv(i), conv(obj[i]));
|
|
54
|
+
}
|
|
55
|
+
return nobj;
|
|
56
|
+
}
|
|
57
|
+
return obj;
|
|
58
|
+
};
|
|
59
|
+
return conv(#<obj>);
|
|
60
|
+
`
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.dump(obj)
|
|
64
|
+
obj.to_json
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class Object
|
|
69
|
+
def to_json; raise end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class Boolean
|
|
73
|
+
alias to_json to_s
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class NilClass
|
|
77
|
+
def to_json; "null" end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class String
|
|
81
|
+
alias to_json inspect # FIXME?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class Number
|
|
85
|
+
alias to_json to_s
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
class Array
|
|
89
|
+
def to_json
|
|
90
|
+
map {|a| a.to_json}.join(",")
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class Hash
|
|
95
|
+
def to_json
|
|
96
|
+
str = "{"
|
|
97
|
+
str += map {|k, v| (k.to_json + ":" + v.to_json) }.join(",")
|
|
98
|
+
str += "}"
|
|
99
|
+
str
|
|
100
|
+
end
|
|
101
|
+
end
|
data/src/rubyjs/model.rb
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Extract the class/module hierarchy and the methods.
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2007 by Michael Neumann (mneumann@ntecs.de).
|
|
5
|
+
# All rights reserved.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
require 'parse_tree'
|
|
9
|
+
require 'sexp_processor'
|
|
10
|
+
require 'enumerator'
|
|
11
|
+
require 'rubyjs/encoder'
|
|
12
|
+
require 'set'
|
|
13
|
+
|
|
14
|
+
class MethodExtractor < SexpProcessor
|
|
15
|
+
attr_accessor :instance_methods, :methods
|
|
16
|
+
|
|
17
|
+
def initialize
|
|
18
|
+
super()
|
|
19
|
+
|
|
20
|
+
self.strict = false
|
|
21
|
+
self.auto_shift_type = false
|
|
22
|
+
self.require_empty = false
|
|
23
|
+
|
|
24
|
+
@instance_methods = {}
|
|
25
|
+
@methods = {}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def process_defn(exp)
|
|
29
|
+
defn, name, code = *exp
|
|
30
|
+
name = name.to_s
|
|
31
|
+
if name =~ /^self\.(.*)$/
|
|
32
|
+
@methods[$1] = exp
|
|
33
|
+
else
|
|
34
|
+
@instance_methods[name] = exp
|
|
35
|
+
end
|
|
36
|
+
return s()
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class Model < Encoder
|
|
41
|
+
SCOPE_R = /^RubyJS::Environment::(.*)$/
|
|
42
|
+
|
|
43
|
+
attr_accessor :models
|
|
44
|
+
attr_accessor :current_model
|
|
45
|
+
|
|
46
|
+
attr_reader :method_calls
|
|
47
|
+
|
|
48
|
+
def initialize
|
|
49
|
+
super()
|
|
50
|
+
|
|
51
|
+
#
|
|
52
|
+
# record all (potential) names of all method calls
|
|
53
|
+
#
|
|
54
|
+
@method_calls = Set.new
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@models = {}
|
|
58
|
+
|
|
59
|
+
# all modules and classes (a Class is_a Module)
|
|
60
|
+
ObjectSpace.each_object {|o|
|
|
61
|
+
@models[o] = model_for(o) if o.is_a?(::Module) && o.name =~ SCOPE_R
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def add_method_call(name)
|
|
66
|
+
@method_calls.add(name)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def iterate_all(seen, &block)
|
|
70
|
+
@models.each_value do |v|
|
|
71
|
+
iterate_rec(v, seen, &block)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def iterate_rec(model, seen, &block)
|
|
76
|
+
return if seen.include?(model[:for])
|
|
77
|
+
iterate_rec(@models[model[:superclass]], seen, &block) if model[:superclass]
|
|
78
|
+
|
|
79
|
+
model[:modules].each do |m|
|
|
80
|
+
iterate_rec(@models[m], seen, &block)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
with_current_model(model) do
|
|
84
|
+
block.call(model)
|
|
85
|
+
end
|
|
86
|
+
seen.add(model[:for])
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
alias old_encode_constant encode_constant
|
|
90
|
+
|
|
91
|
+
def encode_constant(name)
|
|
92
|
+
if @current_model
|
|
93
|
+
lookup_constant(name)
|
|
94
|
+
else
|
|
95
|
+
old_encode_constant(name)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
#
|
|
100
|
+
# Compile time constant lookup.
|
|
101
|
+
#
|
|
102
|
+
# Lookup rules (like Ruby 1.9+):
|
|
103
|
+
#
|
|
104
|
+
# 1. Current class
|
|
105
|
+
# 2. Super classes except object
|
|
106
|
+
# 3. lexically enclosing modules/classes
|
|
107
|
+
# 4. Object
|
|
108
|
+
#
|
|
109
|
+
def lookup_constant(name)
|
|
110
|
+
model = @current_model
|
|
111
|
+
prefix, *path = name.split("::")
|
|
112
|
+
|
|
113
|
+
start_lookup_at = nil
|
|
114
|
+
done = false
|
|
115
|
+
|
|
116
|
+
if prefix.empty?
|
|
117
|
+
# e.g. "::A"
|
|
118
|
+
start_lookup_at = RubyJS::Environment
|
|
119
|
+
done = true
|
|
120
|
+
else
|
|
121
|
+
|
|
122
|
+
# 1. Current class
|
|
123
|
+
if model[:for].constants.include?(prefix)
|
|
124
|
+
start_lookup_at = model[:for].const_get(prefix)
|
|
125
|
+
done = true
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# 2. Super classes except object
|
|
129
|
+
unless done
|
|
130
|
+
m = model
|
|
131
|
+
loop do
|
|
132
|
+
if m[:superclass] and m[:superclass] != RubyJS::Environment::Object
|
|
133
|
+
if m[:superclass].constants.include?(prefix)
|
|
134
|
+
start_lookup_at = m[:superclass].const_get(prefix)
|
|
135
|
+
done = true
|
|
136
|
+
break
|
|
137
|
+
else
|
|
138
|
+
m = @models[m[:superclass]]
|
|
139
|
+
end
|
|
140
|
+
else
|
|
141
|
+
break
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# 3. lexically enclosing modules/classes
|
|
147
|
+
# FIXME
|
|
148
|
+
unless done
|
|
149
|
+
arr = model[:name].split("::")
|
|
150
|
+
loop do
|
|
151
|
+
arr.pop
|
|
152
|
+
|
|
153
|
+
begin
|
|
154
|
+
start_lookup_at = eval((["RubyJS", "Environment"] + arr + [prefix]).join("::"))
|
|
155
|
+
done = true
|
|
156
|
+
break
|
|
157
|
+
rescue NameError
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
break if arr.empty?
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# 4. Object
|
|
165
|
+
unless done
|
|
166
|
+
begin
|
|
167
|
+
start_lookup_at = RubyJS::Environment::Object.const_get(prefix)
|
|
168
|
+
done = true
|
|
169
|
+
rescue NameError
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
unless done
|
|
176
|
+
raise "failed to lookup constant prefix #{prefix}"
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
#
|
|
180
|
+
# follow the whole path, e.g. A::B::C
|
|
181
|
+
#
|
|
182
|
+
value = start_lookup_at
|
|
183
|
+
path.each do |piece|
|
|
184
|
+
value = value.const_get(piece)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
if value.is_a?(::Class) or value.is_a?(::Module)
|
|
188
|
+
# A class or module
|
|
189
|
+
|
|
190
|
+
if model = @models[value]
|
|
191
|
+
return old_encode_constant(model[:name])
|
|
192
|
+
else
|
|
193
|
+
raise("unrecognized class/module referenced by constant")
|
|
194
|
+
end
|
|
195
|
+
else
|
|
196
|
+
# A value
|
|
197
|
+
if value.is_a?(Fixnum)
|
|
198
|
+
# If it is the receiver of a method call, we have to surround it
|
|
199
|
+
# with parens, e.g. (1).
|
|
200
|
+
# As we can't easily decide whether it's a receiver of a method
|
|
201
|
+
# call, we simply surround every constant Fixnum with parens.
|
|
202
|
+
return "(" + value.inspect + ")"
|
|
203
|
+
elsif value.is_a?(String)
|
|
204
|
+
# FIXME: Generate a reference instead?
|
|
205
|
+
return value.inspect
|
|
206
|
+
else
|
|
207
|
+
raise
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def namify(klass)
|
|
213
|
+
name = klass.name
|
|
214
|
+
if name =~ SCOPE_R
|
|
215
|
+
name = $1
|
|
216
|
+
else
|
|
217
|
+
raise "must be scoped inside RubyJS module"
|
|
218
|
+
end
|
|
219
|
+
return name
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def with_current_model(model)
|
|
223
|
+
old_current_model = @current_model
|
|
224
|
+
@current_model = model
|
|
225
|
+
begin
|
|
226
|
+
yield
|
|
227
|
+
ensure
|
|
228
|
+
@current_model = old_current_model
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def model_for(klass)
|
|
233
|
+
name = namify(klass)
|
|
234
|
+
|
|
235
|
+
me = MethodExtractor.new
|
|
236
|
+
me.process(ParseTree.new.parse_tree(klass))
|
|
237
|
+
|
|
238
|
+
if klass.is_a?(::Class)
|
|
239
|
+
a = klass.ancestors
|
|
240
|
+
a = a[0...(a.index(::Object))]
|
|
241
|
+
|
|
242
|
+
s = klass.superclass
|
|
243
|
+
s = nil if s == ::Object
|
|
244
|
+
|
|
245
|
+
# remove klass from the ancestor chain
|
|
246
|
+
a = a[1..-1] if a[0] == klass
|
|
247
|
+
|
|
248
|
+
# a now contains the included modules
|
|
249
|
+
a = a[0...(a.index(s))] if s
|
|
250
|
+
|
|
251
|
+
if klass == RubyJS::Environment::Object
|
|
252
|
+
raise unless s.nil?
|
|
253
|
+
s = nil
|
|
254
|
+
else
|
|
255
|
+
if s.nil?
|
|
256
|
+
s = RubyJS::Environment::Object
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
:for => klass,
|
|
262
|
+
:modules => a,
|
|
263
|
+
:superclass => s,
|
|
264
|
+
:is_a => :class,
|
|
265
|
+
:name => name,
|
|
266
|
+
:instance_methods => me.instance_methods,
|
|
267
|
+
:methods => me.methods
|
|
268
|
+
}
|
|
269
|
+
elsif klass.is_a?(::Module)
|
|
270
|
+
a = klass.ancestors
|
|
271
|
+
|
|
272
|
+
# remove klass from the ancestor chain
|
|
273
|
+
a = a[1..-1] if a[0] == klass
|
|
274
|
+
|
|
275
|
+
return {
|
|
276
|
+
:for => klass,
|
|
277
|
+
:modules => a,
|
|
278
|
+
:is_a => :module,
|
|
279
|
+
:name => name,
|
|
280
|
+
:instance_methods => me.instance_methods,
|
|
281
|
+
:methods => me.methods
|
|
282
|
+
}
|
|
283
|
+
else
|
|
284
|
+
raise
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Generate unique names from a (custom) alphabet.
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2007 by Michael Neumann (mneumann@ntecs.de).
|
|
5
|
+
# All rights reserved.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
class NameGenerator
|
|
9
|
+
|
|
10
|
+
DEFAULT_ALPHABET = ('a' .. 'z').to_a + ('A' .. 'Z').to_a + ('0' .. '9').to_a + ['_', '$']
|
|
11
|
+
RESERVED_WORDS = %w(this self new break continue if then else while true false null undefined function document window)
|
|
12
|
+
|
|
13
|
+
def initialize(alphabet=DEFAULT_ALPHABET, reserved_words=RESERVED_WORDS)
|
|
14
|
+
@alphabet = alphabet
|
|
15
|
+
@reserved_words = reserved_words
|
|
16
|
+
@digits = [0]
|
|
17
|
+
@cache = {}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# We generate names using a g-adic development (where g=alphabet.size)
|
|
22
|
+
#
|
|
23
|
+
# The least significant digit is the first. If you think of it as a
|
|
24
|
+
# bit-string, then bit 0 would be @digits[0].
|
|
25
|
+
#
|
|
26
|
+
# In each call to next we try to increase the least significant digit.
|
|
27
|
+
# If it overflows, then we reset it to zero and increase the next digit.
|
|
28
|
+
# This continues up to the most significant digit. If this overflows,
|
|
29
|
+
# we introduce a new most significant digit and set this to "zero".
|
|
30
|
+
#
|
|
31
|
+
|
|
32
|
+
def fresh
|
|
33
|
+
loop do
|
|
34
|
+
value = @digits.reverse.map {|d| @alphabet[d] }.join("")
|
|
35
|
+
sz = @alphabet.size
|
|
36
|
+
|
|
37
|
+
i = 0
|
|
38
|
+
loop do
|
|
39
|
+
# increase or initialize with 0
|
|
40
|
+
@digits[i] = @digits[i] ? @digits[i]+1 : 0
|
|
41
|
+
|
|
42
|
+
if @digits[i] >= sz
|
|
43
|
+
@digits[i] = 0
|
|
44
|
+
i += 1
|
|
45
|
+
else
|
|
46
|
+
break
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
return value unless @reserved_words.include?(value)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#
|
|
55
|
+
# Generate a name for +name+. Return the same name for the same
|
|
56
|
+
# +name+.
|
|
57
|
+
#
|
|
58
|
+
|
|
59
|
+
def get(name)
|
|
60
|
+
raise unless name.is_a?(String)
|
|
61
|
+
@cache[name] ||= self.fresh
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def reverse_lookup(encoded_name)
|
|
65
|
+
@cache.index(encoded_name)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def cache
|
|
69
|
+
@cache
|
|
70
|
+
end
|
|
71
|
+
end
|