@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,13 +1,8 @@
1
- module immutable/list
1
+ module list
2
2
 
3
3
  import effekt
4
- import immutable/option
5
-
6
- // Used as a type for `Exception` in functions which expect a nonempty list.
7
- record EmptyList()
8
-
9
- // Used as a type for `Exception` in functions where an index can be out of bounds.
10
- record OutOfBounds()
4
+ import option
5
+ import exception
11
6
 
12
7
  // Immutable linked list for finite sequences of elements.
13
8
  type List[A] {
@@ -46,7 +41,7 @@ def build[A](size: Int) { index: Int => A }: List[A] = {
46
41
  // Check if list is empty.
47
42
  //
48
43
  // O(1)
49
- def isEmpty[A](l: List[A]): Boolean = l match {
44
+ def isEmpty[A](l: List[A]): Bool = l match {
50
45
  case Nil() => true
51
46
  case Cons(a, rest) => false
52
47
  }
@@ -54,26 +49,26 @@ def isEmpty[A](l: List[A]): Boolean = l match {
54
49
  // Check if list is nonempty.
55
50
  //
56
51
  // O(1)
57
- def nonEmpty[A](l: List[A]): Boolean = l match {
52
+ def nonEmpty[A](l: List[A]): Bool = l match {
58
53
  case Nil() => false
59
54
  case Cons(a, rest) => true
60
55
  }
61
56
 
62
57
  // Return the first element of a given list.
63
- // Throws a `EmptyList` exception if it's empty.
58
+ // Throws a `MissingValue` exception if it's empty.
64
59
  //
65
60
  // O(1)
66
- def head[A](l: List[A]): A / Exception[EmptyList] = l match {
67
- case Nil() => do raise(EmptyList(), "Trying to get the head of an empty list")
61
+ def head[A](l: List[A]): A / Exception[MissingValue] = l match {
62
+ case Nil() => do raise(MissingValue(), "Trying to get the head of an empty list")
68
63
  case Cons(a, rest) => a
69
64
  }
70
65
 
71
66
  // Return all elements of a given list except the first element.
72
- // Throws a `EmptyList` exception if it's empty.
67
+ // Throws a `MissingValue` exception if it's empty.
73
68
  //
74
69
  // O(1)
75
- def tail[A](l: List[A]): List[A] / Exception[EmptyList] = l match {
76
- case Nil() => do raise(EmptyList(), "Trying to get the head of an empty list")
70
+ def tail[A](l: List[A]): List[A] / Exception[MissingValue] = l match {
71
+ case Nil() => do raise(MissingValue(), "Trying to get the head of an empty list")
77
72
  case Cons(a, rest) => rest
78
73
  }
79
74
 
@@ -86,19 +81,30 @@ def headOption[A](l: List[A]): Option[A] = l match {
86
81
  case Cons(a, rest) => Some(a)
87
82
  }
88
83
 
84
+ // Returns the last element of a given list.
85
+ //
86
+ // O(N)
87
+ def last[A](l: List[A]): A / Exception[MissingValue] = {
88
+ def go(list: List[A]): A = {
89
+ list match {
90
+ case Nil() => do raise(MissingValue(), "Trying to get the last element of an empty list")
91
+ case Cons(x, Nil()) => x
92
+ case Cons(x, xs) => go(xs)
93
+ }
94
+ }
95
+
96
+ go(l)
97
+ }
98
+
89
99
  // Get the value at given index.
90
100
  //
91
101
  // O(N)
92
102
  def get[A](list: List[A], index: Int): A / Exception[OutOfBounds] = {
93
- def go(list: List[A], i: Int): A / Exception[OutOfBounds] = {
103
+ def go(list: List[A], i: Int): A = {
94
104
  list match {
95
105
  case Nil() => do raise(OutOfBounds(), "Trying to get an element outside the bounds of a list")
96
- case Cons(x, xs) =>
97
- if (i == 0) {
98
- x
99
- } else {
100
- go(xs, i - 1)
101
- }
106
+ case Cons(x, xs) and i == 0 => x
107
+ case Cons(x, xs) => go(xs, i - 1)
102
108
  }
103
109
  }
104
110
 
@@ -108,36 +114,53 @@ def get[A](list: List[A], index: Int): A / Exception[OutOfBounds] = {
108
114
  // Traverse a list, applying the given action on every element.
109
115
  //
110
116
  // O(N)
111
- def foreach[A](l: List[A]) { f: A => Unit / Control } : Unit = {
117
+ def foreach[A](l: List[A]) { f: (A) => Unit } : Unit = l match {
118
+ case Nil() => ()
119
+ case Cons(head, tail) => f(head); tail.foreach {f}
120
+ }
121
+
122
+ // Traverse a list, applying the given action on every element.
123
+ //
124
+ // O(N)
125
+ def foreach[A](l: List[A]) { f: (A) {Control} => Unit } : Unit = {
112
126
  var remainder = l
113
- loop {
114
- if (not(remainder.isEmpty)) {
115
- remainder match {
116
- case Nil() => ()
117
- case Cons(a, as) =>
118
- remainder = as
119
- f(a)
120
- }
121
- } else { do break() }
127
+ loop { {label} =>
128
+ remainder match {
129
+ case Nil() => label.break()
130
+ case Cons(head, tail) =>
131
+ remainder = tail
132
+ f(head) {label}
133
+ }
134
+ }
135
+ }
136
+
137
+ // Traverse a list, applying the given action on every element and its (zero-based) index.
138
+ //
139
+ // O(N)
140
+ def foreachIndex[A](list: List[A]){ f: (Int, A) => Unit }: Unit = {
141
+ def loop(index: Int, remainder: List[A]): Unit = remainder match {
142
+ case Nil() => ()
143
+ case Cons(head, tail) =>
144
+ f(index, head);
145
+ loop(index + 1, tail)
122
146
  }
147
+ loop(0, list)
123
148
  }
124
149
 
125
150
  // Traverse a list, applying the given action on every element and its (zero-based) index.
126
151
  //
127
152
  // O(N)
128
- def foreachIndex[A](list: List[A]){ f: (Int, A) => Unit / Control }: Unit = {
153
+ def foreachIndex[A](list: List[A]){ f: (Int, A) {Control} => Unit }: Unit = {
129
154
  var remainder = list
130
155
  var i = -1
131
- loop {
132
- if (not(remainder.isEmpty)) {
156
+ loop { {label} =>
133
157
  remainder match {
134
- case Nil() => ()
135
- case Cons(a, as) =>
136
- remainder = as
158
+ case Nil() => label.break()
159
+ case Cons(head, tail) =>
160
+ remainder = tail
137
161
  i = i + 1
138
- f(i, a)
162
+ f(i, head) {label}
139
163
  }
140
- } else { do break() }
141
164
  }
142
165
  }
143
166
 
@@ -182,7 +205,7 @@ def flatMap[A, B](l: List[A]) { f : A => List[B] }: List[B] = {
182
205
  // Check if predicate is true for all elements of the given list.
183
206
  //
184
207
  // O(N)
185
- def all[A](list: List[A]) { predicate: A => Boolean }: Boolean = {
208
+ def all[A](list: List[A]) { predicate: A => Bool }: Bool = {
186
209
  list match {
187
210
  case Cons(x, xs) => predicate(x) && all(xs) { predicate }
188
211
  case Nil() => true
@@ -192,7 +215,7 @@ def all[A](list: List[A]) { predicate: A => Boolean }: Boolean = {
192
215
  // Check if predicate is true for at least one element of the given list.
193
216
  //
194
217
  // O(N)
195
- def any[A](list: List[A]) { predicate: A => Boolean }: Boolean = {
218
+ def any[A](list: List[A]) { predicate: A => Bool }: Bool = {
196
219
  list match {
197
220
  case Cons(x, xs) => predicate(x) || any(xs) { predicate }
198
221
  case Nil() => false
@@ -594,7 +617,7 @@ def unzip[A, B](pairs: List[(A, B)]): (List[A], List[B]) = {
594
617
  // the right list contains the elements that do not.
595
618
  //
596
619
  // O(N)
597
- def partition[A](l: List[A]) { pred: A => Boolean }: (List[A], List[A]) = {
620
+ def partition[A](l: List[A]) { pred: A => Bool }: (List[A], List[A]) = {
598
621
  var lefts: List[A] = Nil()
599
622
  var rights: List[A] = Nil()
600
623
  l.foreach { el =>
@@ -613,7 +636,7 @@ def partition[A](l: List[A]) { pred: A => Boolean }: (List[A], List[A]) = {
613
636
  // Note: this implementation is not stacksafe!
614
637
  //
615
638
  // O(N log N)
616
- def sortBy[A](l: List[A]) { compare: (A, A) => Boolean }: List[A] =
639
+ def sortBy[A](l: List[A]) { compare: (A, A) => Bool }: List[A] =
617
640
  l match {
618
641
  case Nil() => Nil()
619
642
  case Cons(pivot, rest) =>
@@ -624,14 +647,13 @@ def sortBy[A](l: List[A]) { compare: (A, A) => Boolean }: List[A] =
624
647
  }
625
648
 
626
649
  def sort(l: List[Int]): List[Int] = l.sortBy { (a, b) => a < b }
627
- // def sort(l: List[Double]): List[Double] = l.sortBy { (a, b) => a < b }
628
- // Future work: ^ needs `le` for `Double`
650
+ def sort(l: List[Double]): List[Double] = l.sortBy { (a, b) => a < b }
629
651
 
630
652
  // Check if a list is sorted according to the given comparison function.
631
653
  //
632
654
  // O(N)
633
- def isSortedBy[A](list: List[A]) { compare: (A, A) => Boolean }: Boolean = {
634
- def go(list: List[A]): Boolean = {
655
+ def isSortedBy[A](list: List[A]) { compare: (A, A) => Bool }: Bool = {
656
+ def go(list: List[A]): Bool = {
635
657
  list match {
636
658
  case Nil() => true
637
659
  case Cons(x, Nil()) => true
@@ -643,36 +665,23 @@ def isSortedBy[A](list: List[A]) { compare: (A, A) => Boolean }: Boolean = {
643
665
  go(list)
644
666
  }
645
667
 
646
- // =========================================
647
- // `show` / `println` overloads for options:
648
- // =========================================
649
668
 
650
- // uses the same crude format as other backends
651
- def showList[A](l: List[A]){ showA: A => String }: String = {
669
+ // Show Instances
670
+ // --------------
671
+
672
+ def show[A](l: List[A]) { showA: A => String }: String = {
652
673
  def go(l: List[A]): String = l match {
653
674
  case Nil() => "Nil()"
654
675
  case Cons(x, xs) => "Cons(" ++ showA(x) ++ ", " ++ go(xs) ++ ")"
655
676
  }
656
677
  go(l)
657
678
  }
658
- def show(l: List[Int]): String = showList(l){e => show(e)}
659
- def show(l: List[Double]): String = showList(l){e => show(e)}
660
- def show(l: List[Boolean]): String = showList(l){e => show(e)}
661
- def show(l: List[String]): String = showList(l){e => e}
679
+ def show(l: List[Int]): String = show(l) { e => show(e) }
680
+ def show(l: List[Double]): String = show(l) { e => show(e) }
681
+ def show(l: List[Bool]): String = show(l) { e => show(e) }
682
+ def show(l: List[String]): String = show(l) { e => e }
662
683
 
663
- def println(l: List[Int]): Unit = {
664
- val s: String = show(l)
665
- println(s)
666
- }
667
- def println(l: List[Double]): Unit = {
668
- val s: String = show(l)
669
- println(s)
670
- }
671
- def println(l: List[Boolean]): Unit = {
672
- val s: String = show(l)
673
- println(s)
674
- }
675
- def println(l: List[String]): Unit = {
676
- val s: String = show(l)
677
- println(s)
678
- }
684
+ def println(l: List[Int]): Unit = println(show(l))
685
+ def println(l: List[Double]): Unit = println(show(l))
686
+ def println(l: List[Bool]): Unit = println(show(l))
687
+ def println(l: List[String]): Unit = println(show(l))
@@ -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
+ }