@effekt-lang/effekt 0.4.0 → 0.6.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/bin/effekt CHANGED
Binary file
@@ -4,15 +4,11 @@ import effekt
4
4
  import exception
5
5
  import list
6
6
 
7
- /**
8
- * A mutable 0-indexed fixed-sized array.
9
- */
7
+ /// A mutable 0-indexed fixed-sized array.
10
8
  extern type Array[T]
11
9
 
12
- /**
13
- * Allocates a new array of size `size`, keeping its values _undefined_.
14
- * Prefer using `array` constructor instead to ensure that values are defined.
15
- */
10
+ /// Allocates a new array of size `size`, keeping its values _undefined_.
11
+ /// Prefer using `array` constructor instead to ensure that values are defined.
16
12
  extern global def allocate[T](size: Int): Array[T] =
17
13
  js "(new Array(${size}))"
18
14
  chez "(make-vector ${size})" // creates an array filled with 0s on CS
@@ -21,9 +17,7 @@ extern global def allocate[T](size: Int): Array[T] =
21
17
  ret %Pos %z
22
18
  """
23
19
 
24
- /**
25
- * Creates a new Array of size `size` filled with the value `init`
26
- */
20
+ /// Creates a new Array of size `size` filled with the value `init`
27
21
  def array[T](size: Int, init: T): Array[T] = {
28
22
  val arr = allocate[T](size);
29
23
  each(0, size) { i =>
@@ -32,9 +26,7 @@ def array[T](size: Int, init: T): Array[T] = {
32
26
  arr
33
27
  }
34
28
 
35
- /**
36
- * Converts a List `list` to an Array
37
- */
29
+ /// Converts a List `list` to an Array
38
30
  def fromList[T](list: List[T]): Array[T] = {
39
31
  val listSize = list.size();
40
32
  val arr = allocate(listSize);
@@ -45,9 +37,7 @@ def fromList[T](list: List[T]): Array[T] = {
45
37
  return arr;
46
38
  }
47
39
 
48
- /**
49
- * Gets the length of the array in constant time.
50
- */
40
+ /// Gets the length of the array in constant time.
51
41
  extern pure def size[T](arr: Array[T]): Int =
52
42
  js "${arr}.length"
53
43
  chez "(vector-length ${arr})"
@@ -56,12 +46,10 @@ extern pure def size[T](arr: Array[T]): Int =
56
46
  ret %Int %z
57
47
  """
58
48
 
59
- /**
60
- * Gets the element of the `arr` at given `index` in constant time.
61
- * Unchecked Precondition: `index` is in bounds (0 ≤ index < arr.size)
62
- *
63
- * Prefer using `get` instead.
64
- */
49
+ /// Gets the element of the `arr` at given `index` in constant time.
50
+ /// Unchecked Precondition: `index` is in bounds (0 ≤ index < arr.size)
51
+ ///
52
+ /// Prefer using `get` instead.
65
53
  extern global def unsafeGet[T](arr: Array[T], index: Int): T =
66
54
  js "${arr}[${index}]"
67
55
  chez "(vector-ref ${arr} ${index})"
@@ -77,12 +65,10 @@ extern js """
77
65
  }
78
66
  """
79
67
 
80
- /**
81
- * Sets the element of the `arr` at given `index` to `value` in constant time.
82
- * Unchecked Precondition: `index` is in bounds (0 ≤ index < arr.size)
83
- *
84
- * Prefer using `set` instead.
85
- */
68
+ /// Sets the element of the `arr` at given `index` to `value` in constant time.
69
+ /// Unchecked Precondition: `index` is in bounds (0 ≤ index < arr.size)
70
+ ///
71
+ /// Prefer using `set` instead.
86
72
  extern global def unsafeSet[T](arr: Array[T], index: Int, value: T): Unit =
87
73
  js "array$set(${arr}, ${index}, ${value})"
88
74
  chez "(begin (vector-set! ${arr} ${index} ${value}) #f)"
@@ -91,9 +77,7 @@ extern global def unsafeSet[T](arr: Array[T], index: Int, value: T): Unit =
91
77
  ret %Pos %z
92
78
  """
93
79
 
94
- /**
95
- * Creates a copy of `arr`
96
- */
80
+ /// Creates a copy of `arr`
97
81
  def copy[T](arr: Array[T]): Array[T] = {
98
82
  with on[OutOfBounds].default { <> }; // should not happen
99
83
  val len = arr.size;
@@ -102,10 +86,8 @@ def copy[T](arr: Array[T]): Array[T] = {
102
86
  newArray
103
87
  }
104
88
 
105
- /**
106
- * Copies `length`-many elements from `from` to `to`
107
- * starting at `start` (in `from`) and `offset` (in `to`)
108
- */
89
+ /// Copies `length`-many elements from `from` to `to`
90
+ /// starting at `start` (in `from`) and `offset` (in `to`)
109
91
  def copy[T](from: Array[T], start: Int, to: Array[T], offset: Int, length: Int): Unit / Exception[OutOfBounds] = {
110
92
  val startValid = start >= 0 && start + length <= from.size
111
93
  val offsetValid = offset >= 0 && offset + length <= to.size
@@ -122,26 +104,20 @@ def copy[T](from: Array[T], start: Int, to: Array[T], offset: Int, length: Int):
122
104
 
123
105
  // Derived operations:
124
106
 
125
- /**
126
- * Gets the element of the `arr` at given `index` in constant time,
127
- * throwing an `Exception[OutOfBounds]` unless `0 ≤ index < arr.size`.
128
- */
107
+ /// Gets the element of the `arr` at given `index` in constant time,
108
+ /// throwing an `Exception[OutOfBounds]` unless `0 ≤ index < arr.size`.
129
109
  def get[T](arr: Array[T], index: Int): T / Exception[OutOfBounds] =
130
110
  if (index >= 0 && index < arr.size) arr.unsafeGet(index)
131
111
  else do raise(OutOfBounds(), "Array index out of bounds: " ++ show(index))
132
112
 
133
- /**
134
- * Sets the element of the `arr` at given `index` to `value` in constant time,
135
- * throwing an `Exception[OutOfBounds]` unless `0 ≤ index < arr.size`.
136
- */
113
+ /// Sets the element of the `arr` at given `index` to `value` in constant time,
114
+ /// throwing an `Exception[OutOfBounds]` unless `0 ≤ index < arr.size`.
137
115
  def set[T](arr: Array[T], index: Int, value: T): Unit / Exception[OutOfBounds] =
138
116
  if (index >= 0 && index < arr.size) unsafeSet(arr, index, value)
139
117
  else do raise(OutOfBounds(), "Array index out of bounds: " ++ show(index))
140
118
 
141
- /**
142
- * Builds a new Array of size `size` from a computation `index` which gets an index
143
- * and returns a value that will be on that position in the resulting array
144
- */
119
+ /// Builds a new Array of size `size` from a computation `index` which gets an index
120
+ /// and returns a value that will be on that position in the resulting array
145
121
  def build[T](size: Int) { index: Int => T }: Array[T] = {
146
122
  val arr = allocate[T](size);
147
123
  each(0, size) { i =>
@@ -2,13 +2,11 @@ module bench
2
2
 
3
3
  type Nanos = Int
4
4
 
5
- /**
6
- * The current time (since UNIX Epoch) in nanoseconds.
7
- *
8
- * The actual precision varies across the different backends.
9
- * - js: Milliseconds
10
- * - chez: Microseconds
11
- */
5
+ /// The current time (since UNIX Epoch) in nanoseconds.
6
+ ///
7
+ /// The actual precision varies across the different backends.
8
+ /// - js: Milliseconds
9
+ /// - chez: Microseconds
12
10
  extern io def timestamp(): Nanos =
13
11
  js "Date.now() * 1000000"
14
12
  chez "(timestamp)"
@@ -32,12 +30,10 @@ extern jsNode """
32
30
  const { performance } = require('node:perf_hooks');
33
31
  """
34
32
 
35
- /**
36
- * High-precision timestamp in nanoseconds that should be for measurements.
37
- *
38
- * This timestamp should only be used for **relative** measurements,
39
- * as gives no guarantees on the absolute time (unlike a UNIX timestamp).
40
- */
33
+ /// High-precision timestamp in nanoseconds that should be for measurements.
34
+ ///
35
+ /// This timestamp should only be used for **relative** measurements,
36
+ /// as gives no guarantees on the absolute time (unlike a UNIX timestamp).
41
37
  extern io def relativeTimestamp(): Nanos =
42
38
  js "Math.round(performance.now() * 1000000)"
43
39
  default { timestamp() }
@@ -48,9 +44,7 @@ namespace Duration {
48
44
  def diff(fromNanos: Nanos, toNanos: Nanos): Duration = toNanos - fromNanos
49
45
  }
50
46
 
51
- /**
52
- * Runs the block and returns the time in nanoseconds
53
- */
47
+ /// Runs the block and returns the time in nanoseconds
54
48
  def timed { block: => Unit }: Duration = {
55
49
  val before = relativeTimestamp()
56
50
  block()
@@ -70,9 +64,7 @@ def measure(warmup: Int, iterations: Int) { block: => Unit }: Unit = {
70
64
  run(iterations, true)
71
65
  }
72
66
 
73
- /**
74
- * Takes a duration in nanoseconds and formats it in milliseconds with precision of two decimal digits.
75
- */
67
+ /// Takes a duration in nanoseconds and formats it in milliseconds with precision of two decimal digits.
76
68
  def formatMs(nanos: Nanos): String = {
77
69
  val micros = nanos / 1000000
78
70
  val sub = (nanos.mod(1000000).toDouble / 10000.0).round
@@ -9,34 +9,22 @@ import array
9
9
 
10
10
  record BufferOverflow()
11
11
 
12
- /**
13
- * Fixed-size ring buffers (queues) where one can write
14
- * elements to the head and read from the tail.
15
- */
12
+ /// Fixed-size ring buffers (queues) where one can write
13
+ /// elements to the head and read from the tail.
16
14
  interface Buffer[T] {
17
- /**
18
- * The remaining capacity
19
- */
15
+ /// The remaining capacity
20
16
  def capacity(): Int
21
17
 
22
- /**
23
- * Is this buffer full?
24
- */
18
+ /// Is this buffer full?
25
19
  def full?(): Bool
26
20
 
27
- /**
28
- * Is this buffer empty?
29
- */
21
+ /// Is this buffer empty?
30
22
  def empty?(): Bool
31
23
 
32
- /**
33
- * Read an element from the tail of the buffer
34
- */
24
+ /// Read an element from the tail of the buffer
35
25
  def read(): Option[T]
36
26
 
37
- /**
38
- * Write an element to the head of the buffer
39
- */
27
+ /// Write an element to the head of the buffer
40
28
  def write(el: T): Unit / Exception[BufferOverflow]
41
29
  }
42
30
 
@@ -120,4 +108,4 @@ namespace examples {
120
108
  println(ringbuffer.read());
121
109
  println(ringbuffer.read());
122
110
  }
123
- }
111
+ }
@@ -1,15 +1,11 @@
1
1
  module bytes
2
2
 
3
- /**
4
- * A memory managed, mutable, fixed-length buffer of bytes.
5
- */
3
+ /// A memory managed, mutable, fixed-length buffer of bytes.
6
4
  extern type Bytes
7
5
  // = llvm "%Pos"
8
6
  // = js "Uint8Array"
9
7
 
10
- /**
11
- * Allocates new bytes with the given `capacity`, setting its values to `0`.
12
- */
8
+ /// Allocates new bytes with the given `capacity`, setting its values to `0`.
13
9
  extern io def bytes(capacity: Int): Bytes =
14
10
  js "(new Uint8Array(${capacity}))"
15
11
  llvm """
@@ -55,9 +51,7 @@ extern io def write(b: Bytes, index: Int, value: Byte): Unit =
55
51
  ret %Pos zeroinitializer
56
52
  """
57
53
 
58
- /**
59
- * Returns an *aliased* slice of b starting at offset with the given length
60
- */
54
+ /// Returns an *aliased* slice of b starting at offset with the given length
61
55
  def slice(b: Bytes, offset: Int, length: Int): Bytes = {
62
56
  def validOffset() = offset >= 0 && offset < b.size
63
57
  def validLength() = length >= 0 && (offset + length) <= b.size
@@ -66,9 +60,7 @@ def slice(b: Bytes, offset: Int, length: Int): Bytes = {
66
60
  }
67
61
 
68
62
 
69
- /**
70
- * Returns a view into the buffer, with the length truncated to n
71
- */
63
+ /// Returns a view into the buffer, with the length truncated to n
72
64
  def truncated(b: Bytes, n: Int): Bytes =
73
65
  b.slice(0, n)
74
66
 
@@ -88,9 +80,7 @@ extern pure def toUTF8(b: Bytes): String =
88
80
  """
89
81
 
90
82
  namespace unsafe {
91
- /**
92
- * Unsafe: offset and length are not checked.
93
- */
83
+ /// Unsafe: offset and length are not checked.
94
84
  extern io def slice(b: Bytes, offset: Int, length: Int): Bytes =
95
85
  js "new Uint8Array(${b}.buffer, ${offset}, ${length})"
96
86
  llvm """
@@ -1,11 +1,11 @@
1
1
  module dequeue
2
2
 
3
3
 
4
- // An implementation of a functional dequeue, using Okasaki's
5
- // bankers dequeue implementation.
6
- //
7
- // Translation from the Haskell implementation:
8
- // https://hackage.haskell.org/package/dequeue-0.1.12/docs/src/Data-Dequeue.html#Dequeue
4
+ /// An implementation of a functional dequeue, using Okasaki's
5
+ /// bankers dequeue implementation.
6
+ ///
7
+ /// Translation from the Haskell implementation:
8
+ /// https://hackage.haskell.org/package/dequeue-0.1.12/docs/src/Data-Dequeue.html#Dequeue
9
9
  record Dequeue[R](front: List[R], frontSize: Int, rear: List[R], rearSize: Int)
10
10
 
11
11
  def emptyQueue[R](): Dequeue[R] = Dequeue(Nil(), 0, Nil(), 0)
@@ -144,13 +144,12 @@ extern io def random(): Double =
144
144
 
145
145
  // Equality
146
146
  // ========
147
- /**
148
- * Result of comparison between two objects according to some order:
149
- *
150
- * - `Less()` means that the first object is *before* the first in the order,
151
- * - `Equal()` means that the two objects are the same in the order,
152
- * - and `Greater()` means that the second object is *before* the first in the order.
153
- */
147
+
148
+ /// Result of comparison between two objects according to some order:
149
+ ///
150
+ /// - `Less()` means that the first object is *before* the first in the order,
151
+ /// - `Equal()` means that the two objects are the same in the order,
152
+ /// - and `Greater()` means that the second object is *before* the first in the order.
154
153
  type Ordering {
155
154
  Less();
156
155
  Equal();
@@ -160,7 +159,8 @@ type Ordering {
160
159
  extern pure def genericCompareImpl[R](x: R, y: R): Int =
161
160
  js "$effekt.compare(${x}, ${y})"
162
161
 
163
- // Compares two values of the same type, returning an `Ordering`.
162
+ /// Compares two values of the same type, returning an `Ordering`.
163
+ /// Only available on the JavaScript backend.
164
164
  def genericCompare[R](x: R, y: R): Ordering = {
165
165
  genericCompareImpl(x, y) match {
166
166
  case -1 => Less()
@@ -182,9 +182,7 @@ def println(o: Ordering): Unit = println(o.show)
182
182
  // Comparison ops
183
183
  // ==============
184
184
 
185
- /**
186
- * Structural equality: Not available in the LLVM backend
187
- */
185
+ /// Structural equality: Not available in the LLVM backend
188
186
  extern pure def equals[R](x: R, y: R): Bool =
189
187
  js "$effekt.equals(${x}, ${y})"
190
188
  chez "(equal? ${x} ${y})"
@@ -550,11 +548,19 @@ def infixAnd { first: => Bool } { second: => Bool }: Bool =
550
548
 
551
549
  // Bitwise operations
552
550
  // ==================
551
+
552
+ /// Arithmetic left shift
553
553
  extern pure def bitwiseShl(x: Int, y: Int): Int =
554
554
  js "(${x} << ${y})"
555
555
  chez "(ash ${x} ${y})"
556
556
  llvm "%z = shl %Int ${x}, ${y} ret %Int %z"
557
557
 
558
+ /// Arithmetic right shift
559
+ extern pure def bitwiseShr(x: Int, y: Int): Int =
560
+ js "(${x} >> ${y})"
561
+ chez "(ash ${x} (- ${y}))"
562
+ llvm "%z = ashr %Int ${x}, ${y} ret %Int %z"
563
+
558
564
  extern pure def bitwiseAnd(x: Int, y: Int): Int =
559
565
  js "(${x} & ${y})"
560
566
  chez "(logand ${x} ${y})"
@@ -586,16 +592,12 @@ extern pure def toInt(n: Byte): Int =
586
592
  // chez: #f
587
593
  // llvm: null?
588
594
 
589
- /**
590
- * The value used by the FFI to represent undefined values
591
- */
595
+ /// The value used by the FFI to represent undefined values
592
596
  extern pure def undefined[A](): A =
593
597
  js "undefined"
594
598
  chez "#f"
595
599
 
596
- /**
597
- * Is an FFI value undefined?
598
- */
600
+ /// Is an FFI value undefined?
599
601
  extern pure def isUndefined[A](value: A): Bool =
600
602
  js "(${value} === undefined || ${value} === null)"
601
603
  chez "(eq? ${value} #f)"
@@ -630,9 +632,7 @@ def loop { f: {Control} => Unit }: Unit = try {
630
632
  def continue() = loop { f }
631
633
  }
632
634
 
633
- /**
634
- * Calls provided action repeatedly. `start` is inclusive, `end` is not.
635
- */
635
+ /// Calls provided action repeatedly. `start` is inclusive, `end` is not.
636
636
  def each(start: Int, end: Int) { action: (Int) => Unit } = {
637
637
  def loop(i: Int): Unit =
638
638
  if (i < end) { action(i); loop(i + 1) }
@@ -640,9 +640,7 @@ def each(start: Int, end: Int) { action: (Int) => Unit } = {
640
640
  loop(start)
641
641
  }
642
642
 
643
- /**
644
- * Calls provided action repeatedly with support for breaking. `start` is inclusive, `end` is not.
645
- */
643
+ /// Calls provided action repeatedly with support for breaking. `start` is inclusive, `end` is not.
646
644
  def each(start: Int, end: Int) { action: (Int) {Control} => Unit } = {
647
645
  var i = start;
648
646
  loop { {l} =>
@@ -7,9 +7,7 @@ interface Console {
7
7
  def writeLine(content: String): Unit
8
8
  }
9
9
 
10
- /**
11
- * Handler for the console effect, using the Console available in js
12
- */
10
+ /// Handler for the console effect, using the Console available in js
13
11
  def console[R] { program: () => R / Console }: R = {
14
12
  val c = js::newConsole()
15
13
  try {
@@ -40,8 +38,7 @@ namespace js {
40
38
  jsNode "${console}.close()"
41
39
 
42
40
  extern async def readLine(console: JSConsole): String =
43
- jsNode "$effekt.callcc(callback => ${console}.once('line', callback))"
44
-
41
+ jsNode "$effekt.capture(k => ${console}.once('line', k))"
45
42
  extern io def writeLine(console: JSConsole, message: String): Unit =
46
43
  jsNode "${console}.output.write(${message} + '\\n')"
47
44
  }
@@ -1,18 +1,16 @@
1
1
  module io/error
2
2
 
3
- /**
4
- * Errors defined by libuv that can occur in IO operations.
5
- *
6
- * In addition to the named error codes, we also assign each error a
7
- * (positive) integer value that is stable across the different platforms.
8
- *
9
- * For the mapping of IOError and code values, see function fromCode.
10
- *
11
- * While stable, this integer value is supposed to only be used internally.
12
- * All user-facing operations should use values of type IOError, instead.
13
- *
14
- * see: https://docs.libuv.org/en/v1.x/errors.html
15
- */
3
+ /// Errors defined by libuv that can occur in IO operations.
4
+ ///
5
+ /// In addition to the named error codes, we also assign each error a
6
+ /// (positive) integer value that is stable across the different platforms.
7
+ ///
8
+ /// For the mapping of IOError and code values, see function fromCode.
9
+ ///
10
+ /// While stable, this integer value is supposed to only be used internally.
11
+ /// All user-facing operations should use values of type IOError, instead.
12
+ ///
13
+ /// see: https://docs.libuv.org/en/v1.x/errors.html
16
14
  type IOError {
17
15
  E2BIG();
18
16
  EACCES();
@@ -97,11 +95,9 @@ type IOError {
97
95
  EUNATCH()
98
96
  }
99
97
 
100
- /**
101
- * Corresponding error message for a libuv error
102
- *
103
- * see: https://docs.libuv.org/en/v1.x/errors.html
104
- */
98
+ /// Corresponding error message for a libuv error
99
+ ///
100
+ /// see: https://docs.libuv.org/en/v1.x/errors.html
105
101
  def message(error: IOError): String = error match {
106
102
  case E2BIG() => "argument list too long"
107
103
  case EACCES() => "permission denied"
@@ -186,11 +182,9 @@ def message(error: IOError): String = error match {
186
182
  case EUNATCH() => "protocol driver not attached"
187
183
  }
188
184
 
189
- /**
190
- * Corresponding name of a libuv error
191
- *
192
- * see: https://docs.libuv.org/en/v1.x/errors.html
193
- */
185
+ /// Corresponding name of a libuv error
186
+ ///
187
+ /// see: https://docs.libuv.org/en/v1.x/errors.html
194
188
  def name(error: IOError): String = error match {
195
189
  case E2BIG() => "E2BIG"
196
190
  case EACCES() => "EACCES"
@@ -275,11 +269,9 @@ def name(error: IOError): String = error match {
275
269
  case EUNATCH() => "EUNATCH"
276
270
  }
277
271
 
278
- /**
279
- * Translates a integer code value to an IOError.
280
- *
281
- * See documentation of type IOError for further information.
282
- */
272
+ /// Translates a integer code value to an IOError.
273
+ ///
274
+ /// See documentation of type IOError for further information.
283
275
  def fromNumber(number: Int): IOError = number match {
284
276
  case 1 => EPERM()
285
277
  case 2 => ENOENT()
@@ -6,10 +6,8 @@ import io
6
6
  import io/error
7
7
 
8
8
 
9
- /**
10
- * Represents the file opening modes with their respective flags
11
- * Backends rely on the order of these
12
- */
9
+ /// Represents the file opening modes with their respective flags
10
+ /// Backends rely on the order of these
13
11
  type Mode {
14
12
  // Most common modes
15
13
  ReadOnly() // 'r' exception if does not exist
@@ -30,15 +28,11 @@ type Mode {
30
28
  }
31
29
 
32
30
 
33
- /**
34
- * A file descriptor. Should not be inspected.
35
- */
31
+ /// A file descriptor. Should not be inspected.
36
32
  type File = Int
37
33
 
38
34
 
39
- /**
40
- * Reads a file at given path as utf8 encoded string.
41
- */
35
+ /// Reads a file at given path as utf8 encoded string.
42
36
  def readFile(path: String): String / Exception[IOError] = {
43
37
  val fd = open(path, ReadOnly());
44
38
  with on[IOError].finalize { close(fd) }
@@ -71,9 +65,7 @@ def readFile(path: String): String / Exception[IOError] = {
71
65
  go()
72
66
  }
73
67
 
74
- /**
75
- * Writes the (utf8 encoded) string `contents` into the specified file.
76
- */
68
+ /// Writes the (utf8 encoded) string `contents` into the specified file.
77
69
  def writeFile(path: String, contents: String): Unit / Exception[IOError] = {
78
70
  val fd = open(path, WriteOnly());
79
71
  with on[IOError].finalize { close(fd) }
@@ -100,21 +92,17 @@ def writeFile(path: String, contents: String): Unit / Exception[IOError] = {
100
92
  }
101
93
 
102
94
 
103
- /**
104
- * An abstract interface applications can program against.
105
- *
106
- * Can be interpreted with the `filesystem` handler, or virtualized etc.
107
- *
108
- * See example below.
109
- */
95
+ /// An abstract interface applications can program against.
96
+ ///
97
+ /// Can be interpreted with the `filesystem` handler, or virtualized etc.
98
+ ///
99
+ /// See example below.
110
100
  interface Files {
111
101
  def readFile(path: String): String
112
102
  def writeFile(path: String, contents: String): Unit
113
103
  }
114
104
 
115
- /**
116
- * Using the file system via node.js
117
- */
105
+ /// Using the file system via node.js
118
106
  def filesystem[R] { program: => R / Files }: R / Exception[IOError] = // TODO move Exception to be bidirectional
119
107
  try { program() }
120
108
  with Files {
@@ -220,28 +208,28 @@ namespace internal {
220
208
  """
221
209
 
222
210
  extern async def open(path: String, mode: Mode): Int =
223
- jsNode "$effekt.callcc(callback => open(${path}, ${mode}, callback))"
211
+ jsNode "$effekt.capture(k => open(${path}, ${mode}, k))"
224
212
  llvm """
225
213
  call void @c_fs_open(%Pos ${path}, %Pos ${mode}, %Stack %stack)
226
214
  ret void
227
215
  """
228
216
 
229
217
  extern async def read(fd: Int, buffer: Bytes, offset: Int): Int =
230
- jsNode "$effekt.callcc(callback => read(${fd}, ${buffer}, ${offset}, callback))"
218
+ jsNode "$effekt.capture(k => read(${fd}, ${buffer}, ${offset}, k))"
231
219
  llvm """
232
220
  call void @c_fs_read(%Int ${fd}, %Pos ${buffer}, %Int ${offset}, %Stack %stack)
233
221
  ret void
234
222
  """
235
223
 
236
224
  extern async def write(fd: Int, buffer: Bytes, offset: Int): Int =
237
- jsNode "$effekt.callcc(callback => write(${fd}, ${buffer}, ${offset}, callback))"
225
+ jsNode "$effekt.capture(k => write(${fd}, ${buffer}, ${offset}, k))"
238
226
  llvm """
239
227
  call void @c_fs_write(%Int ${fd}, %Pos ${buffer}, %Int ${offset}, %Stack %stack)
240
228
  ret void
241
229
  """
242
230
 
243
231
  extern async def close(fd: Int): Int =
244
- jsNode "$effekt.callcc(callback => close(${fd}, callback))"
232
+ jsNode "$effekt.capture(k => close(${fd}, k))"
245
233
  llvm """
246
234
  call void @c_fs_close(%Int ${fd}, %Stack %stack)
247
235
  ret void
@@ -18,16 +18,16 @@ namespace js {
18
18
  extern io def server(): JSServer =
19
19
  jsNode "net.createServer()"
20
20
  extern io def listen(server: JSServer, port: Int, host: String, listener: JSSocket => Unit at {io, async, global}): Unit =
21
- jsNode "listen(${server}, ${port}, ${host}, (socket) => (${listener})(socket).run())"
21
+ jsNode "listen(${server}, ${port}, ${host}, (socket) => $effekt.runToplevel((ks, k) => (${listener})(socket, ks, k)))"
22
22
 
23
23
  extern async def send(socket: JSSocket, data: Bytes): Unit =
24
- jsNode "$effekt.callcc(callback => ${socket}.write(${data}, callback))"
24
+ jsNode "$effekt.capture(k => ${socket}.write(${data}, k))"
25
25
 
26
26
  extern async def receive(socket: JSSocket): Bytes =
27
- jsNode "$effekt.callcc(callback => ${socket}.once('data', callback))"
27
+ jsNode "$effekt.capture(k => ${socket}.once('data', k))"
28
28
 
29
29
  extern async def end(socket: JSSocket): Unit =
30
- jsNode "$effekt.callcc(callback => ${socket}.end(callback))"
30
+ jsNode "$effekt.capture(k => ${socket}.end(k))"
31
31
  }
32
32
 
33
33
  interface Socket {
@@ -5,7 +5,7 @@ extern llvm """
5
5
  """
6
6
 
7
7
  extern async def wait(millis: Int): Unit =
8
- js "$effekt.callcc(callback => setTimeout(() => callback($effekt.unit), ${millis}))"
8
+ js "$effekt.capture(k => setTimeout(() => k($effekt.unit), ${millis}))"
9
9
  llvm """
10
10
  call void @c_timer_start(%Int ${millis}, %Stack %stack)
11
11
  ret void