@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,9 +0,0 @@
1
- module io/args
2
-
3
- import effekt
4
- import immutable/list
5
- import mutable/array
6
-
7
- extern io def nativeArgs(): Array[String] = "process.argv.slice(2)"
8
-
9
- def commandLineArgs(): List[String] = nativeArgs().toList
@@ -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)"
@@ -1,2 +0,0 @@
1
- const fs = require("fs")
2
- const fsPromises = fs.promises;
@@ -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}]"
@@ -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
- }