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