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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.rubocop.yml +1 -1
  4. data/Gemfile +3 -0
  5. data/README.md +35 -58
  6. data/Rakefile +2 -1
  7. data/docs/.nojekyll +0 -0
  8. data/docs/Ruff.html +7 -7
  9. data/docs/Ruff/Effect.html +165 -23
  10. data/docs/Ruff/Handler.html +46 -114
  11. data/docs/Ruff/Standard.html +7 -7
  12. data/docs/Ruff/Standard/Async.html +28 -27
  13. data/docs/Ruff/Standard/Async/Instance.html +63 -27
  14. data/docs/Ruff/Standard/Call1cc.html +297 -0
  15. data/docs/Ruff/Standard/CurrentTime.html +6 -6
  16. data/docs/Ruff/Standard/CurrentTime/Instance.html +7 -7
  17. data/docs/Ruff/Standard/Defer.html +6 -6
  18. data/docs/Ruff/Standard/Defer/Instance.html +6 -6
  19. data/docs/Ruff/Standard/DelimCtrl.html +340 -0
  20. data/docs/Ruff/Standard/MeasureTime.html +6 -6
  21. data/docs/Ruff/Standard/MeasureTime/Instance.html +8 -8
  22. data/docs/Ruff/Standard/State.html +6 -6
  23. data/docs/Ruff/Standard/State/Instance.html +6 -6
  24. data/docs/Ruff/Throws.html +6 -11
  25. data/docs/Ruff/Throws/Eff.html +6 -6
  26. data/docs/Ruff/Throws/Resend.html +6 -6
  27. data/docs/_index.html +14 -7
  28. data/docs/class_list.html +3 -3
  29. data/docs/css/style.css +2 -2
  30. data/docs/file.README.html +41 -58
  31. data/docs/file_list.html +2 -2
  32. data/docs/frames.html +2 -2
  33. data/docs/index.html +41 -58
  34. data/docs/js/app.js +14 -3
  35. data/docs/method_list.html +46 -30
  36. data/docs/top-level-namespace.html +6 -6
  37. data/lib/ruff/effect.rb +32 -3
  38. data/lib/ruff/handler.rb +43 -18
  39. data/lib/ruff/standard.rb +1 -0
  40. data/lib/ruff/standard/async.rb +27 -22
  41. data/lib/ruff/standard/current_time.rb +1 -1
  42. data/lib/ruff/standard/delim_ctrl.rb +49 -0
  43. data/lib/ruff/standard/measure_time.rb +2 -2
  44. data/lib/ruff/version.rb +1 -1
  45. data/ruff.gemspec +1 -1
  46. data/version +1 -1
  47. metadata +12 -9
  48. data/Gemfile.lock +0 -62
@@ -6,15 +6,15 @@
6
6
  <title>
7
7
  Top Level Namespace
8
8
 
9
- &mdash; Ruff 1.3.0 Documentation
9
+ &mdash; Ruff 2.1.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 Sun Oct 6 23:09:11 2019 by
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.20 (ruby-2.6.5).
105
+ 0.9.25 (ruby-2.7.1).
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_methods :handlers=
158
183
  end
@@ -24,3 +24,4 @@ require 'ruff/standard/measure_time'
24
24
  require 'ruff/standard/defer'
25
25
  require 'ruff/standard/state'
26
26
  require 'ruff/standard/async'
27
+ require 'ruff/standard/delim_ctrl'
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # `Async` provides effects `Async.async`, `Async.yield` and `Async.await`, and the implementation 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
- _Waiting = Util::ADT.create
51
- _Done = Util::ADT.create
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(_Waiting.new([])), th)
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.handler
109
- .to do |v|
111
+ h = Ruff::Handler.new
112
+ h.to do |v|
110
113
  pp = pr.get
111
114
  l = case pp
112
- when _Waiting
113
- pp.get
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(_Done.new(v))
123
+ pr.set(Done.new(v))
123
124
  @q.dequeue
124
125
  end
125
- .on(@eff.async) do |k, f|
126
- pr_ = Util::Ref.new(_Waiting.new([]))
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
- .on(@eff.yield) do |k|
132
+ h.on(@eff.yield) do |k|
131
133
  @q.enqueue(-> { k[] })
132
134
  @q.dequeue.call
133
135
  end
134
- .on(@eff.await) do |k, pr|
135
- pp = pr.get
136
+
137
+ h.on(@eff.await) do |k, ppr|
138
+ pp = ppr.get
136
139
 
137
140
  return case pp
138
- when _Done
139
- k[pp.get]
140
- when _Waiting
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
- .run { th[] }
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
- @handler.run(&th)
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
- .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.3.0'
4
+ VERSION = '2.1.0'
5
5
  end
@@ -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', '~> 10.0'
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.3.0
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.3.0
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: 2019-10-06 00:00:00.000000000 Z
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: '10.0'
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: '10.0'
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.0.6
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: []