rVM 0.0.5 → 0.0.6

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.
@@ -0,0 +1,17 @@
1
+ module RVM
2
+ module Functions
3
+ class Not < RVM::Functions::Function
4
+ class << self
5
+ def execute params, env
6
+ RVM::Classes::Boolean.new(! params[0].is_true?)
7
+ end
8
+
9
+ def signature
10
+ [:any] # adjust the signature here
11
+ end
12
+
13
+ end
14
+ register_for :not
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ module RVM
2
+ module Functions
3
+ class Or < RVM::Functions::Function
4
+ class << self
5
+ def execute params, env
6
+ while not result and not params.empty?
7
+ v = params.shift.execute(env)
8
+ return v if v.is_true?
9
+ end
10
+ return RVM::Classes::Boolean.new(false)
11
+ end
12
+
13
+ def signature
14
+ [:any] # adjust the signature here
15
+ end
16
+
17
+ def execargs
18
+ false
19
+ end
20
+ end
21
+ register_for :or
22
+ end
23
+ end
24
+ end
@@ -2,15 +2,15 @@ module RVM
2
2
  module Functions
3
3
  class Add < Function
4
4
  def Add.execute params, env
5
- a = RVM::Classes[:number].new 0
6
- params.each do |p|
5
+ a = params.shift
6
+ params.each do |p|
7
7
  a += p
8
8
  end
9
9
  a
10
10
  end
11
11
 
12
12
  def Add.signature
13
- [:number, :number]
13
+ [:any]
14
14
  end
15
15
  register_for :add
16
16
  end
@@ -2,18 +2,16 @@ module RVM
2
2
  module Functions
3
3
  class Div < Function
4
4
  def Div.execute params, env
5
- a = RVM::Classes[:number].new params.shift
6
- params.each do |p|
7
- if p == 0
8
- return RVM::Classes[:error].new(1,"DIVISION BY ZERO")
9
- end
5
+ a = params.shift
6
+
7
+ params.each do |p|
10
8
  a /= p
11
9
  end
12
10
  a
13
11
  end
14
12
 
15
13
  def Div.signature
16
- [:number, :number]
14
+ [:any]
17
15
  end
18
16
  register_for :div
19
17
  end
@@ -2,7 +2,7 @@ module RVM
2
2
  module Functions
3
3
  class Mul < Function
4
4
  def Mul.execute params, env
5
- a = RVM::Classes[:number].new params.shift
5
+ a = params.shift
6
6
  params.each do |p|
7
7
  a *= p
8
8
  end
@@ -2,7 +2,7 @@ module RVM
2
2
  module Functions
3
3
  class Sub < Function
4
4
  def Sub.execute params, env
5
- a = RVM::Classes[:number].new params.shift
5
+ a = params.shift
6
6
  params.each do |p|
7
7
  a -= p
8
8
  end
@@ -0,0 +1,22 @@
1
+ module RVM
2
+ module Functions
3
+ class Send < RVM::Functions::Function
4
+ class << self
5
+ def execute params, env
6
+ obj = params.shift
7
+ method = params.shift
8
+ if obj and method
9
+ obj.obj_send(method, params, env)
10
+ else
11
+
12
+ end
13
+ end
14
+
15
+ def signature
16
+ [:any, :string, :any]
17
+ end
18
+ end
19
+ register_for :send
20
+ end
21
+ end
22
+ end
@@ -22,6 +22,19 @@ module RVM
22
22
  RVM::Interpreter::Constant.new(RVM::Classes[type].new(value))
23
23
  end
24
24
 
25
+ class VariableStorage
26
+ attr_accessor :val
27
+ def initialize val, writable = true
28
+ @writable = writable
29
+ @val = val
30
+ end
31
+
32
+ def val=v
33
+ @val = v if @writable
34
+ @val
35
+ end
36
+ end
37
+
25
38
  # This class represents the enviroment, the memory so to say for the VM.
26
39
  # The enviroment holds enviromental variables like who executes the
27
40
  # code, on what object it runs, what parameters where passed to the call
@@ -35,17 +48,22 @@ module RVM
35
48
  #
36
49
  # If *oldenv* is provided it will also fall back to see if not
37
50
  # existing variables
38
- def initialize data = {}, oldenv=nil
39
- RVM::debug "data: #{data}\noldenv:#{oldenv}"
51
+ def initialize init_data = {}, oldenv=nil
52
+
40
53
  @data = {
41
54
  :locals => {},
42
55
  :functions => {},
43
56
  :evaldeepth => 0,
44
57
  :params => []
45
- }.merge(data)
58
+ }.merge(init_data)
46
59
  @prev = oldenv || {}
60
+ RVM::debug "data: #{data}\noldenv:#{oldenv}"
47
61
  RVM::debug "Creating new enviroment with: #{@data.inspect} as child of #{@prev}"
48
-
62
+ end
63
+
64
+ #allows raw access to the data, be carefull!
65
+ def data
66
+ @data
49
67
  end
50
68
 
51
69
  # returns a parameter that was passed to the call. For function calls
@@ -55,45 +73,143 @@ module RVM
55
73
  # it's 'oldenv' attrib to see if that had a object.
56
74
  def param i
57
75
  RVM::debug "Getting param #{i} (#{@data[:params][i]})"
58
- @data[:params][i]
76
+ @data[:params][i] || @prev.param(i)
59
77
  end
60
78
 
61
79
  # Returns a local variable with the given name.
62
80
  #
63
81
  # If the current enviroment does not have any local variables with
64
82
  # the given name it tries the privious enviroments.
83
+ #
84
+ # This returns the +VariableData+ object NOT the value of the variable.
85
+ # Use +read_var_val+ if you want to read the value of a variable.
65
86
  def [] k
66
87
  r = @data[:locals][k] || @prev[k]
67
88
  RVM::debug "Getting variable #{k} (#{r})"
68
89
  r
69
90
  end
70
91
 
71
- #Sets a local variable witin the enviroment.
92
+ # Sets a local variable witin the enviroment.
93
+ #
94
+ # If the variable exists in a 'higher' enviroment the value is changed.
95
+ #
96
+ # If not it is newly created in the current enviroment and thus not visible
97
+ # in upper enviroments.
72
98
  def []= k, v
73
99
  #TODO: add capability to have the privious env variables changed
74
100
  RVM::debug "Setting variable #{k} to #{v}"
75
- @data[:locals][k] = v
101
+ if (self[:locals] and r = self[:locals][k])
102
+ r.val = v
103
+ else
104
+ @data[:locals][k] = VariableStorage.new(v)
105
+ end
106
+ v
76
107
  end
77
108
 
78
- #Returns a function for the current enviroment
109
+ # Returns a function for the current enviroment.
110
+ # The result is to be execpted to be of the +RVM::Classes::Block+ class.
79
111
  def function k
80
112
  r = @data[:functions][k]
81
113
  if not r and @prev.is_a? Enviroment
82
- r = @prev.function(k)
114
+ r = @prev.function(k)
83
115
  end
84
116
  RVM::debug "Getting functon #{k} (#{r})"
85
117
  r
86
118
  end
87
119
 
88
- #Returns a function for the current enviroment
120
+ # This defines a function within the enviroment and lets you call it later on.
121
+ #
122
+ # It also checks if the given block is truely a +RVM::Classes::Block+ object.
89
123
  def def_function k, b
124
+ rise(ArgumentError, "Function definitions must be of block class.")if not b.is_a?(RVM::Classes::Block)
90
125
  @data[:functions][k] = b
91
126
  RVM::debug "Setting functon #{k} (#{b})"
92
127
  nil
93
128
  end
129
+
130
+ # This functin is closely related to +[]+ with the difference that it returns the value
131
+ # And not the VariableData object.
132
+ def read_var_val name
133
+ if (v = self[name])
134
+ v.val
135
+ end
136
+ end
137
+ end
138
+
139
+
140
+ # Skipps into object context (anther way beside using send)
141
+ #
142
+ # the special variable :self (attention, not to be mixed wiht 'self')
143
+ # is set to the object in which context we are!
144
+ #
145
+ # The class is stred in :class
146
+ class ObjectContext
147
+ def initialize object, code
148
+ @object = object
149
+ @code = code
150
+ end
151
+
152
+ def execute env
153
+ #The new
154
+ obj = @object.execute(env)
155
+ env = Interpreter::Enviroment.new({:functions => obj.functions, :locals => obj.variables}, env)
156
+ @code.execute(env)
157
+ end
158
+ end
159
+
160
+
161
+ #This sets a funciton on a Class (to be included in its objects)
162
+ #
163
+ #To define class functions use ObjectContext and define the function normaly, nifty isn't it?
164
+ class SetClassFunction
165
+ def initialize obj, name, function
166
+ @object = obj
167
+ @name = name
168
+ @function = function
169
+ end
170
+
171
+ def execute env
172
+ @object.object_functions[@name.execute(env)] = @function
173
+ @function
174
+ end
175
+ end
176
+
177
+ # A block localizes variables, do not mix this up with the
178
+ # +RVM::Classes::Block+ class!
179
+ #
180
+ # Blocks are mostly used to handle tasks as not interfeeing
181
+ # With outer code.
182
+ class Block
183
+ attr_reader :content
184
+ def initialize content
185
+ @content = content
186
+ end
187
+
188
+ # When executed a temporary enviroment is created with the passed
189
+ # Enviroement as a parent to it.
190
+ # This new enviroment is discaded after the execution.
191
+ def execute env
192
+ tenv = Enviroment.new({}, env)
193
+ @content.execute tenv
194
+ end
94
195
  end
95
196
 
197
+ # This is a function definition used to write in the function libary
198
+ #
96
199
  class FunctionDefinition
200
+
201
+ # Initializes a new function definition
202
+ #
203
+ # name:: is the name of the function to define, if it is not
204
+ # unique it will overwrite earlyer definitions
205
+ # (unless override is false)
206
+ #
207
+ # body:: is the body of the cuntion. this will be executed
208
+ # when the defined function is called.
209
+ #
210
+ # override:: when true (default) earlyer definitions are
211
+ # replaced when it is called a second time.
212
+ # When false a exception is thrown
97
213
  def initialize name, body, override = true
98
214
  @name = name
99
215
  @body = body
@@ -104,12 +220,21 @@ module RVM
104
220
  if (not @override) and env.function(@name)
105
221
  raise "Function #{@name} already defined!"
106
222
  end
107
- env.def_function(@name.execute(env),@body.execute(env))
223
+ env.def_function(@name.execute(env),@body)
108
224
  nil
109
225
  end
110
226
  end
111
227
 
228
+
229
+ # This is a loop. It is executed over and over again as long as
230
+ # the passed condition evaluates to a value that matches is_true?.
112
231
  class Loop
232
+ # Initializes a new loop.
233
+ #
234
+ # condition:: is executed before each run of the loop. If it evaluates
235
+ # to true the loop is executed another time otherwise the
236
+ # exection ends.
237
+ # body:: For each itteration of the loop this is executed once.
113
238
  def initialize(condition, body)
114
239
  @condition = condition
115
240
  @body = body
@@ -135,6 +260,7 @@ module RVM
135
260
  def data_type
136
261
  @value.data_type
137
262
  end
263
+
138
264
  def == v
139
265
  if v.is_a? Constant
140
266
  @value == v.value
@@ -242,41 +368,12 @@ module RVM
242
368
 
243
369
  def execute env
244
370
  RVM::debug "Executing Variable..."
245
- r = env[@name.execute(env).to_s]
371
+ r = env.read_var_val(@name.execute(env).to_s)
246
372
  @type = r.data_type if r
247
373
  r
248
374
  end
249
375
  end
250
376
 
251
-
252
- # Returns a parameter of the enviroment. This is needed for things like
253
- # *self* or *caller*.
254
- class EnvGetter
255
-
256
- def initialize what
257
- @envvar = what
258
- end
259
-
260
- def data_type
261
- if @envvar == :self or @envvar == :caller
262
- :object
263
- else
264
- :any
265
- end
266
- end
267
-
268
- def execute env
269
- case @envvar
270
- when :self
271
- env.object
272
- when :caller
273
- env.caller
274
- else
275
- RVM::Classes[:sting].new('')
276
- end
277
- end
278
- end
279
-
280
377
  # This evauates to the parameter passed to the function call.
281
378
  # The number of it is evaluated and typecasted to an interger.
282
379
  class Parameter
@@ -322,6 +419,35 @@ module RVM
322
419
  end
323
420
  end
324
421
 
422
+ # This is an exception designed to handle the return statement.
423
+ # It is thrown for for the return and the value can be evaluated.
424
+ #
425
+ # The catching is handled bythe +RVM::Classes::Block+ class.
426
+ class ReturnException < Exception
427
+ attr_reader :val
428
+ def initialize val
429
+ super()
430
+ @val = val
431
+ end
432
+ end
433
+
434
+ # Represents the return statement, it throws a
435
+ # +ReturnException+ which can be caught to have the function
436
+ # or block return what they wish.
437
+ class Return
438
+ def initialize val
439
+ @val = val
440
+ end
441
+
442
+ def data_type
443
+ :any
444
+ end
445
+
446
+ def execute env
447
+ raise ReturnException.new(@val.execute(env))
448
+ end
449
+ end
450
+
325
451
  # A function call or a function or a block. The initialization of a new
326
452
  # enviroment is done by the function Class as it also sorts the arguments
327
453
  # into it.
@@ -21,13 +21,13 @@ module RVM
21
21
  # require 'lib/base/languages'
22
22
  # code = RVM::Classes[:math].compile '(1 + 1) * 3^2'
23
23
  module Languages
24
- extend PluginHost
24
+ extend RVM::PluginHost
25
25
 
26
26
  # The Compiler class, it holds the compiler. As those grow big I suggest
27
27
  # to split the actuall code into multiple fils. Have a look at the MUSHCode
28
28
  # compile for an example.
29
29
  class Language
30
- extend Plugin
30
+ extend RVM::Plugin
31
31
  plugin_host Languages
32
32
  class << self
33
33
 
@@ -37,8 +37,9 @@ module RVM
37
37
  nil
38
38
  end
39
39
 
40
+ # Class method called from the plugin to register witht the plugin host.
40
41
  def register_for *ids
41
- plugin_host.register self.new, *ids
42
+ plugin_host.register self, *ids
42
43
  end
43
44
  end
44
45
  end