AmberVM 0.0.19

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.
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