-
Notifications
You must be signed in to change notification settings - Fork 29
/
annotations.scala
100 lines (95 loc) · 3.13 KB
/
annotations.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package com.thoughtworks.dsl
import scala.annotation.{StaticAnnotation, TypeConstraint}
/** The namespace that contains annotations of control operators for [[https://en.wikipedia.org/wiki/Delimited_continuation delimited continuation]].
*
* All annotations defined here requires the Scala compiler plugin, which can be added in `build.sbt`:
* `<pre>
* addCompilerPlugin("com.thoughtworks.dsl" %% "compilerplugin" % "latest.release")
* </pre>`
*
* == Example of definition of shift control operator ==
*
* Given a class that contains a `doShift` method, which is marked as `@shift`
*
* {{{
* import com.thoughtworks.dsl.annotations.{reset, shift}
* implicit class ShiftOps[R, A](f: (A => R) => R) {
* def cpsApply(handler: A => R): R = f(handler)
* @shift def doShift: A = sys.error("Calls to this method should have been translated to `cpsApply`")
* }
* }}}
*
* @example When creating a `@reset` block that contains the `doShift` method,
* then the `doShift` method should be translated to `cpsApply` with a handler of captured rest code in the method,
*
* {{{
* val explicitResetResult = {
* val i: Int = { (handler: Int => Int) =>
* handler(4) + 2
* }.doShift
* i * 10
* }: @reset
*
* explicitResetResult should be {
* ShiftOps { (handler: Int => Int) =>
* handler(4) + 2
* }.cpsApply { i =>
* i * 10
* }
* }
*
* explicitResetResult should be(42)
* }}}
*
* and the result differs if you move the [[reset]] annotation.
*
* {{{
* val explicitResetResult2 = {
* val i: Int = { (handler: Int => Int) =>
* handler(4) + 2
* }.doShift : @reset
* i * 10
* }
*
* explicitResetResult2 should be {
* val i = ShiftOps { (handler: Int => Int) =>
* handler(4) + 2
* }.cpsApply(identity)
* i * 10
* }
*
* explicitResetResult2 should be(60)
* }}}
*
* @note If you omit an explicit [[reset]] annotation,
*
* {{{
* def automaticallyReset: Int = {
* val i: Int = { (handler: Int => Int) =>
* handler(4) + 2
* }.doShift
* i * 10
* }
* }}}
*
* then the [[reset]] operation will be performed on the enclosing method or function automatically.
*
* {{{
* automaticallyReset should be {
* ShiftOps { (handler: Int => Int) =>
* handler(4) + 2
* }.cpsApply { i =>
* i * 10
* }
* }
*
* automaticallyReset should be(42)
* }}}
* @see [[Dsl.Instruction]] for a sophisticated implementation of `cpsApply`.
*/
object annotations {
/** An annotation to explicitly perform reset control operator on a code block. */
final class reset extends StaticAnnotation
/** An annotation to mark a method is a shift control operator. */
final class shift extends StaticAnnotation
}