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.rb
CHANGED
@@ -2,33 +2,92 @@ require 'rvm/interpreter'
|
|
2
2
|
require 'rvm/classes'
|
3
3
|
require 'rvm/functions'
|
4
4
|
require 'rvm/languages'
|
5
|
-
|
6
|
-
module RVM
|
7
|
-
class << self
|
8
|
-
@@strict = false
|
9
|
-
|
10
|
-
def strict
|
11
|
-
@@strict
|
12
|
-
end
|
13
|
-
|
14
|
-
def compile language, code
|
15
|
-
compiler_for(language).compile(code)
|
16
|
-
end
|
5
|
+
require 'timeout'
|
17
6
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
7
|
+
# This is the rVM library. Including it loads the very basic functionalites rVM offers.
|
8
|
+
#
|
9
|
+
# It however does not yet load any functions or languages for security propose.
|
10
|
+
# This will have to be done by hand for the reason that it will force the user to concider
|
11
|
+
# which functions he wants to offer and which not.
|
12
|
+
#
|
13
|
+
# You may very well load your own functions and languages with rVM in the same way you can
|
14
|
+
# load shipped languages.
|
15
|
+
#
|
16
|
+
# It also contains some usefull functions that wil allow to make the usuage easyer.
|
17
|
+
module RVM
|
18
|
+
|
19
|
+
# This class is designed to allow execting code more safely
|
20
|
+
#
|
21
|
+
# It allows to limit executin in multiple ways to prevent all sorty of runaway code.
|
22
|
+
class Safety
|
23
|
+
|
24
|
+
attr_reader :timeout
|
25
|
+
def initialize
|
26
|
+
@timeout = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
# Sets the timeout for the executin, in seconds (you may use 0.5 and such)
|
30
|
+
#
|
31
|
+
# The execution is aboarded and a exeption thrown if the
|
32
|
+
def timeout=t
|
33
|
+
raise ArgumentError, "The timeout must be a number!" if not t.is_a? Numeric
|
34
|
+
@timeout = t
|
35
|
+
end
|
36
|
+
|
37
|
+
# Executes the code with the former set security measures.
|
38
|
+
#
|
39
|
+
# Exceptions are thrown according to the problem
|
40
|
+
def execute code, env
|
41
|
+
res = nil
|
42
|
+
if @timeout
|
43
|
+
Timeout::timeout(@timeout) do
|
44
|
+
res = code.execute(env)
|
45
|
+
end
|
46
|
+
else
|
47
|
+
res = code.execute(env)
|
48
|
+
end
|
49
|
+
res
|
23
50
|
end
|
24
51
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
52
|
+
class << self
|
53
|
+
@@strict = false
|
54
|
+
|
55
|
+
# This getter returns if rVM handles types strict.
|
56
|
+
#
|
57
|
+
# Calling a method with wrong types will raise a error if this is true.
|
58
|
+
# If false rVM will try to typecast accordingly.
|
59
|
+
def strict
|
60
|
+
@@strict
|
61
|
+
end
|
62
|
+
|
63
|
+
# Sets if variables are strictly typed or casted for function calls.
|
64
|
+
# This allows to make a language either more secure or more flexible.
|
65
|
+
def strict= v
|
66
|
+
@@strict = v
|
67
|
+
end
|
68
|
+
|
69
|
+
# Compils a code the given language.
|
70
|
+
# A new compiler is created for that and discarded afterwards.
|
71
|
+
#
|
72
|
+
# Using +compiler_for+ and calling compile for it yourself
|
73
|
+
# is more performant if you plan on doing thise more then once.
|
74
|
+
def compile language, code
|
75
|
+
compiler_for(language).compile(code)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Creates you a compiler object for the given language.
|
79
|
+
# If no language is given a error is raised.
|
80
|
+
def compiler_for language
|
81
|
+
if (l = RVM::Languages[language])
|
82
|
+
l.new
|
83
|
+
else
|
84
|
+
raise "RVM Error: Unknown Language #{language}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# A utility function to give debug output based on weather $DEBUG is set or not
|
89
|
+
def debug text
|
90
|
+
puts text if $DEBUG
|
91
|
+
end
|
33
92
|
end
|
34
93
|
end
|
data/lib/rvm/classes.rb
CHANGED
@@ -18,7 +18,7 @@ module RVM
|
|
18
18
|
# string = RVM::Classes[:string].new
|
19
19
|
module Classes
|
20
20
|
|
21
|
-
extend PluginHost
|
21
|
+
extend RVM::PluginHost
|
22
22
|
default :string
|
23
23
|
# The Parent for new classes, meant never to be used alone.
|
24
24
|
# It takes care of registering the calss to the PluginHost,
|
@@ -46,9 +46,18 @@ module RVM
|
|
46
46
|
# end
|
47
47
|
class Class
|
48
48
|
|
49
|
-
extend Plugin
|
49
|
+
extend RVM::Plugin
|
50
50
|
plugin_host Classes
|
51
51
|
|
52
|
+
|
53
|
+
def functions
|
54
|
+
@functions ||= {}
|
55
|
+
end
|
56
|
+
|
57
|
+
def variables
|
58
|
+
@variables ||= {:self => self, }
|
59
|
+
end
|
60
|
+
|
52
61
|
# This defines the type of the class, it defaults to :any
|
53
62
|
# it is important for tying and type conversion, as long as it
|
54
63
|
# behaves like a string, it can look like a sting ;)
|
data/lib/rvm/classes/block.rb
CHANGED
@@ -19,7 +19,13 @@ module RVM
|
|
19
19
|
def call params, env
|
20
20
|
#Logger.debug "Calling Block...(#{env},#{params})" if $DEBUG
|
21
21
|
env = RVM::Interpreter::Enviroment.new({:params => params||[]}, env)
|
22
|
-
|
22
|
+
begin
|
23
|
+
@code.execute(env)
|
24
|
+
rescue RVM::Interpreter::ReturnException => e
|
25
|
+
RVM::debug "yuck, cought a result!" if $DEBUG
|
26
|
+
pp e if $DEBUG
|
27
|
+
return e.val
|
28
|
+
end
|
23
29
|
end
|
24
30
|
end
|
25
31
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module RVM
|
2
|
+
module Classes
|
3
|
+
class VMClass < RVM::Classes::Class
|
4
|
+
register_for :class
|
5
|
+
|
6
|
+
attr_reader :object_functions
|
7
|
+
attr_reader :functions
|
8
|
+
|
9
|
+
attr_reader :variables
|
10
|
+
attr_accessor :initializer
|
11
|
+
attr_accessor :parent
|
12
|
+
|
13
|
+
def data_type
|
14
|
+
:class
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(parent = nil, initialize_name = "create");
|
18
|
+
super()
|
19
|
+
@initializer = initialize_name
|
20
|
+
@functions = {}
|
21
|
+
@variables = {}
|
22
|
+
@object_functions = {}
|
23
|
+
@parent = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def obj_send(method, params, env)
|
27
|
+
if method == @initializer
|
28
|
+
instance params, env
|
29
|
+
else
|
30
|
+
m = @functions[method] ||
|
31
|
+
m = @parent.functions(method) if not m and @parent
|
32
|
+
raise "Unknown method #{method} for object #{self}" if not m
|
33
|
+
params.unshift self
|
34
|
+
env = RVM::Interpreter::Enviroment.new({:params => params||[], :locals => @variables, :functions => @functions}, env)
|
35
|
+
m.call(params, env)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def instance params, env
|
40
|
+
o = RVM::Classes::Object.new self
|
41
|
+
env = RVM::Interpreter::Enviroment.new({:params => params||[], :locals => @variables, :functions => @functions}, env)
|
42
|
+
o.obj_send(@initializer, [], env) if @object_functions[@initializer]
|
43
|
+
o
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/rvm/classes/number.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
#TODO: 4
|
2
|
+
module RVM
|
3
|
+
module Classes
|
4
|
+
class Object < RVM::Classes::Class
|
5
|
+
register_for :object
|
6
|
+
attr_reader :functions
|
7
|
+
attr_reader :variables
|
8
|
+
attr_reader :object_class
|
9
|
+
|
10
|
+
def initialize objectClass
|
11
|
+
super()
|
12
|
+
@object_class = objectClass
|
13
|
+
@functions = {}
|
14
|
+
@variables = {}
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def obj_send(method, params, env)
|
19
|
+
m = @functions[method] || @object_class.object_functions(method)
|
20
|
+
raise "Unknown method #{method} for object #{self}" if not m
|
21
|
+
params.unshift self
|
22
|
+
env = RVM::Interpreter::Enviroment.new({:params => params||[], :locals => @variables}, env)
|
23
|
+
m.call(params, env)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def data_type
|
28
|
+
:object
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/rvm/functions.rb
CHANGED
@@ -2,9 +2,9 @@ require File.dirname(__FILE__) + '/plugin'
|
|
2
2
|
require File.dirname(__FILE__) + '/interpreter'
|
3
3
|
module RVM
|
4
4
|
module Functions
|
5
|
-
extend PluginHost
|
5
|
+
extend RVM::PluginHost
|
6
6
|
class Function
|
7
|
-
extend Plugin
|
7
|
+
extend RVM::Plugin
|
8
8
|
plugin_host Functions
|
9
9
|
class << self
|
10
10
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RVM
|
2
|
+
module Functions
|
3
|
+
class Append < Function
|
4
|
+
def Append.execute params, env
|
5
|
+
if params.length == 2
|
6
|
+
array = params.shift
|
7
|
+
value = params.shift
|
8
|
+
array << value
|
9
|
+
else
|
10
|
+
RVM::Classes[:error].new(1,"#-1 FUNCTION (#{self.class.to_s}) EXPECTS 2 OR MORE ARGUMENTS BUT GOT #{params.length}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def Append.signature
|
15
|
+
[:list, :any]
|
16
|
+
end
|
17
|
+
register_for :append
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RVM
|
2
|
+
module Functions
|
3
|
+
class SetAt < Function
|
4
|
+
def SetAt.execute params, env
|
5
|
+
if params.length == 3
|
6
|
+
p params
|
7
|
+
array = params.shift
|
8
|
+
pos = params.shift
|
9
|
+
value = params.shift
|
10
|
+
p array
|
11
|
+
p pos
|
12
|
+
p value
|
13
|
+
array[pos.to_i] = value
|
14
|
+
else
|
15
|
+
RVM::Classes[:error].new(1,"FUNCTION (#{self.class}) EXPECTS 3 ARGUMENTS BUT GOT #{params.length}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def SetAt.signature
|
20
|
+
[:list, :number, :any]
|
21
|
+
end
|
22
|
+
register_for :set_at
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RVM
|
2
|
+
module Functions
|
3
|
+
class Eq < RVM::Functions::Function
|
4
|
+
class << self
|
5
|
+
def execute params, env
|
6
|
+
if params.length == 2
|
7
|
+
return RVM::Classes[:boolean].new(params[0] == params[1])
|
8
|
+
else
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def signature
|
13
|
+
[:any]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
register_for :eq
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RVM
|
2
|
+
module Functions
|
3
|
+
class Gt < RVM::Functions::Function
|
4
|
+
class << self
|
5
|
+
def execute params, env
|
6
|
+
if params.length == 2
|
7
|
+
return RVM::Classes[:boolean].new(params[0] > params[1])
|
8
|
+
else
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def signature
|
13
|
+
[:any]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
register_for :gt
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RVM
|
2
|
+
module Functions
|
3
|
+
class Gte < RVM::Functions::Function
|
4
|
+
class << self
|
5
|
+
def execute params, env
|
6
|
+
if params.length == 2
|
7
|
+
return RVM::Classes[:boolean].new(params[0] >= params[1])
|
8
|
+
else
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def signature
|
13
|
+
[:any]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
register_for :gte
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RVM
|
2
|
+
module Functions
|
3
|
+
class Lt < RVM::Functions::Function
|
4
|
+
class << self
|
5
|
+
def execute params, env
|
6
|
+
if params.length == 2
|
7
|
+
return RVM::Classes[:boolean].new(params[0] < params[1])
|
8
|
+
else
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def signature
|
13
|
+
[:any]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
register_for :lt
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RVM
|
2
|
+
module Functions
|
3
|
+
class Lte < RVM::Functions::Function
|
4
|
+
class << self
|
5
|
+
def execute params, env
|
6
|
+
if params.length == 2
|
7
|
+
return RVM::Classes[:boolean].new(params[0] <= params[1])
|
8
|
+
else
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def signature
|
13
|
+
[:any]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
register_for :lte
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RVM
|
2
|
+
module Functions
|
3
|
+
class Neq < RVM::Functions::Function
|
4
|
+
class << self
|
5
|
+
def execute params, env
|
6
|
+
if params.length == 2
|
7
|
+
return RVM::Classes[:boolean].new(params[0] != params[1])
|
8
|
+
else
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def signature
|
13
|
+
[:any]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
register_for :neq
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|