@effekt-lang/effekt 0.2.2 → 0.3.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 (96) hide show
  1. package/bin/effekt +0 -0
  2. package/bin/effekt.sh +1 -1
  3. package/libraries/chez/common/effekt_primitives.ss +10 -2
  4. package/libraries/chez/common/immutable/cslist.effekt +13 -7
  5. package/libraries/chez/common/mutable/dict.effekt +8 -10
  6. package/libraries/chez/common/text/regex.effekt +7 -9
  7. package/libraries/common/args.effekt +95 -0
  8. package/libraries/common/array.effekt +225 -0
  9. package/libraries/common/bench.effekt +60 -0
  10. package/libraries/common/buffer.effekt +123 -0
  11. package/libraries/common/bytes.effekt +125 -0
  12. package/libraries/{chez/common/immutable → common}/dequeue.effekt +18 -4
  13. package/libraries/common/effekt.effekt +764 -0
  14. package/libraries/common/exception.effekt +122 -0
  15. package/libraries/common/io/console.effekt +66 -0
  16. package/libraries/common/io/error.effekt +365 -0
  17. package/libraries/common/io/files.effekt +282 -0
  18. package/libraries/common/io/network.effekt +105 -0
  19. package/libraries/common/io/time.effekt +15 -0
  20. package/libraries/common/io.effekt +158 -0
  21. package/libraries/{llvm/immutable → common}/list.effekt +83 -74
  22. package/libraries/common/option.effekt +72 -0
  23. package/libraries/common/process.effekt +10 -0
  24. package/libraries/common/queue.effekt +140 -0
  25. package/libraries/common/ref.effekt +63 -0
  26. package/libraries/common/result.effekt +45 -0
  27. package/libraries/{ml/immutable → common}/seq.effekt +30 -19
  28. package/libraries/common/string.effekt +395 -0
  29. package/libraries/common/test.effekt +98 -0
  30. package/libraries/js/effekt_builtins.js +37 -6
  31. package/libraries/js/io.js +143 -0
  32. package/libraries/js/mutable/map.effekt +8 -9
  33. package/libraries/js/text/regex.effekt +7 -8
  34. package/libraries/js/unsafe/cont.effekt +2 -2
  35. package/libraries/js/web/dom.effekt +13 -13
  36. package/libraries/llvm/array.c +53 -0
  37. package/libraries/llvm/buffer.c +181 -76
  38. package/libraries/llvm/forward-declare-c.ll +27 -8
  39. package/libraries/llvm/io.c +543 -1
  40. package/libraries/llvm/io.ll +19 -0
  41. package/libraries/llvm/main.c +3 -1
  42. package/libraries/llvm/ref.c +45 -0
  43. package/libraries/llvm/rts.ll +496 -354
  44. package/libraries/llvm/types.c +23 -0
  45. package/libraries/ml/effekt.sml +2 -0
  46. package/libraries/ml/internal/mllist.effekt +9 -0
  47. package/libraries/ml/internal/mloption.effekt +18 -0
  48. package/libraries/ml/random.effekt +9 -9
  49. package/libraries/ml/text/regex.effekt +14 -19
  50. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
  51. package/licenses/mit license - mit-license.html +527 -57
  52. package/licenses/the bsd license - bsd-license.html +530 -55
  53. package/licenses/the mit license - mit.html +528 -58
  54. package/package.json +2 -2
  55. package/libraries/chez/callcc/effekt.effekt +0 -221
  56. package/libraries/chez/common/effekt_matching.ss +0 -100
  57. package/libraries/chez/common/immutable/list.effekt +0 -643
  58. package/libraries/chez/common/immutable/option.effekt +0 -39
  59. package/libraries/chez/common/immutable/result.effekt +0 -29
  60. package/libraries/chez/common/io/args.effekt +0 -20
  61. package/libraries/chez/common/mutable/array.effekt +0 -27
  62. package/libraries/chez/common/mutable/heap.effekt +0 -12
  63. package/libraries/chez/common/test.effekt +0 -59
  64. package/libraries/chez/common/text/string.effekt +0 -46
  65. package/libraries/chez/lift/effekt.effekt +0 -217
  66. package/libraries/chez/monadic/effekt.effekt +0 -218
  67. package/libraries/js/effekt.effekt +0 -284
  68. package/libraries/js/effekt_matching.js +0 -79
  69. package/libraries/js/immutable/dequeue.effekt +0 -78
  70. package/libraries/js/immutable/list.effekt +0 -643
  71. package/libraries/js/immutable/option.effekt +0 -49
  72. package/libraries/js/immutable/result.effekt +0 -29
  73. package/libraries/js/io/args.effekt +0 -9
  74. package/libraries/js/io/async.effekt +0 -28
  75. package/libraries/js/io/async.js +0 -2
  76. package/libraries/js/io/file.effekt +0 -50
  77. package/libraries/js/io/file_include.js +0 -13
  78. package/libraries/js/mutable/array.effekt +0 -98
  79. package/libraries/js/mutable/heap.effekt +0 -32
  80. package/libraries/js/test.effekt +0 -59
  81. package/libraries/js/text/string.effekt +0 -64
  82. package/libraries/llvm/effekt.effekt +0 -243
  83. package/libraries/llvm/immutable/option.effekt +0 -53
  84. package/libraries/llvm/immutable/result.effekt +0 -29
  85. package/libraries/llvm/io/args.effekt +0 -24
  86. package/libraries/llvm/text/string.effekt +0 -179
  87. package/libraries/ml/effekt.effekt +0 -267
  88. package/libraries/ml/immutable/dequeue.effekt +0 -81
  89. package/libraries/ml/immutable/list.effekt +0 -674
  90. package/libraries/ml/immutable/option.effekt +0 -53
  91. package/libraries/ml/immutable/result.effekt +0 -29
  92. package/libraries/ml/internal/option.effekt +0 -18
  93. package/libraries/ml/io/args.effekt +0 -41
  94. package/libraries/ml/mutable/array.effekt +0 -43
  95. package/libraries/ml/test.effekt +0 -60
  96. package/libraries/ml/text/string.effekt +0 -81
@@ -1,20 +0,0 @@
1
- module io/args
2
-
3
- import effekt
4
- import immutable/option
5
- import immutable/cslist
6
- import immutable/list
7
-
8
-
9
- // ================================================
10
- //
11
- // Conceptual Public Functions:
12
- // - commandLineArgs(): List[String]
13
- //
14
- // ================================================
15
-
16
- // Arguments passed to the script, first one is the file name itself, which we ignore.
17
- extern io def nativeArgs(): CSList[String] =
18
- "(cdr (command-line))"
19
-
20
- def commandLineArgs(): List[String] = nativeArgs().fromChez
@@ -1,27 +0,0 @@
1
- module mutable/array
2
-
3
- import immutable/option
4
- import immutable/cslist
5
-
6
- // a mutable array backed by a scheme vector
7
- extern type Array[T]
8
-
9
- extern pure def emptyArray[T](size: Int): Array[T] =
10
- "(make-vector ${size})"
11
-
12
- def get[T](arr: Array[T], index: Int): Option[T] =
13
- if (index >= arr.size) None() else Some(arr.unsafeGet(index))
14
-
15
- extern pure def size[T](arr: Array[T]): Int =
16
- "(vector-length ${arr})"
17
-
18
- // raises a scheme exception if out of bounds
19
- extern pure def unsafeGet[T](arr: Array[T], index: Int): T =
20
- "(vector-ref ${arr} ${index})"
21
-
22
- // TODO raises a scheme exception if out of bounds
23
- extern io def put[T](arr: Array[T], index: Int, value: T): Unit =
24
- "(begin (vector-set! ${arr} ${index} ${value}) #f)"
25
-
26
- extern pure def toArray[A](l: CSList[A]): Array[A] =
27
- "(list->vector ${l})"
@@ -1,12 +0,0 @@
1
- module mutable/heap
2
-
3
- extern type Ref[T]
4
-
5
- extern io def fresh[T](init: T): Ref[T] =
6
- "(box ${init})"
7
-
8
- extern io def put[T](ref: Ref[T], value: T): Unit =
9
- "(set-box! ${ref} ${value})"
10
-
11
- extern io def get[T](ref: Ref[T]): T =
12
- "(unbox ${ref})"
@@ -1,59 +0,0 @@
1
- import text/string
2
-
3
- interface Assertion {
4
- def assert(condition: Boolean, msg: String): Unit
5
- }
6
-
7
- def assertTrue(condition: Boolean, msg: String) =
8
- do assert(condition, msg)
9
-
10
- def assertTrue(condition: Boolean) =
11
- do assert(condition, "Assertion failed")
12
-
13
- def assertFalse(condition: Boolean, msg: String) =
14
- do assert(not(condition), msg)
15
-
16
- def assertFalse(condition: Boolean) =
17
- do assert(not(condition), "Assertion failed")
18
-
19
- def assertEqual[A](obtained: A, expected: A, msg: String) =
20
- do assert(obtained == expected, msg)
21
-
22
- def assertEqual[A](obtained: A, expected: A) =
23
- do assert(obtained == expected, "Obtained: " ++ obtained.show ++ "\n but expected:" ++ expected.show)
24
-
25
- interface Test {
26
- def success(name: String): Unit
27
- def failure(name: String, msg: String): Unit
28
- }
29
-
30
- def test(name: String) { body: => Unit / Assertion } =
31
- try { body(); do success(name) } with Assertion {
32
- def assert(condition, msg) = if (condition) resume(()) else do failure(name, msg)
33
- }
34
-
35
- def suite(name: String) { body: => Unit / Test }: Boolean = {
36
- println("Running suite: " ++ name);
37
- var failed = 0
38
- var passed = 0
39
-
40
- try { body() } with Test {
41
- def success(name) = {
42
- passed = passed + 1
43
- println(ANSI_GREEN ++ "+ " ++ name ++ "" ++ ANSI_RESET);
44
- resume(())
45
- }
46
- def failure(name, msg) = {
47
- failed = failed + 1
48
- println(ANSI_RED ++ "- (FAIL) " ++ name ++ "\n " ++ msg ++ ANSI_RESET);
49
- resume(())
50
- }
51
- }
52
- if (failed > 0) {
53
- println(ANSI_RED ++ "Some tests failed (" ++ passed.show ++ " passed, " ++ failed.show ++ " failed)" ++ ANSI_RESET)
54
- false
55
- } else {
56
- println(ANSI_GREEN ++ "All tests passed (" ++ passed.show ++ " passed)" ++ ANSI_RESET)
57
- true
58
- }
59
- }
@@ -1,46 +0,0 @@
1
- module text/string
2
-
3
- import immutable/option
4
-
5
- // def charAt(str: String, index: Int): Option[String] =
6
- // str.unsafeCharAt(index).undefinedToOption
7
-
8
- extern pure def length(str: String): Int =
9
- "(string-length ${str})"
10
-
11
- extern pure def repeat(str: String, n: Int): String =
12
- "(letrec ([repeat (lambda (${n} acc) (if (<= ${n} 0) acc (repeat (- ${n} 1) (string-append acc ${str}))))]) (repeat ${n} (list->string '())))"
13
-
14
- extern pure def unsafeSubstring(str: String, from: Int, to: Int): String =
15
- "(substring ${str} ${from} ${to})"
16
-
17
- def substring(str: String, from: Int, to: Int): String = {
18
- def clamp(lower: Int, x: Int, upper: Int) = max(lower, min(x, upper))
19
-
20
- val len = str.length
21
- val clampedTo = clamp(0, to, len)
22
- val clampedFrom = clamp(0, from, to)
23
-
24
- str.unsafeSubstring(clampedFrom, clampedTo)
25
- }
26
-
27
- def substring(str: String, from: Int): String =
28
- str.substring(from, str.length)
29
-
30
- // extern pure def trim(str: String): String =
31
- // "str.trim()"
32
-
33
- def toInt(str: String): Option[Int] =
34
- str.unsafeToInt.undefinedToOption
35
-
36
- // extern pure def unsafeCharAt(str: String, n: Int): String =
37
- // "str[n]"
38
-
39
- // returns #f if not a number
40
- extern pure def unsafeToInt(str: String): Int =
41
- "(string->number ${str})"
42
-
43
- // ANSI escape codes
44
- val ANSI_GREEN = "\033[32m"
45
- val ANSI_RED = "\033[31m"
46
- val ANSI_RESET = "\033[0m"
@@ -1,217 +0,0 @@
1
- module effekt
2
-
3
- extern include "../common/effekt_primitives.ss"
4
- extern include "effekt.ss"
5
- extern include "../common/effekt_matching.ss"
6
-
7
-
8
- def locally[R] { f: => R }: R = f()
9
-
10
- // String ops
11
- // ==========
12
- extern pure def infixConcat(s1: String, s2: String): String =
13
- "(string-append ${s1} ${s2})"
14
-
15
- // TODO implement
16
- extern pure def show[R](value: R): String =
17
- "(show_impl ${value})"
18
-
19
- extern io def println[R](r: R): Unit =
20
- "(println_impl ${r})"
21
-
22
- extern io def error[R](msg: String): R =
23
- "(raise ${msg})"
24
-
25
- extern io def random(): Double =
26
- "(random 1.0)"
27
-
28
- // Math ops
29
- // ========
30
- extern pure def infixAdd(x: Int, y: Int): Int =
31
- "(+ ${x} ${y})"
32
-
33
- extern pure def infixMul(x: Int, y: Int): Int =
34
- "(* ${x} ${y})"
35
-
36
- extern pure def infixDiv(x: Int, y: Int): Int =
37
- "(floor (/ ${x} ${y}))"
38
-
39
- extern pure def infixSub(x: Int, y: Int): Int =
40
- "(- ${x} ${y})"
41
-
42
- extern pure def mod(x: Int, y: Int): Int =
43
- "(modulo ${x} ${y})"
44
-
45
- extern pure def infixAdd(x: Double, y: Double): Double =
46
- "(+ ${x} ${y})"
47
-
48
- extern pure def infixMul(x: Double, y: Double): Double =
49
- "(* ${x} ${y})"
50
-
51
- extern pure def infixDiv(x: Double, y: Double): Double =
52
- "(/ ${x} ${y})"
53
-
54
- extern pure def infixSub(x: Double, y: Double): Double =
55
- "(- ${x} ${y})"
56
-
57
- extern pure def cos(x: Double): Double =
58
- "(cos ${x})"
59
-
60
- extern pure def sin(x: Double): Double =
61
- "(sin ${x})"
62
-
63
- extern pure def atan(x: Double): Double =
64
- "(atan ${x})"
65
-
66
- extern pure def tan(x: Double): Double =
67
- "(tan ${x})"
68
-
69
- extern pure def sqrt(x: Double): Double =
70
- "(sqrt ${x})"
71
-
72
- extern pure def square(x: Double): Double =
73
- "(* x ${x})"
74
-
75
- extern pure def log(x: Double): Double =
76
- "(log ${x})"
77
-
78
- extern pure def log1p(x: Double): Double =
79
- "(log (+ ${x} 1))"
80
-
81
- extern pure def exp(x: Double): Double =
82
- "(exp ${x})"
83
-
84
- // since we do not have "extern val", yet
85
- extern pure def _pi(): Double =
86
- "(* 4 (atan 1))"
87
-
88
- val PI: Double = _pi()
89
-
90
- extern pure def toInt(d: Double): Int =
91
- "(round ${d})"
92
-
93
- extern pure def toDouble(d: Int): Double =
94
- "${d}"
95
-
96
- def min(n: Int, m: Int): Int =
97
- if (n < m) n else m
98
-
99
- def max(n: Int, m: Int): Int =
100
- if (n > m) n else m
101
-
102
- // Comparison ops
103
- // ==============
104
- extern pure def infixEq[R](x: R, y: R): Boolean =
105
- "(equal_impl ${x} ${y})"
106
-
107
- extern pure def infixNeq[R](x: R, y: R): Boolean =
108
- "(not (equal_impl ${x} ${y}))"
109
-
110
- extern pure def infixLt(x: Int, y: Int): Boolean =
111
- "(< ${x} ${y})"
112
-
113
- extern pure def infixLte(x: Int, y: Int): Boolean =
114
- "(<= ${x} ${y})"
115
-
116
- extern pure def infixGt(x: Int, y: Int): Boolean =
117
- "(> ${x} ${y})"
118
-
119
- extern pure def infixGte(x: Int, y: Int): Boolean =
120
- "(>= ${x} ${y})"
121
-
122
- extern pure def infixLt(x: Double, y: Double): Boolean =
123
- "(< ${x} ${y})"
124
-
125
- extern pure def infixLte(x: Double, y: Double): Boolean =
126
- "(<= ${x} ${y})"
127
-
128
- extern pure def infixGt(x: Double, y: Double): Boolean =
129
- "(> ${x} ${y})"
130
-
131
- extern pure def infixGte(x: Double, y: Double): Boolean =
132
- "(>= ${x} ${y})"
133
-
134
- // Boolean ops
135
- // ===========
136
- // for now those are considered eager
137
- extern pure def not(b: Boolean): Boolean =
138
- "(not ${b})"
139
-
140
- extern pure def infixOr(x: Boolean, y: Boolean): Boolean =
141
- "(or ${x} ${y})"
142
-
143
- extern pure def infixAnd(x: Boolean, y: Boolean): Boolean =
144
- "(and ${x} ${y})"
145
-
146
- // Should only be used internally since values in Effekt should not be undefined
147
- extern pure def isUndefined[A](value: A): Boolean =
148
- "(eq? ${value} #f)"
149
-
150
- // Pairs
151
- // =====
152
- record Tuple2[A, B](first: A, second: B)
153
- record Tuple3[A, B, C](first: A, second: B, third: C)
154
- record Tuple4[A, B, C, D](first: A, second: B, third: C, fourth: D)
155
- record Tuple5[A, B, C, D, E](first: A, second: B, third: C, fourth: D, fifth: E)
156
- record Tuple6[A, B, C, D, E, F](first: A, second: B, third: C, fourth: D, fifth: E, sixth: F)
157
-
158
- // Exceptions
159
- // ==========
160
- // a fatal runtime error that cannot be caught
161
- extern io def panic[R](msg: String): R =
162
- "(raise ${msg})"
163
-
164
- interface Exception[E] {
165
- def raise(exception: E, msg: String): Nothing
166
- }
167
- record RuntimeError()
168
-
169
- def raise[A](msg: String): A / Exception[RuntimeError] = do raise(RuntimeError(), msg) match {}
170
- def raise[A, E](exception: E, msg: String): A / Exception[E] = do raise(exception, msg) match {}
171
-
172
- // converts exceptions of (static) type E to an uncatchable panic that aborts the program
173
- def panicOn[E] { prog: => Unit / Exception[E] }: Unit =
174
- try { prog() } with Exception[E] { def raise(exception: E, msg: String) = panic(msg) }
175
-
176
- // reports exceptions of (static) type E to the console
177
- def report[E] { prog: => Unit / Exception[E] }: Unit =
178
- try { prog() } with Exception[E] { def raise(exception: E, msg: String) = println(msg) }
179
-
180
- // ignores exceptions of (static) type E
181
- // TODO this should be called "ignore" but that name currently clashes with internal pattern matching names on $effekt
182
- def ignoring[E] { prog: => Unit / Exception[E] }: Unit =
183
- try { prog() } with Exception[E] { def raise(exception: E, msg: String) = () }
184
-
185
- // Control Flow
186
- // ============
187
- interface Control {
188
- def break(): Unit
189
- def continue(): Unit
190
- }
191
-
192
- def loop { f: () => Unit / Control }: Unit = try {
193
- def go(): Unit = { f(); go() }
194
- go()
195
- } with Control {
196
- def break() = ()
197
- def continue() = loop { f }
198
- }
199
-
200
- /**
201
- * Calls provided action repeatedly. `start` is inclusive, `end` is not.
202
- */
203
- def each(start: Int, end: Int) { action: (Int) => Unit / Control } = {
204
- var i = start;
205
- loop {
206
- if (i < end) { val el = i; i = i + 1; action(el) }
207
- else { do break() }
208
- }
209
- }
210
-
211
- def repeat(n: Int) { action: () => Unit / Control } = each(0, n) { n => action() }
212
-
213
- // Benchmarking
214
- // ============
215
- // should only be used with pure blocks
216
- extern control def measure(warmup: Int, iterations: Int) { block: => Unit }: Unit =
217
- "(delayed (display (measure (lambda () (run ((${box block} here)))) ${warmup} ${iterations})))"
@@ -1,218 +0,0 @@
1
- module effekt
2
-
3
- extern include "../common/effekt_primitives.ss"
4
- extern include "seq0.ss"
5
- extern include "effekt.ss"
6
- extern include "../common/effekt_matching.ss"
7
-
8
-
9
- def locally[R] { f: => R }: R = f()
10
-
11
- // String ops
12
- // ==========
13
- extern pure def infixConcat(s1: String, s2: String): String =
14
- "(string-append ${s1} ${s2})"
15
-
16
- // TODO implement
17
- extern pure def show[R](value: R): String =
18
- "(show_impl ${value})"
19
-
20
- extern io def println[R](r: R): Unit =
21
- "(println_impl ${r})"
22
-
23
- extern io def error[R](msg: String): R =
24
- "(raise ${msg})"
25
-
26
- extern io def random(): Double =
27
- "(random 1.0)"
28
-
29
- // Math ops
30
- // ========
31
- extern pure def infixAdd(x: Int, y: Int): Int =
32
- "(+ ${x} ${y})"
33
-
34
- extern pure def infixMul(x: Int, y: Int): Int =
35
- "(* ${x} ${y})"
36
-
37
- extern pure def infixDiv(x: Int, y: Int): Int =
38
- "(floor (/ ${x} ${y}))"
39
-
40
- extern pure def infixSub(x: Int, y: Int): Int =
41
- "(- ${x} ${y})"
42
-
43
- extern pure def mod(x: Int, y: Int): Int =
44
- "(modulo ${x} ${y})"
45
-
46
- extern pure def infixAdd(x: Double, y: Double): Double =
47
- "(+ ${x} ${y})"
48
-
49
- extern pure def infixMul(x: Double, y: Double): Double =
50
- "(* ${x} ${y})"
51
-
52
- extern pure def infixDiv(x: Double, y: Double): Double =
53
- "(/ ${x} ${y})"
54
-
55
- extern pure def infixSub(x: Double, y: Double): Double =
56
- "(- ${x} ${y})"
57
-
58
- extern pure def cos(x: Double): Double =
59
- "(cos ${x})"
60
-
61
- extern pure def sin(x: Double): Double =
62
- "(sin ${x})"
63
-
64
- extern pure def atan(x: Double): Double =
65
- "(atan ${x})"
66
-
67
- extern pure def tan(x: Double): Double =
68
- "(tan ${x})"
69
-
70
- extern pure def sqrt(x: Double): Double =
71
- "(sqrt ${x})"
72
-
73
- extern pure def square(x: Double): Double =
74
- "(* ${x} ${x})"
75
-
76
- extern pure def log(x: Double): Double =
77
- "(log ${x})"
78
-
79
- extern pure def log1p(x: Double): Double =
80
- "(log (+ ${x} 1))"
81
-
82
- extern pure def exp(x: Double): Double =
83
- "(exp ${x})"
84
-
85
- // since we do not have "extern val", yet
86
- extern pure def _pi(): Double =
87
- "(* 4 (atan 1))"
88
-
89
- val PI: Double = _pi()
90
-
91
- extern pure def toInt(d: Double): Int =
92
- "(round ${d})"
93
-
94
- extern pure def toDouble(d: Int): Double =
95
- "${d}"
96
-
97
- def min(n: Int, m: Int): Int =
98
- if (n < m) n else m
99
-
100
- def max(n: Int, m: Int): Int =
101
- if (n > m) n else m
102
-
103
- // Comparison ops
104
- // ==============
105
- extern pure def infixEq[R](x: R, y: R): Boolean =
106
- "(equal_impl ${x} ${y})"
107
-
108
- extern pure def infixNeq[R](x: R, y: R): Boolean =
109
- "(not (equal_impl ${x} ${y}))"
110
-
111
- extern pure def infixLt(x: Int, y: Int): Boolean =
112
- "(< ${x} ${y})"
113
-
114
- extern pure def infixLte(x: Int, y: Int): Boolean =
115
- "(<= ${x} ${y})"
116
-
117
- extern pure def infixGt(x: Int, y: Int): Boolean =
118
- "(> ${x} ${y})"
119
-
120
- extern pure def infixGte(x: Int, y: Int): Boolean =
121
- "(>= ${x} ${y})"
122
-
123
- extern pure def infixLt(x: Double, y: Double): Boolean =
124
- "(< ${x} ${y})"
125
-
126
- extern pure def infixLte(x: Double, y: Double): Boolean =
127
- "(<= ${x} ${y})"
128
-
129
- extern pure def infixGt(x: Double, y: Double): Boolean =
130
- "(> ${x} ${y})"
131
-
132
- extern pure def infixGte(x: Double, y: Double): Boolean =
133
- "(>= ${x} ${y})"
134
-
135
- // Boolean ops
136
- // ===========
137
- // for now those are considered eager
138
- extern pure def not(b: Boolean): Boolean =
139
- "(not ${b})"
140
-
141
- extern pure def infixOr(x: Boolean, y: Boolean): Boolean =
142
- "(or ${x} ${y})"
143
-
144
- extern pure def infixAnd(x: Boolean, y: Boolean): Boolean =
145
- "(and ${x} ${y})"
146
-
147
- // Should only be used internally since values in Effekt should not be undefined
148
- extern pure def isUndefined[A](value: A): Boolean =
149
- "(eq? ${value} #f)"
150
-
151
- // Pairs
152
- // =====
153
- record Tuple2[A, B](first: A, second: B)
154
- record Tuple3[A, B, C](first: A, second: B, third: C)
155
- record Tuple4[A, B, C, D](first: A, second: B, third: C, fourth: D)
156
- record Tuple5[A, B, C, D, E](first: A, second: B, third: C, fourth: D, fifth: E)
157
- record Tuple6[A, B, C, D, E, F](first: A, second: B, third: C, fourth: D, fifth: E, sixth: F)
158
-
159
- // Exceptions
160
- // ==========
161
- // a fatal runtime error that cannot be caught
162
- extern io def panic[R](msg: String): R =
163
- "(raise ${msg})"
164
-
165
- interface Exception[E] {
166
- def raise(exception: E, msg: String): Nothing
167
- }
168
- record RuntimeError()
169
-
170
- def raise[A](msg: String): A / Exception[RuntimeError] = do raise(RuntimeError(), msg) match {}
171
- def raise[A, E](exception: E, msg: String): A / Exception[E] = do raise(exception, msg) match {}
172
-
173
- // converts exceptions of (static) type E to an uncatchable panic that aborts the program
174
- def panicOn[E] { prog: => Unit / Exception[E] }: Unit =
175
- try { prog() } with Exception[E] { def raise(exception: E, msg: String) = panic(msg) }
176
-
177
- // reports exceptions of (static) type E to the console
178
- def report[E] { prog: => Unit / Exception[E] }: Unit =
179
- try { prog() } with Exception[E] { def raise(exception: E, msg: String) = println(msg) }
180
-
181
- // ignores exceptions of (static) type E
182
- // TODO this should be called "ignore" but that name currently clashes with internal pattern matching names on $effekt
183
- def ignoring[E] { prog: => Unit / Exception[E] }: Unit =
184
- try { prog() } with Exception[E] { def raise(exception: E, msg: String) = () }
185
-
186
- // Control Flow
187
- // ============
188
- interface Control {
189
- def break(): Unit
190
- def continue(): Unit
191
- }
192
-
193
- def loop { f: () => Unit / Control }: Unit = try {
194
- def go(): Unit = { f(); go() }
195
- go()
196
- } with Control {
197
- def break() = ()
198
- def continue() = loop { f }
199
- }
200
-
201
- /**
202
- * Calls provided action repeatedly. `start` is inclusive, `end` is not.
203
- */
204
- def each(start: Int, end: Int) { action: (Int) => Unit / Control } = {
205
- var i = start;
206
- loop {
207
- if (i < end) { val el = i; i = i + 1; action(el) }
208
- else { do break() }
209
- }
210
- }
211
-
212
- def repeat(n: Int) { action: () => Unit / Control } = each(0, n) { n => action() }
213
-
214
- // Benchmarking
215
- // ============
216
- // should only be used with pure blocks
217
- extern control def measure(warmup: Int, iterations: Int) { block: => Unit }: Unit =
218
- "(delayed (display (measure (lambda () (run (${box block}))) ${warmup} ${iterations})))"