@effekt-lang/effekt 0.2.1 → 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/LICENSE +21 -0
- package/README.md +36 -0
- package/bin/effekt +0 -0
- package/bin/effekt.sh +2 -0
- package/libraries/chez/THIRD-PARTY.txt +11 -0
- package/libraries/chez/callcc/datatype.ss +188 -0
- package/libraries/chez/callcc/effekt.ss +31 -0
- package/libraries/chez/callcc/seq.ss +44 -0
- package/libraries/chez/callcc/seq0.ss +69 -0
- package/libraries/chez/callcc/tail.ss +76 -0
- package/libraries/chez/callcc/tail0.ss +89 -0
- package/libraries/chez/common/effekt_primitives.ss +105 -0
- package/libraries/chez/common/immutable/cslist.effekt +37 -0
- package/libraries/chez/common/mutable/dict.effekt +28 -0
- package/libraries/chez/common/text/pregexp.scm +772 -0
- package/libraries/chez/common/text/regex.effekt +31 -0
- package/libraries/chez/lift/effekt.ss +118 -0
- package/libraries/chez/monadic/effekt.ss +84 -0
- package/libraries/chez/monadic/seq0.ss +76 -0
- 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/common/dequeue.effekt +92 -0
- 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/common/list.effekt +687 -0
- 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/common/seq.effekt +914 -0
- package/libraries/common/string.effekt +395 -0
- package/libraries/common/test.effekt +98 -0
- package/libraries/js/effekt_builtins.js +57 -0
- package/libraries/js/effekt_runtime.js +385 -0
- package/libraries/js/io.js +143 -0
- package/libraries/js/mutable/map.effekt +31 -0
- package/libraries/js/text/regex.effekt +33 -0
- package/libraries/js/unsafe/cont.effekt +11 -0
- package/libraries/js/web/dom.effekt +45 -0
- package/libraries/llvm/array.c +53 -0
- package/libraries/llvm/buffer.c +286 -0
- package/libraries/llvm/forward-declare-c.ll +43 -0
- package/libraries/llvm/hole.c +11 -0
- package/libraries/llvm/io.c +566 -0
- package/libraries/llvm/io.ll +19 -0
- package/libraries/llvm/main.c +41 -0
- package/libraries/llvm/ref.c +45 -0
- package/libraries/llvm/rts.ll +761 -0
- package/libraries/llvm/sanity.c +16 -0
- package/libraries/llvm/types.c +43 -0
- package/libraries/ml/effekt.sml +65 -0
- package/libraries/ml/internal/mllist.effekt +9 -0
- package/libraries/ml/internal/mloption.effekt +18 -0
- package/libraries/ml/random.effekt +85 -0
- package/libraries/ml/text/regex.effekt +102 -0
- package/licenses/THIRD-PARTY.txt +21 -0
- package/licenses/apache-2.0 - license-2.0.txt +202 -0
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +61 -0
- package/licenses/kiama-license.txt +373 -0
- package/licenses/kiama-readme.txt +186 -0
- package/licenses/mit license - mit-license.html +1239 -0
- package/licenses/the apache software license, version 2.0 - license-2.0.txt +202 -0
- package/licenses/the bsd license - bsd-license.html +1237 -0
- package/licenses/the mit license - mit.html +1239 -0
- package/package.json +26 -18
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module option
|
|
2
|
+
|
|
3
|
+
import effekt
|
|
4
|
+
import exception
|
|
5
|
+
|
|
6
|
+
type Option[A] {
|
|
7
|
+
None();
|
|
8
|
+
Some(value: A)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
def isDefined[A](self: Option[A]): Bool = self match {
|
|
12
|
+
case None() => false
|
|
13
|
+
case Some(v) => true
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
def isEmpty[A](self: Option[A]): Bool =
|
|
17
|
+
self.isDefined.not
|
|
18
|
+
|
|
19
|
+
def orElse[A](self: Option[A]) { that: => Option[A] }: Option[A] = self match {
|
|
20
|
+
case None() => that()
|
|
21
|
+
case Some(v) => Some(v)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
def getOrElse[A](self: Option[A]) { that: => A }: A = self match {
|
|
25
|
+
case None() => that()
|
|
26
|
+
case Some(v) => v
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
def map[A, B](self: Option[A]) { f: A => B }: Option[B] = self match {
|
|
30
|
+
case None() => None()
|
|
31
|
+
case Some(v) => Some(f(v))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
def foreach[A](self: Option[A]) { f: A => Unit }: Unit = self match {
|
|
35
|
+
case None() => ()
|
|
36
|
+
case Some(v) => f(v)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
def value[A](self: Option[A]): A / Exception[MissingValue] = self match {
|
|
40
|
+
case None() => do raise(MissingValue(), "Trying to get the value of an empty option")
|
|
41
|
+
case Some(v) => v
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
def option[A] { p: => A / Exception[MissingValue] }: Option[A] =
|
|
45
|
+
try { Some(p()) }
|
|
46
|
+
with Exception[MissingValue] { def raise(_, _) = None() }
|
|
47
|
+
|
|
48
|
+
def option[A, E](proxy: on[E]) { p: => A / Exception[E] }: Option[A] =
|
|
49
|
+
try { Some(p()) }
|
|
50
|
+
with Exception[E] { def raise(_, _) = None() }
|
|
51
|
+
|
|
52
|
+
// Interop with FFI
|
|
53
|
+
// ---------------
|
|
54
|
+
// These functions should only be used by libraries that interface with FFI
|
|
55
|
+
def undefinedToOption[A](value: A): Option[A] =
|
|
56
|
+
if (value.isUndefined) { None() } else { Some(value) }
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
// Show Instances
|
|
60
|
+
// --------------
|
|
61
|
+
|
|
62
|
+
def show[A](o: Option[A]) { showA: A => String }: String = o match {
|
|
63
|
+
case None() => "None()"
|
|
64
|
+
case Some(v) => "Some(" ++ showA(v) ++ ")"
|
|
65
|
+
}
|
|
66
|
+
def show(o: Option[Int]): String = show(o) { e => show(e) }
|
|
67
|
+
def show(o: Option[Double]): String = show(o) { e => show(e) }
|
|
68
|
+
def show(o: Option[Bool]): String = show(o) { e => show(e) }
|
|
69
|
+
|
|
70
|
+
def println(o: Option[Int]): Unit = println(show(o))
|
|
71
|
+
def println(o: Option[Double]): Unit = println(show(o))
|
|
72
|
+
def println(o: Option[Bool]): Unit = println(show(o))
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module process
|
|
2
|
+
|
|
3
|
+
extern io def exit(errorCode: Int): Nothing =
|
|
4
|
+
js "(function() { process.exit(${errorCode}) })()"
|
|
5
|
+
llvm """
|
|
6
|
+
call void @exit(i64 ${errorCode})
|
|
7
|
+
ret %Pos zeroinitializer
|
|
8
|
+
"""
|
|
9
|
+
chez "(exit ${errorCode})"
|
|
10
|
+
ml "(Posix.Process.exit (Word8.fromInt ${errorCode}))"
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
module queue
|
|
2
|
+
|
|
3
|
+
import array
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Mutable, automatically resizing queue.
|
|
7
|
+
*/
|
|
8
|
+
interface Queue[T] {
|
|
9
|
+
def empty?(): Bool
|
|
10
|
+
|
|
11
|
+
def popFront(): Option[T]
|
|
12
|
+
|
|
13
|
+
def popBack(): Option[T]
|
|
14
|
+
|
|
15
|
+
def peekFront(): Option[T]
|
|
16
|
+
|
|
17
|
+
def peekBack(): Option[T]
|
|
18
|
+
|
|
19
|
+
def pushFront(el: T): Unit
|
|
20
|
+
|
|
21
|
+
def pushBack(el: T): Unit
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def emptyQueue[T](): Queue[T] at {global} =
|
|
26
|
+
emptyQueue[T](64)
|
|
27
|
+
|
|
28
|
+
def emptyQueue[T](initialCapacity: Int): Queue[T] at {global} = {
|
|
29
|
+
|
|
30
|
+
var contents in global = array[Option[T]](initialCapacity, None())
|
|
31
|
+
var head in global = 0
|
|
32
|
+
var tail in global = 0
|
|
33
|
+
var size in global = 0
|
|
34
|
+
var capacity in global = initialCapacity
|
|
35
|
+
|
|
36
|
+
def remove(arr: Array[Option[T]], index: Int): Option[T] = {
|
|
37
|
+
with on[OutOfBounds].default { None() };
|
|
38
|
+
val value = arr.get(index);
|
|
39
|
+
arr.set(index, None());
|
|
40
|
+
value
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
def nonEmpty[T] { p: => Option[T] / Exception[OutOfBounds] }: Option[T] =
|
|
44
|
+
if (size <= 0) None() else on[OutOfBounds].default { None() } { p() }
|
|
45
|
+
|
|
46
|
+
// Exponential back-off
|
|
47
|
+
def resizeTo(requiredSize: Int): Unit =
|
|
48
|
+
if (requiredSize <= capacity) () else {
|
|
49
|
+
with on[OutOfBounds].ignore // should not happen
|
|
50
|
+
|
|
51
|
+
val oldSize = capacity
|
|
52
|
+
val newSize = capacity * 2
|
|
53
|
+
val oldContents = contents
|
|
54
|
+
val newContents = array::allocate[Option[T]](newSize)
|
|
55
|
+
|
|
56
|
+
if (head < tail) {
|
|
57
|
+
// The queue does not wrap around; direct copy is possible.
|
|
58
|
+
copy(oldContents, head, newContents, 0, size) // changed tail to size
|
|
59
|
+
} else if (size > 0) {
|
|
60
|
+
// The queue wraps around; copy in two segments.
|
|
61
|
+
copy(oldContents, head, newContents, 0, oldSize - head) // changed oldSize to oldSize - head
|
|
62
|
+
copy(oldContents, 0, newContents, oldSize - head, tail) // changed oldSize - head to oldSize - head
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
contents = newContents
|
|
66
|
+
capacity = newSize
|
|
67
|
+
head = 0
|
|
68
|
+
tail = oldSize
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
def queue = new Queue[T] {
|
|
72
|
+
def empty?() = size <= 0
|
|
73
|
+
|
|
74
|
+
def popFront() =
|
|
75
|
+
nonEmpty {
|
|
76
|
+
val result = contents.remove(head)
|
|
77
|
+
head = mod(head + 1, capacity)
|
|
78
|
+
size = size - 1
|
|
79
|
+
result
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
def popBack() =
|
|
83
|
+
nonEmpty {
|
|
84
|
+
tail = mod(tail - 1 + capacity, capacity)
|
|
85
|
+
val result = contents.remove(tail)
|
|
86
|
+
size = size - 1
|
|
87
|
+
result
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
def peekFront() = nonEmpty { contents.get(head) }
|
|
91
|
+
|
|
92
|
+
def peekBack() = nonEmpty { contents.get(tail) }
|
|
93
|
+
|
|
94
|
+
def pushFront(el: T) = {
|
|
95
|
+
resizeTo(size + 1);
|
|
96
|
+
head = mod(head - 1 + capacity, capacity);
|
|
97
|
+
size = size + 1;
|
|
98
|
+
contents.unsafeSet(head, Some(el))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
def pushBack(el: T) = {
|
|
102
|
+
resizeTo(size + 1);
|
|
103
|
+
contents.unsafeSet(tail, Some(el));
|
|
104
|
+
size = size + 1;
|
|
105
|
+
tail = mod(tail + 1, capacity)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
queue
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
namespace examples {
|
|
112
|
+
def main() = {
|
|
113
|
+
// queue with initial capacity 4
|
|
114
|
+
def b = emptyQueue[Int](4);
|
|
115
|
+
println(b.empty?);
|
|
116
|
+
b.pushFront(1);
|
|
117
|
+
b.pushBack(2);
|
|
118
|
+
b.pushFront(3);
|
|
119
|
+
b.pushBack(4);
|
|
120
|
+
// this will cause resizing:
|
|
121
|
+
b.pushBack(5);
|
|
122
|
+
b.pushBack(6);
|
|
123
|
+
b.pushBack(7);
|
|
124
|
+
b.pushBack(8);
|
|
125
|
+
// and again:
|
|
126
|
+
b.pushBack(9);
|
|
127
|
+
|
|
128
|
+
println(b.empty?);
|
|
129
|
+
println(b.popFront()); // Some(3)
|
|
130
|
+
println(b.popFront()); // Some(1)
|
|
131
|
+
println(b.popFront()); // Some(2)
|
|
132
|
+
println(b.popFront()); // Some(4)
|
|
133
|
+
println(b.popFront()); // Some(5)
|
|
134
|
+
println(b.popFront()); // Some(6)
|
|
135
|
+
println(b.popFront()); // Some(7)
|
|
136
|
+
println(b.popFront()); // Some(8)
|
|
137
|
+
println(b.popFront()); // Some(9)
|
|
138
|
+
println(b.popFront()); // None()
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module ref
|
|
2
|
+
|
|
3
|
+
import effekt
|
|
4
|
+
|
|
5
|
+
extern js """
|
|
6
|
+
function set$impl(ref, value) {
|
|
7
|
+
ref.value = value;
|
|
8
|
+
return $effekt.unit;
|
|
9
|
+
}
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Global, mutable references
|
|
14
|
+
*/
|
|
15
|
+
extern type Ref[T]
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Allocates a new reference of size `size`, keeping its value _undefined_.
|
|
19
|
+
* Prefer using `ref` constructor instead to ensure that the value is defined.
|
|
20
|
+
*/
|
|
21
|
+
extern global def allocate[T](): Ref[T] =
|
|
22
|
+
js "{ value: undefined }"
|
|
23
|
+
chez "(box #f)"
|
|
24
|
+
llvm """
|
|
25
|
+
%z = call %Pos @c_ref_fresh(%Pos zeroinitializer)
|
|
26
|
+
ret %Pos %z
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Creates a new reference with the initial value `init`.
|
|
31
|
+
*/
|
|
32
|
+
extern global def ref[T](init: T): Ref[T] =
|
|
33
|
+
js "{ value: ${init} }"
|
|
34
|
+
chez "(box ${init})"
|
|
35
|
+
ml "ref ${init}"
|
|
36
|
+
llvm """
|
|
37
|
+
%z = call %Pos @c_ref_fresh(%Pos ${init})
|
|
38
|
+
ret %Pos %z
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Gets the referenced element of the `ref` in constant time.
|
|
43
|
+
*/
|
|
44
|
+
extern global def get[T](ref: Ref[T]): T =
|
|
45
|
+
js "${ref}.value"
|
|
46
|
+
chez "(unbox ${ref})"
|
|
47
|
+
ml "!${ref}"
|
|
48
|
+
llvm """
|
|
49
|
+
%z = call %Pos @c_ref_get(%Pos ${ref})
|
|
50
|
+
ret %Pos %z
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Sets the referenced element of the `ref` to `value` in constant time.
|
|
55
|
+
*/
|
|
56
|
+
extern global def set[T](ref: Ref[T], value: T): Unit =
|
|
57
|
+
js "set$impl(${ref}, ${value})"
|
|
58
|
+
chez "(set-box! ${ref} ${value})"
|
|
59
|
+
ml "${ref} := ${value}"
|
|
60
|
+
llvm """
|
|
61
|
+
%z = call %Pos @c_ref_set(%Pos ${ref}, %Pos ${value})
|
|
62
|
+
ret %Pos %z
|
|
63
|
+
"""
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module result
|
|
2
|
+
|
|
3
|
+
import effekt
|
|
4
|
+
import option
|
|
5
|
+
import exception
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Represents the result of a potentially failing computation.
|
|
9
|
+
* It is the "reification" of the Exception[E] effect.
|
|
10
|
+
*/
|
|
11
|
+
type Result[A, E] {
|
|
12
|
+
Error(exception: E, msg: String);
|
|
13
|
+
Success(a: A)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Represent ("reify") the result of a potentially failing computation.
|
|
18
|
+
*/
|
|
19
|
+
def result[A, E] { f: => A / Exception[E] }: Result[A, E] = try {
|
|
20
|
+
Success(f())
|
|
21
|
+
} with Exception[E] {
|
|
22
|
+
def raise(exc, msg) = Error(exc, msg)
|
|
23
|
+
}
|
|
24
|
+
def result[A, E](proxy: on[E]) { f: => A / Exception[E] }: Result[A, E] = try {
|
|
25
|
+
Success(f())
|
|
26
|
+
} with Exception[E] {
|
|
27
|
+
def raise(exc, msg) = Error(exc, msg)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Extracts the value of a result, if available
|
|
32
|
+
* Monadic "reflection"
|
|
33
|
+
*/
|
|
34
|
+
def value[A, E](r: Result[A, E]): A / Exception[E] = r match {
|
|
35
|
+
case Success(a) => a
|
|
36
|
+
case Error(exc, msg) => do raise(exc, msg)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Converts a result to an option forgetting the error details
|
|
41
|
+
*/
|
|
42
|
+
def toOption[A, E](r: Result[A, E]): Option[A] = r match {
|
|
43
|
+
case Success(a) => Some(a)
|
|
44
|
+
case Error(exc, msg) => None()
|
|
45
|
+
}
|