@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,24 +0,0 @@
1
- module io/args
2
-
3
- import effekt
4
- import immutable/list
5
-
6
- extern io def get_argc(): Int = """
7
- %c = call %Int @c_get_argc()
8
- ret %Int %c
9
- """
10
- extern io def get_arg(i: Int): String = """
11
- %s = call %Pos @c_get_arg(%Int %i)
12
- ret %Pos %s
13
- """
14
-
15
- def commandLineArgs(): List[String] = {
16
- def rec(start: Int, acc: List[String]): List[String] = {
17
- if (start < 1) {
18
- acc
19
- } else {
20
- rec(start-1, Cons(get_arg(start), acc))
21
- }
22
- }
23
- rec(get_argc()-1, Nil())
24
- }
@@ -1,179 +0,0 @@
1
- module text/string
2
-
3
- import immutable/option
4
- import immutable/list
5
-
6
- extern pure def length(s: String): Int = """
7
- %x = call %Int @c_buffer_length(%Pos %s)
8
- call void @c_buffer_refcount_decrement(%Pos %s)
9
- ret %Int %x
10
- """
11
- extern pure def substring(s: String, start: Int, end: Int): String = """
12
- %x = call %Pos @c_buffer_substring(%Pos %s, i64 %start, i64 %end)
13
- call void @c_buffer_refcount_decrement(%Pos %s)
14
- ret %Pos %x
15
- """
16
- def unsafeCharAt(s: String, i: Int): String = substring(s, i, i+1)
17
-
18
- def charAt(str: String, i: Int): Option[String] = {
19
- if ( i < 0 || i >= length(str)) {
20
- None()
21
- } else {
22
- Some(unsafeCharAt(str, i))
23
- }
24
- }
25
-
26
- def startsWith(str: String, prefix: String): Boolean = {
27
- if (length(str) < length(prefix)) {
28
- false
29
- } else {
30
- substring(str, 0, length(prefix)) == prefix
31
- }
32
- }
33
- def map(str: String){ f: String => String }: String = {
34
- def rec(i: Int, acc: String): String = {
35
- if (i < length(str)) {
36
- rec(i+1, acc ++ f(unsafeCharAt(str, i)))
37
- } else acc
38
- }
39
- rec(0, "")
40
- }
41
- def map[A](str: String){ f: String => A }: List[A] = {
42
- def rec(i: Int): List[A] = {
43
- if (i < length(str)) {
44
- Cons(f(unsafeCharAt(str, i)), rec(i+1))
45
- } else Nil()
46
- }
47
- rec(0)
48
- }
49
- def indexOf(str: String, start: Int, substr: String): Option[Int] = {
50
- if(length(str) - start < length(substr)) {
51
- None()
52
- } else if(substring(str, start, start + length(substr)) == substr) {
53
- Some(start)
54
- } else {
55
- indexOf(str, start + 1, substr)
56
- }
57
- }
58
- // """ // fix some parsing bug for vscode syntax highlighting
59
-
60
- def showQuoted(s: String): String =
61
- "\x22" ++ map(s){ c =>
62
- if(c == "\x22") {
63
- "\\\x22"
64
- } else if (c == "\\") {
65
- "\\\\"
66
- } else c
67
- } ++ "\x22"
68
- def showQuoted(l: List[String]): String = showList(l){e => showQuoted(e)}
69
- def showQuoted(o: Option[String]): String = showOption(o){ e => showQuoted(e) }
70
-
71
- def toInt(s: String): Option[Int] = {
72
- def go(i: Int, acc: Int): Int / Exception[RuntimeError] = {
73
- if(i >= length(s)) {
74
- acc
75
- } else if(unsafeCharAt(s, i) == "0") {
76
- go(i + 1, 10 * acc + 0)
77
- } else if(unsafeCharAt(s, i) == "1") {
78
- go(i + 1, 10 * acc + 1)
79
- } else if(unsafeCharAt(s, i) == "2") {
80
- go(i + 1, 10 * acc + 2)
81
- } else if(unsafeCharAt(s, i) == "3") {
82
- go(i + 1, 10 * acc + 3)
83
- } else if(unsafeCharAt(s, i) == "4") {
84
- go(i + 1, 10 * acc + 4)
85
- } else if(unsafeCharAt(s, i) == "5") {
86
- go(i + 1, 10 * acc + 5)
87
- } else if(unsafeCharAt(s, i) == "6") {
88
- go(i + 1, 10 * acc + 6)
89
- } else if(unsafeCharAt(s, i) == "7") {
90
- go(i + 1, 10 * acc + 7)
91
- } else if(unsafeCharAt(s, i) == "8") {
92
- go(i + 1, 10 * acc + 8)
93
- } else if(unsafeCharAt(s, i) == "9") {
94
- go(i + 1, 10 * acc + 9)
95
- } else {
96
- raise("Not an integer")
97
- }
98
- }
99
- try {
100
- if(s.length == 0) {
101
- None()
102
- } else if(s.startsWith("-")) {
103
- Some(0 - go(1, 0))
104
- } else {
105
- Some(go(0, 0))
106
- }
107
- } with Exception[RuntimeError] {
108
- def raise(e: RuntimeError, msg: String) = {
109
- None()
110
- }
111
- }
112
- }
113
- def toBoolean(s: String): Option[Boolean] = {
114
- if(s == "true") {
115
- Some(true)
116
- } else if (s == "false") {
117
- Some(false)
118
- } else {
119
- None()
120
- }
121
- }
122
-
123
-
124
- // Byte arrays (for compatibility with other backends, we have the Bytes type)
125
- type Bytes = String
126
- def bytes(s: String): Bytes = s
127
- // length(Bytes) = length(String)
128
- extern pure def unsafeIndex(s: Bytes, i: Int): Int = """
129
- %x = call %Int @c_buffer_index(%Pos %s, i64 %i)
130
- call void @c_buffer_refcount_decrement(%Pos %s)
131
- ret %Int %x
132
- """
133
- // """ // fix some parsing bug for vscode syntax highlighting
134
- def index(b: Bytes, i: Int): Option[Int] = if(i < b.length) { Some(b.unsafeIndex(i)) } else { None() }
135
-
136
- def eachInRange(b: Bytes, start: Int, end: Int){ fn: Int => Unit }: Unit = {
137
- if(end < 0 || end > b.length) {
138
- b.eachInRange(start,b.length){fn}
139
- }
140
- def rec(start: Int): Unit = {
141
- if(start < end) {
142
- fn(b.unsafeIndex(start))
143
- rec(start+1)
144
- } else { () }
145
- }
146
- rec(start)
147
- }
148
- def each(b: Bytes){ fn: Int => Unit } = {
149
- b.eachInRange(0,b.length){fn}
150
- }
151
-
152
- effect Abort(): Unit // TODO: Maybe use Control effect
153
- def occursAt(subb: Bytes, b: Bytes, i: Int): Boolean = {
154
- if(i + subb.length <= b.length) {
155
- try{
156
- var x = 0;
157
- b.eachInRange(i, i + subb.length){ b =>
158
- if(b != subb.unsafeIndex(x)){ do Abort() }
159
- x = x + 1
160
- }
161
- true
162
- } with Abort {
163
- () => false
164
- }
165
- } else false
166
- }
167
- def split(b: String, sep: String): List[String] = {
168
- def rec(next: Int, done: Int, acc: List[String]): List[Bytes] = {
169
- if(sep.occursAt(b, next)) {
170
- rec(next - 1, next,
171
- Cons(b.substring(next + sep.length, done), acc))
172
- } else if(next == 0) {
173
- Cons(b.substring(0, done), acc)
174
- } else {
175
- rec(next - 1, done, acc)
176
- }
177
- }
178
- rec(b.length - sep.length, b.length, Nil())
179
- }
@@ -1,267 +0,0 @@
1
- // Based on libraries\js\monadic\effekt.effekt
2
-
3
- module effekt
4
-
5
- extern include "effekt.sml"
6
-
7
- def locally[R] { f: => R }: R = f()
8
-
9
- // Side effecting ops
10
- // ==================
11
- def println(value: Int): Unit = println(value.show)
12
- def println(value: Unit): Unit = println(value.show)
13
- def println(value: Double): Unit = println(value.show)
14
- def println(value: Boolean): Unit = println(value.show)
15
-
16
- def println(value: String): Unit = print(value ++ "\n")
17
- extern io def print(value: String): Unit = "print ${value}"
18
-
19
- extern io def random(): Double =
20
- "mlRandomReal ()"
21
-
22
- // TODO: js is absolute, but that is too big for 32-bit ints
23
- extern io def timestamp(): Int =
24
- "IntInf.toInt ((Time.toMilliseconds (Time.now ())) - mlStartTime)"
25
-
26
- // String ops
27
- // ==========
28
- extern pure def show(value: Int): String =
29
- "show'int ${value}"
30
- extern pure def show(value: Unit): String =
31
- "show'unit ${value}"
32
- extern pure def show(value: Double): String =
33
- "show'real ${value}"
34
- extern pure def show(value: String): String =
35
- "show'string ${value}"
36
- extern pure def show(value: Boolean): String =
37
- "show'bool ${value}"
38
-
39
- extern pure def infixConcat(s1: String, s2: String): String =
40
- "${s1} ^ ${s2}"
41
-
42
- // Math ops
43
- // ========
44
- extern pure def infixAdd(x: Int, y: Int): Int =
45
- "(${x}: int) + ${y}"
46
-
47
- extern pure def infixMul(x: Int, y: Int): Int =
48
- "(${x}: int) * ${y}"
49
-
50
- extern pure def infixDiv(x: Int, y: Int): Int =
51
- "(${x}: int) div ${y}"
52
-
53
- extern pure def infixSub(x: Int, y: Int): Int =
54
- "(${x}: int) - ${y}"
55
-
56
- extern pure def mod(x: Int, y: Int): Int =
57
- "(${x}: int) mod ${y}"
58
-
59
- extern pure def infixAdd(x: Double, y: Double): Double =
60
- "(${x}: real) + ${y}"
61
-
62
- extern pure def infixMul(x: Double, y: Double): Double =
63
- "(${x}: real) * ${y}"
64
-
65
- extern pure def infixSub(x: Double, y: Double): Double =
66
- "(${x}: real) - ${y}"
67
-
68
- extern pure def infixDiv(x: Double, y: Double): Double =
69
- "(${x}: real) / ${y}"
70
-
71
- def min(n: Int, m: Int): Int =
72
- if (n < m) n else m
73
-
74
- def max(n: Int, m: Int): Int =
75
- if (n > m) n else m
76
-
77
- // trig
78
- // ====
79
-
80
- extern pure def cos(x: Double): Double =
81
- "Math.cos ${x}"
82
-
83
- extern pure def sin(x: Double): Double =
84
- "Math.sin ${x}"
85
-
86
- extern pure def atan(x: Double): Double =
87
- "Math.atan ${x}"
88
-
89
- extern pure def tan(x: Double): Double =
90
- "Math.tan ${x}"
91
-
92
- extern pure def sqrt(x: Double): Double =
93
- "Math.sqrt ${x}"
94
-
95
- extern pure def square(x: Double): Double =
96
- "(${x}: real) * ${x}"
97
-
98
- extern pure def log(x: Double): Double =
99
- "Math.ln ${x}"
100
-
101
- extern pure def log1p(x: Double): Double =
102
- "Math.ln (${x} + 1.0)"
103
-
104
- extern pure def exp(x: Double): Double =
105
- "Math.exp ${x}"
106
-
107
- // since we do not have "extern val", yet
108
- extern pure def _pi(): Double =
109
- "Math.pi"
110
-
111
- val PI: Double = _pi()
112
-
113
- extern pure def toInt(d: Double): Int =
114
- "Real.round ${d}"
115
-
116
- extern pure def toDouble(d: Int): Double =
117
- "Real.fromInt ${d}"
118
-
119
- extern pure def floor(d: Double): Int =
120
- "Real.floor ${d}"
121
-
122
- extern pure def ceil(d: Double): Int =
123
- "Real.ceil ${d}"
124
-
125
-
126
- // Comparison ops
127
- // ==============
128
- extern pure def infixEq[R](x: R, y: R): Boolean =
129
- "${x} = ${y}"
130
-
131
- extern pure def infixNeq[R](x: R, y: R): Boolean =
132
- "not (${x} = ${y})"
133
-
134
- extern pure def infixLt(x: Int, y: Int): Boolean =
135
- "(${x}: int) < ${y}"
136
-
137
- extern pure def infixLte(x: Int, y: Int): Boolean =
138
- "(${x}: int) <= ${y}"
139
-
140
- extern pure def infixGt(x: Int, y: Int): Boolean =
141
- "(${x}: int) > ${y}"
142
-
143
- extern pure def infixGte(x: Int, y: Int): Boolean =
144
- "(${x}: int) >= ${y}"
145
-
146
- extern pure def infixLt(x: Double, y: Double): Boolean =
147
- "(${x}: real) < ${y}"
148
-
149
- extern pure def infixLte(x: Double, y: Double): Boolean =
150
- "(${x}: real) <= ${y}"
151
-
152
- extern pure def infixGt(x: Double, y: Double): Boolean =
153
- "(${x}: real) > ${y}"
154
-
155
- extern pure def infixGte(x: Double, y: Double): Boolean =
156
- "(${x}: real) >= ${y}"
157
-
158
- extern pure def infixLt(x: String, y: String): Boolean =
159
- "(${x}: string) < ${y}"
160
-
161
- extern pure def infixLte(x: String, y: String): Boolean =
162
- "(${x}: string) <= ${y}"
163
-
164
- extern pure def infixGt(x: String, y: String): Boolean =
165
- "(${x}: string) > ${y}"
166
-
167
- extern pure def infixGte(x: String, y: String): Boolean =
168
- "(${x}: string) >= ${y}"
169
-
170
- // Boolean ops
171
- // ===========
172
- extern pure def not(b: Boolean): Boolean =
173
- "not ${b}"
174
-
175
- extern pure def infixOr(x: Boolean, y: Boolean): Boolean =
176
- "${x} orelse ${y}"
177
-
178
- extern pure def infixAnd(x: Boolean, y: Boolean): Boolean =
179
- "${x} andalso ${y}"
180
-
181
- // Pairs
182
- // =====
183
- record Tuple2[A, B](first: A, second: B)
184
- record Tuple3[A, B, C](first: A, second: B, third: C)
185
- record Tuple4[A, B, C, D](first: A, second: B, third: C, fourth: D)
186
- record Tuple5[A, B, C, D, E](first: A, second: B, third: C, fourth: D, fifth: E)
187
- record Tuple6[A, B, C, D, E, F](first: A, second: B, third: C, fourth: D, fifth: E, sixth: F)
188
-
189
- // Exceptions
190
- // ==========
191
- // a fatal runtime error that cannot be caught
192
- extern io def panic[R](msg: String): R =
193
- "raise Fail ${msg}"
194
-
195
- interface Exception[E] {
196
- def raise(exception: E, msg: String): Nothing
197
- }
198
- record RuntimeError()
199
-
200
- def raise[A](msg: String): A / Exception[RuntimeError] = do raise(RuntimeError(), msg) match {}
201
- def raise[A, E](exception: E, msg: String): A / Exception[E] = do raise(exception, msg) match {}
202
-
203
- // converts exceptions of (static) type E to an uncatchable panic that aborts the program
204
- def panicOn[E] { prog: => Unit / Exception[E] }: Unit =
205
- try { prog() } with Exception[E] { def raise(exception: E, msg: String) = panic(msg) }
206
-
207
- // reports exceptions of (static) type E to the console
208
- def report[E] { prog: => Unit / Exception[E] }: Unit =
209
- try { prog() } with Exception[E] { def raise(exception: E, msg: String) = println(msg) }
210
-
211
- // ignores exceptions of (static) type E
212
- // TODO this should be called "ignore" but that name currently clashes with internal pattern matching names on $effekt
213
- def ignoring[E] { prog: => Unit / Exception[E] }: Unit =
214
- try { prog() } with Exception[E] { def raise(exception: E, msg: String) = () }
215
-
216
- // Control Flow
217
- // ============
218
- interface Control {
219
- def break(): Unit
220
- def continue(): Unit
221
- }
222
-
223
- def loop { f: () => Unit / Control }: Unit = try {
224
- def go(): Unit = { f(); go() }
225
- go()
226
- } with Control {
227
- def break() = ()
228
- def continue() = loop { f }
229
- }
230
-
231
- /**
232
- * Calls provided action repeatedly. `start` is inclusive, `end` is not.
233
- */
234
- def each(start: Int, end: Int) { action: (Int) => Unit / Control } = {
235
- var i = start;
236
- loop {
237
- if (i < end) { val el = i; i = i + 1; action(el) }
238
- else { do break() }
239
- }
240
- }
241
-
242
- def repeat(n: Int) { action: () => Unit / Control } = each(0, n) { n => action() }
243
-
244
-
245
-
246
- // Benchmarking
247
- // ============
248
-
249
- // runs the block and returns the time in nanoseconds
250
- def timed { block: => Unit }: Int = {
251
- val before = timestamp()
252
- block()
253
- val after = timestamp()
254
- 1000 * (after - before)
255
- }
256
-
257
- def measure(warmup: Int, iterations: Int) { block: => Unit }: Unit = {
258
- def run(n: Int, report: Boolean): Unit = {
259
- if (n <= 0) { () } else {
260
- val time = timed { block() };
261
- if (report) { println(time) } else { () };
262
- run(n - 1, report)
263
- }
264
- }
265
- run(warmup, false)
266
- run(iterations, true)
267
- }
@@ -1,81 +0,0 @@
1
- module immutable/dequeue
2
-
3
- // An implementation of a functional dequeue, using Okasaki's
4
- // bankers dequeue implementation.
5
- //
6
- // Translation from the Haskell implementation:
7
- // https://hackage.haskell.org/package/dequeue-0.1.12/docs/src/Data-Dequeue.html#Dequeue
8
- record Dequeue[R](front: List[R], frontSize: Int, rear: List[R], rearSize: Int)
9
-
10
- def emptyQueue[R](): Dequeue[R] = Dequeue(Nil(), 0, Nil(), 0)
11
-
12
- def isEmpty[R](dq: Dequeue[R]): Boolean = dq match {
13
- case Dequeue(f, fs, r, rs) => (fs == 0) && (rs == 0)
14
- }
15
-
16
- def size[R](dq: Dequeue[R]): Int = dq match {
17
- case Dequeue(f, fs, r, rs) => fs + rs
18
- }
19
-
20
- def first[R](dq: Dequeue[R]): Option[R] = dq match {
21
- case Dequeue(f, fs, r, rs) =>
22
- if ((fs == 0) && (rs == 1)) { r.headOption }
23
- else { f.headOption }
24
- }
25
-
26
- def last[R](dq: Dequeue[R]): Option[R] = dq match {
27
- case Dequeue(f, fs, r, rs) =>
28
- if ((fs == 1) && (rs == 0)) { f.headOption }
29
- else { r.headOption }
30
- }
31
-
32
- def check[R](dq: Dequeue[R]): Dequeue[R] = dq match {
33
- case Dequeue(f, fs, r, rs) =>
34
- val c = 4;
35
- val size1 = (fs + rs) / 2;
36
- val size2 = (fs + rs) - size1;
37
-
38
- if (fs > c * rs + 1) {
39
- val front = f.take(size1);
40
- val rear = r.append(f.drop(size1).reverse);
41
- Dequeue(front, size1, rear, size2)
42
- } else if (rs > c * fs + 1) {
43
- val front = f.append(r.drop(size1).reverse);
44
- val rear = r.take(size1);
45
- Dequeue(front, size2, rear, size1)
46
- } else {
47
- dq
48
- }
49
- }
50
-
51
- def pushFront[R](dq: Dequeue[R], el: R): Dequeue[R] = dq match {
52
- case Dequeue(f, fs, r, rs) => Dequeue(Cons(el, f), fs + 1, r, rs).check
53
- }
54
-
55
- def popFront[R](dq: Dequeue[R]): Option[(R, Dequeue[R])] = dq match {
56
- case Dequeue(Nil(), fs, Cons(x, Nil()), rs) =>
57
- Some((x, emptyQueue()))
58
- case Dequeue(Nil(), fs, r, rs) =>
59
- None()
60
- case Dequeue(Cons(x, rest), fs, r, rs) =>
61
- Some((x, Dequeue(rest, fs - 1, r, rs).check))
62
- }
63
-
64
- def pushBack[R](dq: Dequeue[R], el: R): Dequeue[R] = dq match {
65
- case Dequeue(f, fs, r, rs) => Dequeue(f, fs, Cons(el, r), rs + 1).check
66
- }
67
-
68
- def popBack[R](dq: Dequeue[R]): Option[(R, Dequeue[R])] = dq match {
69
- case Dequeue(Cons(x, Nil()), fs, Nil(), rs) =>
70
- Some((x, emptyQueue()))
71
- case Dequeue(f, fs, Nil(), rs) =>
72
- None()
73
- case Dequeue(f, fs, Cons(x, rest), rs) =>
74
- Some((x, Dequeue(f, fs, rest, rs - 1).check))
75
- }
76
-
77
- def show[A](d: Dequeue[A]) { showA: A => String }: String = {
78
- val Dequeue(front, frontSize, rear, rearSize) = d;
79
- "Dequeue(" ++ show(front){showA} ++ ", " ++ show(frontSize) ++ ", " ++
80
- show(rear){showA} ++ ", " ++ show(rearSize) ++ ")"
81
- }