ruff 1.4.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/Gemfile +2 -1
  4. data/Gemfile.lock +16 -12
  5. data/README.md +35 -58
  6. data/Rakefile +2 -1
  7. data/docs/Ruff.html +7 -7
  8. data/docs/Ruff/Effect.html +165 -23
  9. data/docs/Ruff/Handler.html +45 -50
  10. data/docs/Ruff/Standard.html +6 -6
  11. data/docs/Ruff/Standard/Async.html +26 -26
  12. data/docs/Ruff/Standard/Async/Instance.html +8 -8
  13. data/docs/Ruff/Standard/Call1cc.html +6 -6
  14. data/docs/Ruff/Standard/CurrentTime.html +6 -6
  15. data/docs/Ruff/Standard/CurrentTime/Instance.html +7 -7
  16. data/docs/Ruff/Standard/Defer.html +6 -6
  17. data/docs/Ruff/Standard/Defer/Instance.html +6 -6
  18. data/docs/Ruff/Standard/MeasureTime.html +6 -6
  19. data/docs/Ruff/Standard/MeasureTime/Instance.html +8 -8
  20. data/docs/Ruff/Standard/State.html +6 -6
  21. data/docs/Ruff/Standard/State/Instance.html +6 -6
  22. data/docs/Ruff/Throws.html +6 -11
  23. data/docs/Ruff/Throws/Eff.html +6 -6
  24. data/docs/Ruff/Throws/Resend.html +6 -6
  25. data/docs/_index.html +7 -7
  26. data/docs/class_list.html +2 -2
  27. data/docs/css/style.css +2 -2
  28. data/docs/file.README.html +39 -56
  29. data/docs/file_list.html +2 -2
  30. data/docs/frames.html +2 -2
  31. data/docs/index.html +39 -56
  32. data/docs/js/app.js +14 -3
  33. data/docs/method_list.html +71 -63
  34. data/docs/top-level-namespace.html +6 -6
  35. data/lib/ruff/effect.rb +32 -3
  36. data/lib/ruff/handler.rb +43 -18
  37. data/lib/ruff/standard/async.rb +10 -7
  38. data/lib/ruff/standard/current_time.rb +1 -1
  39. data/lib/ruff/standard/measure_time.rb +2 -2
  40. data/lib/ruff/version.rb +1 -1
  41. data/version +1 -1
  42. metadata +3 -3
@@ -6,15 +6,15 @@
6
6
  <title>
7
7
  Top Level Namespace
8
8
 
9
- &mdash; Ruff 1.3.1 Documentation
9
+ &mdash; Ruff 1.4.0 Documentation
10
10
 
11
11
  </title>
12
12
 
13
- <link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" />
14
14
 
15
- <link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" />
16
16
 
17
- <script type="text/javascript" charset="utf-8">
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 Wed Oct 30 01:51:52 2019 by
103
+ Generated on Thu Jan 2 19:46:22 2020 by
104
104
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
105
- 0.9.20 (ruby-2.6.5).
105
+ 0.9.22 (ruby-2.6.5).
106
106
  </div>
107
107
 
108
108
  </div>
@@ -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 UUID
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 = SecureRandom.uuid
14
- @id.freeze
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)
@@ -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 `id` function to by default.
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.id] = fun
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
- # is also private method.
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.id])
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.id])
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 :handlers=
158
183
  end
@@ -89,7 +89,7 @@ module Ruff::Standard::Async
89
89
  @eff.await.perform p
90
90
  end
91
91
 
92
- # @method with
92
+ # @method with(&th)
93
93
  # @param [Proc<(), _A!{Async.async, Async.yield, Async.await, e}>] th
94
94
  # is a thunk returning `_A` with te possibility to invoke effects,
95
95
  # including `Async.async` , `Async.yield` and `Async.await` .
@@ -108,8 +108,8 @@ module Ruff::Standard::Async
108
108
  # rubocop:disable Metrics/AbcSize
109
109
  # rubocop:disable Metrics/BlockLength
110
110
  define_method :fork do |pr, th|
111
- Ruff.handler
112
- .to do |v|
111
+ h = Ruff::Handler.new
112
+ h.to do |v|
113
113
  pp = pr.get
114
114
  l = case pp
115
115
  when Waiting then pp.get
@@ -123,16 +123,18 @@ module Ruff::Standard::Async
123
123
  pr.set(Done.new(v))
124
124
  @q.dequeue
125
125
  end
126
- .on(@eff.async) do |k, f|
126
+
127
+ h.on(@eff.async) do |k, f|
127
128
  pr_ = Util::Ref.new(Waiting.new([]))
128
129
  @q.enqueue(-> { k[pr_] })
129
130
  fork(pr_, f)
130
131
  end
131
- .on(@eff.yield) do |k|
132
+ h.on(@eff.yield) do |k|
132
133
  @q.enqueue(-> { k[] })
133
134
  @q.dequeue.call
134
135
  end
135
- .on(@eff.await) do |k, ppr|
136
+
137
+ h.on(@eff.await) do |k, ppr|
136
138
  pp = ppr.get
137
139
 
138
140
  return case pp
@@ -142,7 +144,8 @@ module Ruff::Standard::Async
142
144
  @q.dequeue.call
143
145
  end
144
146
  end
145
- .run { th[] }
147
+
148
+ h.run { th[] }
146
149
  end
147
150
  # rubocop:enable Metrics/BlockLength
148
151
  # rubocop:enable Metrics/AbcSize
@@ -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
- @handler.run(&th)
33
+ @handler.run(&th)
34
34
  end
35
35
 
36
36
  # You can reimplement the handler using this effect instance.
@@ -22,13 +22,13 @@ module Ruff::Standard::MeasureTime
22
22
  def initialize
23
23
  @eff = Ruff.instance
24
24
  @handler = Ruff.handler
25
- .on(@eff) do |k, label|
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
- .to { |x| [x] }
31
+ @handler.to { |x| [x] }
32
32
  end
33
33
 
34
34
  # is a smart method to invoke the effect operation.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ruff
4
- VERSION = '1.4.0'
4
+ VERSION = '2.0.0'
5
5
  end
data/version CHANGED
@@ -1 +1 @@
1
- 1.4.0
1
+ 2.0.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.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - nymphium
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-29 00:00:00.000000000 Z
11
+ date: 2020-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  - !ruby/object:Gem::Version
127
127
  version: '0'
128
128
  requirements: []
129
- rubygems_version: 3.0.6
129
+ rubygems_version: 3.1.2
130
130
  signing_key:
131
131
  specification_version: 4
132
132
  summary: ONE-SHOT Algebraic Effects for Ruby!