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.
- data/lib/rvm.rb +84 -25
- data/lib/rvm/classes.rb +11 -2
- data/lib/rvm/classes/block.rb +7 -1
- data/lib/rvm/classes/class.rb +48 -0
- data/lib/rvm/classes/number.rb +1 -0
- data/lib/rvm/classes/object.rb +33 -0
- data/lib/rvm/functions.rb +2 -2
- data/lib/rvm/functions/array.rb +3 -0
- data/lib/rvm/functions/array/append.rb +20 -0
- data/lib/rvm/functions/array/set_at.rb +25 -0
- data/lib/rvm/functions/general/eq.rb +19 -0
- data/lib/rvm/functions/general/gt.rb +19 -0
- data/lib/rvm/functions/general/gte.rb +19 -0
- data/lib/rvm/functions/general/lt.rb +19 -0
- data/lib/rvm/functions/general/lte.rb +19 -0
- data/lib/rvm/functions/general/neq.rb +19 -0
- data/lib/rvm/functions/logic.rb +3 -0
- data/lib/rvm/functions/logic/not.rb +17 -0
- data/lib/rvm/functions/logic/or.rb +24 -0
- data/lib/rvm/functions/math/add.rb +3 -3
- data/lib/rvm/functions/math/div.rb +4 -6
- data/lib/rvm/functions/math/mul.rb +1 -1
- data/lib/rvm/functions/math/sub.rb +1 -1
- data/lib/rvm/functions/objects/send.rb +22 -0
- data/lib/rvm/interpreter.rb +167 -41
- data/lib/rvm/languages.rb +4 -3
- data/lib/rvm/languages/brainfuck.rb +13 -4
- data/lib/rvm/languages/ecma.rb +997 -0
- data/lib/rvm/languages/math.rb +19 -1
- data/lib/rvm/library.rb +71 -0
- data/lib/rvm/plugin.rb +221 -219
- metadata +22 -8
- data/lib/rvm/languages/simple.rb +0 -15
- data/lib/rvm/languages/simple/compiler.rb +0 -73
- data/lib/rvm/languages/simple/tokenizer.rb +0 -75
- data/lib/rvm/languages/simple/tree.rb +0 -144
data/lib/rvm/languages/math.rb
CHANGED
@@ -4,7 +4,25 @@ require File.dirname(__FILE__) + '/math/compiler'
|
|
4
4
|
require 'rvm/functions/math'
|
5
5
|
module RVM
|
6
6
|
module Languages
|
7
|
-
|
7
|
+
# This compiler handels mathematical expressions.
|
8
|
+
#
|
9
|
+
# It is limited to smiple terms, as in for example integration of functions is not offered.
|
10
|
+
# Yet it is hopefully enough to serve most mathematical needs.
|
11
|
+
#
|
12
|
+
# Included are:
|
13
|
+
# * Opperators: +, -, *, /, ^
|
14
|
+
# * Parenthetes
|
15
|
+
# * Functions (as in proveded by the 'rvm/funcions/math' library or custom loaded)
|
16
|
+
# * Currect prioriets in execution
|
17
|
+
# * Support for variables (getting and setting)
|
18
|
+
# * Multiple concatinated statemetns sepperated by ';'
|
19
|
+
# * Custom functions (as in defining as well as calling)
|
20
|
+
module Math
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
# See the Math module for a description of this compiler.
|
25
|
+
class MathLanguage < RVM::Languages::Language
|
8
26
|
include Math
|
9
27
|
def compile text
|
10
28
|
Compiler.compile(Tree.generate(Tokenizer.tokenize(text)))
|
data/lib/rvm/library.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rvm'
|
2
|
+
|
3
|
+
module RVM
|
4
|
+
|
5
|
+
# The Library class is made to provide library loading capabilites
|
6
|
+
# using any rVM supporte langauges and build a frontend between
|
7
|
+
# the rVM code and the Ruby code
|
8
|
+
#
|
9
|
+
# A Library can hold the content of more then one, file and the loaded
|
10
|
+
# files are not required to have the same langauge
|
11
|
+
class Library
|
12
|
+
# This maps rVM classes to usual Ruby classes so you won't need to take care of it
|
13
|
+
CLASS_MAP={
|
14
|
+
String => RVM::Classes::String,
|
15
|
+
Fixnum => RVM::Classes::Number,
|
16
|
+
Bignum => RVM::Classes::Number,
|
17
|
+
Float => RVM::Classes::Number,
|
18
|
+
FalseClass => RVM::Classes::Boolean,
|
19
|
+
TrueClass => RVM::Classes::Boolean,
|
20
|
+
Array => RVM::Classes::List
|
21
|
+
}
|
22
|
+
# Initializes library, if anguage and file are given, they are loaded
|
23
|
+
# Optionally a saftey object can be passed to handle securing the
|
24
|
+
# interpreted code
|
25
|
+
def initialize(language = nil, file = nil, safety = RVM::Safety.new)
|
26
|
+
@env = RVM::Interpreter.env()
|
27
|
+
@safety = safety
|
28
|
+
load_library(language, file) if language and file
|
29
|
+
end
|
30
|
+
|
31
|
+
#Loads a file into the Library, attention it is executed!
|
32
|
+
def load_library(language, file)
|
33
|
+
@safety.execute(RVM::Languages[language].new.compile(File.new(file).read),@env)
|
34
|
+
end
|
35
|
+
|
36
|
+
# This is the most important part, so to say, the ruby magic in here
|
37
|
+
# If a unknown method is called this gets executed to try to resole it form the
|
38
|
+
# loaded libraires
|
39
|
+
#
|
40
|
+
# Priorities are:
|
41
|
+
# 1) check the functions
|
42
|
+
# 2) check if it was a variable
|
43
|
+
# 3) check if the call ended with a '=' then set it's as variable
|
44
|
+
# 4) call super
|
45
|
+
def method_missing(m, *args)
|
46
|
+
# First we convert the args
|
47
|
+
vmargs = args.map do |arg|
|
48
|
+
if c = CLASS_MAP[arg.class]
|
49
|
+
c.new(arg)
|
50
|
+
else
|
51
|
+
arg
|
52
|
+
end
|
53
|
+
end
|
54
|
+
n = m.to_s
|
55
|
+
if fun = @env.function(n)
|
56
|
+
fun.call(@env, vmargs)
|
57
|
+
elsif v = @env[n]
|
58
|
+
v.val
|
59
|
+
elsif n =~ /=$/
|
60
|
+
@env[n.gsub(/=$/,'')] = vmargs.first
|
61
|
+
else
|
62
|
+
super(m,args)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
data/lib/rvm/plugin.rb
CHANGED
@@ -24,248 +24,250 @@
|
|
24
24
|
#
|
25
25
|
# Thanks a lot to Murphy, this code is borrowed from coderay.
|
26
26
|
#
|
27
|
-
module
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
# Alias for +[]+.
|
54
|
-
alias load []
|
55
|
-
|
56
|
-
class << self
|
57
|
-
|
58
|
-
# Adds the module/class to the PLUGIN_HOSTS list.
|
59
|
-
def extended mod
|
60
|
-
PLUGIN_HOSTS << mod
|
61
|
-
end
|
62
|
-
|
63
|
-
# Warns you that you should not #include this module.
|
64
|
-
def included mod
|
65
|
-
warn "#{name} should not be included. Use extend."
|
27
|
+
module RVM
|
28
|
+
module PluginHost
|
29
|
+
|
30
|
+
# Raised if Encoders::[] fails because:
|
31
|
+
# * a file could not be found
|
32
|
+
# * the requested Encoder is not registered
|
33
|
+
PluginNotFound = Class.new Exception
|
34
|
+
HostNotFound = Class.new Exception
|
35
|
+
|
36
|
+
PLUGIN_HOSTS = []
|
37
|
+
PLUGIN_HOSTS_BY_ID = {} # dummy hash
|
38
|
+
|
39
|
+
# Loads all plugins using all_plugin_names and load.
|
40
|
+
|
41
|
+
|
42
|
+
# Returns the Plugin for +id+.
|
43
|
+
#
|
44
|
+
# Example:
|
45
|
+
# yaml_plugin = MyPluginHost[:yaml]
|
46
|
+
def [] id, *args, &blk
|
47
|
+
plugin = validate_id(id)
|
48
|
+
begin
|
49
|
+
plugin = plugin_hash.[] plugin, *args, &blk
|
50
|
+
end while plugin.is_a? Symbol
|
51
|
+
plugin
|
66
52
|
end
|
67
|
-
|
68
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
53
|
+
|
54
|
+
# Alias for +[]+.
|
55
|
+
alias load []
|
56
|
+
|
57
|
+
class << self
|
58
|
+
|
59
|
+
# Adds the module/class to the PLUGIN_HOSTS list.
|
60
|
+
def extended mod
|
61
|
+
PLUGIN_HOSTS << mod
|
62
|
+
end
|
63
|
+
|
64
|
+
# Warns you that you should not #include this module.
|
65
|
+
def included mod
|
66
|
+
warn "#{name} should not be included. Use extend."
|
67
|
+
end
|
68
|
+
|
69
|
+
# Find the PluginHost for host_id.
|
70
|
+
def host_by_id host_id
|
71
|
+
unless PLUGIN_HOSTS_BY_ID.default_proc
|
72
|
+
ph = Hash.new do |h, a_host_id|
|
73
|
+
for host in PLUGIN_HOSTS
|
74
|
+
h[host.host_id] = host
|
75
|
+
end
|
76
|
+
h.fetch a_host_id, nil
|
74
77
|
end
|
75
|
-
|
78
|
+
PLUGIN_HOSTS_BY_ID.replace ph
|
76
79
|
end
|
77
|
-
PLUGIN_HOSTS_BY_ID
|
80
|
+
PLUGIN_HOSTS_BY_ID[host_id]
|
78
81
|
end
|
79
|
-
|
82
|
+
|
80
83
|
end
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
name
|
84
|
+
|
85
|
+
# The host's ID.
|
86
|
+
#
|
87
|
+
# If PLUGIN_HOST_ID is not set, it is simply the class name.
|
88
|
+
def host_id
|
89
|
+
if self.const_defined? :PLUGIN_HOST_ID
|
90
|
+
self::PLUGIN_HOST_ID
|
91
|
+
else
|
92
|
+
name
|
93
|
+
end
|
92
94
|
end
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
95
|
+
|
96
|
+
# Map a plugin_id to another.
|
97
|
+
#
|
98
|
+
# Usage: Put this in a file plugin_path/_map.rb.
|
99
|
+
#
|
100
|
+
# class MyColorHost < PluginHost
|
101
|
+
# map :navy => :dark_blue,
|
102
|
+
# :maroon => :brown,
|
103
|
+
# :luna => :moon
|
104
|
+
# end
|
105
|
+
def map hash
|
106
|
+
for from, to in hash
|
107
|
+
from = validate_id from
|
108
|
+
to = validate_id to
|
109
|
+
plugin_hash[from] = to unless plugin_hash.has_key? from
|
110
|
+
end
|
109
111
|
end
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
raise ArgumentError,
|
112
|
+
|
113
|
+
# Define the default plugin to use when no plugin is found
|
114
|
+
# for a given id.
|
115
|
+
#
|
116
|
+
# See also map.
|
117
|
+
#
|
118
|
+
# class MyColorHost < PluginHost
|
119
|
+
# map :navy => :dark_blue
|
120
|
+
# default :gray
|
121
|
+
# end
|
122
|
+
def default id
|
123
|
+
id = validate_id id
|
124
|
+
plugin_hash[nil] = id
|
125
|
+
end
|
126
|
+
|
127
|
+
# Every plugin must register itself for one or more
|
128
|
+
# +ids+ by calling register_for, which calls this method.
|
129
|
+
#
|
130
|
+
# See Plugin#register_for.
|
131
|
+
def register plugin, *ids
|
132
|
+
for id in ids
|
133
|
+
unless id.is_a? Symbol
|
134
|
+
raise ArgumentError,
|
134
135
|
"id must be a Symbol, but it was a #{id.class}"
|
136
|
+
end
|
137
|
+
plugin_hash[validate_id(id)] = plugin
|
135
138
|
end
|
136
|
-
plugin_hash[validate_id(id)] = plugin
|
137
139
|
end
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
@plugin_hash ||= create_plugin_hash
|
143
|
-
end
|
144
|
-
|
145
|
-
def has? id
|
146
|
-
plugin_hash.has_key? id
|
147
|
-
end
|
148
|
-
|
149
|
-
# Makes a map of all loaded plugins.
|
150
|
-
def inspect
|
151
|
-
map = plugin_hash.dup
|
152
|
-
map.each do |id, plugin|
|
153
|
-
map[id] = plugin.to_s[/(?>[\w_]+)$/]
|
140
|
+
|
141
|
+
# A Hash of plugion_id => Plugin pairs.
|
142
|
+
def plugin_hash
|
143
|
+
@plugin_hash ||= create_plugin_hash
|
154
144
|
end
|
145
|
+
|
146
|
+
def has? id
|
147
|
+
plugin_hash.has_key? id
|
148
|
+
end
|
149
|
+
|
150
|
+
# Makes a map of all loaded plugins.
|
151
|
+
def inspect
|
152
|
+
map = plugin_hash.dup
|
153
|
+
map.each do |id, plugin|
|
154
|
+
map[id] = plugin.to_s[/(?>[\w_]+)$/]
|
155
|
+
end
|
155
156
|
"#{name}[#{host_id}]#{map.inspect}"
|
156
|
-
|
157
|
-
|
158
|
-
protected
|
159
|
-
|
160
|
-
|
161
|
-
|
157
|
+
end
|
158
|
+
|
159
|
+
protected
|
160
|
+
# Created a new plugin list and stores it to @plugin_hash.
|
161
|
+
def create_plugin_hash
|
162
|
+
@plugin_hash =
|
162
163
|
Hash.new do |h, plugin_id|
|
163
164
|
raise "Plugin #{plugin_id} not loaded."
|
164
165
|
end
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
166
|
+
end
|
167
|
+
|
168
|
+
# Returns the Plugin for +id+.
|
169
|
+
# Use it like Hash#fetch.
|
170
|
+
#
|
171
|
+
# Example:
|
172
|
+
# yaml_plugin = MyPluginHost[:yaml, :default]
|
173
|
+
def fetch id, *args, &blk
|
174
|
+
plugin_hash.fetch validate_id(id), *args, &blk
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
# Converts +id+ to a Symbol if it is a String,
|
179
|
+
# or returns +id+ if it already is a Symbol.
|
180
|
+
#
|
181
|
+
# Raises +ArgumentError+ for all other objects, or if the
|
182
|
+
# given String includes non-alphanumeric characters (\W).
|
183
|
+
def validate_id id
|
184
|
+
if id.is_a? Symbol or id.nil?
|
185
|
+
id
|
186
|
+
elsif id.is_a? String
|
187
|
+
if id[/\w+/] == id
|
188
|
+
id.to_sym
|
189
|
+
else
|
190
|
+
raise ArgumentError, "Invalid id: '#{id}' given."
|
191
|
+
end
|
188
192
|
else
|
189
|
-
raise ArgumentError,
|
190
|
-
end
|
191
|
-
else
|
192
|
-
raise ArgumentError,
|
193
|
+
raise ArgumentError,
|
193
194
|
"String or Symbol expected, but #{id.class} given."
|
195
|
+
end
|
194
196
|
end
|
197
|
+
|
195
198
|
end
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
# = Plugin
|
201
|
-
#
|
202
|
-
# Plugins have to include this module.
|
203
|
-
#
|
204
|
-
# IMPORTANT: use extend for this module.
|
205
|
-
#
|
206
|
-
# Example: see PluginHost.
|
207
|
-
module Plugin
|
208
|
-
|
209
|
-
def included mod
|
210
|
-
warn "#{name} should not be included. Use extend."
|
211
|
-
end
|
212
|
-
|
213
|
-
# Register this class for the given langs.
|
214
|
-
# Example:
|
215
|
-
# class MyPlugin < PluginHost::BaseClass
|
216
|
-
# register_for :my_id
|
217
|
-
# ...
|
218
|
-
# end
|
199
|
+
|
200
|
+
|
201
|
+
# = Plugin
|
219
202
|
#
|
220
|
-
#
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
203
|
+
# Plugins have to include this module.
|
204
|
+
#
|
205
|
+
# IMPORTANT: use extend for this module.
|
206
|
+
#
|
207
|
+
# Example: see PluginHost.
|
208
|
+
module Plugin
|
209
|
+
|
210
|
+
def included mod
|
211
|
+
warn "#{name} should not be included. Use extend."
|
212
|
+
end
|
213
|
+
|
214
|
+
# Register this class for the given langs.
|
215
|
+
# Example:
|
216
|
+
# class MyPlugin < PluginHost::BaseClass
|
217
|
+
# register_for :my_id
|
218
|
+
# ...
|
219
|
+
# end
|
220
|
+
#
|
221
|
+
# See PluginHost.register.
|
222
|
+
def register_for *ids
|
223
|
+
plugin_host.register self, *ids
|
224
|
+
end
|
225
|
+
|
226
|
+
# The host for this Plugin class.
|
227
|
+
def plugin_host host = nil
|
228
|
+
if host and not host.is_a? PluginHost
|
229
|
+
raise ArgumentError,
|
229
230
|
"PluginHost expected, but #{host.class} given."
|
231
|
+
end
|
232
|
+
self.const_set :PLUGIN_HOST, host if host and not self.const_defined?(:PLUGIN_HOST)
|
233
|
+
self::PLUGIN_HOST
|
234
|
+
end
|
235
|
+
|
236
|
+
# Require some helper files.
|
237
|
+
#
|
238
|
+
# Example:
|
239
|
+
#
|
240
|
+
# class MyPlugin < PluginHost::BaseClass
|
241
|
+
# register_for :my_id
|
242
|
+
# helper :my_helper
|
243
|
+
#
|
244
|
+
# The above example loads the file myplugin/my_helper.rb relative to the
|
245
|
+
# file in which MyPlugin was defined.
|
246
|
+
def helper *helpers
|
247
|
+
for helper in helpers
|
248
|
+
self::PLUGIN_HOST.require_helper plugin_id, helper.to_s
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# Returns the pulgin id used by the engine.
|
253
|
+
def plugin_id
|
254
|
+
name[/[\w_]+$/].downcase
|
230
255
|
end
|
231
|
-
|
232
|
-
self::PLUGIN_HOST
|
256
|
+
|
233
257
|
end
|
234
|
-
|
235
|
-
|
258
|
+
|
259
|
+
|
260
|
+
# Convenience method for plugin loading.
|
261
|
+
# The syntax used is:
|
236
262
|
#
|
237
|
-
#
|
263
|
+
# require_plugin '<Host ID>/<Plugin ID>'
|
238
264
|
#
|
239
|
-
#
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
# file in which MyPlugin was defined.
|
245
|
-
def helper *helpers
|
246
|
-
for helper in helpers
|
247
|
-
self::PLUGIN_HOST.require_helper plugin_id, helper.to_s
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
# Returns the pulgin id used by the engine.
|
252
|
-
def plugin_id
|
253
|
-
name[/[\w_]+$/].downcase
|
254
|
-
end
|
255
|
-
|
256
|
-
end
|
257
|
-
|
258
|
-
|
259
|
-
# Convenience method for plugin loading.
|
260
|
-
# The syntax used is:
|
261
|
-
#
|
262
|
-
# require_plugin '<Host ID>/<Plugin ID>'
|
263
|
-
#
|
264
|
-
# Returns the loaded plugin.
|
265
|
-
def require_plugin path
|
266
|
-
host_id, plugin_id = path.split '/', 2
|
267
|
-
host = PluginHost.host_by_id(host_id)
|
268
|
-
raise PluginHost::HostNotFound,
|
265
|
+
# Returns the loaded plugin.
|
266
|
+
def require_plugin path
|
267
|
+
host_id, plugin_id = path.split '/', 2
|
268
|
+
host = PluginHost.host_by_id(host_id)
|
269
|
+
raise PluginHost::HostNotFound,
|
269
270
|
"No host for #{host_id.inspect} found." unless host
|
270
|
-
|
271
|
-
end
|
271
|
+
host.load plugin_id
|
272
|
+
end
|
273
|
+
end
|