@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,28 +0,0 @@
|
|
|
1
|
-
module io/async
|
|
2
|
-
|
|
3
|
-
extern include "async.js"
|
|
4
|
-
|
|
5
|
-
extern type Promise[T]
|
|
6
|
-
|
|
7
|
-
interface AsyncIO {
|
|
8
|
-
def read(path: String): Promise[String]
|
|
9
|
-
def await[T](p: Promise[T]): T
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
def asyncIO[R](p: () => R / AsyncIO at {io}): R = try {
|
|
13
|
-
p()
|
|
14
|
-
} with AsyncIO {
|
|
15
|
-
def read(path) = resume(readPromise(path))
|
|
16
|
-
def await[T](p) = awaitPromise(p, resume)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
def block[T](p: Promise[T]) = do await(p)
|
|
20
|
-
|
|
21
|
-
extern io def readPromise(path: String): Promise[String] =
|
|
22
|
-
"fsPromises.readFile(${path}, 'utf8')"
|
|
23
|
-
|
|
24
|
-
extern io def awaitPromise[T, R](p: Promise[T], cont: T => R at {io}): R =
|
|
25
|
-
"${p}.then(res => (${cont})(res).run())"
|
|
26
|
-
|
|
27
|
-
extern io def fork(process: () => Unit at {io}): Unit =
|
|
28
|
-
"setTimeout(() => (${process})().run(), 0)"
|
package/libraries/js/io/async.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
module io/file
|
|
2
|
-
|
|
3
|
-
effect IOException[A](msg: String): A
|
|
4
|
-
|
|
5
|
-
extern include "file_include.js"
|
|
6
|
-
|
|
7
|
-
extern type FileDescriptor
|
|
8
|
-
|
|
9
|
-
extern type Buffer
|
|
10
|
-
|
|
11
|
-
type Result[A] {
|
|
12
|
-
Error(msg: String);
|
|
13
|
-
Success(a: A)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
extern type Promise[T]
|
|
17
|
-
|
|
18
|
-
extern io def readPromise(path: String): Promise[String] =
|
|
19
|
-
"$effekt.delayed(() => fsPromises.readFile(${path}, 'utf8'))"
|
|
20
|
-
|
|
21
|
-
def await[T](p: Promise[T]): T / { IOException } =
|
|
22
|
-
try { awaitImpl(p){exc} } with exc : IOException[A] {
|
|
23
|
-
msg => do IOException(msg)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
extern io def awaitImpl[T](p: Promise[T]){exc: IOException}: T =
|
|
27
|
-
"$effekt.callcc(k => ${p}.then(res => k($effekt.pure(res)), err => k(${box { (msg: String) => do IOException[T](msg) }}(err.message)))).then(c => c)"
|
|
28
|
-
|
|
29
|
-
def open(path: String, mode: String): FileDescriptor / { IOException } =
|
|
30
|
-
try { openImpl(path, mode){exc} } with exc : IOException[A] {
|
|
31
|
-
msg => do IOException(msg)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
extern io def openImpl(path: String, mode: String){exc: IOException}: FileDescriptor =
|
|
35
|
-
"$effekt.delayed(() => { try { return $effekt.pure(fs.openSync(${path}, ${mode})); } catch (err) { return ${box { (msg: String) => do IOException[FileDescriptor](msg) }}(err.message); }}).then(c => c)"
|
|
36
|
-
|
|
37
|
-
extern io def close(fd: FileDescriptor): Unit =
|
|
38
|
-
"$effekt.delayed(() => fs.closeSync(${fd}))"
|
|
39
|
-
|
|
40
|
-
// uses the asynchronous API of node
|
|
41
|
-
extern io def readFile(path: String): Result[String] =
|
|
42
|
-
"$effekt.callcc(k => fs.readFile(${path}, 'utf8', (err, data) => k(err ? ${box Error}(err.message) : ${box Success}(data))))"
|
|
43
|
-
|
|
44
|
-
def read(path: String): String / { IOException } =
|
|
45
|
-
getResult(readFile(path))
|
|
46
|
-
|
|
47
|
-
def getResult[R](r: Result[R]): R / { IOException } = r match {
|
|
48
|
-
case Error(msg) => do IOException(msg)
|
|
49
|
-
case Success(r) => r
|
|
50
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
const fs = require("fs")
|
|
2
|
-
const fsPromises = fs.promises;
|
|
3
|
-
|
|
4
|
-
function readAsyncHelper(path, f) {
|
|
5
|
-
return $effekt.callcc(k => {
|
|
6
|
-
fs.readFile(path, 'utf8', (err, data) => {
|
|
7
|
-
// change f, so it returns true
|
|
8
|
-
const comp = f(err ? Error(err.message) : Success(data)).then(x => $effekt.pure(true))
|
|
9
|
-
k(comp); // restore the stack, since `f` might use effects
|
|
10
|
-
});
|
|
11
|
-
return k($effekt.pure(false))
|
|
12
|
-
}).then(x => x).then(abort => abort ? $effekt.callcc(k => $effekt.pure(null)) : $effekt.pure(null))
|
|
13
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
module mutable/array
|
|
2
|
-
|
|
3
|
-
import immutable/option
|
|
4
|
-
import immutable/list
|
|
5
|
-
|
|
6
|
-
// A mutable 0-based indexed array, backed by a JavaScript array.
|
|
7
|
-
extern type Array[T]
|
|
8
|
-
|
|
9
|
-
def emptyArray[T](): Array[T] = emptyArray(0)
|
|
10
|
-
|
|
11
|
-
// Creates a new Array of size `size` filled with the value `default`
|
|
12
|
-
def fill[T](size: Int, default: T): Array[T] = {
|
|
13
|
-
val arr = emptyArray[T](size)
|
|
14
|
-
each(0, arr.size()) { i =>
|
|
15
|
-
put(arr, i, default)
|
|
16
|
-
}
|
|
17
|
-
return arr;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Builds a new Array of size `size` from a computation `index` which gets an index
|
|
21
|
-
// and returns a value that will be on that position in the resulting array
|
|
22
|
-
def build[T](size: Int) { index: Int => T }: Array[T] = {
|
|
23
|
-
val arr = emptyArray[T](size)
|
|
24
|
-
each(0, arr.size()) { i =>
|
|
25
|
-
put(arr, i, index(i))
|
|
26
|
-
}
|
|
27
|
-
return arr
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Converts a List `list` to an Array
|
|
31
|
-
def fromList[T](list: List[T]): Array[T] = {
|
|
32
|
-
val listSize = list.size();
|
|
33
|
-
val arr = emptyArray(listSize);
|
|
34
|
-
|
|
35
|
-
foreachIndex(list) { (i, head) =>
|
|
36
|
-
put(arr, i, head)
|
|
37
|
-
}
|
|
38
|
-
return arr;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
extern pure def emptyArray[T](initialSize: Int): Array[T] =
|
|
42
|
-
"(new Array(${initialSize}))"
|
|
43
|
-
|
|
44
|
-
def get[T](arr: Array[T], index: Int): Option[T] =
|
|
45
|
-
arr.unsafeGet(index).undefinedToOption
|
|
46
|
-
|
|
47
|
-
extern pure def size[T](arr: Array[T]): Int =
|
|
48
|
-
"${arr}.length"
|
|
49
|
-
|
|
50
|
-
extern io def unsafeGet[T](arr: Array[T], index: Int): T =
|
|
51
|
-
"${arr}[${index}]"
|
|
52
|
-
|
|
53
|
-
extern """
|
|
54
|
-
function put(arr, index, value) {
|
|
55
|
-
arr[index] = value;
|
|
56
|
-
return $effekt.unit
|
|
57
|
-
}
|
|
58
|
-
"""
|
|
59
|
-
|
|
60
|
-
extern io def put[T](arr: Array[T], index: Int, value: T): Unit =
|
|
61
|
-
"put(${arr}, ${index}, ${value})"
|
|
62
|
-
|
|
63
|
-
extern pure def copy[T](arr: Array[T]): Array[T] =
|
|
64
|
-
"[...${arr}]"
|
|
65
|
-
|
|
66
|
-
// Utility functions:
|
|
67
|
-
|
|
68
|
-
def toList[T](arr: Array[T]): List[T] = {
|
|
69
|
-
var i = arr.size - 1;
|
|
70
|
-
var l = Nil[T]()
|
|
71
|
-
while (i >= 0) {
|
|
72
|
-
l = Cons(unsafeGet(arr, i), l)
|
|
73
|
-
i = i - 1
|
|
74
|
-
}
|
|
75
|
-
l
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
def foreach[T](arr: Array[T]){ action: T => Unit / Control }: Unit = {
|
|
79
|
-
each(0, arr.size) { i =>
|
|
80
|
-
val x: T = arr.unsafeGet(i)
|
|
81
|
-
action(x)
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
def foreachIndex[T](arr: Array[T]){ action: (Int, T) => Unit / Control }: Unit = {
|
|
86
|
-
each(0, arr.size) { i =>
|
|
87
|
-
val x: T = arr.unsafeGet(i)
|
|
88
|
-
action(i, x)
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
def sum(list: Array[Int]): Int = {
|
|
93
|
-
var acc = 0
|
|
94
|
-
list.foreach { x =>
|
|
95
|
-
acc = acc + x
|
|
96
|
-
}
|
|
97
|
-
acc
|
|
98
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
module mutable/heap
|
|
2
|
-
|
|
3
|
-
extern """
|
|
4
|
-
var heap$data = {};
|
|
5
|
-
var heap$pointer = 0;
|
|
6
|
-
|
|
7
|
-
function heap$fresh(init) {
|
|
8
|
-
const ref = heap$pointer++;
|
|
9
|
-
heap$data[ref] = init;
|
|
10
|
-
return ref
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function heap$put(ref, value) {
|
|
14
|
-
heap$data[ref] = value;
|
|
15
|
-
return null
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function get$impl(ref) {
|
|
19
|
-
return heap$data[ref];
|
|
20
|
-
}
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
extern type HeapRef[T]
|
|
24
|
-
|
|
25
|
-
extern io def fresh[T](init: T): HeapRef[T] =
|
|
26
|
-
"heap$fresh(${init})"
|
|
27
|
-
|
|
28
|
-
extern io def put[T](ref: HeapRef[T], value: T): Unit =
|
|
29
|
-
"heap$put(${ref}, ${value})"
|
|
30
|
-
|
|
31
|
-
extern io def get[T](ref: HeapRef[T]): T =
|
|
32
|
-
"heap$data[${ref}]"
|
package/libraries/js/test.effekt
DELETED
|
@@ -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,64 +0,0 @@
|
|
|
1
|
-
module text/string
|
|
2
|
-
|
|
3
|
-
import immutable/option
|
|
4
|
-
import mutable/array
|
|
5
|
-
|
|
6
|
-
def charAt(str: String, index: Int): Option[String] =
|
|
7
|
-
str.unsafeCharAt(index).undefinedToOption
|
|
8
|
-
|
|
9
|
-
extern pure def length(str: String): Int =
|
|
10
|
-
"${str}.length"
|
|
11
|
-
|
|
12
|
-
extern pure def repeat(str: String, n: Int): String =
|
|
13
|
-
"${str}.repeat(${n})"
|
|
14
|
-
|
|
15
|
-
extern pure def unsafeSubstring(str: String, from: Int, to: Int): String =
|
|
16
|
-
"${str}.substring(${from}, ${to})"
|
|
17
|
-
|
|
18
|
-
def substring(str: String, from: Int, to: Int): String =
|
|
19
|
-
if (from >= to) { "" }
|
|
20
|
-
else {
|
|
21
|
-
str.unsafeSubstring(from, to)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
def substring(str: String, from: Int): String =
|
|
25
|
-
str.unsafeSubstring(from, str.length)
|
|
26
|
-
|
|
27
|
-
extern pure def split(str: String, sep: String): Array[String] =
|
|
28
|
-
"${str}.split(${sep})"
|
|
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
|
-
extern pure def unsafeToInt(str: String): Int =
|
|
40
|
-
"(Number.isNaN(parseInt(${str})) ? undefined : parseInt(${str}))"
|
|
41
|
-
|
|
42
|
-
def indexOf(str: String, sub: String): Option[Int] = {
|
|
43
|
-
val index = str.unsafeIndexOf(sub)
|
|
44
|
-
if (index < 0) { None() } else { Some(index) }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
def lastIndexOf(str: String, sub: String): Option[Int] = {
|
|
48
|
-
val index = str.unsafeLastIndexOf(sub)
|
|
49
|
-
if (index < 0) { None() } else { Some(index) }
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
extern pure def unsafeIndexOf(str: String, sub: String): Int = "${str}.indexOf(${sub})"
|
|
53
|
-
extern pure def unsafeLastIndexOf(str: String, sub: String): Int = "${str}.lastIndexOf(${sub})"
|
|
54
|
-
|
|
55
|
-
extern pure def startsWith(str: String, prefix: String): Boolean =
|
|
56
|
-
"${str}.startsWith(${prefix})"
|
|
57
|
-
|
|
58
|
-
extern pure def endsWith(str: String, suffix: String): Boolean =
|
|
59
|
-
"${str}.endsWith(${suffix})"
|
|
60
|
-
|
|
61
|
-
// ANSI escape codes
|
|
62
|
-
val ANSI_GREEN = "\u001b[32m"
|
|
63
|
-
val ANSI_RED = "\u001b[31m"
|
|
64
|
-
val ANSI_RESET = "\u001b[0m"
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
module effekt
|
|
2
|
-
|
|
3
|
-
extern include "rts.ll"
|
|
4
|
-
extern include "forward-declare-c.ll"
|
|
5
|
-
|
|
6
|
-
// Effekt-closed stdlib facilities
|
|
7
|
-
|
|
8
|
-
def min(n: Int, m: Int): Int =
|
|
9
|
-
if (n < m) n else m
|
|
10
|
-
|
|
11
|
-
def max(n: Int, m: Int): Int =
|
|
12
|
-
if (n > m) n else m
|
|
13
|
-
|
|
14
|
-
def neg(n: Int): Int =
|
|
15
|
-
0 - n
|
|
16
|
-
|
|
17
|
-
def abs(n: Int): Int =
|
|
18
|
-
max(n, neg(n))
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
// i/o
|
|
22
|
-
|
|
23
|
-
extern io def println(n: Int): Unit = """
|
|
24
|
-
call void @c_io_println_Int(%Int %n)
|
|
25
|
-
ret %Pos zeroinitializer ; Unit
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
extern io def println(b: Boolean): Unit = """
|
|
29
|
-
call void @c_io_println_Boolean(%Pos %b)
|
|
30
|
-
ret %Pos zeroinitializer ; Unit
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
extern io def println(x: Double): Unit = """
|
|
34
|
-
call void @c_io_println_Double(%Double %x)
|
|
35
|
-
ret %Pos zeroinitializer ; Unit
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
extern io def println(str: String): Unit = """
|
|
39
|
-
call void @c_io_println_String(%Pos %str)
|
|
40
|
-
call void @c_buffer_refcount_decrement(%Pos %str)
|
|
41
|
-
ret %Pos zeroinitializer ; Unit
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
def println(u: Unit): Unit = println("unit")
|
|
45
|
-
|
|
46
|
-
// strings
|
|
47
|
-
|
|
48
|
-
extern pure def infixEq(x: String, y: String): Boolean = """
|
|
49
|
-
%res = call %Pos @c_buffer_eq(%Pos %x, %Pos %y)
|
|
50
|
-
call void @c_buffer_refcount_decrement(%Pos %x)
|
|
51
|
-
call void @c_buffer_refcount_decrement(%Pos %y)
|
|
52
|
-
ret %Pos %res
|
|
53
|
-
"""
|
|
54
|
-
def infixNeq(x: String, y: String): Boolean = not(x == y)
|
|
55
|
-
|
|
56
|
-
extern pure def infixConcat(s: String, z: String): String = """
|
|
57
|
-
%spz = call %Pos @c_buffer_concatenate(%Pos %s, %Pos %z)
|
|
58
|
-
call void @c_buffer_refcount_decrement(%Pos %s)
|
|
59
|
-
call void @c_buffer_refcount_decrement(%Pos %z)
|
|
60
|
-
ret %Pos %spz
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
// integer arithmetic
|
|
64
|
-
|
|
65
|
-
extern pure def infixAdd(x: Int, y: Int): Int = "%z = add %Int ${x}, ${y} ret %Int %z"
|
|
66
|
-
extern pure def infixSub(x: Int, y: Int): Int = "%z = sub %Int ${x}, ${y} ret %Int %z"
|
|
67
|
-
extern pure def infixMul(x: Int, y: Int): Int = "%z = mul %Int ${x}, ${y} ret %Int %z"
|
|
68
|
-
extern pure def infixDiv(x: Int, y: Int): Int = "%z = sdiv %Int ${x}, ${y} ret %Int %z"
|
|
69
|
-
|
|
70
|
-
extern pure def mod (x: Int, y: Int): Int = "%z = srem %Int ${x}, ${y} ret %Int %z"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// floating-point arithmetic
|
|
74
|
-
|
|
75
|
-
extern pure def infixAdd(x: Double, y: Double): Double = "%z = fadd %Double ${x}, ${y} ret %Double %z"
|
|
76
|
-
extern pure def infixSub(x: Double, y: Double): Double = "%z = fsub %Double ${x}, ${y} ret %Double %z"
|
|
77
|
-
extern pure def infixMul(x: Double, y: Double): Double = "%z = fmul %Double ${x}, ${y} ret %Double %z"
|
|
78
|
-
extern pure def infixDiv(x: Double, y: Double): Double = "%z = fdiv %Double ${x}, ${y} ret %Double %z"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
// ordering on signed integers
|
|
82
|
-
|
|
83
|
-
extern pure def infixEq(x: Int, y: Int): Boolean = """
|
|
84
|
-
%z = icmp eq %Int %x, %y
|
|
85
|
-
%fat_z = zext i1 %z to i64
|
|
86
|
-
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
87
|
-
ret %Pos %adt_boolean
|
|
88
|
-
"""
|
|
89
|
-
|
|
90
|
-
extern pure def infixNeq(x: Int, y: Int): Boolean = """
|
|
91
|
-
%z = icmp ne %Int %x, %y
|
|
92
|
-
%fat_z = zext i1 %z to i64
|
|
93
|
-
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
94
|
-
ret %Pos %adt_boolean
|
|
95
|
-
"""
|
|
96
|
-
|
|
97
|
-
extern pure def infixLt(x: Int, y: Int): Boolean = """
|
|
98
|
-
%z = icmp slt %Int %x, %y
|
|
99
|
-
%fat_z = zext i1 %z to i64
|
|
100
|
-
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
101
|
-
ret %Pos %adt_boolean
|
|
102
|
-
"""
|
|
103
|
-
|
|
104
|
-
extern pure def infixLte(x: Int, y: Int): Boolean = """
|
|
105
|
-
%z = icmp sle %Int %x, %y
|
|
106
|
-
%fat_z = zext i1 %z to i64
|
|
107
|
-
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
108
|
-
ret %Pos %adt_boolean
|
|
109
|
-
"""
|
|
110
|
-
|
|
111
|
-
extern pure def infixGt(x: Int, y: Int): Boolean = """
|
|
112
|
-
%z = icmp sgt %Int %x, %y
|
|
113
|
-
%fat_z = zext i1 %z to i64
|
|
114
|
-
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
115
|
-
ret %Pos %adt_boolean
|
|
116
|
-
"""
|
|
117
|
-
|
|
118
|
-
extern pure def infixGte(x: Int, y: Int): Boolean = """
|
|
119
|
-
%z = icmp sge %Int %x, %y
|
|
120
|
-
%fat_z = zext i1 %z to i64
|
|
121
|
-
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
122
|
-
ret %Pos %adt_boolean
|
|
123
|
-
"""
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// boolean algebra
|
|
127
|
-
|
|
128
|
-
extern pure def infixEq(x: Boolean, y: Boolean): Boolean = """
|
|
129
|
-
%slim_x = extractvalue %Pos %x, 0
|
|
130
|
-
%slim_y = extractvalue %Pos %y, 0
|
|
131
|
-
%slim_z = icmp eq i64 %slim_x, %slim_y
|
|
132
|
-
%fat_z = zext i1 %slim_z to i64
|
|
133
|
-
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
134
|
-
ret %Pos %adt_boolean
|
|
135
|
-
"""
|
|
136
|
-
|
|
137
|
-
extern pure def infixNeq(x: Boolean, y: Boolean): Boolean = """
|
|
138
|
-
%slim_x = extractvalue %Pos %x, 0
|
|
139
|
-
%slim_y = extractvalue %Pos %y, 0
|
|
140
|
-
%slim_z = icmp ne i64 %slim_x, %slim_y
|
|
141
|
-
%fat_z = zext i1 %slim_z to i64
|
|
142
|
-
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
143
|
-
ret %Pos %adt_boolean
|
|
144
|
-
"""
|
|
145
|
-
|
|
146
|
-
extern pure def not(adt_p: Boolean): Boolean = """
|
|
147
|
-
%p = extractvalue %Pos %adt_p, 0
|
|
148
|
-
%q = xor i64 1, %p
|
|
149
|
-
%adt_q = insertvalue %Pos zeroinitializer, i64 %q, 0
|
|
150
|
-
ret %Pos %adt_q
|
|
151
|
-
"""
|
|
152
|
-
|
|
153
|
-
extern pure def infixOr(adt_p: Boolean, adt_q: Boolean): Boolean = """
|
|
154
|
-
%p = extractvalue %Pos %adt_p, 0
|
|
155
|
-
%q = extractvalue %Pos %adt_q, 0
|
|
156
|
-
%r = or i64 %p, %q
|
|
157
|
-
%adt_r = insertvalue %Pos zeroinitializer, i64 %r, 0
|
|
158
|
-
ret %Pos %adt_r
|
|
159
|
-
"""
|
|
160
|
-
|
|
161
|
-
extern pure def infixAnd(adt_p: Boolean, adt_q: Boolean): Boolean = """
|
|
162
|
-
%p = extractvalue %Pos %adt_p, 0
|
|
163
|
-
%q = extractvalue %Pos %adt_q, 0
|
|
164
|
-
%r = and i64 %p, %q
|
|
165
|
-
%adt_r = insertvalue %Pos zeroinitializer, i64 %r, 0
|
|
166
|
-
ret %Pos %adt_r
|
|
167
|
-
"""
|
|
168
|
-
|
|
169
|
-
// show
|
|
170
|
-
extern pure def show(i: Int): String = """
|
|
171
|
-
%z = call %Pos @c_buffer_show_Int(%Int %i)
|
|
172
|
-
ret %Pos %z
|
|
173
|
-
"""
|
|
174
|
-
extern pure def show(x: Double): String = """
|
|
175
|
-
%z = call %Pos @c_buffer_show_Double(%Double %x)
|
|
176
|
-
ret %Pos %z
|
|
177
|
-
"""
|
|
178
|
-
def show(b: Boolean): String = {
|
|
179
|
-
if(b) { "true" } else { "false" }
|
|
180
|
-
}
|
|
181
|
-
def show(u: Unit): String = { "unit" }
|
|
182
|
-
|
|
183
|
-
// For boxing polymorphic values
|
|
184
|
-
record BoxedUnit(unboxUnit: Unit)
|
|
185
|
-
record BoxedInt(unboxInt: Int)
|
|
186
|
-
record BoxedBoolean(unboxBoolean: Boolean)
|
|
187
|
-
record BoxedDouble(unboxDouble: Double)
|
|
188
|
-
record BoxedString(unboxString: String)
|
|
189
|
-
|
|
190
|
-
// Pairs
|
|
191
|
-
// =====
|
|
192
|
-
record Tuple2[A, B](first: A, second: B)
|
|
193
|
-
record Tuple3[A, B, C](first: A, second: B, third: C)
|
|
194
|
-
record Tuple4[A, B, C, D](first: A, second: B, third: C, fourth: D)
|
|
195
|
-
record Tuple5[A, B, C, D, E](first: A, second: B, third: C, fourth: D, fifth: E)
|
|
196
|
-
record Tuple6[A, B, C, D, E, F](first: A, second: B, third: C, fourth: D, fifth: E, sixth: F)
|
|
197
|
-
|
|
198
|
-
// Exceptions
|
|
199
|
-
// ==========
|
|
200
|
-
interface Exception[E] {
|
|
201
|
-
def raise(exception: E, msg: String): Nothing
|
|
202
|
-
}
|
|
203
|
-
record RuntimeError()
|
|
204
|
-
|
|
205
|
-
def raise[A](msg: String): A / Exception[RuntimeError] = do raise(RuntimeError(), msg) match {}
|
|
206
|
-
def raise[A, E](exception: E, msg: String): A / Exception[E] = do raise(exception, msg) match {}
|
|
207
|
-
|
|
208
|
-
// reports exceptions of (static) type E to the console
|
|
209
|
-
def report[E] { prog: => Unit / Exception[E] }: Unit =
|
|
210
|
-
try { prog() } with Exception[E] { def raise(exception: E, msg: String) = println(msg) }
|
|
211
|
-
|
|
212
|
-
// ignores exceptions of (static) type E
|
|
213
|
-
// TODO this should be called "ignore" but that name currently clashes with internal pattern matching names on $effekt
|
|
214
|
-
def ignoring[E] { prog: => Unit / Exception[E] }: Unit =
|
|
215
|
-
try { prog() } with Exception[E] { def raise(exception: E, msg: String) = () }
|
|
216
|
-
|
|
217
|
-
// Control Flow
|
|
218
|
-
// ============
|
|
219
|
-
interface Control {
|
|
220
|
-
def break(): Unit
|
|
221
|
-
def continue(): Unit
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
def loop { f: () => Unit / Control }: Unit = try {
|
|
225
|
-
def go(): Unit = { f(); go() }
|
|
226
|
-
go()
|
|
227
|
-
} with Control {
|
|
228
|
-
def break() = ()
|
|
229
|
-
def continue() = loop { f }
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Calls provided action repeatedly. `start` is inclusive, `end` is not.
|
|
234
|
-
*/
|
|
235
|
-
def each(start: Int, end: Int) { action: (Int) => Unit / Control } = {
|
|
236
|
-
var i = start;
|
|
237
|
-
loop {
|
|
238
|
-
if (i < end) { val el = i; i = i + 1; action(el) }
|
|
239
|
-
else { do break() }
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
def repeat(n: Int) { action: () => Unit / Control } = each(0, n) { n => action() }
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
module immutable/option
|
|
2
|
-
|
|
3
|
-
import effekt
|
|
4
|
-
|
|
5
|
-
type Option[A] {
|
|
6
|
-
None();
|
|
7
|
-
Some(value: A)
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
def isDefined[A](self: Option[A]): Boolean = self match {
|
|
11
|
-
case None() => false
|
|
12
|
-
case Some(v) => true
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
def isEmpty[A](self: Option[A]): Boolean =
|
|
16
|
-
self.isDefined.not
|
|
17
|
-
|
|
18
|
-
def orElse[A](self: Option[A]) { that: => Option[A] }: Option[A] = self match {
|
|
19
|
-
case None() => that()
|
|
20
|
-
case Some(v) => Some(v)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
def getOrElse[A](self: Option[A]) { that: => A }: A = self match {
|
|
24
|
-
case None() => that()
|
|
25
|
-
case Some(v) => v
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
def map[A, B](self: Option[A]) { f: A => B }: Option[B] = self match {
|
|
29
|
-
case None() => None()
|
|
30
|
-
case Some(v) => Some(f(v))
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
def foreach[A](self: Option[A]) { f: A => Unit }: Unit = self match {
|
|
34
|
-
case None() => ()
|
|
35
|
-
case Some(v) => f(v)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// =========================================
|
|
39
|
-
// `show` / `println` overloads for options:
|
|
40
|
-
// =========================================
|
|
41
|
-
|
|
42
|
-
// for now define some common cases; TODO better solution
|
|
43
|
-
def showOption[A](o: Option[A]){ showA: A => String }: String = o match {
|
|
44
|
-
case None() => "None()"
|
|
45
|
-
case Some(v) => "Some(" ++ showA(v) ++ ")"
|
|
46
|
-
}
|
|
47
|
-
def show(o: Option[Int]): String = showOption(o){ e => show(e) }
|
|
48
|
-
def show(o: Option[Double]): String = showOption(o){ e => show(e) }
|
|
49
|
-
def show(o: Option[Boolean]): String = showOption(o){ e => show(e) }
|
|
50
|
-
|
|
51
|
-
def println(o: Option[Int]): Unit = println(show(o))
|
|
52
|
-
def println(o: Option[Double]): Unit = println(show(o))
|
|
53
|
-
def println(o: Option[Boolean]): Unit = println(show(o))
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import immutable/option
|
|
2
|
-
|
|
3
|
-
// Results
|
|
4
|
-
// =======
|
|
5
|
-
// The "reification" of the Exception[E] effect.
|
|
6
|
-
type Result[A, E] {
|
|
7
|
-
Error(exception: E, msg: String);
|
|
8
|
-
Success(a: A)
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
def result[A, E] { f: () => A / Exception[E] }: Result[A, E] = try {
|
|
12
|
-
Success(f())
|
|
13
|
-
} with Exception[E] {
|
|
14
|
-
def raise(exc, msg) = Error(exc, msg)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Extracts the value of a result, if available
|
|
19
|
-
* Monadic "reflection"
|
|
20
|
-
*/
|
|
21
|
-
def value[A, E](r: Result[A, E]): A / Exception[E] = r match {
|
|
22
|
-
case Success(a) => a
|
|
23
|
-
case Error(exc, msg) => do raise(exc, msg)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
def toOption[A, E](r: Result[A, E]): Option[A] = r match {
|
|
27
|
-
case Success(a) => Some(a)
|
|
28
|
-
case Error(exc, msg) => None()
|
|
29
|
-
}
|