serializable_proc 0.3.1 → 0.4.0
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/HISTORY.txt +5 -1
- data/README.rdoc +6 -123
- data/Rakefile +4 -28
- data/VERSION +1 -1
- data/lib/serializable_proc/binding.rb +11 -15
- data/lib/serializable_proc/isolatable.rb +59 -42
- data/lib/serializable_proc.rb +15 -18
- data/serializable_proc.gemspec +12 -53
- data/spec/bounded_vars/errors_spec.rb +12 -4
- data/spec/bounded_vars/local_vars_within_block_scope_spec.rb +7 -7
- data/spec/code_block/magic_vars_spec.rb +1 -1
- data/spec/proc_like/invoking_with_args_spec.rb +6 -2
- data/spec/proc_like/others_spec.rb +15 -7
- data/spec/spec_helper.rb +6 -16
- metadata +47 -45
- data/lib/serializable_proc/parsers/dynamic.rb +0 -13
- data/lib/serializable_proc/parsers/static.rb +0 -103
- data/lib/serializable_proc/parsers.rb +0 -30
- data/spec/code_block/errors_spec.rb +0 -65
- data/spec/code_block/multiple_arities_spec.rb +0 -159
- data/spec/code_block/optional_arity_spec.rb +0 -160
- data/spec/code_block/single_arity_spec.rb +0 -159
- data/spec/code_block/zero_arity_spec.rb +0 -159
- data/spec/extending/new_matcher_w_multiple_arities_spec.rb +0 -152
- data/spec/extending/new_matcher_w_optional_arity_spec.rb +0 -152
- data/spec/extending/new_matcher_w_single_arity_spec.rb +0 -152
- data/spec/extending/new_matcher_w_zero_arity_spec.rb +0 -152
- data/spec/extending/spec_helper.rb +0 -23
- data/spec/extending/subclassing_w_multiple_arities_spec.rb +0 -74
- data/spec/extending/subclassing_w_optional_arity_spec.rb +0 -74
- data/spec/extending/subclassing_w_single_arity_spec.rb +0 -74
- data/spec/extending/subclassing_w_zero_arity_spec.rb +0 -74
data/HISTORY.txt
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
===
|
1
|
+
=== 0.4.0 (Sep 10, 2010)
|
2
|
+
|
3
|
+
* code extraction is now delegated to more well-tested & robust sourcify [#ngty]
|
4
|
+
|
5
|
+
=== 0.3.1 (Aug 18, 2010)
|
2
6
|
|
3
7
|
* @@_not_isolated_vars now supports :all, which is an alias of :global + :local +
|
4
8
|
:instance + :class [#ngty]
|
data/README.rdoc
CHANGED
@@ -4,7 +4,7 @@ As the name suggests, SerializableProc is a proc that can be serialized (marshal
|
|
4
4
|
A proc is a closure, which consists of the code block defining it, and binding of
|
5
5
|
local variables. SerializableProc's approach to serializability is to extract:
|
6
6
|
|
7
|
-
1. the code from the proc (using
|
7
|
+
1. the code from the proc (using sourcify), and
|
8
8
|
2. the local, instance, class & global variables reference within the proc from the
|
9
9
|
proc's binding, using deep copy via Marshal.load(Marshal.dump(var))
|
10
10
|
|
@@ -63,137 +63,20 @@ No throwing of TypeError when marshalling a SerializableProc:
|
|
63
63
|
|
64
64
|
The religiously standard way:
|
65
65
|
|
66
|
-
$ gem install
|
67
|
-
|
68
|
-
Or on 1.9.* or JRuby:
|
69
|
-
|
70
|
-
$ gem install ruby_parser serializable_proc
|
71
|
-
|
72
|
-
By default, SerializableProc attempts to load ParseTree, which supports better
|
73
|
-
performance & offers many dynamic goodness. If ParseTree cannot be found,
|
74
|
-
SerializableProc falls back to the RubyParser-based which suffers some gotchas due
|
75
|
-
to its static analysis nature (see 'Gotchas' section).
|
76
|
-
|
77
|
-
== Performance
|
78
|
-
|
79
|
-
SerializableProc relies on ParseTree or RubyParser to do code extraction. While running
|
80
|
-
in ParseTree mode, thanks to the goodness of dynamic code analysis, SerializableProc
|
81
|
-
performs faster by a magnitude of abt 6 times for the same ruby, as illustrated with
|
82
|
-
the following benchmark results:
|
83
|
-
|
84
|
-
MRI & implementation user system total real
|
85
|
-
1.8.7p299 (ParseTree) 0.000000 0.000000 3.510000 3.660623
|
86
|
-
1.8.7p299 (RubyParser) 0.000000 0.000000 20.780000 21.328566
|
87
|
-
1.9.1p376 (RubyParser) 0.010000 0.000000 16.990000 17.370586
|
88
|
-
|
89
|
-
Note:
|
90
|
-
* the above are obtained from running the specs suite of 393 specifications with 1330
|
91
|
-
requirements
|
92
|
-
* hardware & OS specs: x86_64 Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz
|
66
|
+
$ gem install serializable_proc
|
93
67
|
|
94
68
|
== Gotchas
|
95
69
|
|
96
|
-
|
97
|
-
|
98
|
-
perfect (yet), pls take note of the following:
|
99
|
-
|
100
|
-
=== 1. Cannot have multiple initializing code block per line
|
101
|
-
|
102
|
-
The following initializations throw SerializableProc::CannotAnalyseCodeError:
|
103
|
-
|
104
|
-
# Multiple SerializableProc.new per line
|
105
|
-
SerializableProc.new { ... } ; SerializableProc.new { ... }
|
106
|
-
|
107
|
-
# Multiple lambda per line (the same applies to proc & Proc.new)
|
108
|
-
x_proc = lambda { ... } ; y_proc = lambda { ... }
|
109
|
-
SerializableProc.new(&x_proc)
|
110
|
-
|
111
|
-
# Mixed lambda, proc & Proc.new per line
|
112
|
-
x_proc = proc { ... } ; y_proc = lambda { ... }
|
113
|
-
SerializableProc.new(&x_proc)
|
114
|
-
|
115
|
-
=== 2. Limited ways to initialize code blocks
|
116
|
-
|
117
|
-
Code block must be initialized with lambda, proc, Proc.new & SerializableProc.new,
|
118
|
-
the following will throw SerializableProc::CannotAnalyseCodeError:
|
119
|
-
|
120
|
-
def create_magic_proc(&block)
|
121
|
-
SerializableProc.new(&block)
|
122
|
-
end
|
123
|
-
|
124
|
-
create_magic_proc { ... }
|
125
|
-
|
126
|
-
But the following will work as expected:
|
127
|
-
|
128
|
-
x_proc = lambda { ... }
|
129
|
-
create_magic_proc(&x_proc)
|
130
|
-
|
131
|
-
There are several strategies to workaround this limitation:
|
132
|
-
|
133
|
-
==== 2.1. Subclassing SerializableProc
|
134
|
-
|
135
|
-
Any subclass of SerializableProc shows traits of a SerializableProc:
|
136
|
-
|
137
|
-
class MagicProc < SerializableProc ; end
|
138
|
-
m_proc = MagicProc.new { ... } # m_proc walks & quacks like a SerializableProc
|
139
|
-
|
140
|
-
==== 2.2. Adding custom matcher(s)
|
141
|
-
|
142
|
-
To support more match cases, we can declare new matchers:
|
143
|
-
|
144
|
-
def work(&block)
|
145
|
-
s_proc = SerializableProc.new(&block)
|
146
|
-
...
|
147
|
-
end
|
148
|
-
|
149
|
-
SerializableProc::Parsers::Static.matchers << 'create_magic_proc'
|
150
|
-
work { ... }
|
151
|
-
|
152
|
-
Or if the method above takes arguments:
|
153
|
-
|
154
|
-
def create_magic_proc(*args, &block)
|
155
|
-
s_proc = SerializableProc.new(&block)
|
156
|
-
...
|
157
|
-
end
|
158
|
-
|
159
|
-
SerializableProc::Parsers::Static.matchers << 'create_magic_proc\W+.*?\W+'
|
160
|
-
create_magic_proc(1, :a => 2, :b => 3) { ... }
|
161
|
-
|
162
|
-
=== 3. One liner for ...
|
163
|
-
|
164
|
-
This is embarassing, but being flexible can aggrevates performance even more.
|
165
|
-
Currently, the declarative (eg. lambda, proc, SerializableProc.new, Proc.new,
|
166
|
-
subclasses of SerializableProc, & any user-defined matcher(s)), & the start of
|
167
|
-
the code-block (the 'do' & '{' chars) must be on the same line. Meaning the
|
168
|
-
following won't work:
|
169
|
-
|
170
|
-
SerializableProc.new \
|
171
|
-
do
|
172
|
-
...
|
173
|
-
end
|
174
|
-
|
175
|
-
create_magic_proc(
|
176
|
-
1, :a => 2
|
177
|
-
) { ... }
|
70
|
+
Under the hood, SerializableProc relies on sourcify[http://github.com/ngty/sourcify] to
|
71
|
+
do code extraction, thus it shares the same gotchas as sourcify.
|
178
72
|
|
179
73
|
== Supported Rubies
|
180
74
|
|
181
75
|
SerializableProc has been tested to work on the following rubies:
|
182
76
|
|
183
77
|
1. MRI 1.8.6, 1.8.7 & 1.9.1
|
184
|
-
2.
|
185
|
-
|
186
|
-
|
187
|
-
== TODO (just brain-dumping)
|
188
|
-
|
189
|
-
1. The RubyParser-based implementation probably need alot more optimization to catch up
|
190
|
-
on ParseTree-based one
|
191
|
-
2. Implementing alternative means (if possible) of extracting the code block without
|
192
|
-
requiring help of ParseTree or RubyParser
|
193
|
-
3. Implement workaround to tackle line-numbering bug in JRuby, which causes the
|
194
|
-
RubyParser-based implementation to fail, for more info abt JRuby's line-numbering
|
195
|
-
bug, see http://stackoverflow.com/questions/3454838/jruby-line-numbering-problem &
|
196
|
-
http://jira.codehaus.org/browse/JRUBY-5014
|
78
|
+
2. REE 1.8.7
|
79
|
+
2. JRuby 1.5.1+
|
197
80
|
|
198
81
|
== Note on Patches/Pull Requests
|
199
82
|
|
data/Rakefile
CHANGED
@@ -8,39 +8,15 @@ begin
|
|
8
8
|
gem.name = "serializable_proc"
|
9
9
|
gem.summary = %Q{Proc that can be serialized (as the name suggests)}
|
10
10
|
gem.description = %Q{
|
11
|
-
Give & take, serializing a ruby proc is possible, though not a perfect one.
|
12
|
-
Requires either ParseTree (faster) or RubyParser (& Ruby2Ruby).
|
11
|
+
Give & take, serializing a ruby proc is possible, though not a perfect one (yet).
|
13
12
|
}
|
14
13
|
gem.email = "ngty77@gmail.com"
|
15
14
|
gem.homepage = "http://github.com/ngty/serializable_proc"
|
16
15
|
gem.authors = ["NgTzeYang"]
|
17
|
-
gem.add_dependency "
|
16
|
+
gem.add_dependency "sourcify", ">= 0.2.2.1"
|
17
|
+
gem.add_dependency "ruby2ruby", ">= 1.2.5"
|
18
|
+
gem.add_dependency "sexp_processor", ">= 3.0.5"
|
18
19
|
gem.add_development_dependency "bacon", ">= 0"
|
19
|
-
# Plus one of the following groups:
|
20
|
-
#
|
21
|
-
# 1). ParseTree (better performance + dynamic goodness, but not supported on java & 1.9.*)
|
22
|
-
# >> gem.add_dependency "ParseTree", ">= 3.0.5"
|
23
|
-
#
|
24
|
-
# 2). RubyParser (supported for all)
|
25
|
-
# >> gem.add_dependency "ruby_parser", ">= 2.0.4"
|
26
|
-
|
27
|
-
unless RUBY_PLATFORM =~ /java/i or RUBY_VERSION.include?('1.9.')
|
28
|
-
gem.post_install_message = %Q{
|
29
|
-
/////////////////////////////////////////////////////////////////////////////////
|
30
|
-
|
31
|
-
** SerializableProc **
|
32
|
-
|
33
|
-
You are installing SerializableProc on a ruby platform & version that supports
|
34
|
-
ParseTree. With ParseTree, u can enjoy better performance of SerializableProc,
|
35
|
-
as well as other dynamic code analysis goodness, as compared to the default
|
36
|
-
implementation using RubyParser's less flexible static code analysis.
|
37
|
-
|
38
|
-
Anyway, u have been informed, SerializableProc will fallback on its default
|
39
|
-
implementation using RubyParser.
|
40
|
-
|
41
|
-
/////////////////////////////////////////////////////////////////////////////////
|
42
|
-
}
|
43
|
-
end
|
44
20
|
end
|
45
21
|
|
46
22
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
@@ -9,21 +9,8 @@ class SerializableProc
|
|
9
9
|
marshal_attr :vars
|
10
10
|
|
11
11
|
def initialize(binding, sexp)
|
12
|
-
|
13
|
-
|
14
|
-
unless types.empty?
|
15
|
-
sexp_str = sexp.inspect
|
16
|
-
while m = sexp_str.match(/^(.*?s\(:(?:#{types.join('|')})var, :([^\)]+)\))/)
|
17
|
-
ignore, var = m[1..2]
|
18
|
-
sexp_str.sub!(ignore,'')
|
19
|
-
next unless isolatable?(var)
|
20
|
-
begin
|
21
|
-
val = eval(var, binding) rescue nil
|
22
|
-
@vars.update(isolated_var(var) => mclone(val))
|
23
|
-
rescue TypeError
|
24
|
-
raise CannotSerializeVariableError.new("Variable #{var} cannot be serialized !!")
|
25
|
-
end
|
26
|
-
end
|
12
|
+
@vars = isolatable_vars(sexp).inject({}) do |memo, (o_var, n_var)|
|
13
|
+
memo.merge(n_var => bounded_val(o_var, binding))
|
27
14
|
end
|
28
15
|
end
|
29
16
|
|
@@ -45,5 +32,14 @@ class SerializableProc
|
|
45
32
|
@declare_vars ||= @vars.map{|(k,v)| "#{k} = Marshal.load(%|#{mdump(v)}|)" } * '; '
|
46
33
|
end
|
47
34
|
|
35
|
+
def bounded_val(var, binding)
|
36
|
+
begin
|
37
|
+
val = eval(var.to_s, binding) rescue nil
|
38
|
+
mclone(val)
|
39
|
+
rescue TypeError
|
40
|
+
raise CannotSerializeVariableError.new("Variable #{var} cannot be serialized !!")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
48
44
|
end
|
49
45
|
end
|
@@ -1,66 +1,83 @@
|
|
1
1
|
class SerializableProc
|
2
2
|
module Isolatable
|
3
3
|
|
4
|
+
MAPPERS = {'l' => '', 'c' => '@@', 'i' => '@', 'g' => '$'}
|
5
|
+
ISOLATION_VAR = :@@_not_isolated_vars
|
6
|
+
BLOCK_SCOPES = [:class, :sclass, :defn, :module]
|
7
|
+
|
4
8
|
protected
|
5
9
|
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def isolatable_vars(sexp)
|
11
|
+
sexp = sexp.to_a if sexp.is_a?(Sexp)
|
12
|
+
return if BLOCK_SCOPES.include?(sexp[0])
|
13
|
+
sexp.inject({}) do |memo, e|
|
14
|
+
if e.is_a?(Array)
|
15
|
+
memo.merge(isolatable_vars(e) || {})
|
16
|
+
elsif e.to_s =~ /^((l|c|g|i)var_(\w+))$/
|
17
|
+
memo.merge((MAPPERS[$2] + $3).to_sym => $1.to_sym)
|
18
|
+
else
|
19
|
+
memo
|
12
20
|
end
|
13
|
-
|
21
|
+
end
|
14
22
|
end
|
15
23
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
sexp_str.sub(tmp_marker.inspect, block_sexp_str)
|
24
|
-
end
|
24
|
+
def isolated_sexp_and_code(sexp)
|
25
|
+
sexp_arry, @types = sexp.to_a, isolated_types(sexp).join('|')
|
26
|
+
sexp_arry = isolated_sexp_arry(sexp_arry) unless @types.empty?
|
27
|
+
[
|
28
|
+
Sexp.from_array(sexp_arry),
|
29
|
+
Ruby2Ruby.new.process(Sexp.from_array(sexp_arry))
|
30
|
+
]
|
25
31
|
end
|
26
32
|
|
27
|
-
|
28
|
-
n_sexp_str = nil
|
29
|
-
var_pattern = /^(.*?s\(:)((#{types.join('|')})(asgn|var|vdecl))(,\ :)((|@|@@|\$)([\w]+))(\)|,)/
|
33
|
+
private
|
30
34
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
def isolated_types(sexp)
|
36
|
+
if (declarative = isolatable_declarative(sexp)).empty?
|
37
|
+
MAPPERS.keys
|
38
|
+
elsif declarative.include?('all')
|
39
|
+
[]
|
40
|
+
else
|
41
|
+
MAPPERS.keys - declarative.map{|e| e[0].chr }
|
37
42
|
end
|
38
|
-
|
39
|
-
"#{n_sexp_str}#{o_sexp_str}"
|
40
43
|
end
|
41
44
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
45
|
+
def isolated_sexp_arry(array)
|
46
|
+
return array if BLOCK_SCOPES.include?(array[0])
|
47
|
+
array.map do |e|
|
48
|
+
case e
|
49
|
+
when Array
|
50
|
+
if e.size == 2 && e[0].to_s =~ /^(#{@types})var$/
|
51
|
+
isolatable?(var = e[1]) ? [:lvar, isolated_var(var,$1)] : e
|
52
|
+
elsif e[0].to_s =~ /^(#{@types})(vdel|asgn)$/ && isolatable?(var = e[1])
|
53
|
+
isolated_sexp_arry([:lasgn, isolated_var(var,$1), *e[2..-1]])
|
54
|
+
else
|
55
|
+
isolated_sexp_arry(e)
|
56
|
+
end
|
57
|
+
else
|
58
|
+
e
|
59
|
+
end
|
60
|
+
end
|
46
61
|
end
|
47
62
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
|
63
|
+
def isolated_var(var, type = nil)
|
64
|
+
m = var.to_s.match(/^(\W*)(\w+)$/)[1..2]
|
65
|
+
type ||= MAPPERS.invert[m[0]]
|
66
|
+
:"#{type}var_#{m[1]}"
|
67
|
+
end
|
52
68
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
69
|
+
def isolatable_declarative(sexp)
|
70
|
+
declaratives = []
|
71
|
+
sexp.each_of_type(:cvdecl) do |node|
|
72
|
+
next unless node.to_a[1] == ISOLATION_VAR
|
73
|
+
node.each_of_type(:lit) {|_node| declaratives << _node.to_a[-1].to_s }
|
74
|
+
break
|
59
75
|
end
|
76
|
+
declaratives
|
60
77
|
end
|
61
78
|
|
62
79
|
def isolatable?(var)
|
63
|
-
var !=
|
80
|
+
var.to_s != ISOLATION_VAR.to_s
|
64
81
|
end
|
65
82
|
|
66
83
|
end
|
data/lib/serializable_proc.rb
CHANGED
@@ -1,18 +1,12 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'forwardable'
|
3
|
+
require 'sourcify'
|
3
4
|
require 'ruby2ruby'
|
5
|
+
require 'sexp_processor'
|
6
|
+
|
4
7
|
require 'serializable_proc/marshalable'
|
5
8
|
require 'serializable_proc/isolatable'
|
6
|
-
require 'serializable_proc/parsers'
|
7
9
|
require 'serializable_proc/binding'
|
8
|
-
require 'serializable_proc/fixes'
|
9
|
-
|
10
|
-
begin
|
11
|
-
require 'parse_tree'
|
12
|
-
require 'parse_tree_extensions'
|
13
|
-
rescue LoadError
|
14
|
-
require 'ruby_parser'
|
15
|
-
end
|
16
10
|
|
17
11
|
##
|
18
12
|
# SerializableProc differs from the vanilla Proc in 2 ways:
|
@@ -72,8 +66,9 @@ end
|
|
72
66
|
#
|
73
67
|
class SerializableProc
|
74
68
|
|
69
|
+
include Isolatable
|
75
70
|
include Marshalable
|
76
|
-
marshal_attrs :file, :line, :
|
71
|
+
marshal_attrs :file, :line, :codes, :arity, :binding, :sexps
|
77
72
|
|
78
73
|
##
|
79
74
|
# Creates a new instance of SerializableProc by passing in a code block, in the process,
|
@@ -92,10 +87,12 @@ class SerializableProc
|
|
92
87
|
# action { ... }
|
93
88
|
#
|
94
89
|
def initialize(&block)
|
95
|
-
|
96
|
-
|
97
|
-
@
|
98
|
-
@
|
90
|
+
e_code, e_sexp = block.to_source, block.to_sexp
|
91
|
+
r_sexp, r_code = isolated_sexp_and_code(e_sexp)
|
92
|
+
@arity, @file, @line = block.arity, *block.source_location
|
93
|
+
@codes = {:extracted => e_code, :runnable => r_code}
|
94
|
+
@sexps = {:extracted => e_sexp, :runnable => r_sexp}
|
95
|
+
@binding = Binding.new(block.binding, r_sexp)
|
99
96
|
end
|
100
97
|
|
101
98
|
##
|
@@ -132,9 +129,9 @@ class SerializableProc
|
|
132
129
|
#
|
133
130
|
def to_proc(binding = nil)
|
134
131
|
if binding
|
135
|
-
eval(@
|
132
|
+
eval(@codes[:runnable], @binding.eval!(binding), @file, @line)
|
136
133
|
else
|
137
|
-
@proc ||= eval(@
|
134
|
+
@proc ||= eval(@codes[:runnable], @binding.eval!, @file, @line)
|
138
135
|
end
|
139
136
|
end
|
140
137
|
|
@@ -159,7 +156,7 @@ class SerializableProc
|
|
159
156
|
# * global variable -> replaced '$ with 'gvar_'
|
160
157
|
#
|
161
158
|
def to_s(debug = false)
|
162
|
-
@
|
159
|
+
@codes[debug ? :runnable : :extracted]
|
163
160
|
end
|
164
161
|
|
165
162
|
##
|
@@ -169,7 +166,7 @@ class SerializableProc
|
|
169
166
|
# SerializableProc.new { [x, @x, @@x, $x].join(', ') }.to_sexp
|
170
167
|
#
|
171
168
|
def to_sexp(debug = false)
|
172
|
-
@
|
169
|
+
@sexps[debug ? :runnable : :extracted]
|
173
170
|
end
|
174
171
|
|
175
172
|
##
|
data/serializable_proc.gemspec
CHANGED
@@ -5,14 +5,13 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{serializable_proc}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["NgTzeYang"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-09-15}
|
13
13
|
s.description = %q{
|
14
|
-
Give & take, serializing a ruby proc is possible, though not a perfect one.
|
15
|
-
Requires either ParseTree (faster) or RubyParser (& Ruby2Ruby).
|
14
|
+
Give & take, serializing a ruby proc is possible, though not a perfect one (yet).
|
16
15
|
}
|
17
16
|
s.email = %q{ngty77@gmail.com}
|
18
17
|
s.extra_rdoc_files = [
|
@@ -32,9 +31,6 @@ Gem::Specification.new do |s|
|
|
32
31
|
"lib/serializable_proc/fixes.rb",
|
33
32
|
"lib/serializable_proc/isolatable.rb",
|
34
33
|
"lib/serializable_proc/marshalable.rb",
|
35
|
-
"lib/serializable_proc/parsers.rb",
|
36
|
-
"lib/serializable_proc/parsers/dynamic.rb",
|
37
|
-
"lib/serializable_proc/parsers/static.rb",
|
38
34
|
"serializable_proc.gemspec",
|
39
35
|
"spec/bounded_vars/class_vars_spec.rb",
|
40
36
|
"spec/bounded_vars/class_vars_within_block_scope_spec.rb",
|
@@ -45,22 +41,8 @@ Gem::Specification.new do |s|
|
|
45
41
|
"spec/bounded_vars/instance_vars_within_block_scope_spec.rb",
|
46
42
|
"spec/bounded_vars/local_vars_spec.rb",
|
47
43
|
"spec/bounded_vars/local_vars_within_block_scope_spec.rb",
|
48
|
-
"spec/code_block/errors_spec.rb",
|
49
44
|
"spec/code_block/magic_vars_spec.rb",
|
50
|
-
"spec/code_block/multiple_arities_spec.rb",
|
51
|
-
"spec/code_block/optional_arity_spec.rb",
|
52
45
|
"spec/code_block/renaming_vars_spec.rb",
|
53
|
-
"spec/code_block/single_arity_spec.rb",
|
54
|
-
"spec/code_block/zero_arity_spec.rb",
|
55
|
-
"spec/extending/new_matcher_w_multiple_arities_spec.rb",
|
56
|
-
"spec/extending/new_matcher_w_optional_arity_spec.rb",
|
57
|
-
"spec/extending/new_matcher_w_single_arity_spec.rb",
|
58
|
-
"spec/extending/new_matcher_w_zero_arity_spec.rb",
|
59
|
-
"spec/extending/spec_helper.rb",
|
60
|
-
"spec/extending/subclassing_w_multiple_arities_spec.rb",
|
61
|
-
"spec/extending/subclassing_w_optional_arity_spec.rb",
|
62
|
-
"spec/extending/subclassing_w_single_arity_spec.rb",
|
63
|
-
"spec/extending/subclassing_w_zero_arity_spec.rb",
|
64
46
|
"spec/proc_like/extras_spec.rb",
|
65
47
|
"spec/proc_like/invoking_with_args_spec.rb",
|
66
48
|
"spec/proc_like/invoking_with_class_vars_spec.rb",
|
@@ -72,21 +54,6 @@ Gem::Specification.new do |s|
|
|
72
54
|
"spec/spec_helper.rb"
|
73
55
|
]
|
74
56
|
s.homepage = %q{http://github.com/ngty/serializable_proc}
|
75
|
-
s.post_install_message = %q{
|
76
|
-
/////////////////////////////////////////////////////////////////////////////////
|
77
|
-
|
78
|
-
** SerializableProc **
|
79
|
-
|
80
|
-
You are installing SerializableProc on a ruby platform & version that supports
|
81
|
-
ParseTree. With ParseTree, u can enjoy better performance of SerializableProc,
|
82
|
-
as well as other dynamic code analysis goodness, as compared to the default
|
83
|
-
implementation using RubyParser's less flexible static code analysis.
|
84
|
-
|
85
|
-
Anyway, u have been informed, SerializableProc will fallback on its default
|
86
|
-
implementation using RubyParser.
|
87
|
-
|
88
|
-
/////////////////////////////////////////////////////////////////////////////////
|
89
|
-
}
|
90
57
|
s.rdoc_options = ["--charset=UTF-8"]
|
91
58
|
s.require_paths = ["lib"]
|
92
59
|
s.rubygems_version = %q{1.3.7}
|
@@ -101,21 +68,7 @@ Gem::Specification.new do |s|
|
|
101
68
|
"spec/proc_like/invoking_with_global_vars_spec.rb",
|
102
69
|
"spec/proc_like/marshalling_spec.rb",
|
103
70
|
"spec/code_block/magic_vars_spec.rb",
|
104
|
-
"spec/code_block/multiple_arities_spec.rb",
|
105
|
-
"spec/code_block/zero_arity_spec.rb",
|
106
|
-
"spec/code_block/errors_spec.rb",
|
107
71
|
"spec/code_block/renaming_vars_spec.rb",
|
108
|
-
"spec/code_block/single_arity_spec.rb",
|
109
|
-
"spec/code_block/optional_arity_spec.rb",
|
110
|
-
"spec/extending/subclassing_w_optional_arity_spec.rb",
|
111
|
-
"spec/extending/subclassing_w_single_arity_spec.rb",
|
112
|
-
"spec/extending/new_matcher_w_multiple_arities_spec.rb",
|
113
|
-
"spec/extending/subclassing_w_zero_arity_spec.rb",
|
114
|
-
"spec/extending/new_matcher_w_single_arity_spec.rb",
|
115
|
-
"spec/extending/subclassing_w_multiple_arities_spec.rb",
|
116
|
-
"spec/extending/new_matcher_w_optional_arity_spec.rb",
|
117
|
-
"spec/extending/new_matcher_w_zero_arity_spec.rb",
|
118
|
-
"spec/extending/spec_helper.rb",
|
119
72
|
"spec/bounded_vars/global_vars_within_block_scope_spec.rb",
|
120
73
|
"spec/bounded_vars/instance_vars_within_block_scope_spec.rb",
|
121
74
|
"spec/bounded_vars/errors_spec.rb",
|
@@ -133,14 +86,20 @@ Gem::Specification.new do |s|
|
|
133
86
|
s.specification_version = 3
|
134
87
|
|
135
88
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
136
|
-
s.add_runtime_dependency(%q<
|
89
|
+
s.add_runtime_dependency(%q<sourcify>, [">= 0.2.2.1"])
|
90
|
+
s.add_runtime_dependency(%q<ruby2ruby>, [">= 1.2.5"])
|
91
|
+
s.add_runtime_dependency(%q<sexp_processor>, [">= 3.0.5"])
|
137
92
|
s.add_development_dependency(%q<bacon>, [">= 0"])
|
138
93
|
else
|
139
|
-
s.add_dependency(%q<
|
94
|
+
s.add_dependency(%q<sourcify>, [">= 0.2.2.1"])
|
95
|
+
s.add_dependency(%q<ruby2ruby>, [">= 1.2.5"])
|
96
|
+
s.add_dependency(%q<sexp_processor>, [">= 3.0.5"])
|
140
97
|
s.add_dependency(%q<bacon>, [">= 0"])
|
141
98
|
end
|
142
99
|
else
|
143
|
-
s.add_dependency(%q<
|
100
|
+
s.add_dependency(%q<sourcify>, [">= 0.2.2.1"])
|
101
|
+
s.add_dependency(%q<ruby2ruby>, [">= 1.2.5"])
|
102
|
+
s.add_dependency(%q<sexp_processor>, [">= 3.0.5"])
|
144
103
|
s.add_dependency(%q<bacon>, [">= 0"])
|
145
104
|
end
|
146
105
|
end
|
@@ -6,22 +6,30 @@ describe 'SerializableProc::CannotSerializeVariableError' do
|
|
6
6
|
|
7
7
|
should "raise if local variable cannot be marshalled" do
|
8
8
|
f = Tempfile.new('fake')
|
9
|
-
lambda {
|
9
|
+
lambda {
|
10
|
+
SerializableProc.new{ f }
|
11
|
+
}.should.be raising_cannot_serialize_variable_error('f')
|
10
12
|
end
|
11
13
|
|
12
14
|
should "raise if class variable cannot be marshalled" do
|
13
15
|
@@f = Tempfile.new('fake')
|
14
|
-
lambda {
|
16
|
+
lambda {
|
17
|
+
SerializableProc.new{ @@f }
|
18
|
+
}.should.be raising_cannot_serialize_variable_error('@@f')
|
15
19
|
end
|
16
20
|
|
17
21
|
should "raise if instance variable cannot be marshalled" do
|
18
22
|
@f = Tempfile.new('fake')
|
19
|
-
lambda {
|
23
|
+
lambda {
|
24
|
+
SerializableProc.new{ @f }
|
25
|
+
}.should.be raising_cannot_serialize_variable_error('@f')
|
20
26
|
end
|
21
27
|
|
22
28
|
should "raise if global variable cannot be marshalled" do
|
23
29
|
$f = Tempfile.new('fake')
|
24
|
-
lambda {
|
30
|
+
lambda {
|
31
|
+
SerializableProc.new{ $f }
|
32
|
+
}.should.be raising_cannot_serialize_variable_error('$f')
|
25
33
|
end
|
26
34
|
|
27
35
|
end
|
@@ -4,35 +4,35 @@ describe 'Extracting local vars within block scope' do
|
|
4
4
|
|
5
5
|
extend SerializableProc::Spec::Helpers
|
6
6
|
|
7
|
-
should "not handle w @@
|
7
|
+
should "not handle w @@_not_isolated_vars unspecified" do
|
8
8
|
x = 'ox'
|
9
9
|
should_have_empty_binding \
|
10
10
|
SerializableProc.new { def test ; x = 'lx' ; end }
|
11
11
|
end
|
12
12
|
|
13
|
-
should "not handle if @@
|
13
|
+
should "not handle if @@_not_isolated_vars includes :local" do
|
14
14
|
x = 'ox'
|
15
15
|
should_have_empty_binding \
|
16
16
|
SerializableProc.new {
|
17
|
-
@@
|
17
|
+
@@_not_isolated_vars = :local
|
18
18
|
def test ; x = 'lx' ; end
|
19
19
|
}
|
20
20
|
end
|
21
21
|
|
22
|
-
should "not handle if @@
|
22
|
+
should "not handle if @@_not_isolated_vars includes :all" do
|
23
23
|
x = 'ox'
|
24
24
|
should_have_empty_binding \
|
25
25
|
SerializableProc.new {
|
26
|
-
@@
|
26
|
+
@@_not_isolated_vars = :all
|
27
27
|
def test ; x = 'lx' ; end
|
28
28
|
}
|
29
29
|
end
|
30
30
|
|
31
|
-
should "not handle if @@
|
31
|
+
should "not handle if @@_not_isolated_vars excludes :local" do
|
32
32
|
x = 'ox'
|
33
33
|
should_have_empty_binding \
|
34
34
|
SerializableProc.new {
|
35
|
-
@@
|
35
|
+
@@_not_isolated_vars = nil
|
36
36
|
def test ; x = 'lx' ; end
|
37
37
|
}
|
38
38
|
end
|