rVM 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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