AmberVM 0.0.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. data/README +38 -0
  2. data/bin/ambervm +278 -0
  3. data/lib/amber/acts_as_rvm_type.rb +157 -0
  4. data/lib/amber/classes/association.rb +36 -0
  5. data/lib/amber/classes/block.rb +52 -0
  6. data/lib/amber/classes/boolean.rb +40 -0
  7. data/lib/amber/classes/class.rb +50 -0
  8. data/lib/amber/classes/error.rb +22 -0
  9. data/lib/amber/classes/list.rb +96 -0
  10. data/lib/amber/classes/null.rb +35 -0
  11. data/lib/amber/classes/number.rb +95 -0
  12. data/lib/amber/classes/object.rb +56 -0
  13. data/lib/amber/classes/string.rb +79 -0
  14. data/lib/amber/classes.rb +113 -0
  15. data/lib/amber/environment.rb +251 -0
  16. data/lib/amber/fukubukuro/ecma_core.rb +409 -0
  17. data/lib/amber/fukubukuro.rb +866 -0
  18. data/lib/amber/functions/all.rb +3 -0
  19. data/lib/amber/functions/array/append.rb +50 -0
  20. data/lib/amber/functions/array/at.rb +50 -0
  21. data/lib/amber/functions/array/set_at.rb +50 -0
  22. data/lib/amber/functions/array.rb +30 -0
  23. data/lib/amber/functions/association/assoc_get.rb +55 -0
  24. data/lib/amber/functions/association/assoc_set.rb +56 -0
  25. data/lib/amber/functions/bitwise/bitwise_and.rb +41 -0
  26. data/lib/amber/functions/bitwise/bitwise_not.rb +41 -0
  27. data/lib/amber/functions/bitwise/bitwise_or.rb +41 -0
  28. data/lib/amber/functions/bitwise/bitwise_xor.rb +41 -0
  29. data/lib/amber/functions/bitwise.rb +3 -0
  30. data/lib/amber/functions/collection/get.rb +66 -0
  31. data/lib/amber/functions/collection/set.rb +67 -0
  32. data/lib/amber/functions/collection/size.rb +54 -0
  33. data/lib/amber/functions/general/cmp.rb +43 -0
  34. data/lib/amber/functions/general/eq.rb +45 -0
  35. data/lib/amber/functions/general/gt.rb +45 -0
  36. data/lib/amber/functions/general/gte.rb +45 -0
  37. data/lib/amber/functions/general/lt.rb +45 -0
  38. data/lib/amber/functions/general/lte.rb +45 -0
  39. data/lib/amber/functions/general/neq.rb +45 -0
  40. data/lib/amber/functions/general/type.rb +43 -0
  41. data/lib/amber/functions/general.rb +3 -0
  42. data/lib/amber/functions/io/print.rb +45 -0
  43. data/lib/amber/functions/io.rb +3 -0
  44. data/lib/amber/functions/list/align.rb +73 -0
  45. data/lib/amber/functions/list/join.rb +45 -0
  46. data/lib/amber/functions/list/map.rb +58 -0
  47. data/lib/amber/functions/list/split.rb +55 -0
  48. data/lib/amber/functions/list.rb +3 -0
  49. data/lib/amber/functions/logic/and.rb +55 -0
  50. data/lib/amber/functions/logic/not.rb +40 -0
  51. data/lib/amber/functions/logic/or.rb +50 -0
  52. data/lib/amber/functions/logic.rb +3 -0
  53. data/lib/amber/functions/math/abs.rb +39 -0
  54. data/lib/amber/functions/math/acos.rb +39 -0
  55. data/lib/amber/functions/math/add.rb +40 -0
  56. data/lib/amber/functions/math/asin.rb +39 -0
  57. data/lib/amber/functions/math/atan.rb +39 -0
  58. data/lib/amber/functions/math/ceil.rb +39 -0
  59. data/lib/amber/functions/math/cos.rb +39 -0
  60. data/lib/amber/functions/math/dec.rb +39 -0
  61. data/lib/amber/functions/math/div.rb +44 -0
  62. data/lib/amber/functions/math/exp.rb +39 -0
  63. data/lib/amber/functions/math/floor.rb +39 -0
  64. data/lib/amber/functions/math/inc.rb +39 -0
  65. data/lib/amber/functions/math/log.rb +39 -0
  66. data/lib/amber/functions/math/mod.rb +41 -0
  67. data/lib/amber/functions/math/mul.rb +43 -0
  68. data/lib/amber/functions/math/neg.rb +43 -0
  69. data/lib/amber/functions/math/power.rb +43 -0
  70. data/lib/amber/functions/math/rand.rb +36 -0
  71. data/lib/amber/functions/math/round.rb +39 -0
  72. data/lib/amber/functions/math/shl.rb +41 -0
  73. data/lib/amber/functions/math/shr.rb +41 -0
  74. data/lib/amber/functions/math/sin.rb +39 -0
  75. data/lib/amber/functions/math/sub.rb +43 -0
  76. data/lib/amber/functions/math/tan.rb +39 -0
  77. data/lib/amber/functions/math.rb +3 -0
  78. data/lib/amber/functions/objects/send.rb +22 -0
  79. data/lib/amber/functions/rails/print.rb +44 -0
  80. data/lib/amber/functions/rails.rb +3 -0
  81. data/lib/amber/functions/string/ansi.rb +24 -0
  82. data/lib/amber/functions/string/capstr.rb +23 -0
  83. data/lib/amber/functions/string/center.rb +25 -0
  84. data/lib/amber/functions/string/chr.rb +16 -0
  85. data/lib/amber/functions/string/ljust.rb +26 -0
  86. data/lib/amber/functions/string/regmatch.rb +34 -0
  87. data/lib/amber/functions/string/rjust.rb +26 -0
  88. data/lib/amber/functions/string.rb +3 -0
  89. data/lib/amber/functions.rb +103 -0
  90. data/lib/amber/interpreter.rb +1380 -0
  91. data/lib/amber/languages/brainfuck.rb +153 -0
  92. data/lib/amber/languages/ecma/compiler.rb +1661 -0
  93. data/lib/amber/languages/ecma/core-math.js +67 -0
  94. data/lib/amber/languages/ecma/core-objects.js +57 -0
  95. data/lib/amber/languages/ecma.rb +9 -0
  96. data/lib/amber/languages/ecma_fuku/compiler.rb +1622 -0
  97. data/lib/amber/languages/ecma_fuku/core-math.js +67 -0
  98. data/lib/amber/languages/ecma_fuku/core-objects.js +56 -0
  99. data/lib/amber/languages/ecma_fuku.rb +13 -0
  100. data/lib/amber/languages/math/compiler.rb +70 -0
  101. data/lib/amber/languages/math/tokenizer.rb +69 -0
  102. data/lib/amber/languages/math/tree.rb +110 -0
  103. data/lib/amber/languages/math.rb +26 -0
  104. data/lib/amber/languages.rb +99 -0
  105. data/lib/amber/library.rb +79 -0
  106. data/lib/amber/optimisation.rb +299 -0
  107. data/lib/amber/plugin.rb +337 -0
  108. data/lib/amber/rails.rb +90 -0
  109. data/lib/amber.rb +106 -0
  110. data/spec/amber/class_spec.rb +27 -0
  111. data/spec/amber/enviroment_spec.rb +61 -0
  112. data/spec/amber/function_spec.rb +25 -0
  113. data/spec/amber/functions/association/assoc_get_spec.rb +41 -0
  114. data/spec/amber/functions/association/assoc_set_spec.rb +43 -0
  115. data/spec/amber/functions/collection/get_spec.rb +12 -0
  116. data/spec/amber/functions/collection/set_spec.rb +10 -0
  117. data/spec/amber/functions/collection/size_spec.rb +10 -0
  118. data/spec/amber/functions/list/split_spec.rb +47 -0
  119. data/spec/amber/functions/string/ansi_spec.rb +44 -0
  120. data/spec/amber/functions/string/capstr_spec.rb +42 -0
  121. data/spec/amber/functions/string/center_spec.rb +49 -0
  122. data/spec/amber/functions/string/ljust_spec.rb +49 -0
  123. data/spec/amber/functions/string/regmatch_spec.rb +52 -0
  124. data/spec/amber/functions/string/rjust_spec.rb +49 -0
  125. data/spec/amber/interpreter/assignment_spec.rb +22 -0
  126. data/spec/amber/interpreter/condition_spec.rb +103 -0
  127. data/spec/amber/interpreter/constant_spec.rb +31 -0
  128. data/spec/amber/interpreter/core_call_spec.rb +72 -0
  129. data/spec/amber/interpreter/interpreter_spec.rb +11 -0
  130. data/spec/amber/interpreter/parameter_spec.rb +24 -0
  131. data/spec/amber/interpreter/sequence_spec.rb +47 -0
  132. data/spec/amber/interpreter/variable_spec.rb +24 -0
  133. data/spec/amber/plugin_spec.rb +10 -0
  134. data/spec/classes/atom/association_spec.rb +39 -0
  135. data/spec/classes/atom/block_spec.rb +25 -0
  136. data/spec/classes/atom/boolean_spec.rb +67 -0
  137. data/spec/classes/atom/error_spec.rb +43 -0
  138. data/spec/classes/atom/list_spec.rb +68 -0
  139. data/spec/classes/atom/number_spec.rb +132 -0
  140. data/spec/classes/atom/string_spec.rb +175 -0
  141. data/spec/languages/ecma/ecma_array_spec.rb +79 -0
  142. data/spec/languages/ecma/ecma_closure_spec.rb +38 -0
  143. data/spec/languages/ecma/ecma_literals_spec.rb +71 -0
  144. data/spec/languages/ecma/ecma_objects_spec.rb +165 -0
  145. data/spec/languages/ecma/ecma_old_spec.rb +540 -0
  146. data/spec/languages/ecma/ecma_spec.rb +64 -0
  147. data/spec/languages/ecma_fuku/ecma_array_spec.rb +61 -0
  148. data/spec/languages/ecma_fuku/ecma_closure_spec.rb +33 -0
  149. data/spec/languages/ecma_fuku/ecma_function_spec.rb +84 -0
  150. data/spec/languages/ecma_fuku/ecma_literals_spec.rb +55 -0
  151. data/spec/languages/ecma_fuku/ecma_objects_spec.rb +133 -0
  152. data/spec/languages/ecma_fuku/ecma_old_spec.rb +415 -0
  153. data/spec/languages/ecma_fuku/ecma_operator_spec.rb +33 -0
  154. data/spec/languages/ecma_fuku/ecma_spec.rb +52 -0
  155. data/spec/languages/math/compiler_spec.rb +49 -0
  156. data/spec/languages/math/tokenizer_spec.rb +73 -0
  157. data/spec/languages/math/tree_spec.rb +153 -0
  158. metadata +225 -0
@@ -0,0 +1,251 @@
1
+ module AmberVM
2
+ module Interpreter
3
+
4
+ def Interpreter.makevs(value)
5
+ if value.is_a?(VariableStorage)
6
+ value
7
+ else
8
+ VariableStorage.new(value)
9
+ end
10
+ end
11
+ # This class represents the environment, the memory so to say for the VM.
12
+ # The environment holds environmental variables like who executes the
13
+ # code, on what object it runs, what parameters where passed to the call
14
+ # and as well, and perhaps most importantly the local variables.
15
+ #
16
+ # Some of the functions called will initialize new environments, as
17
+ # for example function calls.
18
+ class Environment
19
+ attr_accessor :prev
20
+ # This creates a new environment environment, it generates a new env
21
+ # default variables are set if not defined in +data+.
22
+ #
23
+ # If +oldenv+ is provided it will also fall back to see if not
24
+ # existing variables
25
+ #
26
+ # +init_data+ is a hash that can be passed the following values:
27
+ # :locals:: A hash with local variables mapped name => value
28
+ # :functions:: A hash with functions for the scope.
29
+ # :evaldeepth:: A fixnum that indicates how deep the evaluation is.
30
+ # :params:: A array that holds local parameters for example for functions
31
+ # or blocks.
32
+ def initialize init_data = {}, oldenv=nil
33
+
34
+ @data = {
35
+ :locals => {}, #oldenv ? oldenv.data[:locals] : {},
36
+ :locals_swapped => true, # init_data.keys.include?(:locals),
37
+ :evaldeepth => 0,
38
+ :params => oldenv ? oldenv.data[:params] : [],
39
+ :params_swapped => init_data.keys.include?(:params)
40
+ }.merge(init_data)
41
+ @path = [] if oldenv.nil?
42
+
43
+ # Make sure that all locals that are passed, are actually in a variable
44
+ # storage.
45
+ if init_data[:locals]
46
+ # For easy access we get us a link to the locals
47
+ locals = @data[:locals]
48
+ # Now we itterate through them
49
+ init_data[:locals].each do |k,v|
50
+ #For every variable that isn't already in a storage
51
+ # We put it in a storage to assure the environment is propper.
52
+ locals[k] = AmberVM::Interpreter::makevs(v)
53
+ end
54
+ end
55
+
56
+ # We store the priviouse environment to look upwards through the scopes
57
+ # for priviouse defined variables, if no old environment was given we
58
+ # set the priviose scope to an empty hash.
59
+ @prev = oldenv || {}
60
+ AmberVM::debug "data: #{data}\noldenv:#{oldenv}" if $DEBUG
61
+ AmberVM::debug "Creating new environment with: #{@data.inspect} as child" +
62
+ " of #{@prev}" if $DEBUG
63
+ end
64
+
65
+
66
+ # Allows raw access to the data, it should not be used unless
67
+ # somoene knows pretty exactly what they are doing.
68
+ def data
69
+ @data
70
+ end
71
+
72
+ def path
73
+ @path || @pre.path
74
+ end
75
+
76
+ # returns a parameter that was passed to the call. For function calls
77
+ # this is especially important, it beginns with 0.
78
+ #
79
+ # If the current environment does not have the given paramenter it tries
80
+ # it's 'oldenv' attrib to see if that had a object.
81
+ def param i
82
+ AmberVM::debug "Getting param #{i} (#{@data[:params][i]})" if $DEBUG
83
+ if @data[:params_swapped]
84
+ @data[:params][i] || @prev.param(i)
85
+ else
86
+ @data[:params][i]
87
+ end
88
+ end
89
+
90
+ # Returns a local variable with the given name.
91
+ #
92
+ # If the current environment does not have any local variables with
93
+ # the given name it tries the privious environments.
94
+ #
95
+ # This returns the +VariableData+ object NOT the value of the variable.
96
+ # Use +read_var_val+ if you want to read the value of a variable.
97
+ def [] k
98
+ r = @data[:locals][k]
99
+ r = @prev[k] if not r and @data[:locals_swapped]
100
+ AmberVM::debug "Getting variable #{k} (#{r})" if $DEBUG
101
+ r
102
+ end
103
+
104
+ # Sets a local variable witin the environment.
105
+ #
106
+ # If the variable exists in a 'higher' environment the value is changed.
107
+ #
108
+ # If not it is newly created in the current environment and thus not
109
+ # visible in upper environments.
110
+ def []= name, value
111
+ AmberVM::debug "Setting variable #{name} to #{value}" if $DEBUG
112
+
113
+ # First we try to get the variable storage of the variable requested.
114
+ # This will work if it was defined in this or a priviouse scope.
115
+ if storage = self[name]
116
+ # If we found the storage we'll change it's value and not define it
117
+ # again.
118
+ storage.val = value
119
+ storage
120
+ else
121
+ # If we didn't found a Variable storage, the variable wasn't defined
122
+ # before so we make a new VariableStorage and save the variable in
123
+ # it.
124
+ storage = declare name, value
125
+ end
126
+ storage
127
+ end
128
+
129
+ # Defines a varialbe in the current scope, priviose variables are not
130
+ # changed.
131
+ # This is needed for local varialbe declarations that overwrite priviouse
132
+ # globals.
133
+ def declare name, value
134
+ #Now we need to make our own set of storage!
135
+ if not @data[:locals_swapped]
136
+ @data[:locals_swapped] = true
137
+ @data[:locals] = {}
138
+ end
139
+ value = AmberVM::Interpreter::makevs(value)
140
+ @data[:locals][name] = value
141
+ end
142
+
143
+ # This functin is closely related to +[]+ with the difference that it
144
+ # returns the value and not the VariableStorage object.
145
+ # It is equivalent to [].val just that it also deals with nil ojects and
146
+ # and returns a AmberVM::Classes::Error if the requested variable wasn't
147
+ # found.
148
+ def read_var_val name
149
+
150
+ r = nil
151
+ if (v = self[name])
152
+ r = v.val
153
+ else
154
+ raise "Variable #{name} is not defined."
155
+ end
156
+ AmberVM::debug "Getting variable value #{name} (#{r})" if $DEBUG
157
+ r
158
+ end
159
+ end
160
+ # This class is used to store the variable content to allow chross
161
+ # refferencing and passing variables upwards through different scopes.
162
+ class VariableStorage
163
+
164
+ # Lets the script read the value of the variable.
165
+ attr_accessor :val
166
+
167
+ # The storage is initialized with two optional parameters:
168
+ #
169
+ # +val+:: which is the value to be stores.
170
+ # +writable+:: which when set to false prevents the variable to be
171
+ # written, which might be helpfull when trying to publish
172
+ # some data to a script that is not supposed to be changed.
173
+ def initialize val = nil
174
+ @val = val
175
+ end
176
+
177
+ def to_s
178
+ "#<#{self.class}:#{self.object_id} @val=#{@val}>"
179
+ end
180
+
181
+ def pretty_print(q)
182
+ q.text "Variable(#{object_id}=(#{@val}))"
183
+ end
184
+ end
185
+
186
+ class ROVariableStorage
187
+
188
+ # Lets the script read the value of the variable.
189
+ attr_reader :val
190
+
191
+ # The storage is initialized with two optional parameters:
192
+ #
193
+ # +val+:: which is the value to be stores.
194
+ # +writable+:: which when set to false prevents the variable to be
195
+ # written, which might be helpfull when trying to publish
196
+ # some data to a script that is not supposed to be changed.
197
+ def initialize val = nil
198
+ @val = val
199
+ end
200
+
201
+ def pretty_print(q)
202
+ q.text "Variable(#{object_id})"
203
+ end
204
+ # Used to write to the variable, if +writable+ was set to false this
205
+ # will have no effect.
206
+ #
207
+ # It returns the new value set or, if +writable+ was false the old value.
208
+ def val=v
209
+ @val
210
+ end
211
+ end
212
+
213
+ # The callback storang is used to help publishing variables from a ruby
214
+ # class to the rVM, it will get and set the variables during runtime.
215
+ #
216
+ # It will link getter and setter methods and not the instance variable
217
+ # itself, which means also computed attributes can be handled by this.
218
+ #
219
+ # This class is made if it is nessessary that a script always has access
220
+ # to constantly chaning data within a object and not only deal with static
221
+ # values set once.
222
+ class VariableStorageCallback < VariableStorage
223
+ # The construtor takes 3 parameters to specifie the object it shold
224
+ # be linked with, the attribute to handle and +writable+ that will define
225
+ # if the VariableStorage can be written too by the script.
226
+ #
227
+ # var is expected to by a Symbol equal the the function, the getter will
228
+ # call obj.var and the setter will call obj.var=.
229
+ #
230
+ def initialize obj, var, writable = true
231
+ super(nil)
232
+ @obj = obj
233
+ @get = var.to_sym
234
+ @set = "#{var}=".to_sym
235
+ end
236
+
237
+ # This methods sets the variable passed to the object by sending it to
238
+ # the setter method.
239
+ def val= v
240
+ @obj.send(@set,v) if @writable
241
+ @obj.send(@get)
242
+ end
243
+
244
+ # The getter will call the getter of the object to handle to get the
245
+ # current value.
246
+ def val
247
+ @obj.send(@get)
248
+ end
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,409 @@
1
+ module Fukubukuro
2
+ module ECMA
3
+
4
+ # TODO: recursion detection
5
+ def self.make_core_object_from value
6
+ case value
7
+ when Numeric
8
+ ECMA::Core::Number.new value
9
+ when String
10
+ ECMA::Core::String.new value
11
+ when Array
12
+ array = value.map { |item| make_core_object_from item }
13
+ ECMA::Core::Array.bind_to_original(array, value)
14
+ when nil
15
+ ECMA::Core::Null::Null
16
+ when true
17
+ ECMA::Core::Boolean::True
18
+ when false
19
+ ECMA::Core::Boolean::False
20
+ when Symbol
21
+ ECMA::Core::Symbol.new value
22
+ when Proc
23
+ ECMA::Core::Lambda.new value
24
+ when :undefined
25
+ ECMA::Core::Undefined::Undefined
26
+ when OpenStruct
27
+ core_object = OpenStruct.new
28
+ for key, val in value.instance_variable_get :@table
29
+ core_object.send :"#{key}=", make_core_object_from(val)
30
+ end
31
+ ECMA::Core::Object.new core_object
32
+ else
33
+ ECMA::Core::ObjectWrapper.new value
34
+ end
35
+ end
36
+
37
+ module Core
38
+
39
+ class Container < ::Object
40
+ attr_accessor :value
41
+ alias initialize value=
42
+ private :initialize
43
+ def method_missing(meth, *args, &blk)
44
+ raise "%s doesn't know about %p" % [self.class, meth]
45
+ end
46
+ alias to_ruby value
47
+
48
+ attr_accessor :original
49
+ def self.bind_to_original value, original
50
+ container = new(value)
51
+ container.original = original
52
+ container
53
+ end
54
+
55
+ def inspect
56
+ "%p(%s)" % [self.class, value_inspect]
57
+ end
58
+ def pretty_print q
59
+ q.text inspect
60
+ end
61
+ def self.inspect
62
+ name[/\w+$/]
63
+ end
64
+ def value_inspect
65
+ value.inspect
66
+ end
67
+
68
+ end
69
+
70
+ class Number < Container
71
+
72
+ def value_inspect
73
+ case value
74
+ when ::Integer
75
+ value.to_s
76
+ when ::Float
77
+ ('%0.0f' % value).chomp('.0')
78
+ end
79
+ end
80
+
81
+ def + other
82
+ case other
83
+ when Number
84
+ Number.new value + other.value
85
+ when String
86
+ String.new value.to_s + other.value
87
+ else
88
+ raise ::ArgumentError, 'expected Number, got %p' % [other]
89
+ end
90
+ end
91
+
92
+ def - other
93
+ case other
94
+ when Number
95
+ Number.new value - other.value
96
+ else
97
+ raise ::ArgumentError, 'expected Number, got %p' % [other]
98
+ end
99
+ end
100
+
101
+ def _increment_prefix
102
+ self.value += 1
103
+ self
104
+ end
105
+
106
+ def _increment_suffix
107
+ self.value += 1
108
+ Number.new value - 1
109
+ end
110
+
111
+ def _decrement_prefix
112
+ self.value -= 1
113
+ self
114
+ end
115
+
116
+ def _decrement_suffix
117
+ self.value -= 1
118
+ Number.new value + 1
119
+ end
120
+
121
+ def increment by
122
+ self.value += by.value
123
+ self
124
+ end
125
+
126
+ def increment_const by
127
+ self.value += by
128
+ self
129
+ end
130
+
131
+ def decrement by
132
+ self.value -= by.value
133
+ self
134
+ end
135
+
136
+ def decrement_const by
137
+ self.value -= by
138
+ self
139
+ end
140
+
141
+ def < other
142
+ case other
143
+ when Number
144
+ value < other.value
145
+ else
146
+ raise ::ArgumentError, 'expected Number, got %p' % [other]
147
+ end
148
+ end
149
+
150
+ def <= other
151
+ case other
152
+ when Number
153
+ value <= other.value
154
+ else
155
+ raise ::ArgumentError, 'expected Number, got %p' % [other]
156
+ end
157
+ end
158
+
159
+ def == other
160
+ case other
161
+ when Number
162
+ value == other.value
163
+ else
164
+ false
165
+ end
166
+ end
167
+
168
+ module_eval %{
169
+ def != other
170
+ case other
171
+ when Number
172
+ value != other.value
173
+ else
174
+ false
175
+ end
176
+ end
177
+ } if ::RUBY_VERSION >= '1.9'
178
+
179
+ def not_equal_const other
180
+ value != other
181
+ end
182
+
183
+ def -@
184
+ Number.new(-value)
185
+ end
186
+
187
+ def +@
188
+ # Number.new(+value)
189
+ self
190
+ end
191
+
192
+ def * other
193
+ case other
194
+ when Number
195
+ Number.new value * other.value
196
+ else
197
+ raise ::ArgumentError, 'expected Number, got %p' % [other]
198
+ end
199
+ end
200
+
201
+ def / other
202
+ case other
203
+ when Number
204
+ Number.new value.to_f / other.value
205
+ else
206
+ raise ::ArgumentError, 'expected Number, got %p' % [other]
207
+ end
208
+ end
209
+
210
+ def << other
211
+ case other
212
+ when Number
213
+ Number.new value << other.value
214
+ else
215
+ raise ::ArgumentError, 'expected Number, got %p' % [other]
216
+ end
217
+ end
218
+
219
+ def lsr other
220
+ case other
221
+ when Number
222
+ Number.new value.lsr(other.value)
223
+ else
224
+ raise ::ArgumentError, 'expected Number, got %p' % [other]
225
+ end
226
+ end
227
+
228
+ def false?
229
+ value.zero?
230
+ end
231
+ def true?
232
+ value.nonzero?
233
+ end
234
+
235
+ end
236
+
237
+ class Array < Container
238
+
239
+ def [] index
240
+ case index
241
+ when Number
242
+ value[index.value]
243
+ else
244
+ raise ::ArgumentError, 'expected Number, got %p' % [index]
245
+ end
246
+ end
247
+
248
+ def []= index, object
249
+ case index
250
+ when Number
251
+ value[index.value] = object
252
+ else
253
+ raise ::ArgumentError, 'expected Number, got %p' % [index]
254
+ end
255
+ end
256
+
257
+ def to_ruby
258
+ original.replace value.map { |item| item.is_a?(Container) ? item.to_ruby : item }
259
+ end
260
+
261
+ def length
262
+ Number.new value.size
263
+ end
264
+
265
+ def fuku_send meth, *args
266
+ return send(meth, *args) if respond_to? meth
267
+ method_missing meth, *args
268
+ end
269
+
270
+ end
271
+
272
+ class String < Container
273
+
274
+ def + other
275
+ case other
276
+ when String
277
+ String.new value + other.value
278
+ when Number
279
+ String.new value + other.value.to_s
280
+ else
281
+ raise ::ArgumentError, 'expected String, got %p' % [other]
282
+ end
283
+ end
284
+
285
+ def to_ruby
286
+ if original
287
+ original.replace value
288
+ else
289
+ value
290
+ end
291
+ end
292
+
293
+ def to_number
294
+ value[/\D/] ? value.to_f : value.to_i
295
+ end
296
+
297
+ def _increment_suffix
298
+ as_number = self.to_number
299
+ new_value = as_number + 1
300
+ raise ::Fukubukuro::CastException.new(Number.new(new_value), Number.new(as_number))
301
+ end
302
+
303
+ end
304
+
305
+ class Boolean < Container
306
+ True = new true
307
+ def True.true?; true; end
308
+ def True.false?; false; end
309
+ False = new false
310
+ def False.true?; false; end
311
+ def False.false?; true; end
312
+ def new value
313
+ value ? True : False
314
+ end
315
+ def inspect
316
+ value.inspect
317
+ end
318
+ end unless defined? Core::Boolean
319
+
320
+ class Null < Container
321
+ Null = new nil
322
+ def Null.true?; false; end
323
+ def Null.false?; true; end
324
+ def new value
325
+ Null
326
+ end
327
+ def inspect
328
+ 'null'
329
+ end
330
+ end unless defined? Core::Null
331
+
332
+ class Undefined < Container
333
+ Undefined = new nil
334
+ def Undefined.true?; false; end
335
+ def Undefined.false?; true; end
336
+ def new value
337
+ Undefined
338
+ end
339
+ def inspect
340
+ 'undefined'
341
+ end
342
+ end unless defined? Core::Undefined
343
+
344
+ class Symbol < Container
345
+ end
346
+
347
+ class Object < Container
348
+
349
+ def fuku_send(meth, *args)
350
+ if meth.to_s[-1] == ?=
351
+ raise 'Expected 1 argument for member assignment; got %p' % [args.size] if args.size != 1
352
+ value.send(meth, args.first)
353
+ else
354
+ value.send(meth, *args)
355
+ end
356
+ end
357
+
358
+ def fuku_method_call(meth, *args)
359
+ raise "Can't method-call a setter method." if meth.to_s[-1] == ?=
360
+ Fukubukuro::CurrentReceiver.set self
361
+ value.send(meth).fuku_call(*args)
362
+ end
363
+
364
+ def to_ruby
365
+ raise unless value.is_a? OpenStruct
366
+ ruby = OpenStruct.new
367
+ for key, val in value.instance_variable_get :@table
368
+ ruby.send :"#{key}=", val.to_ruby
369
+ end
370
+ ruby
371
+ end
372
+
373
+ end
374
+
375
+ class ObjectWrapper < Container
376
+
377
+ def fuku_send(meth, *args)
378
+ if meth.to_s[-1] == ?=
379
+ raise 'Expected 1 argument for member assignment; got %p' % [args.size] if args.size != 1
380
+ value.send(meth, args.first.to_ruby)
381
+ else
382
+ ECMA.make_core_object_from value.send(meth, *args.map { |arg| arg.to_ruby })
383
+ end
384
+ end
385
+
386
+ def fuku_method_call(meth, *args)
387
+ raise "Can't method-call a setter method." if meth.to_s[-1] == ?=
388
+ Fukubukuro::CurrentReceiver.set self
389
+ ECMA.make_core_object_from value.send(meth).call(*args.map { |arg| arg.to_ruby })
390
+ end
391
+
392
+ def fuku_call *args
393
+ ECMA.make_core_object_from value.send(:call, *args.map { |arg| arg.to_ruby })
394
+ end
395
+
396
+ end
397
+
398
+ class Lambda < Container
399
+
400
+ def fuku_call *args
401
+ ECMA.make_core_object_from value.send(:call, *args)
402
+ end
403
+
404
+ end
405
+
406
+ end
407
+
408
+ end
409
+ end