mame-dynamicwind 1.0.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 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