@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.
- package/bin/effekt +0 -0
- package/bin/effekt.sh +1 -1
- package/libraries/chez/common/effekt_primitives.ss +10 -2
- package/libraries/chez/common/immutable/cslist.effekt +13 -7
- package/libraries/chez/common/mutable/dict.effekt +8 -10
- package/libraries/chez/common/text/regex.effekt +7 -9
- package/libraries/common/args.effekt +95 -0
- package/libraries/common/array.effekt +225 -0
- package/libraries/common/bench.effekt +60 -0
- package/libraries/common/buffer.effekt +123 -0
- package/libraries/common/bytes.effekt +125 -0
- package/libraries/{chez/common/immutable → common}/dequeue.effekt +18 -4
- package/libraries/common/effekt.effekt +764 -0
- package/libraries/common/exception.effekt +122 -0
- package/libraries/common/io/console.effekt +66 -0
- package/libraries/common/io/error.effekt +365 -0
- package/libraries/common/io/files.effekt +282 -0
- package/libraries/common/io/network.effekt +105 -0
- package/libraries/common/io/time.effekt +15 -0
- package/libraries/common/io.effekt +158 -0
- package/libraries/{llvm/immutable → common}/list.effekt +83 -74
- package/libraries/common/option.effekt +72 -0
- package/libraries/common/process.effekt +10 -0
- package/libraries/common/queue.effekt +140 -0
- package/libraries/common/ref.effekt +63 -0
- package/libraries/common/result.effekt +45 -0
- package/libraries/{ml/immutable → common}/seq.effekt +30 -19
- package/libraries/common/string.effekt +395 -0
- package/libraries/common/test.effekt +98 -0
- package/libraries/js/effekt_builtins.js +37 -6
- package/libraries/js/io.js +143 -0
- package/libraries/js/mutable/map.effekt +8 -9
- package/libraries/js/text/regex.effekt +7 -8
- package/libraries/js/unsafe/cont.effekt +2 -2
- package/libraries/js/web/dom.effekt +13 -13
- package/libraries/llvm/array.c +53 -0
- package/libraries/llvm/buffer.c +181 -76
- package/libraries/llvm/forward-declare-c.ll +27 -8
- package/libraries/llvm/io.c +543 -1
- package/libraries/llvm/io.ll +19 -0
- package/libraries/llvm/main.c +3 -1
- package/libraries/llvm/ref.c +45 -0
- package/libraries/llvm/rts.ll +496 -354
- package/libraries/llvm/types.c +23 -0
- package/libraries/ml/effekt.sml +2 -0
- package/libraries/ml/internal/mllist.effekt +9 -0
- package/libraries/ml/internal/mloption.effekt +18 -0
- package/libraries/ml/random.effekt +9 -9
- package/libraries/ml/text/regex.effekt +14 -19
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/licenses/mit license - mit-license.html +527 -57
- package/licenses/the bsd license - bsd-license.html +530 -55
- package/licenses/the mit license - mit.html +528 -58
- package/package.json +2 -2
- package/libraries/chez/callcc/effekt.effekt +0 -221
- package/libraries/chez/common/effekt_matching.ss +0 -100
- package/libraries/chez/common/immutable/list.effekt +0 -643
- package/libraries/chez/common/immutable/option.effekt +0 -39
- package/libraries/chez/common/immutable/result.effekt +0 -29
- package/libraries/chez/common/io/args.effekt +0 -20
- package/libraries/chez/common/mutable/array.effekt +0 -27
- package/libraries/chez/common/mutable/heap.effekt +0 -12
- package/libraries/chez/common/test.effekt +0 -59
- package/libraries/chez/common/text/string.effekt +0 -46
- package/libraries/chez/lift/effekt.effekt +0 -217
- package/libraries/chez/monadic/effekt.effekt +0 -218
- package/libraries/js/effekt.effekt +0 -284
- package/libraries/js/effekt_matching.js +0 -79
- package/libraries/js/immutable/dequeue.effekt +0 -78
- package/libraries/js/immutable/list.effekt +0 -643
- package/libraries/js/immutable/option.effekt +0 -49
- package/libraries/js/immutable/result.effekt +0 -29
- package/libraries/js/io/args.effekt +0 -9
- package/libraries/js/io/async.effekt +0 -28
- package/libraries/js/io/async.js +0 -2
- package/libraries/js/io/file.effekt +0 -50
- package/libraries/js/io/file_include.js +0 -13
- package/libraries/js/mutable/array.effekt +0 -98
- package/libraries/js/mutable/heap.effekt +0 -32
- package/libraries/js/test.effekt +0 -59
- package/libraries/js/text/string.effekt +0 -64
- package/libraries/llvm/effekt.effekt +0 -243
- package/libraries/llvm/immutable/option.effekt +0 -53
- package/libraries/llvm/immutable/result.effekt +0 -29
- package/libraries/llvm/io/args.effekt +0 -24
- package/libraries/llvm/text/string.effekt +0 -179
- package/libraries/ml/effekt.effekt +0 -267
- package/libraries/ml/immutable/dequeue.effekt +0 -81
- package/libraries/ml/immutable/list.effekt +0 -674
- package/libraries/ml/immutable/option.effekt +0 -53
- package/libraries/ml/immutable/result.effekt +0 -29
- package/libraries/ml/internal/option.effekt +0 -18
- package/libraries/ml/io/args.effekt +0 -41
- package/libraries/ml/mutable/array.effekt +0 -43
- package/libraries/ml/test.effekt +0 -60
- 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
|
-
}
|