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.
- data/README +38 -0
- data/bin/ambervm +278 -0
- data/lib/amber/acts_as_rvm_type.rb +157 -0
- data/lib/amber/classes/association.rb +36 -0
- data/lib/amber/classes/block.rb +52 -0
- data/lib/amber/classes/boolean.rb +40 -0
- data/lib/amber/classes/class.rb +50 -0
- data/lib/amber/classes/error.rb +22 -0
- data/lib/amber/classes/list.rb +96 -0
- data/lib/amber/classes/null.rb +35 -0
- data/lib/amber/classes/number.rb +95 -0
- data/lib/amber/classes/object.rb +56 -0
- data/lib/amber/classes/string.rb +79 -0
- data/lib/amber/classes.rb +113 -0
- data/lib/amber/environment.rb +251 -0
- data/lib/amber/fukubukuro/ecma_core.rb +409 -0
- data/lib/amber/fukubukuro.rb +866 -0
- data/lib/amber/functions/all.rb +3 -0
- data/lib/amber/functions/array/append.rb +50 -0
- data/lib/amber/functions/array/at.rb +50 -0
- data/lib/amber/functions/array/set_at.rb +50 -0
- data/lib/amber/functions/array.rb +30 -0
- data/lib/amber/functions/association/assoc_get.rb +55 -0
- data/lib/amber/functions/association/assoc_set.rb +56 -0
- data/lib/amber/functions/bitwise/bitwise_and.rb +41 -0
- data/lib/amber/functions/bitwise/bitwise_not.rb +41 -0
- data/lib/amber/functions/bitwise/bitwise_or.rb +41 -0
- data/lib/amber/functions/bitwise/bitwise_xor.rb +41 -0
- data/lib/amber/functions/bitwise.rb +3 -0
- data/lib/amber/functions/collection/get.rb +66 -0
- data/lib/amber/functions/collection/set.rb +67 -0
- data/lib/amber/functions/collection/size.rb +54 -0
- data/lib/amber/functions/general/cmp.rb +43 -0
- data/lib/amber/functions/general/eq.rb +45 -0
- data/lib/amber/functions/general/gt.rb +45 -0
- data/lib/amber/functions/general/gte.rb +45 -0
- data/lib/amber/functions/general/lt.rb +45 -0
- data/lib/amber/functions/general/lte.rb +45 -0
- data/lib/amber/functions/general/neq.rb +45 -0
- data/lib/amber/functions/general/type.rb +43 -0
- data/lib/amber/functions/general.rb +3 -0
- data/lib/amber/functions/io/print.rb +45 -0
- data/lib/amber/functions/io.rb +3 -0
- data/lib/amber/functions/list/align.rb +73 -0
- data/lib/amber/functions/list/join.rb +45 -0
- data/lib/amber/functions/list/map.rb +58 -0
- data/lib/amber/functions/list/split.rb +55 -0
- data/lib/amber/functions/list.rb +3 -0
- data/lib/amber/functions/logic/and.rb +55 -0
- data/lib/amber/functions/logic/not.rb +40 -0
- data/lib/amber/functions/logic/or.rb +50 -0
- data/lib/amber/functions/logic.rb +3 -0
- data/lib/amber/functions/math/abs.rb +39 -0
- data/lib/amber/functions/math/acos.rb +39 -0
- data/lib/amber/functions/math/add.rb +40 -0
- data/lib/amber/functions/math/asin.rb +39 -0
- data/lib/amber/functions/math/atan.rb +39 -0
- data/lib/amber/functions/math/ceil.rb +39 -0
- data/lib/amber/functions/math/cos.rb +39 -0
- data/lib/amber/functions/math/dec.rb +39 -0
- data/lib/amber/functions/math/div.rb +44 -0
- data/lib/amber/functions/math/exp.rb +39 -0
- data/lib/amber/functions/math/floor.rb +39 -0
- data/lib/amber/functions/math/inc.rb +39 -0
- data/lib/amber/functions/math/log.rb +39 -0
- data/lib/amber/functions/math/mod.rb +41 -0
- data/lib/amber/functions/math/mul.rb +43 -0
- data/lib/amber/functions/math/neg.rb +43 -0
- data/lib/amber/functions/math/power.rb +43 -0
- data/lib/amber/functions/math/rand.rb +36 -0
- data/lib/amber/functions/math/round.rb +39 -0
- data/lib/amber/functions/math/shl.rb +41 -0
- data/lib/amber/functions/math/shr.rb +41 -0
- data/lib/amber/functions/math/sin.rb +39 -0
- data/lib/amber/functions/math/sub.rb +43 -0
- data/lib/amber/functions/math/tan.rb +39 -0
- data/lib/amber/functions/math.rb +3 -0
- data/lib/amber/functions/objects/send.rb +22 -0
- data/lib/amber/functions/rails/print.rb +44 -0
- data/lib/amber/functions/rails.rb +3 -0
- data/lib/amber/functions/string/ansi.rb +24 -0
- data/lib/amber/functions/string/capstr.rb +23 -0
- data/lib/amber/functions/string/center.rb +25 -0
- data/lib/amber/functions/string/chr.rb +16 -0
- data/lib/amber/functions/string/ljust.rb +26 -0
- data/lib/amber/functions/string/regmatch.rb +34 -0
- data/lib/amber/functions/string/rjust.rb +26 -0
- data/lib/amber/functions/string.rb +3 -0
- data/lib/amber/functions.rb +103 -0
- data/lib/amber/interpreter.rb +1380 -0
- data/lib/amber/languages/brainfuck.rb +153 -0
- data/lib/amber/languages/ecma/compiler.rb +1661 -0
- data/lib/amber/languages/ecma/core-math.js +67 -0
- data/lib/amber/languages/ecma/core-objects.js +57 -0
- data/lib/amber/languages/ecma.rb +9 -0
- data/lib/amber/languages/ecma_fuku/compiler.rb +1622 -0
- data/lib/amber/languages/ecma_fuku/core-math.js +67 -0
- data/lib/amber/languages/ecma_fuku/core-objects.js +56 -0
- data/lib/amber/languages/ecma_fuku.rb +13 -0
- data/lib/amber/languages/math/compiler.rb +70 -0
- data/lib/amber/languages/math/tokenizer.rb +69 -0
- data/lib/amber/languages/math/tree.rb +110 -0
- data/lib/amber/languages/math.rb +26 -0
- data/lib/amber/languages.rb +99 -0
- data/lib/amber/library.rb +79 -0
- data/lib/amber/optimisation.rb +299 -0
- data/lib/amber/plugin.rb +337 -0
- data/lib/amber/rails.rb +90 -0
- data/lib/amber.rb +106 -0
- data/spec/amber/class_spec.rb +27 -0
- data/spec/amber/enviroment_spec.rb +61 -0
- data/spec/amber/function_spec.rb +25 -0
- data/spec/amber/functions/association/assoc_get_spec.rb +41 -0
- data/spec/amber/functions/association/assoc_set_spec.rb +43 -0
- data/spec/amber/functions/collection/get_spec.rb +12 -0
- data/spec/amber/functions/collection/set_spec.rb +10 -0
- data/spec/amber/functions/collection/size_spec.rb +10 -0
- data/spec/amber/functions/list/split_spec.rb +47 -0
- data/spec/amber/functions/string/ansi_spec.rb +44 -0
- data/spec/amber/functions/string/capstr_spec.rb +42 -0
- data/spec/amber/functions/string/center_spec.rb +49 -0
- data/spec/amber/functions/string/ljust_spec.rb +49 -0
- data/spec/amber/functions/string/regmatch_spec.rb +52 -0
- data/spec/amber/functions/string/rjust_spec.rb +49 -0
- data/spec/amber/interpreter/assignment_spec.rb +22 -0
- data/spec/amber/interpreter/condition_spec.rb +103 -0
- data/spec/amber/interpreter/constant_spec.rb +31 -0
- data/spec/amber/interpreter/core_call_spec.rb +72 -0
- data/spec/amber/interpreter/interpreter_spec.rb +11 -0
- data/spec/amber/interpreter/parameter_spec.rb +24 -0
- data/spec/amber/interpreter/sequence_spec.rb +47 -0
- data/spec/amber/interpreter/variable_spec.rb +24 -0
- data/spec/amber/plugin_spec.rb +10 -0
- data/spec/classes/atom/association_spec.rb +39 -0
- data/spec/classes/atom/block_spec.rb +25 -0
- data/spec/classes/atom/boolean_spec.rb +67 -0
- data/spec/classes/atom/error_spec.rb +43 -0
- data/spec/classes/atom/list_spec.rb +68 -0
- data/spec/classes/atom/number_spec.rb +132 -0
- data/spec/classes/atom/string_spec.rb +175 -0
- data/spec/languages/ecma/ecma_array_spec.rb +79 -0
- data/spec/languages/ecma/ecma_closure_spec.rb +38 -0
- data/spec/languages/ecma/ecma_literals_spec.rb +71 -0
- data/spec/languages/ecma/ecma_objects_spec.rb +165 -0
- data/spec/languages/ecma/ecma_old_spec.rb +540 -0
- data/spec/languages/ecma/ecma_spec.rb +64 -0
- data/spec/languages/ecma_fuku/ecma_array_spec.rb +61 -0
- data/spec/languages/ecma_fuku/ecma_closure_spec.rb +33 -0
- data/spec/languages/ecma_fuku/ecma_function_spec.rb +84 -0
- data/spec/languages/ecma_fuku/ecma_literals_spec.rb +55 -0
- data/spec/languages/ecma_fuku/ecma_objects_spec.rb +133 -0
- data/spec/languages/ecma_fuku/ecma_old_spec.rb +415 -0
- data/spec/languages/ecma_fuku/ecma_operator_spec.rb +33 -0
- data/spec/languages/ecma_fuku/ecma_spec.rb +52 -0
- data/spec/languages/math/compiler_spec.rb +49 -0
- data/spec/languages/math/tokenizer_spec.rb +73 -0
- data/spec/languages/math/tree_spec.rb +153 -0
- 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
|