borx 0.0.1.alpha2 → 0.0.1.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/borx.rb +13 -0
- data/lib/borx/binding.rb +40 -0
- data/lib/borx/environment.rb +61 -14
- data/lib/borx/rewriter.rb +7 -8
- metadata +1 -1
data/lib/borx.rb
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
module Borx
|
2
2
|
|
3
|
+
def self.Binding(binding = nil)
|
4
|
+
if binding.kind_of? ::Binding
|
5
|
+
return Binding::Adapter.new(binding)
|
6
|
+
elsif binding.kind_of? Binding
|
7
|
+
return binding
|
8
|
+
elsif binding.nil?
|
9
|
+
return Binding::Terminal.new
|
10
|
+
else
|
11
|
+
raise ArgumentError, "Expected a Binding, got #{binding.inspect}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
3
15
|
end
|
4
16
|
|
5
17
|
require 'borx/environment'
|
6
18
|
require 'borx/rewriter'
|
19
|
+
require 'borx/binding'
|
data/lib/borx/binding.rb
CHANGED
@@ -31,6 +31,20 @@ class Borx::Binding
|
|
31
31
|
@variables[name] = value
|
32
32
|
end
|
33
33
|
|
34
|
+
alias actual_binding binding
|
35
|
+
|
36
|
+
def cached_actual_binding
|
37
|
+
@actual_binding ||= actual_binding
|
38
|
+
end
|
39
|
+
|
40
|
+
def binding
|
41
|
+
return self
|
42
|
+
end
|
43
|
+
|
44
|
+
def eval(code, *args)
|
45
|
+
Kernel::eval(code, cached_actual_binding, *args)
|
46
|
+
end
|
47
|
+
|
34
48
|
def block(*args, &block)
|
35
49
|
Block.new(self, args, block)
|
36
50
|
end
|
@@ -54,6 +68,28 @@ class Borx::Binding
|
|
54
68
|
|
55
69
|
end
|
56
70
|
|
71
|
+
class Terminal < self
|
72
|
+
|
73
|
+
def initialize
|
74
|
+
@variables = {}
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_variable(name)
|
78
|
+
return @variables[name]
|
79
|
+
end
|
80
|
+
|
81
|
+
def set_variable(name, value)
|
82
|
+
return @variables[name] = value
|
83
|
+
end
|
84
|
+
|
85
|
+
def variable?(name)
|
86
|
+
return @variables.key?(name)
|
87
|
+
end
|
88
|
+
|
89
|
+
alias set_variable! set_variable
|
90
|
+
|
91
|
+
end
|
92
|
+
|
57
93
|
class Adapter < self
|
58
94
|
|
59
95
|
def initialize(real_binding)
|
@@ -73,6 +109,10 @@ class Borx::Binding
|
|
73
109
|
return @binding.eval("local_variables.any?{|v| v.to_s == #{name.inspect}}")
|
74
110
|
end
|
75
111
|
|
112
|
+
def eval(*args)
|
113
|
+
@binding.eval(*args)
|
114
|
+
end
|
115
|
+
|
76
116
|
end
|
77
117
|
|
78
118
|
end
|
data/lib/borx/environment.rb
CHANGED
@@ -22,6 +22,58 @@ base = Class.new do
|
|
22
22
|
raise Borx::Environment::NotImplemented::SetVariable
|
23
23
|
end
|
24
24
|
|
25
|
+
def get_magic(binding, name, actual)
|
26
|
+
raise Borx::Environment::NotImplemented::GetMagic
|
27
|
+
end
|
28
|
+
|
29
|
+
# @!method eval(code, binding = nil, file = 'borx', line = 0)
|
30
|
+
# @param [String, Borx::Code] code
|
31
|
+
# @param [Binding, Borx::Binding, nil] binding
|
32
|
+
# @param [String] file
|
33
|
+
# @param [Numeric] line
|
34
|
+
#
|
35
|
+
# @!method eval(code, options = {})
|
36
|
+
# @param [String, Borx::Code] code
|
37
|
+
# @param [Hash] options
|
38
|
+
# @option options [Binding, Borx::Binding] :binding
|
39
|
+
# @option options [Object] :self main object, only used when no binding is given
|
40
|
+
# @option options [String] :file
|
41
|
+
# @option options [Numeric] :line
|
42
|
+
#
|
43
|
+
def eval(code, opts_or_binding = nil, file = 'borx', line = 0)
|
44
|
+
bindink = opts_or_binding
|
45
|
+
case(opts_or_binding)
|
46
|
+
when nil then
|
47
|
+
bindink = proc{}.binding
|
48
|
+
when Hash then
|
49
|
+
opts = opts_or_binding
|
50
|
+
if opts[:binding]
|
51
|
+
bindink = opts[:binding]
|
52
|
+
elsif opts[:self]
|
53
|
+
bindink = opts[:self].instance_eval{ binding }
|
54
|
+
else
|
55
|
+
bindink = proc{}.binding
|
56
|
+
end
|
57
|
+
file = opts[:file] || 'borx'
|
58
|
+
line = opts[:line] || 0
|
59
|
+
when Borx::Binding, ::Binding then
|
60
|
+
bindink = opts_or_binding
|
61
|
+
else
|
62
|
+
raise ArgumentException, "Expected a Hash or a Binding, got #{opts_or_binding.inspect}"
|
63
|
+
end
|
64
|
+
eval_code( Borx::Rewriter.rewrite(code), bindink, file, line)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def eval_code(code, binding, file, line)
|
70
|
+
old_borx, setter = binding.eval('__borx__ ||= nil ; __borx_binding__ = Borx::Binding(binding) ; [__borx__, lambda{|v| __borx__ = v}]')
|
71
|
+
setter.call(self)
|
72
|
+
binding.eval(code.code, file, line)
|
73
|
+
ensure
|
74
|
+
setter.call(old_borx) if setter
|
75
|
+
end
|
76
|
+
|
25
77
|
end
|
26
78
|
|
27
79
|
class Borx::Environment < base
|
@@ -76,9 +128,16 @@ class Borx::Environment < base
|
|
76
128
|
include GetConstant
|
77
129
|
end
|
78
130
|
|
131
|
+
module GetMagic
|
132
|
+
def get_magic(_binding, _name, actual)
|
133
|
+
return actual
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
79
137
|
include GetSetVariable
|
80
138
|
include GetSetConstant
|
81
139
|
include CallMethod
|
140
|
+
include GetMagic
|
82
141
|
|
83
142
|
class NotImplemented < StandardError
|
84
143
|
class GetConstant < self
|
@@ -91,20 +150,8 @@ class Borx::Environment < base
|
|
91
150
|
end
|
92
151
|
class SetVariable < self
|
93
152
|
end
|
94
|
-
|
95
|
-
|
96
|
-
def eval(code, bin_ding = nil)
|
97
|
-
bin_ding ||= proc{}.binding
|
98
|
-
eval_code( Borx::Rewriter.rewrite(code), bin_ding)
|
99
|
-
end
|
100
|
-
|
101
|
-
private
|
102
|
-
def eval_code(code, binding, file = '(eval)', line = 0)
|
103
|
-
old_borx, setter = binding.eval('__borx__ ||= nil ; __borx_binding__ = Borx::Binding::Adapter.new(binding) ; [__borx__, lambda{|v| __borx__ = v}]')
|
104
|
-
setter.call(self)
|
105
|
-
binding.eval(code.code, file, line)
|
106
|
-
ensure
|
107
|
-
setter.call(old_borx) if setter
|
153
|
+
class GetMagic < self
|
154
|
+
end
|
108
155
|
end
|
109
156
|
|
110
157
|
end
|
data/lib/borx/rewriter.rb
CHANGED
@@ -1,10 +1,4 @@
|
|
1
|
-
|
2
|
-
require 'ripper'
|
3
|
-
rescue NotFound
|
4
|
-
# :nocov:
|
5
|
-
raise NotFound, "Ripper extension not found. Please add it to your bundle."
|
6
|
-
# :nocov:
|
7
|
-
end
|
1
|
+
require 'ripper'
|
8
2
|
require 'sorcerer'
|
9
3
|
require 'borx/code'
|
10
4
|
class Borx::Rewriter < Ripper::SexpBuilder
|
@@ -69,13 +63,18 @@ private
|
|
69
63
|
|
70
64
|
def on_var_ref(x)
|
71
65
|
var = super
|
66
|
+
if var[1][0] == :@kw
|
67
|
+
return call_borx('get_magic', [:args_add,
|
68
|
+
[:args_add, [:args_new], ident_to_string(var[1])],
|
69
|
+
var
|
70
|
+
])
|
71
|
+
end
|
72
72
|
fun = case(var[1][0])
|
73
73
|
when :@const then 'get_constant'
|
74
74
|
when :@gvar then 'get_global_variable'
|
75
75
|
when :@cvar then 'get_class_variable'
|
76
76
|
when :@ivar then 'get_instance_variable'
|
77
77
|
when :@ident then 'get_variable'
|
78
|
-
when :@kw then 'get_magic'
|
79
78
|
# :nocov:
|
80
79
|
else
|
81
80
|
raise "Unknown var_ref type in #{var[1]}, this is a bug, please report it"
|