@effekt-lang/effekt 0.55.0 → 0.57.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 (33) hide show
  1. package/README.md +1 -1
  2. package/bin/effekt +0 -0
  3. package/libraries/chez/common/effekt_primitives.ss +10 -4
  4. package/libraries/common/array.effekt +107 -104
  5. package/libraries/common/buffer.effekt +3 -3
  6. package/libraries/common/bytearray.effekt +41 -18
  7. package/libraries/common/control.effekt +27 -0
  8. package/libraries/common/dictionary.effekt +133 -0
  9. package/libraries/common/effekt.effekt +27 -24
  10. package/libraries/common/heap.effekt +23 -15
  11. package/libraries/common/io/filesystem.effekt +2 -2
  12. package/libraries/common/json.effekt +19 -19
  13. package/libraries/common/list.effekt +4 -3
  14. package/libraries/common/option.effekt +1 -1
  15. package/libraries/common/queue.effekt +3 -3
  16. package/libraries/common/random.effekt +1 -1
  17. package/libraries/common/ref.effekt +2 -2
  18. package/libraries/common/resizable_array.effekt +39 -73
  19. package/libraries/common/seq.effekt +7 -7
  20. package/libraries/common/stream.effekt +3 -22
  21. package/libraries/common/string.effekt +1 -1
  22. package/libraries/common/stringbuffer.effekt +1 -1
  23. package/libraries/common/union_find.effekt +7 -7
  24. package/libraries/js/effekt_builtins.js +1 -1
  25. package/libraries/llvm/forward-declare-c.ll +2 -2
  26. package/libraries/llvm/io.c +2 -2
  27. package/libraries/llvm/panic.c +2 -0
  28. package/libraries/llvm/rts.ll +17 -38
  29. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +3 -3
  30. package/licenses/mit license - mit-license.html +76 -45
  31. package/licenses/the bsd license - bsd-license.html +75 -46
  32. package/licenses/the mit license - mit.html +76 -45
  33. package/package.json +1 -1
@@ -2,6 +2,7 @@ module bytearray
2
2
 
3
3
  import effekt
4
4
  import stream
5
+ import control
5
6
 
6
7
  /**
7
8
  * A memory managed, mutable, fixed-length array of bytes.
@@ -22,12 +23,12 @@ extern type ByteArray
22
23
  // = js "Uint8Array"
23
24
  // = chez "bytevector"
24
25
 
25
- /// Allocates a new bytearray with the given `size`, its values are undefined.
26
+ /// Allocates a new bytearray with the given `size`, its values are zero bytes.
26
27
  extern def allocate(size: Int) at global: ByteArray =
27
28
  js "(new Uint8Array(${size}))"
28
29
  llvm """
29
30
  %object_size = add i64 ${size}, 16
30
- %object_alloc = tail call noalias ptr @malloc(i64 noundef %object_size)
31
+ %object_alloc = tail call noalias ptr @calloc(i64 %object_size, i64 1)
31
32
  store i64 0, ptr %object_alloc, align 8
32
33
  %object_data_ptr = getelementptr inbounds i8, ptr %object_alloc, i64 8
33
34
  store ptr @bytearray_erase_noop, ptr %object_data_ptr, align 8
@@ -48,9 +49,30 @@ extern def size(arr: ByteArray) at {}: Int =
48
49
  chez "(bytevector-length ${arr})"
49
50
  vm "bytearray::size(ByteArray)"
50
51
 
51
- extern def unsafeGet(arr: ByteArray, index: Int) at global: Byte =
52
- js "(${arr})[${index}]"
52
+ extern js """
53
+ function bytearray$get(arr, index) {
54
+ if (index < 0 || index >= arr.length) throw 'Index out of bounds';
55
+ return arr[index];
56
+ }
57
+ """
58
+
59
+ extern llvm """
60
+ define void @assertInboundsByteArray(i64 %index, %Pos %arr) alwaysinline {
61
+ %size = extractvalue %Pos %arr, 0
62
+ %in_bounds = icmp ult i64 %index, %size
63
+ br i1 %in_bounds, label %ok, label %out
64
+ out:
65
+ call void @exit(i64 1)
66
+ unreachable
67
+ ok:
68
+ ret void
69
+ }
70
+ """
71
+
72
+ extern def get(arr: ByteArray, index: Int) at global: Byte =
73
+ js "bytearray$get(${arr}, ${index})"
53
74
  llvm """
75
+ call void @assertInboundsByteArray(i64 ${index}, %Pos ${arr})
54
76
  %arr_ptr = extractvalue %Pos ${arr}, 1
55
77
  %arr_data_ptr = getelementptr inbounds i8, ptr %arr_ptr, i64 16
56
78
  %element_ptr = getelementptr inbounds i8, ptr %arr_data_ptr, i64 ${index}
@@ -59,11 +81,12 @@ extern def unsafeGet(arr: ByteArray, index: Int) at global: Byte =
59
81
  ret i8 %element
60
82
  """
61
83
  chez "(bytevector-u8-ref ${arr} ${index})"
62
- vm "bytearray::unsafeGet(ByteArray, Int)"
84
+ vm "bytearray::get(ByteArray, Int)"
63
85
 
64
- extern def unsafeSet(arr: ByteArray, index: Int, value: Byte) at global: Unit =
86
+ extern def set(arr: ByteArray, index: Int, value: Byte) at global: Unit =
65
87
  js "bytearray$set(${arr}, ${index}, ${value})"
66
88
  llvm """
89
+ call void @assertInboundsByteArray(i64 ${index}, %Pos ${arr})
67
90
  %arr_ptr = extractvalue %Pos ${arr}, 1
68
91
  %arr_data_ptr = getelementptr inbounds i8, ptr %arr_ptr, i64 16
69
92
  %element_ptr = getelementptr inbounds i8, ptr %arr_data_ptr, i64 ${index}
@@ -72,13 +95,13 @@ extern def unsafeSet(arr: ByteArray, index: Int, value: Byte) at global: Unit =
72
95
  ret %Pos zeroinitializer
73
96
  """
74
97
  chez "(bytevector-u8-set! ${arr} ${index} ${value})"
75
- vm "bytearray::unsafeSet(ByteArray, Int, Byte)"
98
+ vm "bytearray::set(ByteArray, Int, Byte)"
76
99
 
77
100
  /// Creates a new ByteArray of size `size` filled with the value `init`
78
101
  def bytearray(size: Int, init: Byte): ByteArray = {
79
102
  val arr = allocate(size);
80
103
  each(0, size) { i =>
81
- unsafeSet(arr, i, init)
104
+ set(arr, i, init)
82
105
  };
83
106
  arr
84
107
  }
@@ -88,7 +111,7 @@ def resize(source: ByteArray, size: Int): ByteArray = {
88
111
  val n = min(source.size, target.size)
89
112
  def go(i: Int): ByteArray =
90
113
  if (i < n) {
91
- target.unsafeSet(i, source.unsafeGet(i))
114
+ target.set(i, source.get(i))
92
115
  go(i + 1)
93
116
  } else {
94
117
  target
@@ -98,22 +121,22 @@ def resize(source: ByteArray, size: Int): ByteArray = {
98
121
 
99
122
  def foreach(arr: ByteArray){ action: Byte => Unit }: Unit =
100
123
  each(0, arr.size) { i =>
101
- action(arr.unsafeGet(i))
124
+ action(arr.get(i))
102
125
  }
103
126
 
104
- def foreach(arr: ByteArray){ action: (Byte) {Control} => Unit }: Unit =
127
+ def foreach(arr: ByteArray){ action: (Byte) {Label} => Unit }: Unit =
105
128
  each(0, arr.size) { (i) {label} =>
106
- action(arr.unsafeGet(i)) {label}
129
+ action(arr.get(i)) {label}
107
130
  }
108
131
 
109
132
  def foreachIndex(arr: ByteArray){ action: (Int, Byte) => Unit }: Unit =
110
133
  each(0, arr.size) { i =>
111
- action(i, arr.unsafeGet(i))
134
+ action(i, arr.get(i))
112
135
  }
113
136
 
114
- def foreachIndex(arr: ByteArray){ action: (Int, Byte) {Control} => Unit }: Unit =
137
+ def foreachIndex(arr: ByteArray){ action: (Int, Byte) {Label} => Unit }: Unit =
115
138
  each(0, arr.size) { (i) {label} =>
116
- action(i, arr.unsafeGet(i)) {label}
139
+ action(i, arr.get(i)) {label}
117
140
  }
118
141
 
119
142
  extern def fromString(str: String) at {}: ByteArray =
@@ -214,7 +237,7 @@ def each(bytes: ByteArray): Unit / emit[Byte] = {
214
237
  val n = bytes.size
215
238
  def go(i: Int): Unit = {
216
239
  if (i < n) {
217
- do emit(bytes.unsafeGet(i))
240
+ do emit(bytes.get(i))
218
241
  go(i + 1)
219
242
  }
220
243
  }
@@ -230,7 +253,7 @@ def feed[R](bytes: ByteArray) { reader: () => R / read[Byte] }: R = {
230
253
  if (i < bytes.size) {
231
254
  val c = i
232
255
  i = c + 1
233
- bytes.unsafeGet(c)
256
+ bytes.get(c)
234
257
  } else {
235
258
  do stop()
236
259
  }
@@ -249,7 +272,7 @@ namespace returning {
249
272
  (stream(), a.resize(i))
250
273
  } with emit[Byte] { (v) =>
251
274
  if (i >= a.size) { a = a.resize(2 * a.size) }
252
- a.unsafeSet(i, v)
275
+ a.set(i, v)
253
276
  i = i + 1
254
277
  resume(())
255
278
  }
@@ -0,0 +1,27 @@
1
+ module control
2
+
3
+ import effekt
4
+
5
+ interface Label {
6
+ def break(): Unit
7
+ def continue(): Unit
8
+ }
9
+
10
+ def loop { f: {Label} => Unit }: Unit = try {
11
+ def go(): Unit = { f {label}; go() }
12
+ go()
13
+ } with label: Label {
14
+ def break() = ()
15
+ def continue() = loop { f }
16
+ }
17
+
18
+ /// Calls provided action repeatedly with support for breaking. `start` is inclusive, `end` is not.
19
+ def each(start: Int, end: Int) { action: (Int) {Label} => Unit } = {
20
+ var i = start;
21
+ loop { {l} =>
22
+ if (i < end) { val el = i; i = i + 1; action(el){l} }
23
+ else { l.break() }
24
+ }
25
+ }
26
+
27
+ def repeat(n: Int) { action: () {Label} => Unit } = each(0, n) { (n) {l} => action() {l} }
@@ -0,0 +1,133 @@
1
+ module dictionary
2
+
3
+ import array
4
+ import bytearray
5
+ import stream
6
+
7
+
8
+ /// A trie-based dictionary for efficient key-value storage with bytearray keys.
9
+ /// Supports String and ByteArray keys with fast lookup and insertion.
10
+ type Dictionary[A] {
11
+ Empty()
12
+ Leaf(value: A)
13
+ Branch(children: Array[Dictionary[A]])
14
+ Node(value: A, children: Array[Dictionary[A]])
15
+ }
16
+
17
+ /// Insert a value with a String key.
18
+ def insert[A](trie: Dictionary[A], key: String, value: A): Dictionary[A] =
19
+ insert(trie, key.fromString, value)
20
+
21
+ /// Insert a key-value pair into the dictionary with a ByteArray key.
22
+ def insert[A](trie: Dictionary[A], key: ByteArray, value: A): Dictionary[A] = {
23
+ def go(trie: Dictionary[A], i: Int): Dictionary[A] =
24
+ if (i < key.size) {
25
+ trie match {
26
+ case Empty() =>
27
+ val child = go(Empty(), i + 1)
28
+ val children = array(256, Empty())
29
+ children.set(key.get(i).toInt, child)
30
+ Branch(children)
31
+ case Leaf(existing) =>
32
+ val child = go(Empty(), i + 1)
33
+ val children = array(256, Empty())
34
+ children.set(key.get(i).toInt, child)
35
+ Node(existing, children)
36
+ case Branch(children) =>
37
+ val child = go(children.get(key.get(i).toInt), i + 1)
38
+ children.set(key.get(i).toInt, child)
39
+ Branch(children)
40
+ case Node(existing, children) =>
41
+ val child = go(children.get(key.get(i).toInt), i + 1)
42
+ children.set(key.get(i).toInt, child)
43
+ Node(existing, children)
44
+ }
45
+ } else {
46
+ trie match {
47
+ case Empty() => Leaf(value)
48
+ case Leaf(_) => Leaf(value)
49
+ case Node(_, children) => Node(value, children)
50
+ case Branch(children) => Node(value, children)
51
+ }
52
+ }
53
+ go(trie, 0)
54
+ }
55
+
56
+ /// Look up a value in the dictionary by string key.
57
+ def lookup[A](trie: Dictionary[A], key: String): Option[A] =
58
+ lookup(trie, key.fromString)
59
+
60
+ /// Look up a value in the dictionary by bytearray key.
61
+ def lookup[A](trie: Dictionary[A], key: ByteArray): Option[A] = {
62
+ def go(trie: Dictionary[A], i: Int): Option[A] =
63
+ if (i < key.size) {
64
+ trie match {
65
+ case Empty() => None()
66
+ case Leaf(_) => None()
67
+ case Branch(children) => go(children.get(key.get(i).toInt), i + 1)
68
+ case Node(_, children) => go(children.get(key.get(i).toInt), i + 1)
69
+ }
70
+ } else {
71
+ trie match {
72
+ case Empty() => None()
73
+ case Leaf(value) => Some(value)
74
+ case Branch(_) => None()
75
+ case Node(value, _) => Some(value)
76
+ }
77
+ }
78
+ go(trie, 0)
79
+ }
80
+
81
+ /// A record pairing a key with a value for use in streams.
82
+ record Tagged[A](key: ByteArray, value: A)
83
+
84
+ /// Collect key-value pairs from a stream of Tagged elements into a Dictionary.
85
+ def collect[A] { stream: () => Unit / emit[Tagged[A]] }: Dictionary[A] = {
86
+ var trie = Empty()
87
+ for[Tagged[A]] { stream() } { case Tagged(bytes, value) =>
88
+ trie = trie.insert(bytes, value)
89
+ }
90
+ return trie
91
+ }
92
+
93
+ /// Emit all values stored in the dictionary as a push stream.
94
+ def each[A](trie: Dictionary[A]): Unit / emit[A] =
95
+ trie match {
96
+ case Empty() => ()
97
+ case Leaf(value) => do emit(value)
98
+ case Branch(children) =>
99
+ each(0, children.size) { i =>
100
+ each(children.get(i))
101
+ }
102
+ case Node(value, children) =>
103
+ do emit(value)
104
+ each(0, children.size) { i =>
105
+ each(children.get(i))
106
+ }
107
+ }
108
+
109
+ /// Emit all key-value pairs stored in the dictionary as a push stream of Tagged elements.
110
+ def eachTagged[A](trie: Dictionary[A]): Unit / emit[Tagged[A]] = {
111
+ def fromBytesReverse(bytes: List[Byte], n: Int): ByteArray = {
112
+ val key = bytearray::allocate(n)
113
+ foreachIndex(bytes) { (i, b) => key.set(n - 1 - i, b) }
114
+ key
115
+ }
116
+ def go(trie: Dictionary[A], key: List[Byte], n: Int): Unit =
117
+ trie match {
118
+ case Empty() => ()
119
+ case Leaf(value) => do emit(Tagged(fromBytesReverse(key, n), value))
120
+ case Branch(children) =>
121
+ each(0, children.size) { i =>
122
+ go(children.get(i), Cons(i.toByte, key), n + 1)
123
+ }
124
+ case Node(value, children) =>
125
+ do emit(Tagged(fromBytesReverse(key, n), value))
126
+ each(0, children.size) { i =>
127
+ go(children.get(i), Cons(i.toByte, key), n + 1)
128
+ }
129
+ }
130
+ go(trie, Nil(), 0)
131
+ }
132
+
133
+
@@ -732,23 +732,37 @@ type OneOrBoth[A, B] {
732
732
 
733
733
  // Control Flow
734
734
  // ============
735
- interface Control {
736
- def break(): Unit
737
- def continue(): Unit
738
- }
739
735
 
740
- def loop { f: () => Unit }: Unit = {
741
- def go(): Unit = { f(); go() }
736
+ /// Repeat `action` forever
737
+ def forever { action: () => Unit }: Nothing = {
738
+ def go(): Nothing = { action(); go() }
742
739
  go()
743
740
  }
744
741
 
745
- def loop { f: {Control} => Unit }: Unit = try {
746
- def go(): Unit = { f {label}; go() }
747
- go()
748
- } with label: Control {
749
- def break() = ()
750
- def continue() = loop { f }
751
- }
742
+ /// Signal that we should stop.
743
+ effect stop(): Nothing
744
+
745
+ /// When the program stops, then to here.
746
+ def boundary { program: () => Unit / stop }: Unit =
747
+ try { program() } with stop { () }
748
+
749
+ /// Repeat `action` until `stop` is thrown.
750
+ def loop { action: () => Unit / stop }: Unit =
751
+ try {
752
+ def go(): Unit = { action(); go() }
753
+ go()
754
+ } with stop {
755
+ ()
756
+ }
757
+
758
+ /// Repeat `action` until `stop` is thrown, supplying the iteration count.
759
+ def loop { action: Int => Unit / stop }: Unit =
760
+ try {
761
+ def go(i: Int): Unit = { action(i); go(i + 1) }
762
+ go(0)
763
+ } with stop {
764
+ ()
765
+ }
752
766
 
753
767
  /// Calls provided action repeatedly. `start` is inclusive, `end` is not.
754
768
  def each(start: Int, end: Int) { action: (Int) => Unit } = {
@@ -758,19 +772,8 @@ def each(start: Int, end: Int) { action: (Int) => Unit } = {
758
772
  loop(start)
759
773
  }
760
774
 
761
- /// Calls provided action repeatedly with support for breaking. `start` is inclusive, `end` is not.
762
- def each(start: Int, end: Int) { action: (Int) {Control} => Unit } = {
763
- var i = start;
764
- loop { {l} =>
765
- if (i < end) { val el = i; i = i + 1; action(el){l} }
766
- else { l.break() }
767
- }
768
- }
769
-
770
775
  def repeat(n: Int) { action: () => Unit } = each(0, n) { n => action() }
771
776
 
772
- def repeat(n: Int) { action: () {Control} => Unit } = each(0, n) { (n) {l} => action() {l} }
773
-
774
777
  // NOTE: This is emitted by the close hole code action: do not remove unless you also adjust the code action
775
778
  /// Scopes a local computation
776
779
  def locally[R] { p: => R } : R = p()
@@ -23,8 +23,8 @@ namespace internal {
23
23
  arr.boundsCheck(idx) // idx > parent(idx), parent(parent(idx)) etc
24
24
 
25
25
  def go(idx: Int): Unit = {
26
- if (idx > 0 and (heap.cmp)(arr.unsafeGet(parent(idx)), arr.unsafeGet(idx)) is Greater()) {
27
- arr.unsafeSwap(parent(idx), idx)
26
+ if (idx > 0 and (heap.cmp)(arr.get(parent(idx)), arr.get(idx)) is Greater()) {
27
+ arr.swap(parent(idx), idx)
28
28
  go(parent(idx))
29
29
  }
30
30
  }
@@ -39,28 +39,28 @@ namespace internal {
39
39
 
40
40
  def go(idx: Int): Unit = {
41
41
  if (right(idx) < arr.size) {
42
- val v = arr.unsafeGet(idx)
43
- val l = arr.unsafeGet(left(idx))
44
- val r = arr.unsafeGet(right(idx))
42
+ val v = arr.get(idx)
43
+ val l = arr.get(left(idx))
44
+ val r = arr.get(right(idx))
45
45
  if (l < v && r < v) {
46
46
  // swap with the smaller one
47
47
  if (l < r) {
48
- arr.unsafeSwap(left(idx), idx)
48
+ arr.swap(left(idx), idx)
49
49
  go(left(idx))
50
50
  } else {
51
- arr.unsafeSwap(right(idx), idx)
51
+ arr.swap(right(idx), idx)
52
52
  go(right(idx))
53
53
  }
54
54
  } else if (l < v) {
55
- arr.unsafeSwap(left(idx), idx)
55
+ arr.swap(left(idx), idx)
56
56
  go(left(idx))
57
57
  } else if (r < v) {
58
- arr.unsafeSwap(right(idx), idx)
58
+ arr.swap(right(idx), idx)
59
59
  go(right(idx))
60
60
  }
61
61
  } else if (left(idx) < arr.size) {
62
- if (arr.unsafeGet(left(idx)) < arr.unsafeGet(idx)) {
63
- arr.unsafeSwap(left(idx), idx)
62
+ if (arr.get(left(idx)) < arr.get(idx)) {
63
+ arr.swap(left(idx), idx)
64
64
  go(left(idx))
65
65
  }
66
66
  } // else: we are at the bottom
@@ -79,6 +79,7 @@ def insert[T](heap: Heap[T], value: T): Unit = {
79
79
  }
80
80
 
81
81
  /// find and return (but not remove) the minimal element in this heap
82
+ /// panics when heap is empty
82
83
  ///
83
84
  /// O(1)
84
85
  def findMin[T](heap: Heap[T]): T / Exception[OutOfBounds] = {
@@ -86,13 +87,20 @@ def findMin[T](heap: Heap[T]): T / Exception[OutOfBounds] = {
86
87
  }
87
88
 
88
89
  /// find and remove the minimal element in this heap
90
+ /// panics when heap is empty
89
91
  ///
90
92
  /// O(log n)
91
93
  def deleteMin[T](heap: Heap[T]): T / Exception[OutOfBounds] = {
92
- val res = heap.rawContents.get(0)
93
- heap.rawContents.unsafeSet(0, heap.rawContents.popRight())
94
- internal::sinkDown(heap, 0)
95
- res
94
+ val arr = heap.rawContents
95
+ val res = arr.get(0)
96
+ if (arr.size == 1) {
97
+ arr.popRight()
98
+ res
99
+ } else {
100
+ arr.set(0, arr.popRight())
101
+ internal::sinkDown(heap, 0)
102
+ res
103
+ }
96
104
  }
97
105
 
98
106
  /// Number of elements in the heap
@@ -102,7 +102,7 @@ def writeFile[R](path: String) { stream: () => R / emit[Byte] }: R / Exception[I
102
102
  push(0, buffer.size)
103
103
  offset = 0
104
104
  }
105
- buffer.unsafeSet(offset, byte)
105
+ buffer.set(offset, byte)
106
106
  offset = offset + 1
107
107
  resume(())
108
108
  }
@@ -135,7 +135,7 @@ def readFile[R](path: String) { reader: () => R / read[Byte] }: R / Exception[IO
135
135
  pull()
136
136
  offset = 0
137
137
  }
138
- val byte = buffer.unsafeGet(offset)
138
+ val byte = buffer.get(offset)
139
139
  offset = offset + 1
140
140
  return byte
141
141
  }
@@ -25,12 +25,12 @@ def handleJsonBuilder[R]{b: JsonBuilder}{ body: => R / JsonBuilder }: R = try bo
25
25
  def bool(v) = resume(b.bool(v))
26
26
  def number(n) = resume(b.number(n))
27
27
  def string(s) = resume(b.string(s))
28
- def list() = resume { {c} => b.list{c} }
29
- def dict() = resume { {c} => b.dict{c} }
28
+ def list[T]() = resume { {c} => b.list{c} }
29
+ def dict[T]() = resume { {c} => b.dict{c} }
30
30
  }
31
31
  /// Make explicitly bound JsonObjectBuilder instance implicit
32
32
  def handleJsonObjectBuilder[R]{b: JsonObjectBuilder}{ body: => R / JsonObjectBuilder }: R = try body() with JsonObjectBuilder {
33
- def field(k) = resume { {c} => b.field(k){c} }
33
+ def field[T](k) = resume { {c} => b.field(k){c} }
34
34
  }
35
35
 
36
36
  // --------------------------------------------------------------------------------
@@ -49,8 +49,8 @@ def encodeJsonList[R]{ body: => R / JsonBuilder }: R / emit[String] = {
49
49
  def bool(v) = { c(); resume(do bool(v)) }
50
50
  def number(n) = { c(); resume(do number(n)) }
51
51
  def string(s) = { c(); resume(do string(s)) }
52
- def list() = resume { { b } => c(); do list{b} }
53
- def dict() = resume { { b } => c(); do dict{b} }
52
+ def list[T]() = resume { { b } => c(); do list{b} }
53
+ def dict[T]() = resume { { b } => c(); do dict{b} }
54
54
  }
55
55
  }
56
56
  do emit("]")
@@ -66,7 +66,7 @@ def encodeJsonObject[R]{ body: => R / JsonObjectBuilder }: R / emit[String] = {
66
66
  }
67
67
  val r = encodeJson {
68
68
  try body() with JsonObjectBuilder {
69
- def field(k) = resume { {b} => c(k); b() }
69
+ def field[T](k) = resume { {b} => c(k); b() }
70
70
  }
71
71
  }
72
72
  do emit("}")
@@ -80,8 +80,8 @@ def encodeJson[R]{ body: => R / JsonBuilder }: R / emit[String] = {
80
80
  def bool(v) = { resume(do emit( if(v){ "true" } else { "false" } )) }
81
81
  def number(n) = { resume(do emit(show(n))) }
82
82
  def string(s) = { resume(do emit(escape(s))) }
83
- def list() = resume { {b} => encodeJsonList { b() } }
84
- def dict() = resume { {b} => encodeJsonObject { b() } }
83
+ def list[T]() = resume { {b} => encodeJsonList { b() } }
84
+ def dict[T]() = resume { {b} => encodeJsonObject { b() } }
85
85
  }
86
86
  }
87
87
 
@@ -209,7 +209,7 @@ def decodeJsonList(): Unit / {Scan[Char], JsonBuilder, Exception[WrongFormat]} =
209
209
  // --------------------------------------------------------------------------------
210
210
  /// Ignore the generated calls to JsonObjectBuilder
211
211
  def ignoreDict[R](){ body: => R / JsonObjectBuilder }: R = try body() with JsonObjectBuilder {
212
- def field(k) = resume { {v} => ignore{v} }
212
+ def field[T](k) = resume { {v} => ignore{v} }
213
213
  }
214
214
 
215
215
  /// Ignore the generated calls to JsonBuilder
@@ -218,8 +218,8 @@ def ignore[R](){ body: => R / JsonBuilder }: R = try body() with JsonBuilder {
218
218
  def bool(b) = resume(())
219
219
  def null() = resume(())
220
220
  def string(s) = resume(())
221
- def list() = resume { {e} => ignore{e} }
222
- def dict() = resume { {e} => ignoreDict{e} }
221
+ def list[T]() = resume { {e} => ignore{e} }
222
+ def dict[T]() = resume { {e} => ignoreDict{e} }
223
223
  }
224
224
 
225
225
  // --------------------------------------------------------------------------------
@@ -264,12 +264,12 @@ def build[R](){ body: => R / JsonBuilder }: (R, JsonValue) = {
264
264
  def bool(b) = { r = Bool(b); resume(()) }
265
265
  def null() = { r = Null(); resume(()) }
266
266
  def string(s) = { r = String(s); resume(()) }
267
- def list() = resume { {els} =>
267
+ def list[T]() = resume { {els} =>
268
268
  val x = buildList {els}
269
269
  r = List(x.second)
270
270
  x.first
271
271
  }
272
- def dict() = resume { {fs} =>
272
+ def dict[T]() = resume { {fs} =>
273
273
  val x = buildDict {fs}
274
274
  r = Dict(x.second)
275
275
  x.first
@@ -283,12 +283,12 @@ def buildList[R](){ body: => R / JsonBuilder }: (R, List[JsonValue]) = list::ret
283
283
  def bool(b) = { do emit(Bool(b)); resume(()) }
284
284
  def null() = { do emit(Null()); resume(()) }
285
285
  def string(s) = { do emit(String(s)); resume(()) }
286
- def list() = resume { {els} =>
286
+ def list[T]() = resume { {els} =>
287
287
  val x = buildList {els}
288
288
  do emit(List(x.second))
289
289
  x.first
290
290
  }
291
- def dict() = resume { {fs} =>
291
+ def dict[T]() = resume { {fs} =>
292
292
  val x = buildDict {fs}
293
293
  do emit(Dict(x.second))
294
294
  x.first
@@ -297,7 +297,7 @@ def buildList[R](){ body: => R / JsonBuilder }: (R, List[JsonValue]) = list::ret
297
297
  }
298
298
  def buildDict[R](){ body: => R / JsonObjectBuilder }: (R, List[(String, JsonValue)]) = list::returning::collect[(String, JsonValue), R] {
299
299
  try body() with JsonObjectBuilder {
300
- def field(k) = resume { {v} =>
300
+ def field[T](k) = resume { {v} =>
301
301
  val x = build{v}
302
302
  do emit((k, x.second))
303
303
  x.first
@@ -325,7 +325,7 @@ namespace test {
325
325
  with scanner[Char]
326
326
 
327
327
  def k = new JsonObjectBuilder {
328
- def field(k){v} = { println(k); ignore{v} }
328
+ def field[T](k){v} = { println(k); ignore{v} }
329
329
  }
330
330
  def jsonBuilder[R] {e: => R / JsonBuilder}: R = {
331
331
  def d = new JsonBuilder {
@@ -333,8 +333,8 @@ namespace test {
333
333
  def bool(b) = ()
334
334
  def null() = println("NULL")
335
335
  def string(s) = ()
336
- def list(){e} = jsonBuilder{e}
337
- def dict(){e} = handleJsonObjectBuilder{k}{e}
336
+ def list[T](){e} = jsonBuilder{e}
337
+ def dict[T](){e} = handleJsonObjectBuilder{k}{e}
338
338
  }
339
339
  handleJsonBuilder{d}{e}
340
340
  }
@@ -2,8 +2,9 @@ module list
2
2
 
3
3
  import effekt
4
4
  import option
5
- import exception
5
+ import control
6
6
  import stream
7
+ import exception
7
8
 
8
9
  /// Immutable linked list for finite sequences of elements.
9
10
  type List[A] {
@@ -123,7 +124,7 @@ def foreach[A](l: List[A]) { f: (A) => Unit } : Unit = l match {
123
124
  /// Traverse a list, applying the given action on every element.
124
125
  ///
125
126
  /// O(N)
126
- def foreach[A](l: List[A]) { f: (A) {Control} => Unit } : Unit = {
127
+ def foreach[A](l: List[A]) { f: (A) {Label} => Unit } : Unit = {
127
128
  var remainder = l
128
129
  loop { {label} =>
129
130
  remainder match {
@@ -151,7 +152,7 @@ def foreachIndex[A](list: List[A]){ f: (Int, A) => Unit }: Unit = {
151
152
  /// Traverse a list, applying the given action on every element and its (zero-based) index.
152
153
  ///
153
154
  /// O(N)
154
- def foreachIndex[A](list: List[A]){ f: (Int, A) {Control} => Unit }: Unit = {
155
+ def foreachIndex[A](list: List[A]){ f: (Int, A) {Label} => Unit }: Unit = {
155
156
  var remainder = list
156
157
  var i = -1
157
158
  loop { {label} =>
@@ -37,7 +37,7 @@ def foreach[A](self: Option[A]) { f: A => Unit }: Unit = self match {
37
37
  }
38
38
 
39
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")
40
+ case None() => do raise(MissingValue(), "Trying to get the value of an empty option") match {}
41
41
  case Some(v) => v
42
42
  }
43
43
 
@@ -49,7 +49,7 @@ def emptyQueue[T](initialCapacity: Int): Queue[T] at global = {
49
49
  val oldSize = capacity.get
50
50
  val newSize = capacity.get * 2
51
51
  val oldContents = contents.get
52
- val newContents = array::allocate[Option[T]](newSize)
52
+ val newContents = array[Option[T]](newSize, None())
53
53
 
54
54
  if (head.get < tail.get) {
55
55
  // The queue does not wrap around; direct copy is possible.
@@ -93,12 +93,12 @@ def emptyQueue[T](initialCapacity: Int): Queue[T] at global = {
93
93
  resizeTo(size.get + 1)
94
94
  head.set(mod(head.get - 1 + capacity.get, capacity.get))
95
95
  size.set(size.get + 1)
96
- contents.get.unsafeSet(head.get, Some(el))
96
+ contents.get.set(head.get, Some(el))
97
97
  }
98
98
 
99
99
  def pushBack(el: T) = {
100
100
  resizeTo(size.get + 1)
101
- contents.get.unsafeSet(tail.get, Some(el))
101
+ contents.get.set(tail.get, Some(el))
102
102
  size.set(size.get + 1)
103
103
  tail.set(mod(tail.get + 1, capacity.get))
104
104
  }
@@ -170,7 +170,7 @@ def main() = {
170
170
  val b = randomInt(0, 9)
171
171
  val c = randomInt(0, 9)
172
172
  println(a.show ++ " " ++ b.show ++ " " ++ c.show)
173
- println(a*100 + b*10 + c)
173
+ println(a * 100 + b * 10 + c)
174
174
  }
175
175
  }
176
176