@effekt-lang/effekt 0.18.0 → 0.20.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.
@@ -0,0 +1,64 @@
1
+ module regex
2
+
3
+ import string
4
+
5
+ extern include chez "text/pregexp.scm"
6
+
7
+ extern type Regex
8
+
9
+ record Match(matched: String, index: Int)
10
+
11
+ extern pure def regex(str: String): Regex =
12
+ js "new RegExp(${str})"
13
+ chez "(pregexp ${str})"
14
+ vm "regex::regex(String)"
15
+
16
+ def exec(reg: Regex, str: String): Option[Match] = {
17
+ val v = internal::exec(reg, str)
18
+ if (v.isUndefined)
19
+ None()
20
+ else
21
+ Some(Match(internal::matched(v), internal::index(v)))
22
+ }
23
+
24
+ namespace internal {
25
+
26
+ /// The type RegexMatch is used internally to represent platform
27
+ /// dependent results of matching a regex.
28
+ extern type RegexMatch
29
+ // js: { matched: String, index: Int } | undefined
30
+ // vm: scala.util.matching.Regex.Match | null
31
+
32
+ extern pure def matched(r: RegexMatch): String =
33
+ js "${r}.matched"
34
+ chez "(vector-ref ${r} 0)"
35
+ vm "regex::matched(RegexMatch)"
36
+
37
+ extern pure def index(r: RegexMatch): Int =
38
+ js "${r}.index"
39
+ chez "(vector-ref ${r} 1)"
40
+ vm "regex::index(RegexMatch)"
41
+
42
+ extern js """
43
+ function regex$exec(reg, str) {
44
+ var res = reg.exec(str);
45
+ if (res === null) { return undefined }
46
+ else { return { matched: res[0], index: res.index } }
47
+ }
48
+ """
49
+
50
+ extern chez """
51
+ (define regex-exec
52
+ (lambda (regex str)
53
+ (let* ([positions (pregexp-match-positions regex str)]
54
+ [match (pregexp-match regex str)])
55
+ (if (and positions match)
56
+ (vector (car match) (caar positions))
57
+ #f))))
58
+ """
59
+
60
+ extern io def exec(reg: Regex, str: String): RegexMatch =
61
+ js "regex$exec(${reg}, ${str})"
62
+ chez "(regex-exec ${reg} ${str})"
63
+ vm "regex::exec(Regex, String)"
64
+ }
@@ -0,0 +1,235 @@
1
+ module resizable_array
2
+
3
+ import ref
4
+ import array
5
+
6
+ record ResizableArray[T](rawSizePtr: Ref[Int], rawContentPtr: Ref[Array[T]])
7
+
8
+ // These numbers should be optimized based on benchmarking
9
+ // According to https://en.wikipedia.org/wiki/Dynamic_array most use 1.5 or 2
10
+
11
+ /// Factor by which to grow the capacity when it becomes too small
12
+ val growFactor = 1.5
13
+ /// shrink array when size / capacity falls below this threshold
14
+ /// should be < 1/growFactor
15
+ val shrinkThreshold = 0.4
16
+
17
+ /// Number of elements in the dynamic array
18
+ ///
19
+ /// O(1)
20
+ def size[T](arr: ResizableArray[T]) = arr.rawSizePtr.get
21
+
22
+ /// Allocate a new, empty dynamic array with given initial capacity
23
+ def resizableArray[T](capacity: Int): ResizableArray[T] = {
24
+ ResizableArray(ref(0), ref(allocate(capacity)))
25
+ }
26
+
27
+ /// Allocate a new, empty dynamic array
28
+ def resizableArray[T](): ResizableArray[T] = resizableArray(8)
29
+
30
+ /// Throw an OutOfBounds exception if index is not a valid index into arr
31
+ def boundsCheck[T](arr: ResizableArray[T], index: Int): Unit / Exception[OutOfBounds] = {
32
+ if (index < 0 && index >= arr.size) {
33
+ do raise(OutOfBounds(), "Array index out of bounds: " ++ show(index))
34
+ }
35
+ }
36
+
37
+ /// get the element at position index in the array
38
+ ///
39
+ /// precondition: index is a valid index into the array
40
+ ///
41
+ /// O(1)
42
+ def unsafeGet[T](arr: ResizableArray[T], index: Int): T = {
43
+ arr.rawContentPtr.get.unsafeGet(index)
44
+ }
45
+ /// get the element at position index in the array
46
+ ///
47
+ /// O(1)
48
+ def get[T](arr: ResizableArray[T], index: Int): T / Exception[OutOfBounds] = {
49
+ arr.boundsCheck(index);
50
+ arr.unsafeGet(index)
51
+ }
52
+
53
+ /// set the element at position index in the array
54
+ ///
55
+ /// precondition: index is a valid index into the array
56
+ ///
57
+ /// O(1)
58
+ def unsafeSet[T](arr: ResizableArray[T], index: Int, value: T): Unit = {
59
+ arr.rawContentPtr.get.unsafeSet(index, value)
60
+ }
61
+
62
+ /// set the element at position index in the array
63
+ ///
64
+ /// O(1)
65
+ def set[T](arr: ResizableArray[T], index: Int, value: T): Unit / Exception[OutOfBounds] = {
66
+ arr.boundsCheck(index);
67
+ arr.unsafeSet(index, value)
68
+ }
69
+
70
+ /// swap the elements at the given positions in the array
71
+ ///
72
+ /// precondition: both are valid indices into the array
73
+ ///
74
+ /// O(1)
75
+ def unsafeSwap[T](arr: ResizableArray[T], index1: Int, index2: Int): Unit = {
76
+ val raw = arr.rawContentPtr.get
77
+ val tmp = raw.unsafeGet(index1)
78
+ raw.unsafeSet(index1, raw.unsafeGet(index2))
79
+ raw.unsafeSet(index2, tmp)
80
+ }
81
+
82
+ /// swap the elements at the given positions in the array
83
+ ///
84
+ /// O(1)
85
+ def swap[T](arr: ResizableArray[T], index1: Int, index2: Int): Unit / Exception[OutOfBounds] = {
86
+ arr.boundsCheck(max(index1, index2))
87
+ arr.unsafeSwap(index1, index2)
88
+ }
89
+
90
+ /// Change the dynamic to have exactly the given capacity
91
+ ///
92
+ /// precondition: given capacity is at least the size of the array
93
+ ///
94
+ /// O(n)
95
+ def unsafeSetCapacity[T](arr: ResizableArray[T], capacity: Int): Unit = {
96
+ with on[OutOfBounds].panic
97
+ val oldRaw = arr.rawContentPtr.get
98
+ if (oldRaw.size != capacity) {
99
+ val newRaw = array::allocate(capacity)
100
+ oldRaw.copy(0, newRaw, 0, arr.size)
101
+ arr.rawContentPtr.set(newRaw)
102
+ }
103
+ }
104
+
105
+ /// Change the resizable array to have exactly the given capacity.
106
+ /// This only changes the size of the backing array, not the `size`.
107
+ ///
108
+ /// O(n)
109
+ def setCapacity[T](arr: ResizableArray[T], capacity: Int): Unit / Exception[OutOfBounds] = {
110
+ if (arr.size > capacity) {
111
+ do raise(OutOfBounds(), "Cannot change capacity of ResizableArray to " ++ capacity.show ++ " below size " ++ arr.size.show)
112
+ }
113
+ arr.unsafeSetCapacity(capacity)
114
+ }
115
+
116
+ /// If the shrinkThreshold is reached, shrink by growFactor, otherwise do nothing
117
+ ///
118
+ /// O(n)
119
+ def maybeShrink[T](arr: ResizableArray[T]): Unit = {
120
+ if(arr.size.toDouble < arr.rawContentPtr.get.size.toDouble * shrinkThreshold) {
121
+ val newCap = max(arr.size, (arr.rawContentPtr.get.size.toDouble / growFactor).ceil)
122
+ arr.unsafeSetCapacity(newCap)
123
+ }
124
+ }
125
+
126
+ /// makes sure capacity is at least the given one
127
+ ///
128
+ /// O(given capacity - current capacity) amortized, O(n) worst case // TODO ?
129
+ def ensureCapacity[T](arr: ResizableArray[T], capacity: Int): Unit / Exception[OutOfBounds] = {
130
+ if (arr.rawContentPtr.get.size < capacity) {
131
+ val curCapd: Double = arr.rawContentPtr.get.size.toDouble
132
+ val minGrowCapacity: Int = (curCapd * growFactor + 1.0).toInt
133
+ val newCapacity = max(capacity, minGrowCapacity)
134
+ arr.setCapacity(newCapacity)
135
+ }
136
+ }
137
+
138
+ /// Set the value at given position, resizing if necessary
139
+ /// Note: New elements might be uninitialized!!!
140
+ ///
141
+ /// O(max(1,index - n)) amortized, O(n) worst case if index > capacity
142
+ def setResizing[T](arr: ResizableArray[T], index: Int, value: T): Unit / Exception[OutOfBounds] = {
143
+ if (index < 0) {
144
+ do raise(OutOfBounds(), "Negative index " ++ index.show)
145
+ }
146
+ if (index < arr.size) {
147
+ arr.rawContentPtr.get.unsafeSet(index, value)
148
+ }
149
+ ensureCapacity(arr, index + 1)
150
+ arr.rawContentPtr.get.unsafeSet(index, value)
151
+ arr.rawSizePtr.set(index + 1)
152
+ }
153
+
154
+ /// Add a new element at the end of the resizable array.
155
+ /// Return the index of the new element
156
+ ///
157
+ /// O(1) amortized, O(n) worst case
158
+ def add[T](arr: ResizableArray[T], value: T): Int = {
159
+ with on[OutOfBounds].panic();
160
+ val idx = arr.size
161
+ arr.setResizing(idx, value)
162
+ idx
163
+ }
164
+
165
+ /// Remove and return the rightmost element in the resizable array.
166
+ ///
167
+ /// O(1) amortized, O(n) worst case
168
+ def popRight[T](arr: ResizableArray[T]): T / Exception[OutOfBounds] = {
169
+ arr.boundsCheck(arr.size - 1)
170
+ arr.rawSizePtr.set(arr.size - 1)
171
+ val r = arr.unsafeGet(arr.size)
172
+ arr.maybeShrink()
173
+ r
174
+ }
175
+
176
+
177
+ def foreachIndex[T](arr: ResizableArray[T]){ body: (Int, T) => Unit }: Unit = {
178
+ each(0, arr.size) { i =>
179
+ body(i, arr.rawContentPtr.get.unsafeGet(i))
180
+ }
181
+ }
182
+ def foreachIndex[T](arr: ResizableArray[T]){ body: (Int, T) {Control} => Unit }: Unit = {
183
+ each(0, arr.size) { (i){label} =>
184
+ body(i, arr.rawContentPtr.get.unsafeGet(i)){label}
185
+ }
186
+ }
187
+ def foreach[T](arr: ResizableArray[T]){ body: T => Unit }: Unit = {
188
+ each(0, arr.size) { i =>
189
+ body(arr.rawContentPtr.get.unsafeGet(i))
190
+ }
191
+ }
192
+ def foreach[T](arr: ResizableArray[T]){ body: (T) {Control} => Unit }: Unit = {
193
+ each(0, arr.size) { (i){label} =>
194
+ body(arr.rawContentPtr.get.unsafeGet(i)){label}
195
+ }
196
+ }
197
+ def foreachIndexReversed[T](arr: ResizableArray[T]){ body: (Int, T){Control} => Unit }: Unit = {
198
+ var i = arr.size - 1
199
+ loop { {l} =>
200
+ if (i < 0) { l.break() }
201
+ body(i, arr.rawContentPtr.get.unsafeGet(i)){l}
202
+ i = i - 1
203
+ }
204
+ }
205
+ def foreachIndexReversed[T](arr: ResizableArray[T]){ body: (Int, T) => Unit }: Unit = {
206
+ var i = arr.size - 1
207
+ while(i >= 0) {
208
+ body(i, arr.rawContentPtr.get.unsafeGet(i))
209
+ i = i - 1
210
+ }
211
+ }
212
+ def foreachReversed[T](arr: ResizableArray[T]){ body: (T){Control} => Unit }: Unit = {
213
+ var i = arr.size - 1
214
+ loop { {l} =>
215
+ if (i < 0) { l.break() }
216
+ body(arr.rawContentPtr.get.unsafeGet(i)){l}
217
+ i = i - 1
218
+ }
219
+ }
220
+ def foreachReversed[T](arr: ResizableArray[T]){ body: T => Unit }: Unit = {
221
+ var i = arr.size - 1
222
+ while (i >= 0) {
223
+ body(arr.rawContentPtr.get.unsafeGet(i))
224
+ i = i - 1
225
+ }
226
+ }
227
+
228
+ def toList[T](arr: ResizableArray[T]): List[T] = {
229
+ def go(i: Int, acc: List[T]): List[T] = {
230
+ if (i < 0) { acc } else {
231
+ go(i - 1, Cons(arr.unsafeGet(i), acc))
232
+ }
233
+ }
234
+ go(arr.size - 1, Nil())
235
+ }
@@ -0,0 +1,234 @@
1
+ module set
2
+
3
+ import map
4
+
5
+ /// Ordered finite immutable set, backed by balanced binary trees of logarithmic depth.
6
+ record Set[A](tree: internal::Tree[A, Unit], compare: (A, A) => Ordering at {})
7
+
8
+ /// Create a new empty set using a pure, first-class comparison function.
9
+ ///
10
+ /// O(1)
11
+ def empty[A](compare: (A, A) => Ordering at {}): Set[A] =
12
+ Set(internal::empty(), compare)
13
+
14
+ /// Create a new empty set using a generic comparison function.
15
+ /// Only available on JavaScript backends!
16
+ ///
17
+ /// O(1)
18
+ def emptyGeneric[A](): Set[A] =
19
+ Set(
20
+ internal::empty(),
21
+ box { (left: A, right: A) => genericCompare(left, right) }
22
+ )
23
+
24
+ /// Check if set `s` is empty.
25
+ ///
26
+ /// O(1)
27
+ def isEmpty[A](s: Set[A]): Bool = internal::isEmpty(s.tree)
28
+
29
+ /// Check if set `s` is nonempty.
30
+ ///
31
+ /// O(1)
32
+ def nonEmpty[A](s: Set[A]): Bool = internal::nonEmpty(s.tree)
33
+
34
+ /// Create a new set containing a single `element`.
35
+ /// Requires a pure, first-class comparison function.
36
+ ///
37
+ /// O(1)
38
+ def singleton[A](element: A, compare: (A, A) => Ordering at {}): Set[A] =
39
+ Set(internal::singleton(element, ()), compare)
40
+
41
+ /// Create a new set containing a single `element` and a generic comparison function.
42
+ /// Only available on the JavaScript backends!
43
+ ///
44
+ /// O(1)
45
+ def singletonGeneric[A](element: A): Set[A] =
46
+ Set(
47
+ internal::singleton(element, ()),
48
+ box { (left: A, right: A) => genericCompare(left, right) }
49
+ )
50
+
51
+ /// Get the size of the set (the number of its elements).
52
+ ///
53
+ /// O(1)
54
+ def size[A](s: Set[A]): Int = internal::size(s.tree)
55
+
56
+ /// Insert a new element `a` into the set `s`.
57
+ ///
58
+ /// O(log N)
59
+ def insert[A](s: Set[A], a: A): Set[A] = {
60
+ val newTree = internal::put(s.tree, s.compare, a, ())
61
+ Set(newTree, s.compare)
62
+ }
63
+
64
+ /// Create a set from a given map by ignoring the values.
65
+ ///
66
+ /// O(N)
67
+ def fromMapKeys[K, V](map: Map[K, V]): Set[K] =
68
+ Set(internal::forget(map.tree), map.compare)
69
+
70
+ /// Create a map from a set and a function,
71
+ /// reusing the set's comparison.
72
+ ///
73
+ /// O(N)
74
+ def toMap[K, V](keys: Set[K]) { valueOf: K => V }: Map[K, V] = {
75
+ val newTree: internal::Tree[K, V] = internal::map(keys.tree) { (k, _v) => valueOf(k) }
76
+ Map(newTree, keys.compare)
77
+ }
78
+
79
+ /// Create a set from a given list and a pure, first-class comparison function.
80
+ ///
81
+ /// O(N log N)
82
+ /// O(N) if the list is sorted
83
+ def fromList[A](list: List[A], compare: (A, A) => Ordering at {}): Set[A] = {
84
+ val tree: internal::Tree[A, Unit] = internal::fromList(list.map { k => (k, ()) }, compare)
85
+ Set(tree, compare)
86
+ }
87
+
88
+ /// Create a set from a given list with a generic comparison function.
89
+ /// Works only on the JavaScript backends!
90
+ ///
91
+ /// O(N log N)
92
+ /// O(N) if the list is sorted
93
+ def fromListGeneric[A](list: List[A]): Set[A] = {
94
+ val compare: (A, A) => Ordering at {} = box { (left, right) => genericCompare(left, right) }
95
+ val tree: internal::Tree[A, Unit] = internal::fromList(list.map { k => (k, ()) }, compare)
96
+ Set(tree, compare)
97
+ }
98
+
99
+ /// Traverse all elements in order, running the function `action` on each element.
100
+ ///
101
+ /// Law: `s.foreach { action } === s.toList.foreach { action }`
102
+ ///
103
+ /// O(N)
104
+ def foreach[A](s: Set[A]) { action: A => Unit }: Unit =
105
+ internal::foreach(s.tree) { (k, _v) => action(k) }
106
+
107
+ /// Create a list from a given set.
108
+ ///
109
+ /// O(N)
110
+ def toList[A](s: Set[A]): List[A] = {
111
+ var acc = Nil()
112
+ s.foreach { a =>
113
+ acc = Cons(a, acc)
114
+ }
115
+ acc.reverse
116
+ }
117
+
118
+ /// Check if a predicate holds for all elements in a given set.
119
+ ///
120
+ /// O(N)
121
+ def all[A](s: Set[A]) { predicate : A => Bool }: Bool = {
122
+ var result = true
123
+ s.foreach { a =>
124
+ if (not(predicate(a))) { result = false }
125
+ }
126
+ result
127
+ }
128
+
129
+ /// Check if a predicate holds for at least one element in a given set.
130
+ ///
131
+ /// O(N)
132
+ def any[A](s: Set[A]) { predicate: A => Bool }: Bool = {
133
+ var result = false
134
+ s.foreach { a =>
135
+ if (predicate(a)) { result = true }
136
+ }
137
+ result
138
+ }
139
+
140
+ /// Check if a set contains a given element.
141
+ ///
142
+ /// O(log N)
143
+ def contains[A](s: Set[A], a: A): Bool =
144
+ internal::get(s.tree, s.compare, a) match {
145
+ case None() => false
146
+ case Some(v) => true
147
+ }
148
+
149
+
150
+ /// Check if set `s1` is a subset of set `s2`.
151
+ ///
152
+ /// O(N log N)
153
+ def subset[A](s1: Set[A], s2: Set[A]): Bool = {
154
+ s1.all { a =>
155
+ s2.contains(a)
156
+ }
157
+ }
158
+
159
+ /// Check if set `s1` is a superset of set `s2`.
160
+ ///
161
+ /// O(N log N)
162
+ def superset[A](s1: Set[A], s2: Set[A]): Bool = {
163
+ s2.subset(s1)
164
+ }
165
+
166
+ /// Remove an element from a set.
167
+ /// If the element is not in the set, the original set is returned.
168
+ ///
169
+ /// O(log N)
170
+ def delete[A](s: Set[A], a: A): Set[A] = {
171
+ val newTree = internal::delete(s.tree, s.compare, a)
172
+ Set(newTree, s.compare)
173
+ }
174
+
175
+ /// Remove many elements from a set.
176
+ ///
177
+ /// O(M log N) where M is the size of the list.
178
+ def deleteMany[A](s: Set[A], list: List[A]): Set[A] = {
179
+ var tmp = s
180
+ list.foreach { a =>
181
+ tmp = tmp.delete(a)
182
+ }
183
+ tmp
184
+ }
185
+
186
+ /// Construct a new set which contains all elements of `s1`
187
+ /// except those where the element is in `s2`.
188
+ /// Uses an explicit comparison function.
189
+ ///
190
+ /// O(???)
191
+ def difference[A](s1: Set[A], s2: Set[A], compare: (A, A) => Ordering at {}): Set[A] = {
192
+ val newTree = internal::difference(s1.tree, s2.tree, compare)
193
+ Set(newTree, compare)
194
+ }
195
+
196
+ /// Construct a new set which contains all elements of `s1`
197
+ /// except those where the element is in `s2`.
198
+ /// Uses a comparison function from `s1`.
199
+ ///
200
+ /// O(???)
201
+ def difference[A](s1: Set[A], s2: Set[A]): Set[A] =
202
+ s1.difference(s2, s1.compare)
203
+
204
+ /// Construct a new set which contains both elements of `s1` and `s2`.
205
+ /// Uses an explicit comparison function.
206
+ ///
207
+ /// O(???)
208
+ def union[A](s1: Set[A], s2: Set[A], compare: (A, A) => Ordering at {}): Set[A] = {
209
+ val newTree = internal::union(s1.tree, s2.tree, compare) { (_k, _v1, _v2) => () }
210
+ Set(newTree, compare)
211
+ }
212
+
213
+ /// Construct a new set which contains both elements of `s1` and `s2`.
214
+ /// Uses a comparison function from `s1`.
215
+ ///
216
+ /// O(???)
217
+ def union[A](s1: Set[A], s2: Set[A]): Set[A] =
218
+ s1.union(s2, s1.compare)
219
+
220
+ /// Construct a new set which contains only elements which are in both of `s1` and `s2`.
221
+ /// Uses an explicit comparison function.
222
+ ///
223
+ /// O(???)
224
+ def intersection[A](s1: Set[A], s2: Set[A], compare: (A, A) => Ordering at {}): Set[A] = {
225
+ val newTree = internal::intersection(s1.tree, s2.tree, compare) { (_k, _v1, _v2) => () }
226
+ Set(newTree, compare)
227
+ }
228
+
229
+ /// Construct a new set which contains only elements which are in both of `s1` and `s2`.
230
+ /// Uses a comparison function from `s1`.
231
+ ///
232
+ /// O(???)
233
+ def intersection[A](s1: Set[A], s2: Set[A]): Set[A] =
234
+ s1.intersection(s2, s1.compare)
@@ -2,6 +2,9 @@ module stream
2
2
 
3
3
  import array
4
4
  import bytearray
5
+ import map
6
+ import set
7
+
5
8
  import io/filesystem
6
9
  import io/error
7
10
 
@@ -63,6 +66,26 @@ def each(bytes: ByteArray): Unit / emit[Byte] = {
63
66
  go(0)
64
67
  }
65
68
 
69
+ /// Turns a `map` into a producer of a push stream
70
+ /// of `(key, value)` pairs by emitting each contained *in order*.
71
+ def each[K, V](map: Map[K, V]): Unit / emit[(K, V)] =
72
+ map.foreach { (k, v) => do emit((k, v)) }
73
+
74
+ /// Turns a `map` into a producer of a push stream
75
+ /// of its keys by emitting each contained *in order*.
76
+ def eachKey[K, V](map: Map[K, V]): Unit / emit[K] =
77
+ map.foreach { (k, _v) => do emit(k) }
78
+
79
+ /// Turns a `map` into a producer of a push stream
80
+ /// of its values by emitting each contained.
81
+ def eachValue[K, V](map: Map[K, V]): Unit / emit[V] =
82
+ map.foreach { (_k, v) => do emit(v) }
83
+
84
+ /// Turns a `set` into a producer of a push stream
85
+ /// by emitting each contained *in order*.
86
+ def each[A](set: Set[A]): Unit / emit[A] =
87
+ set.foreach { x => do emit(x) }
88
+
66
89
  // not option
67
90
  // not dequeue
68
91
  // not queue
@@ -168,6 +191,28 @@ def feed[T, R](list: List[T]) { reader: () => R / read[T] }: R = {
168
191
  }
169
192
  }
170
193
 
194
+ def collectMap[K, V, R](compare: (K, K) => Ordering at {}) { stream: () => R / emit[(K, V)] }: (R, Map[K, V]) =
195
+ try {
196
+ (stream(), map::empty(compare))
197
+ } with emit[(K, V)] { case (k, v) =>
198
+ val (r, map) = resume(());
199
+ (r, map.put(k, v))
200
+ }
201
+
202
+ def collectMap[K, V](compare: (K, K) => Ordering at {}) { stream: () => Any / emit[(K, V)] }: Map[K, V] =
203
+ collectMap[K, V, Any](compare){stream}.second
204
+
205
+ def collectSet[A, R](compare: (A, A) => Ordering at {}) { stream: () => R / emit[A] }: (R, Set[A]) =
206
+ try {
207
+ (stream(), set::empty(compare))
208
+ } with emit[A] { (v) =>
209
+ val (r, set) = resume(());
210
+ (r, set.insert(v))
211
+ }
212
+
213
+ def collectSet[A](compare: (A, A) => Ordering at {}) { stream: () => Any / emit[A] }: Set[A] =
214
+ collectSet[A, Any](compare){stream}.second
215
+
171
216
  def feed[T, R](array: Array[T]) { reader: () => R / read[T] }: R = {
172
217
  var i = 0
173
218
  try {
@@ -218,7 +263,7 @@ def zip[A, B] { stream1: () => Unit / emit[A] } { stream2: () => Unit / emit[B]
218
263
 
219
264
  def writeFile[R](path: String) { stream: () => R / emit[Byte] }: R / Exception[IOError] = {
220
265
 
221
- val file = open(path, WriteOnly());
266
+ val file = openForWriting(path);
222
267
  with on[IOError].finalize { close(file) }
223
268
 
224
269
  val chunkSize = 1048576 // 1MB
@@ -246,7 +291,7 @@ def writeFile[R](path: String) { stream: () => R / emit[Byte] }: R / Exception[I
246
291
 
247
292
  def readFile[R](path: String) { reader: () => R / read[Byte] }: R / Exception[IOError] = {
248
293
 
249
- val file = open(path, ReadOnly());
294
+ val file = openForReading(path);
250
295
  with on[IOError].finalize { close(file) }
251
296
 
252
297
  val chunkSize = 1048576 // 1MB
@@ -243,11 +243,13 @@ extern pure def toInt(ch: Char): Int =
243
243
  js "${ch}"
244
244
  chez "${ch}"
245
245
  llvm "ret %Int ${ch}"
246
+ vm "string::toInt(Char)"
246
247
 
247
248
  extern pure def toChar(codepoint: Int): Char =
248
249
  js "${codepoint}"
249
250
  chez "${codepoint}"
250
251
  llvm "ret %Int ${codepoint}"
252
+ vm "string::toChar(Int)"
251
253
 
252
254
 
253
255
  extern pure def infixLt(x: Char, y: Char): Bool =
@@ -259,6 +261,7 @@ extern pure def infixLt(x: Char, y: Char): Bool =
259
261
  %adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
260
262
  ret %Pos %adt_boolean
261
263
  """
264
+ vm "string::infixLt(Char, Char)"
262
265
 
263
266
  extern pure def infixLte(x: Char, y: Char): Bool =
264
267
  js "(${x} <= ${y})"
@@ -269,6 +272,7 @@ extern pure def infixLte(x: Char, y: Char): Bool =
269
272
  %adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
270
273
  ret %Pos %adt_boolean
271
274
  """
275
+ vm "string::infixLte(Char, Char)"
272
276
 
273
277
  extern pure def infixGt(x: Char, y: Char): Bool =
274
278
  js "(${x} > ${y})"
@@ -279,6 +283,7 @@ extern pure def infixGt(x: Char, y: Char): Bool =
279
283
  %adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
280
284
  ret %Pos %adt_boolean
281
285
  """
286
+ vm "string::infixGt(Char, Char)"
282
287
 
283
288
  extern pure def infixGte(x: Char, y: Char): Bool =
284
289
  js "(${x} >= ${y})"
@@ -289,6 +294,7 @@ extern pure def infixGte(x: Char, y: Char): Bool =
289
294
  %adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
290
295
  ret %Pos %adt_boolean
291
296
  """
297
+ vm "string::infixGte(Char, Char)"
292
298
 
293
299
 
294
300
  /**
@@ -327,3 +333,4 @@ extern pure def unsafeCharAt(str: String, n: Int): Char =
327
333
  %x = call %Int @c_bytearray_character_at(%Pos ${str}, %Int ${n})
328
334
  ret %Int %x
329
335
  """
336
+ vm "string::unsafeCharAt(String, Int)"