@effekt-lang/effekt 0.3.0 → 0.5.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.
- package/README.md +6 -18
- package/bin/effekt +0 -0
- package/libraries/common/args.effekt +0 -27
- package/libraries/common/array.effekt +34 -63
- package/libraries/common/bench.effekt +40 -22
- package/libraries/common/buffer.effekt +8 -20
- package/libraries/common/bytes.effekt +5 -15
- package/libraries/common/dequeue.effekt +5 -5
- package/libraries/common/effekt.effekt +51 -92
- package/libraries/common/exception.effekt +0 -1
- package/libraries/common/io/console.effekt +30 -36
- package/libraries/common/io/error.effekt +131 -30
- package/libraries/common/io/filesystem.effekt +262 -0
- package/libraries/common/io/network.effekt +30 -54
- package/libraries/common/io/time.effekt +9 -12
- package/libraries/common/io.effekt +54 -124
- package/libraries/common/list.effekt +345 -327
- package/libraries/common/process.effekt +0 -1
- package/libraries/common/queue.effekt +1 -3
- package/libraries/common/ref.effekt +11 -24
- package/libraries/common/result.effekt +6 -14
- package/libraries/common/seq.effekt +28 -49
- package/libraries/common/string/tty.effekt +66 -0
- package/libraries/common/string.effekt +7 -49
- package/libraries/common/test.effekt +96 -34
- package/libraries/js/unsafe/cont.effekt +1 -1
- package/libraries/llvm/io.c +258 -378
- package/libraries/llvm/main.c +3 -0
- package/libraries/llvm/rts.ll +57 -38
- package/libraries/llvm/types.c +10 -1
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +4 -4
- package/licenses/mit license - mit-license.html +21 -20
- package/licenses/the bsd license - bsd-license.html +20 -21
- package/licenses/the mit license - mit.html +22 -21
- package/package.json +1 -1
- package/libraries/chez/lift/effekt.ss +0 -118
- package/libraries/common/io/files.effekt +0 -282
- package/libraries/js/io.js +0 -143
- package/libraries/llvm/io.ll +0 -19
- package/libraries/ml/effekt.sml +0 -65
- package/libraries/ml/internal/mllist.effekt +0 -9
- package/libraries/ml/internal/mloption.effekt +0 -18
- package/libraries/ml/random.effekt +0 -85
- package/libraries/ml/text/regex.effekt +0 -102
package/README.md
CHANGED
|
@@ -11,26 +11,14 @@ aims to be significantly more lightweight in its concepts.
|
|
|
11
11
|
Also, Effekt comes with no warranty and there are (probably) many bugs -- If this does not discourage you, feel free to
|
|
12
12
|
play with it and give us your feedback :)
|
|
13
13
|
|
|
14
|
-
##
|
|
15
|
-
|
|
16
|
-
You need to have Java (>= 11) and Node (>= 12) and npm installed.
|
|
17
|
-
|
|
18
|
-
The recommended way of installing Effekt is by running:
|
|
14
|
+
## Examples
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
npm install -g https://github.com/effekt-lang/effekt/releases/latest/download/effekt.tgz
|
|
22
|
-
```
|
|
16
|
+
If you are looking for examples of the Effekt language, we invite you to look at the [casestudies](https://github.com/effekt-lang/effekt/tree/master/examples/casestudies) and the [language tour](https://effekt-lang.org/tour).
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
npm install -g effekt.tgz
|
|
28
|
-
```
|
|
18
|
+
## Installation
|
|
29
19
|
|
|
30
|
-
|
|
20
|
+
Please navigate to the [getting-started guide](https://effekt-lang.org/docs/getting-started#installing-effekt) on our [website](https://effekt-lang.org) for detailed instructions of how to install Effekt.
|
|
31
21
|
|
|
32
|
-
|
|
33
|
-
> effekt
|
|
34
|
-
```
|
|
22
|
+
## Contributing
|
|
35
23
|
|
|
36
|
-
|
|
24
|
+
Thanks for considering to contribute to the Effekt compiler! For setting up your local environment, please check out our [contributing guide](https://effekt-lang.org/contributing.html) on the [website](https://effekt-lang.org).
|
package/bin/effekt
CHANGED
|
Binary file
|
|
@@ -3,7 +3,6 @@ module args
|
|
|
3
3
|
extern io def commandLineArgs(): List[String] =
|
|
4
4
|
js { js::commandLineArgs() }
|
|
5
5
|
chez { chez::commandLineArgs() }
|
|
6
|
-
ml { ml::commandLineArgs() }
|
|
7
6
|
llvm { llvm::commandLineArgs() }
|
|
8
7
|
|
|
9
8
|
namespace js {
|
|
@@ -46,32 +45,6 @@ namespace chez {
|
|
|
46
45
|
def commandLineArgs(): List[String] = nativeArgs().toList
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
namespace ml {
|
|
50
|
-
|
|
51
|
-
// MLList[String]
|
|
52
|
-
// we inline these from mllist to not have a dependency
|
|
53
|
-
extern type Args
|
|
54
|
-
|
|
55
|
-
extern io def nativeArgs(): Args =
|
|
56
|
-
ml "CommandLine.arguments ()"
|
|
57
|
-
|
|
58
|
-
extern pure def isEmpty(args: Args): Bool =
|
|
59
|
-
ml "null ${args}"
|
|
60
|
-
|
|
61
|
-
extern io def first(a: Args): String =
|
|
62
|
-
ml "hd ${a}"
|
|
63
|
-
|
|
64
|
-
extern io def rest(a: Args): Args =
|
|
65
|
-
ml "tl ${a}"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def commandLineArgs(): List[String] = {
|
|
69
|
-
def toList(args: Args): List[String] =
|
|
70
|
-
if (args.isEmpty) Nil() else Cons(args.first, args.rest.toList)
|
|
71
|
-
nativeArgs().toList
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
48
|
namespace llvm {
|
|
76
49
|
extern io def argCount(): Int =
|
|
77
50
|
llvm """
|
|
@@ -4,15 +4,11 @@ import effekt
|
|
|
4
4
|
import exception
|
|
5
5
|
import list
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
* A mutable 0-indexed fixed-sized array.
|
|
9
|
-
*/
|
|
7
|
+
/// A mutable 0-indexed fixed-sized array.
|
|
10
8
|
extern type Array[T]
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* Prefer using `array` constructor instead to ensure that values are defined.
|
|
15
|
-
*/
|
|
10
|
+
/// Allocates a new array of size `size`, keeping its values _undefined_.
|
|
11
|
+
/// Prefer using `array` constructor instead to ensure that values are defined.
|
|
16
12
|
extern global def allocate[T](size: Int): Array[T] =
|
|
17
13
|
js "(new Array(${size}))"
|
|
18
14
|
chez "(make-vector ${size})" // creates an array filled with 0s on CS
|
|
@@ -21,22 +17,16 @@ extern global def allocate[T](size: Int): Array[T] =
|
|
|
21
17
|
ret %Pos %z
|
|
22
18
|
"""
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
unsafeSet(arr, i, init)
|
|
33
|
-
};
|
|
34
|
-
arr
|
|
35
|
-
}
|
|
20
|
+
/// Creates a new Array of size `size` filled with the value `init`
|
|
21
|
+
def array[T](size: Int, init: T): Array[T] = {
|
|
22
|
+
val arr = allocate[T](size);
|
|
23
|
+
each(0, size) { i =>
|
|
24
|
+
unsafeSet(arr, i, init)
|
|
25
|
+
};
|
|
26
|
+
arr
|
|
27
|
+
}
|
|
36
28
|
|
|
37
|
-
|
|
38
|
-
* Converts a List `list` to an Array
|
|
39
|
-
*/
|
|
29
|
+
/// Converts a List `list` to an Array
|
|
40
30
|
def fromList[T](list: List[T]): Array[T] = {
|
|
41
31
|
val listSize = list.size();
|
|
42
32
|
val arr = allocate(listSize);
|
|
@@ -47,58 +37,47 @@ def fromList[T](list: List[T]): Array[T] = {
|
|
|
47
37
|
return arr;
|
|
48
38
|
}
|
|
49
39
|
|
|
50
|
-
|
|
51
|
-
* Gets the length of the array in constant time.
|
|
52
|
-
*/
|
|
40
|
+
/// Gets the length of the array in constant time.
|
|
53
41
|
extern pure def size[T](arr: Array[T]): Int =
|
|
54
42
|
js "${arr}.length"
|
|
55
43
|
chez "(vector-length ${arr})"
|
|
56
|
-
ml "Array.length ${arr}"
|
|
57
44
|
llvm """
|
|
58
45
|
%z = call %Int @c_array_size(%Pos ${arr})
|
|
59
46
|
ret %Int %z
|
|
60
47
|
"""
|
|
61
48
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
* Prefer using `get` instead.
|
|
67
|
-
*/
|
|
49
|
+
/// Gets the element of the `arr` at given `index` in constant time.
|
|
50
|
+
/// Unchecked Precondition: `index` is in bounds (0 ≤ index < arr.size)
|
|
51
|
+
///
|
|
52
|
+
/// Prefer using `get` instead.
|
|
68
53
|
extern global def unsafeGet[T](arr: Array[T], index: Int): T =
|
|
69
54
|
js "${arr}[${index}]"
|
|
70
55
|
chez "(vector-ref ${arr} ${index})"
|
|
71
|
-
ml "Array.sub (${arr}, ${index})"
|
|
72
56
|
llvm """
|
|
73
57
|
%z = call %Pos @c_array_get(%Pos ${arr}, %Int ${index})
|
|
74
58
|
ret %Pos %z
|
|
75
59
|
"""
|
|
76
60
|
|
|
77
61
|
extern js """
|
|
78
|
-
function array$set(arr, index, value) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
62
|
+
function array$set(arr, index, value) {
|
|
63
|
+
arr[index] = value;
|
|
64
|
+
return $effekt.unit
|
|
65
|
+
}
|
|
82
66
|
"""
|
|
83
67
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
* Prefer using `set` instead.
|
|
89
|
-
*/
|
|
68
|
+
/// Sets the element of the `arr` at given `index` to `value` in constant time.
|
|
69
|
+
/// Unchecked Precondition: `index` is in bounds (0 ≤ index < arr.size)
|
|
70
|
+
///
|
|
71
|
+
/// Prefer using `set` instead.
|
|
90
72
|
extern global def unsafeSet[T](arr: Array[T], index: Int, value: T): Unit =
|
|
91
73
|
js "array$set(${arr}, ${index}, ${value})"
|
|
92
74
|
chez "(begin (vector-set! ${arr} ${index} ${value}) #f)"
|
|
93
|
-
ml "Array.update (${arr}, ${index}, ${value})"
|
|
94
75
|
llvm """
|
|
95
76
|
%z = call %Pos @c_array_set(%Pos ${arr}, %Int ${index}, %Pos ${value})
|
|
96
77
|
ret %Pos %z
|
|
97
78
|
"""
|
|
98
79
|
|
|
99
|
-
|
|
100
|
-
* Creates a copy of `arr`
|
|
101
|
-
*/
|
|
80
|
+
/// Creates a copy of `arr`
|
|
102
81
|
def copy[T](arr: Array[T]): Array[T] = {
|
|
103
82
|
with on[OutOfBounds].default { <> }; // should not happen
|
|
104
83
|
val len = arr.size;
|
|
@@ -107,10 +86,8 @@ def copy[T](arr: Array[T]): Array[T] = {
|
|
|
107
86
|
newArray
|
|
108
87
|
}
|
|
109
88
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
* starting at `start` (in `from`) and `offset` (in `to`)
|
|
113
|
-
*/
|
|
89
|
+
/// Copies `length`-many elements from `from` to `to`
|
|
90
|
+
/// starting at `start` (in `from`) and `offset` (in `to`)
|
|
114
91
|
def copy[T](from: Array[T], start: Int, to: Array[T], offset: Int, length: Int): Unit / Exception[OutOfBounds] = {
|
|
115
92
|
val startValid = start >= 0 && start + length <= from.size
|
|
116
93
|
val offsetValid = offset >= 0 && offset + length <= to.size
|
|
@@ -127,26 +104,20 @@ def copy[T](from: Array[T], start: Int, to: Array[T], offset: Int, length: Int):
|
|
|
127
104
|
|
|
128
105
|
// Derived operations:
|
|
129
106
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
* throwing an `Exception[OutOfBounds]` unless `0 ≤ index < arr.size`.
|
|
133
|
-
*/
|
|
107
|
+
/// Gets the element of the `arr` at given `index` in constant time,
|
|
108
|
+
/// throwing an `Exception[OutOfBounds]` unless `0 ≤ index < arr.size`.
|
|
134
109
|
def get[T](arr: Array[T], index: Int): T / Exception[OutOfBounds] =
|
|
135
110
|
if (index >= 0 && index < arr.size) arr.unsafeGet(index)
|
|
136
111
|
else do raise(OutOfBounds(), "Array index out of bounds: " ++ show(index))
|
|
137
112
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
* throwing an `Exception[OutOfBounds]` unless `0 ≤ index < arr.size`.
|
|
141
|
-
*/
|
|
113
|
+
/// Sets the element of the `arr` at given `index` to `value` in constant time,
|
|
114
|
+
/// throwing an `Exception[OutOfBounds]` unless `0 ≤ index < arr.size`.
|
|
142
115
|
def set[T](arr: Array[T], index: Int, value: T): Unit / Exception[OutOfBounds] =
|
|
143
116
|
if (index >= 0 && index < arr.size) unsafeSet(arr, index, value)
|
|
144
117
|
else do raise(OutOfBounds(), "Array index out of bounds: " ++ show(index))
|
|
145
118
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
* and returns a value that will be on that position in the resulting array
|
|
149
|
-
*/
|
|
119
|
+
/// Builds a new Array of size `size` from a computation `index` which gets an index
|
|
120
|
+
/// and returns a value that will be on that position in the resulting array
|
|
150
121
|
def build[T](size: Int) { index: Int => T }: Array[T] = {
|
|
151
122
|
val arr = allocate[T](size);
|
|
152
123
|
each(0, size) { i =>
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
module bench
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
extern io def timestamp(): Int =
|
|
3
|
+
type Nanos = Int
|
|
4
|
+
|
|
5
|
+
/// The current time (since UNIX Epoch) in nanoseconds.
|
|
6
|
+
///
|
|
7
|
+
/// The actual precision varies across the different backends.
|
|
8
|
+
/// - js: Milliseconds
|
|
9
|
+
/// - chez: Microseconds
|
|
10
|
+
extern io def timestamp(): Nanos =
|
|
12
11
|
js "Date.now() * 1000000"
|
|
13
12
|
chez "(timestamp)"
|
|
14
|
-
ml "IntInf.toInt (Time.toNanoseconds (Time.now ()))"
|
|
15
13
|
llvm """
|
|
16
14
|
%time_ptr = alloca { i64, i64 }
|
|
17
15
|
call i32 @clock_gettime(i32 0, ptr %time_ptr)
|
|
@@ -27,24 +25,31 @@ extern llvm """
|
|
|
27
25
|
declare i32 @clock_gettime(i32, ptr)
|
|
28
26
|
"""
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
28
|
+
// This should not be needed when using NodeJS 16.x or newer.
|
|
29
|
+
extern jsNode """
|
|
30
|
+
const { performance } = require('node:perf_hooks');
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
/// High-precision timestamp in nanoseconds that should be for measurements.
|
|
34
|
+
///
|
|
35
|
+
/// This timestamp should only be used for **relative** measurements,
|
|
36
|
+
/// as gives no guarantees on the absolute time (unlike a UNIX timestamp).
|
|
37
|
+
extern io def relativeTimestamp(): Nanos =
|
|
37
38
|
js "Math.round(performance.now() * 1000000)"
|
|
38
39
|
default { timestamp() }
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def
|
|
41
|
+
type Duration = Int
|
|
42
|
+
|
|
43
|
+
namespace Duration {
|
|
44
|
+
def diff(fromNanos: Nanos, toNanos: Nanos): Duration = toNanos - fromNanos
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Runs the block and returns the time in nanoseconds
|
|
48
|
+
def timed { block: => Unit }: Duration = {
|
|
44
49
|
val before = relativeTimestamp()
|
|
45
50
|
block()
|
|
46
51
|
val after = relativeTimestamp()
|
|
47
|
-
after
|
|
52
|
+
Duration::diff(before, after)
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
def measure(warmup: Int, iterations: Int) { block: => Unit }: Unit = {
|
|
@@ -58,3 +63,16 @@ def measure(warmup: Int, iterations: Int) { block: => Unit }: Unit = {
|
|
|
58
63
|
run(warmup, false)
|
|
59
64
|
run(iterations, true)
|
|
60
65
|
}
|
|
66
|
+
|
|
67
|
+
/// Takes a duration in nanoseconds and formats it in milliseconds with precision of two decimal digits.
|
|
68
|
+
def formatMs(nanos: Nanos): String = {
|
|
69
|
+
val micros = nanos / 1000000
|
|
70
|
+
val sub = (nanos.mod(1000000).toDouble / 10000.0).round
|
|
71
|
+
|
|
72
|
+
if (sub == 100) {
|
|
73
|
+
// overflow because of rounding
|
|
74
|
+
(micros + 1).show ++ ".0ms"
|
|
75
|
+
} else {
|
|
76
|
+
micros.show ++ "." ++ sub.show ++ "ms"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -9,34 +9,22 @@ import array
|
|
|
9
9
|
|
|
10
10
|
record BufferOverflow()
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* elements to the head and read from the tail.
|
|
15
|
-
*/
|
|
12
|
+
/// Fixed-size ring buffers (queues) where one can write
|
|
13
|
+
/// elements to the head and read from the tail.
|
|
16
14
|
interface Buffer[T] {
|
|
17
|
-
|
|
18
|
-
* The remaining capacity
|
|
19
|
-
*/
|
|
15
|
+
/// The remaining capacity
|
|
20
16
|
def capacity(): Int
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
* Is this buffer full?
|
|
24
|
-
*/
|
|
18
|
+
/// Is this buffer full?
|
|
25
19
|
def full?(): Bool
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
* Is this buffer empty?
|
|
29
|
-
*/
|
|
21
|
+
/// Is this buffer empty?
|
|
30
22
|
def empty?(): Bool
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
* Read an element from the tail of the buffer
|
|
34
|
-
*/
|
|
24
|
+
/// Read an element from the tail of the buffer
|
|
35
25
|
def read(): Option[T]
|
|
36
26
|
|
|
37
|
-
|
|
38
|
-
* Write an element to the head of the buffer
|
|
39
|
-
*/
|
|
27
|
+
/// Write an element to the head of the buffer
|
|
40
28
|
def write(el: T): Unit / Exception[BufferOverflow]
|
|
41
29
|
}
|
|
42
30
|
|
|
@@ -120,4 +108,4 @@ namespace examples {
|
|
|
120
108
|
println(ringbuffer.read());
|
|
121
109
|
println(ringbuffer.read());
|
|
122
110
|
}
|
|
123
|
-
}
|
|
111
|
+
}
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
module bytes
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
* A memory managed, mutable, fixed-length buffer of bytes.
|
|
5
|
-
*/
|
|
3
|
+
/// A memory managed, mutable, fixed-length buffer of bytes.
|
|
6
4
|
extern type Bytes
|
|
7
5
|
// = llvm "%Pos"
|
|
8
6
|
// = js "Uint8Array"
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
* Allocates new bytes with the given `capacity`, setting its values to `0`.
|
|
12
|
-
*/
|
|
8
|
+
/// Allocates new bytes with the given `capacity`, setting its values to `0`.
|
|
13
9
|
extern io def bytes(capacity: Int): Bytes =
|
|
14
10
|
js "(new Uint8Array(${capacity}))"
|
|
15
11
|
llvm """
|
|
@@ -55,9 +51,7 @@ extern io def write(b: Bytes, index: Int, value: Byte): Unit =
|
|
|
55
51
|
ret %Pos zeroinitializer
|
|
56
52
|
"""
|
|
57
53
|
|
|
58
|
-
|
|
59
|
-
* Returns an *aliased* slice of b starting at offset with the given length
|
|
60
|
-
*/
|
|
54
|
+
/// Returns an *aliased* slice of b starting at offset with the given length
|
|
61
55
|
def slice(b: Bytes, offset: Int, length: Int): Bytes = {
|
|
62
56
|
def validOffset() = offset >= 0 && offset < b.size
|
|
63
57
|
def validLength() = length >= 0 && (offset + length) <= b.size
|
|
@@ -66,9 +60,7 @@ def slice(b: Bytes, offset: Int, length: Int): Bytes = {
|
|
|
66
60
|
}
|
|
67
61
|
|
|
68
62
|
|
|
69
|
-
|
|
70
|
-
* Returns a view into the buffer, with the length truncated to n
|
|
71
|
-
*/
|
|
63
|
+
/// Returns a view into the buffer, with the length truncated to n
|
|
72
64
|
def truncated(b: Bytes, n: Int): Bytes =
|
|
73
65
|
b.slice(0, n)
|
|
74
66
|
|
|
@@ -88,9 +80,7 @@ extern pure def toUTF8(b: Bytes): String =
|
|
|
88
80
|
"""
|
|
89
81
|
|
|
90
82
|
namespace unsafe {
|
|
91
|
-
|
|
92
|
-
* Unsafe: offset and length are not checked.
|
|
93
|
-
*/
|
|
83
|
+
/// Unsafe: offset and length are not checked.
|
|
94
84
|
extern io def slice(b: Bytes, offset: Int, length: Int): Bytes =
|
|
95
85
|
js "new Uint8Array(${b}.buffer, ${offset}, ${length})"
|
|
96
86
|
llvm """
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
module dequeue
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
/// An implementation of a functional dequeue, using Okasaki's
|
|
5
|
+
/// bankers dequeue implementation.
|
|
6
|
+
///
|
|
7
|
+
/// Translation from the Haskell implementation:
|
|
8
|
+
/// https://hackage.haskell.org/package/dequeue-0.1.12/docs/src/Data-Dequeue.html#Dequeue
|
|
9
9
|
record Dequeue[R](front: List[R], frontSize: Int, rear: List[R], rearSize: Int)
|
|
10
10
|
|
|
11
11
|
def emptyQueue[R](): Dequeue[R] = Dequeue(Nil(), 0, Nil(), 0)
|