borx 0.0.1.alpha2 → 0.0.1.beta1
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/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"
|