mame-dynamicwind 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2008-11-20
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,6 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/dynamicwind.rb
6
+ test/test_dynamicwind.rb
data/README.txt ADDED
@@ -0,0 +1,48 @@
1
+ = dynamicwind
2
+
3
+ * http://github.com/mame/dynamicwind/tree/master
4
+
5
+ == DESCRIPTION:
6
+
7
+ An implementation of dynamic-wind for ruby's continuation.
8
+ See R6RS 11.15 Control features for detail.
9
+ http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_idx_764
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ * callcc becomes robust!
14
+
15
+ == SYNOPSIS:
16
+
17
+ require "dynamicwind"
18
+
19
+ callcc do |c|
20
+ dynamicwind(
21
+ proc { p :before },
22
+ proc { p :thunk; c.call },
23
+ proc { p :after }
24
+ )
25
+ end
26
+ #=> :before, :thunk, :after
27
+
28
+ dynamicwind(
29
+ proc { p :before },
30
+ proc { callcc {|c| $c = c }; p :thunk },
31
+ proc { p :after }
32
+ )
33
+ #=> :before, :thunk, :after
34
+
35
+ $c.call #=> :before, :thunk, :after, ...(infinite loop)
36
+
37
+ == REQUIREMENTS:
38
+
39
+ None
40
+
41
+ == INSTALL:
42
+
43
+ * gem install mame-dynamicwind
44
+
45
+ == LICENSE:
46
+
47
+ Copyright:: Yusuke Endoh <mame@tsg.ne.jp>
48
+ License:: Ruby's
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/dynamicwind.rb'
6
+
7
+ Hoe.new('dynamicwind', DynamicWind::VERSION) do |p|
8
+ p.rubyforge_name = 'dynamicwind'
9
+ p.developer('Yusuke Endoh', 'mame@tsg.ne.jp')
10
+ end
11
+
12
+ # vim: syntax=ruby
@@ -0,0 +1,50 @@
1
+ begin
2
+ require "continuation"
3
+ rescue LoadError
4
+ end
5
+
6
+ module DynamicWind
7
+ VERSION = '1.0.0'
8
+
9
+ Stack = Struct.new(:fst, :snd, :next)
10
+
11
+ alias __callcc_orig callcc
12
+
13
+ def callcc
14
+ mark = __top
15
+ __callcc_orig do |ctn|
16
+ yield(proc {|*ret| __switch(mark); ctn.call(*ret) })
17
+ end
18
+ end
19
+
20
+ def dynamicwind(before, thunk, after)
21
+ mark = __top
22
+ __switch(Stack[[before, nil], [nil, after], mark])
23
+ thunk.call ensure __switch(mark)
24
+ end
25
+
26
+ def __top
27
+ Thread.current[:dynamicwind_stack] ||= Stack.new
28
+ end
29
+
30
+ def __top=(x)
31
+ Thread.current[:dynamicwind_stack] = x
32
+ end
33
+
34
+ def __switch(mark)
35
+ return if __top.equal?(mark)
36
+ __switch(mark.next)
37
+ fst, snd = mark.fst, mark.snd
38
+ fst.first.call if fst.first
39
+ __top.fst = snd
40
+ __top.snd = fst
41
+ __top.next = mark
42
+ self.__top = mark
43
+ __top.fst = nil
44
+ __top.snd = nil
45
+ __top.next = nil
46
+ fst.last.call if fst.last
47
+ end
48
+ end
49
+
50
+ include DynamicWind
@@ -0,0 +1,188 @@
1
+ require "dynamicwind"
2
+ require "test/unit"
3
+
4
+ class TestDynamicWind < Test::Unit::TestCase
5
+ def test_leave
6
+ ary = []
7
+ callcc do |c|
8
+ dynamicwind(
9
+ proc { ary << :before },
10
+ proc { ary << :thunk; c.call },
11
+ proc { ary << :after }
12
+ )
13
+ end
14
+ assert_equal([:before, :thunk, :after], ary)
15
+ end
16
+
17
+ def test_enter
18
+ ary = []
19
+ ctn = nil
20
+ flag = true
21
+ dynamicwind(
22
+ proc { ary << :before },
23
+ proc { callcc {|c| ctn = c }; ary << :thunk },
24
+ proc { ary << :after }
25
+ )
26
+ (flag = false; ctn.call) if flag
27
+ assert_equal([:before, :thunk, :after] * 2, ary)
28
+ end
29
+
30
+ def test_leave_enter
31
+ ary = []
32
+ c2 = nil
33
+ flag = true
34
+ callcc do |c1|
35
+ dynamicwind(
36
+ proc { ary << :before },
37
+ proc do
38
+ ary << :thunk1
39
+ callcc {|c| c2 = c }
40
+ ary << :thunk2
41
+ c1.call
42
+ ary << :thunk3
43
+ end,
44
+ proc { ary << :after }
45
+ )
46
+ end
47
+ ary << :end
48
+ (flag = false; c2.call) if flag
49
+ assert_equal([:before, :thunk1, :thunk2, :after, :end, :before, :thunk2, :after, :end], ary)
50
+ end
51
+
52
+ def test_leave_enter_2
53
+ ary = []
54
+ c2 = nil
55
+ flag = true
56
+ callcc do |c1|
57
+ dynamicwind(
58
+ proc { ary << :before },
59
+ proc do
60
+ ary << :thunk1
61
+ callcc do |c|
62
+ c2 = c
63
+ ary << :thunk2
64
+ c1.call
65
+ end
66
+ ary << :thunk3
67
+ end,
68
+ proc { ary << :after }
69
+ )
70
+ end
71
+ ary << :end
72
+ (flag = false; c2.call) if flag
73
+ assert_equal([:before, :thunk1, :thunk2, :after, :end, :before, :thunk3, :after, :end], ary)
74
+ end
75
+
76
+ def test_callcc_in_before
77
+ ary = []
78
+ ctn = nil
79
+ flag = true
80
+ dynamicwind(
81
+ proc do
82
+ ary << :before1
83
+ callcc {|c| ctn = c }
84
+ ary << :before2
85
+ end,
86
+ proc { ary << :thunk },
87
+ proc do
88
+ ary << :after1
89
+ (flag = false; ctn.call) if flag
90
+ ary << :after2
91
+ end
92
+ )
93
+ assert_equal([:before1, :before2, :thunk, :after1, :before2, :thunk, :after1, :after2], ary)
94
+ end
95
+
96
+ def test_raise
97
+ ary = []
98
+ assert_raise(RuntimeError) do
99
+ dynamicwind(
100
+ proc { ary << :before; raise },
101
+ proc { ary << :thunk },
102
+ proc { ary << :after }
103
+ )
104
+ end
105
+ assert_equal([:before], ary)
106
+
107
+ ary = []
108
+ assert_raise(RuntimeError) do
109
+ dynamicwind(
110
+ proc { ary << :before },
111
+ proc { ary << :thunk; raise },
112
+ proc { ary << :after }
113
+ )
114
+ end
115
+ assert_equal([:before, :thunk, :after], ary)
116
+
117
+ ary = []
118
+ assert_raise(RuntimeError) do
119
+ dynamicwind(
120
+ proc { ary << :before },
121
+ proc { ary << :thunk },
122
+ proc { ary << :after; raise }
123
+ )
124
+ end
125
+ assert_equal([:before, :thunk, :after], ary)
126
+ end
127
+
128
+ def test_throw
129
+ ary = []
130
+ assert_throws(:foo) do
131
+ dynamicwind(
132
+ proc { ary << :before; throw :foo },
133
+ proc { ary << :thunk },
134
+ proc { ary << :after }
135
+ )
136
+ end
137
+ assert_equal([:before], ary)
138
+
139
+ ary = []
140
+ assert_throws(:foo) do
141
+ dynamicwind(
142
+ proc { ary << :before },
143
+ proc { ary << :thunk; throw :foo },
144
+ proc { ary << :after }
145
+ )
146
+ end
147
+ assert_equal([:before, :thunk, :after], ary)
148
+
149
+ ary = []
150
+ assert_throws(:foo) do
151
+ dynamicwind(
152
+ proc { ary << :before },
153
+ proc { ary << :thunk },
154
+ proc { ary << :after; throw :foo }
155
+ )
156
+ end
157
+ assert_equal([:before, :thunk, :after], ary)
158
+ end
159
+
160
+ def test_double_wind
161
+ ary = []
162
+ c2 = nil
163
+ flag = true
164
+ callcc do |c1|
165
+ dynamicwind(
166
+ proc { ary << :before1 },
167
+ proc do
168
+ dynamicwind(
169
+ proc { ary << :before2 },
170
+ proc do
171
+ ary << :thunk1
172
+ callcc do |c|
173
+ c2 = c
174
+ c1.call
175
+ end
176
+ ary << :thunk2
177
+ end,
178
+ proc { ary << :after2 }
179
+ )
180
+ end,
181
+ proc { ary << :after1 }
182
+ )
183
+ end
184
+ ary << :end
185
+ (flag = false; c2.call) if flag
186
+ assert_equal([:before1, :before2, :thunk1, :after2, :after1, :end, :before1, :before2, :thunk2, :after2, :after1, :end], ary)
187
+ end
188
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mame-dynamicwind
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Yusuke Endoh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-11-20 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.8.2
23
+ version:
24
+ description: An implementation of dynamic-wind for ruby's continuation. See R6RS 11.15 Control features for detail. http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_idx_764
25
+ email:
26
+ - mame@tsg.ne.jp
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - History.txt
33
+ - Manifest.txt
34
+ - README.txt
35
+ files:
36
+ - History.txt
37
+ - Manifest.txt
38
+ - README.txt
39
+ - Rakefile
40
+ - lib/dynamicwind.rb
41
+ - test/test_dynamicwind.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/mame/dynamicwind/tree/master
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --main
47
+ - README.txt
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project: dynamicwind
65
+ rubygems_version: 1.2.0
66
+ signing_key:
67
+ specification_version: 2
68
+ summary: An implementation of dynamic-wind for ruby's continuation
69
+ test_files:
70
+ - test/test_dynamicwind.rb