rVM 0.0.1

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 ADDED
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,85 @@
1
+ # = classes.rb - Class Plugin Library
2
+ #
3
+ # Copyright (C) 2008 Heinz N. Gies (heinz@licenser.net)
4
+ #
5
+ # This file is published under the MIT Licenser, see LICENSE for details.
6
+ #
7
+ require File.dirname(__FILE__) + '/plugin'
8
+ module RVM
9
+ # This module is the basic class container, classes are supposed to be
10
+ # used by this as in: RVM::Classes[<class id>] this guarnatees that,
11
+ # in the case of overwriting a standard class the code still works.
12
+ #
13
+ # == Example
14
+ #
15
+ # === Creating a string calss
16
+ #
17
+ # require 'lib/base/classes'
18
+ # string = RVM::Classes[:string].new
19
+ module Classes
20
+
21
+ extend PluginHost
22
+ plugin_path File.dirname(__FILE__), '../classes/'
23
+ default :string
24
+ # The Parent for new classes, meant never to be used alone.
25
+ # It takes care of registering the calss to the PluginHost,
26
+ # as well of basic functionality.
27
+ #
28
+ # Also it offers access to the function plugins to be used
29
+ # as functions within the commands.
30
+ #
31
+ # == Examples
32
+ #
33
+ # === COMPLES NUMBERS
34
+ #
35
+ # # file: lib/classes/math/complex.rb
36
+ # require 'lib/base/classes'
37
+ # module RVM
38
+ # module Classes
39
+ # class Complex < RVM::Classes::Class
40
+ # def initialize i, n
41
+ # @i = i
42
+ # @j = j
43
+ # end
44
+ # #...
45
+ # end
46
+ # end
47
+ # end
48
+ class Class
49
+
50
+ extend Plugin
51
+ plugin_host Classes
52
+
53
+ # This defines the type of the class, it defaults to :any
54
+ # it is important for tying and type conversion, as long as it
55
+ # behaves like a string, it can look like a sting ;)
56
+ def data_type
57
+ :any
58
+ end
59
+
60
+ # Returns if the objects is true or not,
61
+ # this is interesting for things like errors overwrite it if your
62
+ # class is not always true.
63
+ def is_true?
64
+ true
65
+ end
66
+
67
+ alias method_missing_old method_missing
68
+ alias respond_to_old respond_to?
69
+
70
+ # Implements a fallcback to allow use of function plugins within classes.
71
+ def respond_to?(symbol,include_private = false)
72
+ respond_to_old(symbol,include_private)
73
+ end
74
+
75
+ def method_missing(m, *args)
76
+ if (RVM::Functions.has? m)
77
+ RVM::Functions[m].execute args, @env
78
+ else
79
+ method_missing_old m, *args
80
+ end
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + '/plugin'
2
+ require File.dirname(__FILE__) + '/interpreter'
3
+ module RVM
4
+ module Functions
5
+ extend PluginHost
6
+ plugin_path File.dirname(__FILE__), '../functions/*/'
7
+ class Function
8
+ extend Plugin
9
+ plugin_host Functions
10
+ class << self
11
+
12
+ def data_type
13
+ :any
14
+ end
15
+
16
+ alias method_missing_old method_missing
17
+ alias respond_to_old respond_to?
18
+ def respond_to?(symbol,include_private = false)
19
+ respond_to_old(symbol,include_private)
20
+ end
21
+
22
+ def method_missing(m, *args)
23
+ if (RVM::Functions.has? m)
24
+ RVM::Functions[m].execute args, @env
25
+ else
26
+ method_missing_old m, *args
27
+ end
28
+ end
29
+
30
+ #This is for letting he itnerpreter know that it shall interprete the arguments
31
+ #and not let the function do it itself (this is needed for logical functions)
32
+ def execargs
33
+ true
34
+ end
35
+
36
+ def call params, env
37
+ i = 0
38
+ sig = :any
39
+ params.map! do |p|
40
+ sig = signature[i] || sig
41
+ if sig != :any and p.class != RVM::Classes[sig]
42
+ raise "TYPE MISMATCH" if RVM::strict
43
+ p = RVM::Classes[sig].new(p)
44
+ end
45
+ i+=1
46
+ p
47
+ end if not signature.empty?
48
+ r = execute(params, env)
49
+ RVM::debug "#{self.inspect}: #{signature.inspect} = '#{r}'"
50
+ r
51
+ end
52
+
53
+ def execute params, env
54
+
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,342 @@
1
+ require File.dirname(__FILE__) + '/functions'
2
+ require File.dirname(__FILE__) + '/classes'
3
+ module RVM
4
+ # This Module hold all the VM Classes, so it is quite important to read
5
+ # and understand if you feel like making a own compiler.
6
+ #
7
+ # The basic idea is to translate your own code into a tree of objects
8
+ # from this.
9
+ #
10
+ module Interpreter
11
+
12
+ # This is a helper fuctio to quickly generate a empty enviorment.
13
+ def Interpreter.env aenv = {}
14
+ RVM::debug "Interpreter.env"
15
+ Enviroment.new aenv
16
+ end
17
+
18
+ # This is a helper function that generates a constat of a simple constant,
19
+ # for example if you've a lot of string constants it is way quickly to call
20
+ # this then writing it out the whole time.
21
+ def Interpreter.const type,value
22
+ RVM::Interpreter::Constant.new(RVM::Classes[type].new(value))
23
+ end
24
+
25
+ # This class represents the enviroment, the memory so to say for the VM.
26
+ # The enviroment holds enviromental variables like who executes the
27
+ # code, on what object it runs, what parameters where passed to the call
28
+ # and as well, and perhaps most importantly the local variables.
29
+ #
30
+ # Some of the functions called will initialize new enviroments, as
31
+ # for example function calls.
32
+ class Enviroment
33
+ # This creates a new enviroment enviroment, it generates a new env
34
+ # default variables are set if not defined in *data*.
35
+ #
36
+ # If *oldenv* is provided it will also fall back to see if not
37
+ # existing variables
38
+ def initialize data = {}, oldenv=nil
39
+ RVM::debug "data: #{data}\noldenv:#{oldenv}"
40
+ @data = {
41
+ :locals => {},
42
+ :caller => nil,
43
+ :self => nil,
44
+ :evaldeepth => 0,
45
+ :params => []
46
+ }.merge(data)
47
+ @prev = oldenv || {}
48
+ RVM::debug "Creating new enviroment with: #{@data.inspect} as child of #{@prev}"
49
+
50
+ end
51
+
52
+ # returns the object that issued the VM call - so to say it's owner.
53
+ #
54
+ # If the current enviroment has no caller it tries it's 'oldenv' attrib
55
+ # to see if that had a owner.
56
+ def caller
57
+ r = @data[:caller] || (@prev.is_a?(Enviroment) ? @prev.caller : nil)
58
+ RVM::debug "Getting caller: #{r}"
59
+ r
60
+ end
61
+
62
+ # returns the object that the code is run as, so it has the rights of
63
+ # this object.
64
+ #
65
+ # If the current enviroment has no object it tries it's 'oldenv' attrib
66
+ # to see if that had a object.
67
+ def object
68
+ r = @data[:self] || (@prev.is_a?(Enviroment) ? @prev.object : nil)
69
+ RVM::debug "Getting object: #{r}"
70
+ r
71
+ end
72
+
73
+ # returns a parameter that was passed to the call. For function calls
74
+ # this is especially important, it beginns with 0.
75
+ #
76
+ # If the current enviroment does not have the given paramenter it tries
77
+ # it's 'oldenv' attrib to see if that had a object.
78
+ def param i
79
+ RVM::debug "Getting param #{i} (#{@data[:params][i]})"
80
+ @data[:params][i]
81
+ end
82
+
83
+ # Returns a local variable with the given name.
84
+ #
85
+ # If the current enviroment does not have any local variables with
86
+ # the given name it tries the privious enviroments.
87
+ def [] k
88
+ r = @data[:locals][k] || @prev[k]
89
+ RVM::debug "Getting ariable #{k} (#{r})"
90
+ r
91
+ end
92
+
93
+ #Sets a local variable witin the enviroment.
94
+ def []= k, v
95
+ #TODO: add capability to have the privious env variables changed
96
+ RVM::debug "Setting variable #{k} to #{v}"
97
+ @data[:locals][k] = v
98
+ end
99
+
100
+ end
101
+
102
+ # A constant, it evaluates to thevalue given and end the evaluation.
103
+ # Meaning that no further execution is done in this tree branch, so the
104
+ # value isn't evaluated.
105
+ class Constant
106
+ attr_reader :value
107
+ def initialize value
108
+ @value = value
109
+ end
110
+
111
+ def data_type
112
+ @value.data_type
113
+ end
114
+ def == v
115
+ if v.is_a? Constant
116
+ @value == v.value
117
+ else
118
+ false
119
+ end
120
+ end
121
+
122
+ def execute env
123
+ RVM::debug "Executing Constant: #{@value}"
124
+ @value
125
+ end
126
+ end
127
+
128
+ # The condition is most widely known as 'if' statement, also the tertier
129
+ # opperator is a condition.
130
+ #
131
+ # Conditions are quite important, elseif can be implemented by chaining
132
+ # if statements.
133
+ #
134
+ # == Example
135
+ #
136
+ # === TRANSLATING IF
137
+ #
138
+ # cond = Interpreter::Condition.new(
139
+ # <... thing for the condition ...>,
140
+ # <... what to do if condition is true ...>
141
+ # [<... what to do if condition is false ...>])
142
+ #
143
+ # if now cond.execute is called the following happens:
144
+ # * execute is called for the condition
145
+ # * if the result of it true and is_true? is also true:
146
+ # * execute for the true case is called and it's result returned
147
+ # * if the result is false or is_true? is false:
148
+ # * execute is called for the false case and it's result is returned
149
+ class Condition
150
+ # Creates a new condition with the given parameters. The false_case can
151
+ # be ommitted.
152
+ #
153
+ # * value - is executed, and depandant of the result either true_case or
154
+ # false casae s executed.
155
+ # * true_case - is only executed if value evalutes to true (is_true?)
156
+ # * false_case - is only executed if value evalutes to false (!is_true?)
157
+ def initialize value, true_case, false_case = nil
158
+ @value = value
159
+ @true_case = true_case
160
+ @false_case = false_case
161
+ end
162
+
163
+ def data_type
164
+ if @true_case.data_type == @false_case.data_type
165
+ @false_case.data_type
166
+ else
167
+ :any
168
+ end
169
+ end
170
+
171
+ def execute env
172
+ if @value.execute(env).is_true?
173
+ RVM::debug "Executing Condition... (true)"
174
+ @true_case.execute env
175
+ elsif @false_case
176
+ RVM::debug "Executing Condition... (false)"
177
+ @false_case.execute env
178
+ end
179
+ end
180
+ end
181
+
182
+ # A variable assignment that sets a local variable, a declaration
183
+ # is not required before the assignment can be done.
184
+ #
185
+ # Both the *name* and the *value* are evaluated before the assignment
186
+ # is done.
187
+ class Assignment
188
+ def initialize name, value
189
+ @name = name
190
+ @value = value
191
+ end
192
+
193
+ def data_type
194
+ @value.data_type
195
+ end
196
+
197
+ def execute env
198
+ RVM::debug "Executing Assignment..."
199
+ env[@name.execute(env).to_s] = @value.execute env
200
+ end
201
+ end
202
+
203
+ # Reads the value of a variable in the enviroment.
204
+ #
205
+ # The *name* is evaluated before the variable is retrieved.
206
+ class Variable
207
+ def initialize name
208
+ @name = name
209
+ @type = :any
210
+ end
211
+
212
+ # The type can only be tretrieved when the name is aconstant
213
+ # as it can be evaluated without sideffect.
214
+ def data_type
215
+ @type
216
+ end
217
+
218
+ def execute env
219
+ RVM::debug "Executing Variable..."
220
+ r = env[@name.execute(env).to_s]
221
+ @type = r.data_type
222
+ r
223
+ end
224
+ end
225
+
226
+
227
+ # Returns a parameter of the enviroment. This is needed for things like
228
+ # *self* or *caller*.
229
+ class EnvGetter
230
+
231
+ def initialize what
232
+ @envvar = what
233
+ end
234
+
235
+ def data_type
236
+ if @envvar == :self or @envvar == :caller
237
+ :object
238
+ else
239
+ :any
240
+ end
241
+ end
242
+
243
+ def execute env
244
+ case @envvar
245
+ when :self
246
+ env.object
247
+ when :caller
248
+ env.caller
249
+ else
250
+ RVM::Classes[:sting].new('')
251
+ end
252
+ end
253
+ end
254
+
255
+ # This evauates to the parameter passed to the function call.
256
+ # The number of it is evaluated and typecasted to an interger.
257
+ class Parameter
258
+ def initialize num
259
+ @num = num
260
+ @type = :any
261
+ end
262
+
263
+ # The type can only be tretrieved when the num is aconstant
264
+ # as it can be evaluated without sideffect.
265
+ def data_type
266
+ @type
267
+ end
268
+
269
+ def execute env
270
+ RVM::debug "Executing Parameter..."
271
+ r = env.param(@num.execute(env).to_i)
272
+ @type = r.data_type
273
+ r
274
+ end
275
+ end
276
+
277
+ # A sequence is a list of commands that are executed one after
278
+ # another.
279
+ # The type of the squence is equal to the last element of the sequence.
280
+ class Sequence < Array
281
+ def execute env
282
+ RVM::debug "Executing Sequence... #{inspect}"
283
+ r = nil
284
+ self.map { |seq|
285
+ RVM::debug "Executing Sequence step..."
286
+ r = seq.execute env
287
+ }
288
+ r
289
+ end
290
+
291
+ def data_type
292
+ :any
293
+ end
294
+ end
295
+
296
+ # A function call or a function or a block. The initialization of a new
297
+ # enviroment is done by the function Class as it also sorts the arguments
298
+ # into it.
299
+ #
300
+ # Arguments are only executed when the function does return true for
301
+ # execargs.
302
+ class FunctionCall
303
+ attr_reader :arguments
304
+ attr_reader :function
305
+ # The constructor. *function* can either be a block object or a function
306
+ # class.
307
+ #
308
+ # Arguments is a list of the arguments to the function.
309
+ def initialize function, arguments
310
+ if function.is_a? RVM::Classes[:block]
311
+ @function = function
312
+ else
313
+ @function = RVM::Functions[function]
314
+ end
315
+ @arguments = arguments
316
+ end
317
+
318
+ def data_type
319
+ @function.data_type
320
+ end
321
+
322
+ def == v
323
+ if v.is_a? FunctionCall
324
+ (@arguments == v.arguments) && (@function == v.function)
325
+ else
326
+ false
327
+ end
328
+ end
329
+
330
+ def execute env
331
+ RVM::debug "Executing FunctionCall..."
332
+ args = @arguments
333
+ if @function.execargs
334
+ args = @arguments.map do |arg|
335
+ arg.execute env
336
+ end
337
+ end
338
+ @function.call(args, env)
339
+ end
340
+ end
341
+ end
342
+ end
@@ -0,0 +1,47 @@
1
+ # = languages.rb - Class Plugin Library
2
+ #
3
+ # Copyright (C) 2008 Heinz N. Gies (heinz@licenser.net)
4
+ #
5
+ # This file is published under the MIT Licenser, see LICENSE for details.
6
+ require File.dirname(__FILE__) + '/plugin'
7
+ module RVM
8
+ # This module is the basic language container, classes are supposed to be
9
+ # used by this as in: RVM::Language[<class id>] this guarnatees that,
10
+ # in the case of overwriting a standard compilers the code still works.
11
+ #
12
+ # This are *COMPILERS* not *INTERPRETERS* they compile source code to a
13
+ # VM bytecode to be executed later
14
+ #
15
+ # Have a look at RVM::Interpreter for details
16
+ #
17
+ # == Example
18
+ #
19
+ # === COMPILING A MATHEMATICAL EQUILATION
20
+ #
21
+ # require 'lib/base/languages'
22
+ # code = RVM::Classes[:math].compile '(1 + 1) * 3^2'
23
+ module Languages
24
+ extend PluginHost
25
+ plugin_path File.dirname(__FILE__), '../languages'
26
+
27
+ # The Compiler class, it holds the compiler. As those grow big I suggest
28
+ # to split the actuall code into multiple fils. Have a look at the MUSHCode
29
+ # compile for an example.
30
+ class Language
31
+ extend Plugin
32
+ plugin_host Languages
33
+ class << self
34
+
35
+ # Method placeholder, your compiler /needs/ to implement this
36
+ # or it won't work (of cause).
37
+ def compile code
38
+ nil
39
+ end
40
+
41
+ def register_for *ids
42
+ plugin_host.register self.new, *ids
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end