with_refinements 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46acf7bee0e43d24b1cd6c98a3875573b0125b00b5f171c12b52947c8099d908
4
- data.tar.gz: 0ae6e9f1af73a7a30343e2030a4e28266501ed129d0a035a4cc6c74a18115c89
3
+ metadata.gz: 540b9343999aeee6303dc94c36486399f6852b5ec904114851c3b254de0805de
4
+ data.tar.gz: ba4682ae1ac92d3c2f1d3094fb75bbe39b9c02a74d88fe8d55b3383f049909a3
5
5
  SHA512:
6
- metadata.gz: 0b184d7693abd0d8efb1bf5aecc7ca4f8369eceaa7a7d92a4c6139156aaf7ccc5c7d128783c27cec1dbf5b8efacdf35489685968b6c4c04e17401edae586f335
7
- data.tar.gz: 64b53f1b80c3d79467d38ad1ad312efec6aa0f7196f1c9d73de9aeb7833f2531644c1385262013a32981a013c4b36b687e17a2ec6310555866062f6811982c15
6
+ metadata.gz: 9a2689931a6e93e4355f6f6493c3002a7de1dacbb5a6cc4c940c10a72f445b73ba8fbde9ace4eeaacbf0526319864bbd0396b61dccce978b5884af20eb5021bc
7
+ data.tar.gz: de929a1c059c4488f9381cf7dd518beb3a0384f1e0e7cdb6303e85d9d1a615cf9bb86c682e61bf8a5451ee0bd2980cfa760d79187f070ff54539c67f13130b6a
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- with_refinements (0.4.0)
4
+ with_refinements (0.5.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -2,6 +2,7 @@ require "benchmark_driver"
2
2
 
3
3
  Benchmark.driver do |x|
4
4
  x.prelude <<~RUBY
5
+ require "sin_refinements"
5
6
  require "bundler/setup"
6
7
  require "with_refinements"
7
8
 
@@ -14,18 +15,45 @@ Benchmark.driver do |x|
14
15
  end
15
16
  end
16
17
  end
18
+
19
+ module Plain
20
+ refine(String) do
21
+ def world
22
+ -"world"
23
+ end
24
+ end
25
+ end
26
+
27
+ using Plain
28
+
29
+ class String
30
+ def george
31
+ -"george"
32
+ end
33
+ end
17
34
  RUBY
18
35
 
19
- x.report 'plain', %{
20
- using M
21
- "hello".goodbye
36
+ x.report 'plain monkey patch', %{
37
+ "hello".george
38
+ }
39
+
40
+ x.report 'plain refinements', %{
41
+ "hello".world
22
42
  }
23
43
 
24
44
  x.report 'with_refinements', %{
25
45
  with_refinements(M) { "hello".goodbye }
26
46
  }
27
47
 
28
- x.report 'with_refinements(local_variables: false)', %{
29
- with_refinements(M, local_variables: false) { "hello".goodbye }
48
+ x.report 'with_refinements_light', %{
49
+ with_refinements_light(M) { "hello".goodbye }
50
+ }
51
+
52
+ x.report 'SinRefinements.refining', %{
53
+ SinRefinements.refining(M) { "hello".goodbye }
54
+ }
55
+
56
+ x.report 'SinRefinements.light_refining', %{
57
+ SinRefinements.light_refining(M) { "hello".goodbye }
30
58
  }
31
59
  end
@@ -1,15 +1,56 @@
1
1
  require "with_refinements/version"
2
2
 
3
3
  module WithRefinements
4
+ @context_cache = {}
5
+ @refined_proc_cache = Hash.new {|h,k| h[k] = {} }
6
+ @refined_proc_light_cache = Hash.new {|h,k| h[k] = {} }
7
+
4
8
  class << self
5
- def clean_binding
6
- eval('module Class.new::CleanRoom; binding; end')
9
+ def context(refinements)
10
+ @context_cache[refinements] ||= clean_binding.tap do |b|
11
+ b.local_variable_set(:__refinements__, refinements)
12
+ b.eval('__refinements__.each {|r| using r }')
13
+ end
7
14
  end
8
15
 
9
- def code_from_block(block)
16
+ def refined_proc(c, block)
17
+ @refined_proc_cache[c][block.source_location] ||= (
18
+ lvars = block.binding.local_variables
19
+ c.eval(<<~RUBY)
20
+ proc do |__binding__|
21
+ proc { |#{lvars.join(",")}|
22
+ ret = __binding__.receiver.instance_exec #{code_from_block(block)}
23
+ #{lvars.map {|v| "__binding__.local_variable_set(:#{v}, #{v})" }.join("\n")}
24
+ ret
25
+ }.call(*__binding__.local_variables.map {|v| __binding__.local_variable_get(v) })
26
+ end
27
+ RUBY
28
+ )
29
+ end
30
+
31
+ def refined_proc_light(c, block)
32
+ @refined_proc_light_cache[c][block.source_location] ||= (
33
+ c.eval(<<~RUBY)
34
+ proc { |__receiver__, __args__| __receiver__.instance_exec(*__args__) #{code_from_block(block)} }
35
+ RUBY
36
+ )
37
+ end
38
+
39
+ private
40
+
41
+ def block_source_location(block)
10
42
  iseq = RubyVM::InstructionSequence.of(block).to_a
11
43
  loc = iseq[4].yield_self {|h| h[:code_range] || h[:code_location] }
12
44
  path = iseq[7]
45
+ return path, loc
46
+ end
47
+
48
+ def clean_binding
49
+ TOPLEVEL_BINDING.eval('Module.new { break binding }')
50
+ end
51
+
52
+ def code_from_block(block)
53
+ path, loc = block_source_location(block)
13
54
  File.readlines(path)[loc[0]-1..loc[2]-1].tap {|ls|
14
55
  if loc[0] == loc[2]
15
56
  ls[0] = ls[0][loc[1]...loc[3]]
@@ -25,31 +66,19 @@ module WithRefinements
25
66
  end
26
67
  end
27
68
 
28
- refine(Object) do
29
- def with_refinements(*ms, local_variables: true, &block)
30
- # enable refinements
31
- b = WithRefinements.clean_binding
32
- b.local_variable_set(:__modules__, ms)
33
- b.eval('__modules__.each {|m| using m }')
34
-
35
- # setup block eval context
36
- bb = block.binding
37
- b.local_variable_set(:__self__, bb.receiver)
38
-
39
- # copy local_variables
40
- if local_variables
41
- bb.local_variables.each {|n| b.local_variable_set(n, bb.local_variable_get(n)) }
42
- end
69
+ def with_refinements(*refinements, &block)
70
+ c = WithRefinements.context(refinements)
71
+ p = WithRefinements.refined_proc(c, block)
72
+ p.call(block.binding)
73
+ end
43
74
 
44
- # eval block code
45
- ret = b.eval("__self__.instance_eval #{WithRefinements.code_from_block(block)}")
75
+ def with_refinements_light(*refinements, args: [], &block)
76
+ c = WithRefinements.context(refinements)
77
+ p = WithRefinements.refined_proc_light(c, block)
78
+ p.call(block.binding.receiver, args)
79
+ end
46
80
 
47
- # write back local_variables
48
- if local_variables
49
- bb.local_variables.each {|n| bb.local_variable_set(n, b.local_variable_get(n)) }
50
- end
81
+ module_function :with_refinements, :with_refinements_light
51
82
 
52
- ret
53
- end
54
- end
83
+ refine(Object) { include WithRefinements }
55
84
  end
@@ -0,0 +1,3 @@
1
+ require "with_refinements"
2
+
3
+ Object.include(WithRefinements)
@@ -1,3 +1,3 @@
1
1
  module WithRefinements
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: with_refinements
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Seiei Miyagi
@@ -34,7 +34,7 @@ cert_chain:
34
34
  OKwDKKYe2ogJ/XrOjTltlugSNvq/NgD53wc4TA0F5KofdIZSJELTCUyyZMPztwI4
35
35
  OawPtyIyOegL6pM8fc7IfzLzjkdO3Bis1qFZcg==
36
36
  -----END CERTIFICATE-----
37
- date: 2018-08-02 00:00:00.000000000 Z
37
+ date: 2018-08-04 00:00:00.000000000 Z
38
38
  dependencies:
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: bundler
@@ -111,6 +111,7 @@ files:
111
111
  - examples/b.rb
112
112
  - examples/greeting.rb
113
113
  - lib/with_refinements.rb
114
+ - lib/with_refinements/core_ext.rb
114
115
  - lib/with_refinements/version.rb
115
116
  - with_refinements.gemspec
116
117
  homepage: https://github.com/hanachin/with_refinements
metadata.gz.sig CHANGED
Binary file