ruff 1.3.0 → 2.1.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.rubocop.yml +1 -1
- data/Gemfile +3 -0
- data/README.md +35 -58
- data/Rakefile +2 -1
- data/docs/.nojekyll +0 -0
- data/docs/Ruff.html +7 -7
- data/docs/Ruff/Effect.html +165 -23
- data/docs/Ruff/Handler.html +46 -114
- data/docs/Ruff/Standard.html +7 -7
- data/docs/Ruff/Standard/Async.html +28 -27
- data/docs/Ruff/Standard/Async/Instance.html +63 -27
- data/docs/Ruff/Standard/Call1cc.html +297 -0
- data/docs/Ruff/Standard/CurrentTime.html +6 -6
- data/docs/Ruff/Standard/CurrentTime/Instance.html +7 -7
- data/docs/Ruff/Standard/Defer.html +6 -6
- data/docs/Ruff/Standard/Defer/Instance.html +6 -6
- data/docs/Ruff/Standard/DelimCtrl.html +340 -0
- data/docs/Ruff/Standard/MeasureTime.html +6 -6
- data/docs/Ruff/Standard/MeasureTime/Instance.html +8 -8
- data/docs/Ruff/Standard/State.html +6 -6
- data/docs/Ruff/Standard/State/Instance.html +6 -6
- data/docs/Ruff/Throws.html +6 -11
- data/docs/Ruff/Throws/Eff.html +6 -6
- data/docs/Ruff/Throws/Resend.html +6 -6
- data/docs/_index.html +14 -7
- data/docs/class_list.html +3 -3
- data/docs/css/style.css +2 -2
- data/docs/file.README.html +41 -58
- data/docs/file_list.html +2 -2
- data/docs/frames.html +2 -2
- data/docs/index.html +41 -58
- data/docs/js/app.js +14 -3
- data/docs/method_list.html +46 -30
- data/docs/top-level-namespace.html +6 -6
- data/lib/ruff/effect.rb +32 -3
- data/lib/ruff/handler.rb +43 -18
- data/lib/ruff/standard.rb +1 -0
- data/lib/ruff/standard/async.rb +27 -22
- data/lib/ruff/standard/current_time.rb +1 -1
- data/lib/ruff/standard/delim_ctrl.rb +49 -0
- data/lib/ruff/standard/measure_time.rb +2 -2
- data/lib/ruff/version.rb +1 -1
- data/ruff.gemspec +1 -1
- data/version +1 -1
- metadata +12 -9
- data/Gemfile.lock +0 -62
@@ -6,15 +6,15 @@
|
|
6
6
|
<title>
|
7
7
|
Top Level Namespace
|
8
8
|
|
9
|
-
— Ruff 1.
|
9
|
+
— Ruff 2.1.0 Documentation
|
10
10
|
|
11
11
|
</title>
|
12
12
|
|
13
|
-
<link rel="stylesheet" href="css/style.css" type="text/css"
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
14
14
|
|
15
|
-
<link rel="stylesheet" href="css/common.css" type="text/css"
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
16
16
|
|
17
|
-
<script type="text/javascript"
|
17
|
+
<script type="text/javascript">
|
18
18
|
pathId = "";
|
19
19
|
relpath = '';
|
20
20
|
</script>
|
@@ -100,9 +100,9 @@
|
|
100
100
|
</div>
|
101
101
|
|
102
102
|
<div id="footer">
|
103
|
-
Generated on
|
103
|
+
Generated on Wed Jun 10 21:24:09 2020 by
|
104
104
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
105
|
-
0.9.
|
105
|
+
0.9.25 (ruby-2.7.1).
|
106
106
|
</div>
|
107
107
|
|
108
108
|
</div>
|
data/lib/ruff/effect.rb
CHANGED
@@ -2,7 +2,10 @@
|
|
2
2
|
|
3
3
|
# This class provides an effect instance.
|
4
4
|
class Ruff::Effect
|
5
|
-
# Each instance must be unique so they have unique id with
|
5
|
+
# Each instance must be unique so they have unique id with an annonymous class instance.
|
6
|
+
#
|
7
|
+
# The class instance may have subtyping relation.
|
8
|
+
# @see <<
|
6
9
|
attr_reader :id
|
7
10
|
|
8
11
|
# instaciates an effect setting `id`.
|
@@ -10,13 +13,39 @@ class Ruff::Effect
|
|
10
13
|
# @example
|
11
14
|
# Log = Effect.new #==> it _might_ be Effect<string, nil>
|
12
15
|
def initialize
|
13
|
-
@id =
|
14
|
-
|
16
|
+
@id = Class.new.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# instanciates an effect, which has an relation `self <: parent`
|
20
|
+
# from the subtyping of `id` object.
|
21
|
+
#
|
22
|
+
# @param [Effect<Arg, Ret>] parent
|
23
|
+
# @return [Effect<Arg, Ret>] with an relation `it <: parent`
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# Exception = Ruff::Effect.new
|
27
|
+
# RuntimeException = Ruff::Effect << Exception
|
28
|
+
#
|
29
|
+
# Ruff::Handler.new
|
30
|
+
# .on(Exception){
|
31
|
+
# puts "catch"
|
32
|
+
# }
|
33
|
+
# .run {
|
34
|
+
# RuntimeException.perform
|
35
|
+
# }
|
36
|
+
# # ==> prints "catch"
|
37
|
+
def self.<<(parent)
|
38
|
+
inst = new
|
39
|
+
parent_id = parent.instance_variable_get('@id')
|
40
|
+
inst.instance_variable_set('@id', (Class.new parent_id.class).new)
|
41
|
+
inst
|
15
42
|
end
|
16
43
|
|
17
44
|
# sends an effect ID and its arguments to a nearmost handler.
|
45
|
+
#
|
18
46
|
# @param [Arg] a of the object `Effect<Arg, Ret>`
|
19
47
|
# @return [Ret] of the object `Effect<Arg, Ret>`
|
48
|
+
#
|
20
49
|
# @example
|
21
50
|
# Log.perform "hello"
|
22
51
|
def perform(*a)
|
data/lib/ruff/handler.rb
CHANGED
@@ -2,17 +2,41 @@
|
|
2
2
|
|
3
3
|
# In algebraic effects, handler is an first-class object.
|
4
4
|
class Ruff::Handler
|
5
|
-
include Ruff::Throws
|
6
|
-
|
7
5
|
# makes a new handler, internally having fresh empty hash.
|
8
6
|
#
|
9
7
|
# This is a effect-handler store and when handliong it is looked up.
|
10
|
-
# Value handler is set
|
11
|
-
|
8
|
+
# Value handler is set an identity function to by default.
|
9
|
+
|
10
|
+
class Store
|
11
|
+
# is a private class to manage registered handlers
|
12
|
+
def initialize
|
13
|
+
@handler = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(r, e)
|
17
|
+
@handler[r.id] = e
|
18
|
+
end
|
19
|
+
|
20
|
+
def [](eff)
|
21
|
+
# get a set {(eff', f) | forall (eff', f) in store. eff <: eff'}
|
22
|
+
fns = @handler.filter do |effky, _fun|
|
23
|
+
eff.id.is_a? effky.class
|
24
|
+
end
|
25
|
+
|
26
|
+
# pick a function with *smallest* effect class
|
27
|
+
return fns.min_by { |effky, _| effky.class }[1] unless fns.empty?
|
28
|
+
|
29
|
+
# if found nothing
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private_constant :Store
|
35
|
+
|
12
36
|
# @example
|
13
37
|
# handler = Handler.new
|
14
38
|
def initialize
|
15
|
-
@handlers =
|
39
|
+
@handlers = Store.new
|
16
40
|
@valh = ->(x) { x }
|
17
41
|
end
|
18
42
|
|
@@ -56,7 +80,10 @@ class Ruff::Handler
|
|
56
80
|
self
|
57
81
|
end
|
58
82
|
|
59
|
-
# sets effec handler `&fun` for `eff`
|
83
|
+
# sets or updates effec handler `&fun` for `eff`
|
84
|
+
#
|
85
|
+
# Note that `eff` can be a supertype of an effect to be caught.
|
86
|
+
# @see Effect.<<
|
60
87
|
#
|
61
88
|
# @param [Effect<Arg, Ret>] eff
|
62
89
|
# the effect instance to be handled
|
@@ -73,7 +100,7 @@ class Ruff::Handler
|
|
73
100
|
# k[]
|
74
101
|
# }
|
75
102
|
def on(eff, &fun)
|
76
|
-
@handlers[eff
|
103
|
+
@handlers[eff] = fun
|
77
104
|
|
78
105
|
self
|
79
106
|
end
|
@@ -107,13 +134,13 @@ class Ruff::Handler
|
|
107
134
|
continue(co).call(nil)
|
108
135
|
end
|
109
136
|
|
110
|
-
|
137
|
+
protected
|
138
|
+
|
139
|
+
# receives `handlers` as new handlers.
|
111
140
|
def handlers=(handlers)
|
112
141
|
@handlers = handlers.dup
|
113
142
|
end
|
114
143
|
|
115
|
-
private
|
116
|
-
|
117
144
|
def continue(co)
|
118
145
|
->(*arg) { handle(co, co.resume(*arg)) }
|
119
146
|
end
|
@@ -121,20 +148,20 @@ class Ruff::Handler
|
|
121
148
|
# rubocop:disable Metrics/AbcSize
|
122
149
|
def handle(co, r)
|
123
150
|
case r
|
124
|
-
when Eff
|
125
|
-
if (effh = @handlers[r
|
151
|
+
when Ruff::Throws::Eff
|
152
|
+
if (effh = @handlers[r])
|
126
153
|
effh[continue(co), *r.args]
|
127
154
|
else
|
128
|
-
Fiber.yield Resend.new(r, continue(co))
|
155
|
+
Fiber.yield Ruff::Throws::Resend.new(r, continue(co))
|
129
156
|
end
|
130
|
-
when Resend then
|
157
|
+
when Ruff::Throws::Resend then
|
131
158
|
eff = r.eff
|
132
159
|
next_k = rehandles(co, r.k)
|
133
160
|
|
134
|
-
if (effh = @handlers[eff
|
161
|
+
if (effh = @handlers[eff])
|
135
162
|
effh.call(next_k, *eff.args)
|
136
163
|
else
|
137
|
-
Fiber.yield Resend.new(eff, next_k)
|
164
|
+
Fiber.yield Ruff::Throws::Resend.new(eff, next_k)
|
138
165
|
end
|
139
166
|
else
|
140
167
|
@valh.call(r)
|
@@ -153,6 +180,4 @@ class Ruff::Handler
|
|
153
180
|
.run { k.call(*args) }
|
154
181
|
}
|
155
182
|
end
|
156
|
-
|
157
|
-
private_methods :handlers=
|
158
183
|
end
|
data/lib/ruff/standard.rb
CHANGED
data/lib/ruff/standard/async.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# `Async` provides effects `Async.async`, `Async.yield` and `Async.await`,
|
3
|
+
# `Async` provides effects `Async.async`, `Async.yield` and `Async.await`,
|
4
|
+
# and the implementation async/await.
|
4
5
|
# This implementation is based on the tutorial for Multicore OCaml.
|
5
6
|
# @see https://github.com/ocamllabs/ocaml-effects-tutorial/blob/master/sources/solved/async_await.ml
|
6
7
|
#
|
@@ -47,8 +48,8 @@ module Ruff::Standard::Async
|
|
47
48
|
# type 'a promise =
|
48
49
|
# | Waiting of ('a, unit) continuation list
|
49
50
|
# | Done of 'a
|
50
|
-
|
51
|
-
|
51
|
+
Waiting = Util::ADT.create
|
52
|
+
Done = Util::ADT.create
|
52
53
|
|
53
54
|
# makes a new instance.
|
54
55
|
def initialize
|
@@ -88,14 +89,14 @@ module Ruff::Standard::Async
|
|
88
89
|
@eff.await.perform p
|
89
90
|
end
|
90
91
|
|
91
|
-
# @method with
|
92
|
+
# @method with(&th)
|
92
93
|
# @param [Proc<(), _A!{Async.async, Async.yield, Async.await, e}>] th
|
93
94
|
# is a thunk returning `_A` with te possibility to invoke effects,
|
94
95
|
# including `Async.async` , `Async.yield` and `Async.await` .
|
95
96
|
# @return [()!{e}]
|
96
97
|
# returns unit but still has the possibility to invoke effects `e` .
|
97
98
|
define_method :with do |&th|
|
98
|
-
fork(Util::Ref.new(
|
99
|
+
fork(Util::Ref.new(Waiting.new([])), th)
|
99
100
|
end
|
100
101
|
|
101
102
|
# You can reimplement the handler using these effect instances
|
@@ -104,46 +105,50 @@ module Ruff::Standard::Async
|
|
104
105
|
|
105
106
|
private
|
106
107
|
|
108
|
+
# rubocop:disable Metrics/AbcSize
|
109
|
+
# rubocop:disable Metrics/BlockLength
|
107
110
|
define_method :fork do |pr, th|
|
108
|
-
Ruff.
|
109
|
-
|
111
|
+
h = Ruff::Handler.new
|
112
|
+
h.to do |v|
|
110
113
|
pp = pr.get
|
111
114
|
l = case pp
|
112
|
-
when
|
113
|
-
|
114
|
-
else
|
115
|
-
raise 'impossible'
|
115
|
+
when Waiting then pp.get
|
116
|
+
else raise 'impossible'
|
116
117
|
end
|
117
118
|
|
118
119
|
l.each do |k|
|
119
120
|
@q.enqueue(-> { k[v] })
|
120
121
|
end
|
121
122
|
|
122
|
-
pr.set(
|
123
|
+
pr.set(Done.new(v))
|
123
124
|
@q.dequeue
|
124
125
|
end
|
125
|
-
|
126
|
-
|
126
|
+
|
127
|
+
h.on(@eff.async) do |k, f|
|
128
|
+
pr_ = Util::Ref.new(Waiting.new([]))
|
127
129
|
@q.enqueue(-> { k[pr_] })
|
128
130
|
fork(pr_, f)
|
129
131
|
end
|
130
|
-
|
132
|
+
h.on(@eff.yield) do |k|
|
131
133
|
@q.enqueue(-> { k[] })
|
132
134
|
@q.dequeue.call
|
133
135
|
end
|
134
|
-
|
135
|
-
|
136
|
+
|
137
|
+
h.on(@eff.await) do |k, ppr|
|
138
|
+
pp = ppr.get
|
136
139
|
|
137
140
|
return case pp
|
138
|
-
when
|
139
|
-
|
140
|
-
|
141
|
-
pr.set(_Waiting.new(@q.cons(k)))
|
141
|
+
when Done then k[pp.get]
|
142
|
+
when Waiting
|
143
|
+
pr.set(Waiting.new(@q.cons(k)))
|
142
144
|
@q.dequeue.call
|
143
145
|
end
|
144
146
|
end
|
145
|
-
|
147
|
+
|
148
|
+
h.run { th[] }
|
146
149
|
end
|
150
|
+
# rubocop:enable Metrics/BlockLength
|
151
|
+
# rubocop:enable Metrics/AbcSize
|
147
152
|
end
|
148
153
|
|
149
154
|
# ---
|
@@ -30,7 +30,7 @@ module Ruff::Standard::CurrentTime
|
|
30
30
|
# returns `A` , without modification by value handler.
|
31
31
|
# But it still has the possibility to invoke effects(`e`).
|
32
32
|
def with(&th)
|
33
|
-
|
33
|
+
@handler.run(&th)
|
34
34
|
end
|
35
35
|
|
36
36
|
# You can reimplement the handler using this effect instance.
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# `DelimCtrl` provides one-shot delimited control operators, `shift` and `reset`.
|
4
|
+
# @example
|
5
|
+
# DelimCtrl.reset {
|
6
|
+
# puts "hello"
|
7
|
+
# DelimCtrl.shift { |k|
|
8
|
+
# k.call
|
9
|
+
# puts "!"
|
10
|
+
# }
|
11
|
+
#
|
12
|
+
# puts "world"
|
13
|
+
# }
|
14
|
+
# # ==>
|
15
|
+
# # hello
|
16
|
+
# # world
|
17
|
+
# # !
|
18
|
+
module Ruff::Standard::DelimCtrl
|
19
|
+
# prompt stack
|
20
|
+
@stack = []
|
21
|
+
|
22
|
+
# delimits a continuation
|
23
|
+
# @param [Proc<(), A>] th
|
24
|
+
# is a thunk. In this thunk `shift` captures a continuation delimited with the thunk.
|
25
|
+
def reset(&th)
|
26
|
+
eff = Ruff::Effect.new
|
27
|
+
@stack.push eff
|
28
|
+
|
29
|
+
ret = Ruff.handler
|
30
|
+
.on(eff) do |k, f|
|
31
|
+
f.call(k)
|
32
|
+
end
|
33
|
+
.run(&th)
|
34
|
+
|
35
|
+
@stack.pop
|
36
|
+
ret
|
37
|
+
end
|
38
|
+
|
39
|
+
# captures a continuation.
|
40
|
+
# @param [Proc<Proc<C, A>, A/B>] k
|
41
|
+
# is a continuation.
|
42
|
+
def shift(&k)
|
43
|
+
# fetch nearmost prompt
|
44
|
+
top = @stack.last
|
45
|
+
top.perform(k)
|
46
|
+
end
|
47
|
+
|
48
|
+
module_function :reset, :shift
|
49
|
+
end
|
@@ -22,13 +22,13 @@ module Ruff::Standard::MeasureTime
|
|
22
22
|
def initialize
|
23
23
|
@eff = Ruff.instance
|
24
24
|
@handler = Ruff.handler
|
25
|
-
|
25
|
+
@handler.on(@eff) do |k, label|
|
26
26
|
t1 = Time.now
|
27
27
|
result = k[]
|
28
28
|
t2 = Time.now
|
29
29
|
result + [{ label: label, time: t2 - t1 }]
|
30
30
|
end
|
31
|
-
|
31
|
+
@handler.to { |x| [x] }
|
32
32
|
end
|
33
33
|
|
34
34
|
# is a smart method to invoke the effect operation.
|
data/lib/ruff/version.rb
CHANGED
data/ruff.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.require_paths = ['lib']
|
22
22
|
|
23
23
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
24
|
-
spec.add_development_dependency 'rake', '~>
|
24
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
25
25
|
|
26
26
|
spec.metadata = {
|
27
27
|
'documentation_uri' => 'https://nymphium.github.io/ruff'
|
data/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
2.1.0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nymphium
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '13.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '13.0'
|
41
41
|
description: ONE-SHOT Algebraic Effects for Ruby!
|
42
42
|
email:
|
43
43
|
- s1311350@gmail.com
|
@@ -49,20 +49,22 @@ files:
|
|
49
49
|
- ".rubocop.yml"
|
50
50
|
- ".solargraph.yml"
|
51
51
|
- Gemfile
|
52
|
-
- Gemfile.lock
|
53
52
|
- LICENSE
|
54
53
|
- README.md
|
55
54
|
- Rakefile
|
55
|
+
- docs/.nojekyll
|
56
56
|
- docs/Ruff.html
|
57
57
|
- docs/Ruff/Effect.html
|
58
58
|
- docs/Ruff/Handler.html
|
59
59
|
- docs/Ruff/Standard.html
|
60
60
|
- docs/Ruff/Standard/Async.html
|
61
61
|
- docs/Ruff/Standard/Async/Instance.html
|
62
|
+
- docs/Ruff/Standard/Call1cc.html
|
62
63
|
- docs/Ruff/Standard/CurrentTime.html
|
63
64
|
- docs/Ruff/Standard/CurrentTime/Instance.html
|
64
65
|
- docs/Ruff/Standard/Defer.html
|
65
66
|
- docs/Ruff/Standard/Defer/Instance.html
|
67
|
+
- docs/Ruff/Standard/DelimCtrl.html
|
66
68
|
- docs/Ruff/Standard/MeasureTime.html
|
67
69
|
- docs/Ruff/Standard/MeasureTime/Instance.html
|
68
70
|
- docs/Ruff/Standard/State.html
|
@@ -96,6 +98,7 @@ files:
|
|
96
98
|
- lib/ruff/standard/async.rb
|
97
99
|
- lib/ruff/standard/current_time.rb
|
98
100
|
- lib/ruff/standard/defer.rb
|
101
|
+
- lib/ruff/standard/delim_ctrl.rb
|
99
102
|
- lib/ruff/standard/measure_time.rb
|
100
103
|
- lib/ruff/standard/state.rb
|
101
104
|
- lib/ruff/standard/util.rb
|
@@ -108,7 +111,7 @@ licenses:
|
|
108
111
|
- MIT
|
109
112
|
metadata:
|
110
113
|
documentation_uri: https://nymphium.github.io/ruff
|
111
|
-
post_install_message:
|
114
|
+
post_install_message:
|
112
115
|
rdoc_options: []
|
113
116
|
require_paths:
|
114
117
|
- lib
|
@@ -123,8 +126,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
126
|
- !ruby/object:Gem::Version
|
124
127
|
version: '0'
|
125
128
|
requirements: []
|
126
|
-
rubygems_version: 3.
|
127
|
-
signing_key:
|
129
|
+
rubygems_version: 3.1.3
|
130
|
+
signing_key:
|
128
131
|
specification_version: 4
|
129
132
|
summary: ONE-SHOT Algebraic Effects for Ruby!
|
130
133
|
test_files: []
|