@effekt-lang/effekt 0.46.0 → 0.48.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 (41) hide show
  1. package/bin/effekt +0 -0
  2. package/libraries/chez/common/immutable/cslist.effekt +6 -6
  3. package/libraries/chez/common/mutable/dict.effekt +7 -7
  4. package/libraries/common/args.effekt +10 -10
  5. package/libraries/common/array.effekt +57 -4
  6. package/libraries/common/bench.effekt +2 -2
  7. package/libraries/common/buffer.effekt +5 -5
  8. package/libraries/common/bytearray.effekt +69 -7
  9. package/libraries/common/char.effekt +95 -8
  10. package/libraries/common/effekt.effekt +74 -71
  11. package/libraries/common/exception.effekt +1 -1
  12. package/libraries/common/io/console.effekt +4 -4
  13. package/libraries/common/io/error.effekt +12 -1
  14. package/libraries/common/io/filesystem.effekt +78 -16
  15. package/libraries/common/io/network.effekt +97 -65
  16. package/libraries/common/io/time.effekt +1 -1
  17. package/libraries/common/io.effekt +7 -8
  18. package/libraries/common/json.effekt +5 -5
  19. package/libraries/common/list.effekt +154 -18
  20. package/libraries/common/map.effekt +35 -1
  21. package/libraries/common/process.effekt +1 -1
  22. package/libraries/common/queue.effekt +3 -3
  23. package/libraries/common/random.effekt +1 -0
  24. package/libraries/common/ref.effekt +8 -4
  25. package/libraries/common/regex.effekt +4 -4
  26. package/libraries/common/seq.effekt +1 -1
  27. package/libraries/common/set.effekt +24 -1
  28. package/libraries/common/stream.effekt +2 -360
  29. package/libraries/common/string.effekt +35 -5
  30. package/libraries/common/stringbuffer.effekt +1 -0
  31. package/libraries/js/mutable/map.effekt +5 -5
  32. package/libraries/js/web/dom.effekt +11 -11
  33. package/libraries/llvm/io.c +281 -8
  34. package/libraries/llvm/main.c +1 -2
  35. package/libraries/llvm/rts.ll +14 -7
  36. package/libraries/llvm/types.c +3 -3
  37. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
  38. package/licenses/mit license - mit-license.html +48 -48
  39. package/licenses/the bsd license - bsd-license.html +50 -50
  40. package/licenses/the mit license - mit.html +48 -48
  41. package/package.json +1 -1
@@ -60,7 +60,7 @@ $effekt.readln = function readln$impl(callback) {
60
60
  }
61
61
  """
62
62
 
63
- extern async def readln(): String =
63
+ extern def readln() at async: String =
64
64
  jsNode "$effekt.capture(callback => $effekt.readln(callback))"
65
65
  llvm """
66
66
  %result = call %Pos @c_io_readln()
@@ -74,7 +74,7 @@ def println(value: Double): Unit = println(value.show)
74
74
  def println(value: Bool): Unit = println(value.show)
75
75
  def println(value: Byte): Unit = println(value.show)
76
76
 
77
- extern pure def show(value: Int): String =
77
+ extern def show(value: Int) at {}: String =
78
78
  js "'' + ${value}"
79
79
  chez "(show-number ${value})"
80
80
  llvm """
@@ -85,7 +85,7 @@ extern pure def show(value: Int): String =
85
85
 
86
86
  def show(value: Unit): String = "()"
87
87
 
88
- extern pure def show(value: Double): String =
88
+ extern def show(value: Double) at {}: String =
89
89
  js "'' + ${value}"
90
90
  chez "(show-number ${value})"
91
91
  llvm """
@@ -100,7 +100,7 @@ def show(value: String): String =
100
100
  def show(value: Bool): String =
101
101
  if (value) "true" else "false"
102
102
 
103
- extern pure def show(value: Char): String =
103
+ extern def show(value: Char) at {}: String =
104
104
  js "String.fromCodePoint(${value})"
105
105
  chez "(string (integer->char ${value}))"
106
106
  llvm """
@@ -109,7 +109,7 @@ extern pure def show(value: Char): String =
109
109
  """
110
110
  vm "effekt::show(Char)"
111
111
 
112
- extern pure def show(value: Byte): String =
112
+ extern def show(value: Byte) at {}: String =
113
113
  js "'' + ${value}"
114
114
  chez "(string ${value})"
115
115
  llvm """
@@ -118,11 +118,11 @@ extern pure def show(value: Byte): String =
118
118
  """
119
119
  vm "effekt::show(Byte)"
120
120
 
121
- extern pure def genericShow[R](value: R): String =
121
+ extern def genericShow[R](value: R) at {}: String =
122
122
  js "$effekt.show(${value})"
123
123
  chez "(show_impl ${value})"
124
124
 
125
- extern io def inspect[R](value: R): Unit =
125
+ extern def inspect[R](value: R) at io: Unit =
126
126
  js { println(genericShow(value)) }
127
127
  chez { println(genericShow(value)) }
128
128
  vm "effekt::inspect(Any)"
@@ -130,7 +130,7 @@ extern io def inspect[R](value: R): Unit =
130
130
 
131
131
  // Strings
132
132
  // =======
133
- extern pure def infixConcat(s1: String, s2: String): String =
133
+ extern def infixConcat(s1: String, s2: String) at {}: String =
134
134
  js "${s1} + ${s2}"
135
135
  chez "(string-append ${s1} ${s2})"
136
136
  llvm """
@@ -139,7 +139,7 @@ extern pure def infixConcat(s1: String, s2: String): String =
139
139
  """
140
140
  vm "effekt::infixConcat(String, String)"
141
141
 
142
- extern pure def length(str: String): Int =
142
+ extern def length(str: String) at {}: Int =
143
143
  js "${str}.length"
144
144
  chez "(string-length ${str})"
145
145
  llvm """
@@ -148,7 +148,7 @@ extern pure def length(str: String): Int =
148
148
  """
149
149
  vm "effekt::length(String)"
150
150
 
151
- extern pure def unsafeSubstring(str: String, from: Int, to: Int): String =
151
+ extern def unsafeSubstring(str: String, from: Int, to: Int) at {}: String =
152
152
  js "${str}.substring(${from}, ${to})"
153
153
  chez "(substring ${str} ${from} ${to})" // potentially raises: "Exception in substring: ..."
154
154
  llvm """
@@ -161,7 +161,7 @@ extern pure def unsafeSubstring(str: String, from: Int, to: Int): String =
161
161
  // Side effecting ops
162
162
  // ==================
163
163
 
164
- extern io def random(): Double =
164
+ extern def random() at io: Double =
165
165
  js "Math.random()"
166
166
  chez "(random 1.0)"
167
167
  vm "effekt::random()"
@@ -170,8 +170,8 @@ extern io def random(): Double =
170
170
  // ====================
171
171
  // the following type is defined in builtins.scala
172
172
  // interface Ref[T] { def get(): T; def put(t: T): Unit }
173
- // extern io def freshIn[T](t: T) {r: Region}: Ref[T] at {r} = js "r.fresh(${t})"
174
- // extern io def freshGlobal[T](t: T): Ref[T] at {global} = js "$effekt.fresh(${t})"
173
+ // extern io def freshIn[T](t: T) {r: Region}: Ref[T] at r = js "r.fresh(${t})"
174
+ // extern io def freshGlobal[T](t: T): Ref[T] at global = js "$effekt.fresh(${t})"
175
175
 
176
176
 
177
177
  // Equality
@@ -193,7 +193,7 @@ def compareInt(n: Int, m: Int) =
193
193
  else if (n < m) Less()
194
194
  else Greater()
195
195
 
196
- extern pure def genericCompareImpl[R](x: R, y: R): Int =
196
+ extern def genericCompareImpl[R](x: R, y: R) at {}: Int =
197
197
  js "$effekt.compare(${x}, ${y})"
198
198
 
199
199
  /// Compares two values of the same type, returning an `Ordering`.
@@ -222,7 +222,7 @@ def println(o: Ordering): Unit = println(o.show)
222
222
  // ==============
223
223
 
224
224
  /// Structural equality: Not available in the LLVM backend
225
- extern pure def equals[R](x: R, y: R): Bool =
225
+ extern def equals[R](x: R, y: R) at {}: Bool =
226
226
  js "$effekt.equals(${x}, ${y})"
227
227
  chez "(equal_impl ${x} ${y})"
228
228
 
@@ -230,10 +230,10 @@ def differsFrom[R](x: R, y: R): Bool =
230
230
  not(equals(x, y))
231
231
 
232
232
  // TODO fix this in the pattern matching compiler
233
- extern pure def infixEq(x: Unit, y: Unit): Bool =
233
+ extern def infixEq(x: Unit, y: Unit) at {}: Bool =
234
234
  default { true }
235
235
 
236
- extern pure def infixEq(x: Int, y: Int): Bool =
236
+ extern def infixEq(x: Int, y: Int) at {}: Bool =
237
237
  js "${x} === ${y}"
238
238
  chez "(equal? ${x} ${y})"
239
239
  llvm """
@@ -244,7 +244,7 @@ extern pure def infixEq(x: Int, y: Int): Bool =
244
244
  """
245
245
  vm "effekt::infixEq(Int, Int)"
246
246
 
247
- extern pure def infixNeq(x: Int, y: Int): Bool =
247
+ extern def infixNeq(x: Int, y: Int) at {}: Bool =
248
248
  js "${x} !== ${y}"
249
249
  chez "(not (equal? ${x} ${y}))"
250
250
  llvm """
@@ -255,7 +255,7 @@ extern pure def infixNeq(x: Int, y: Int): Bool =
255
255
  """
256
256
  vm "effekt::infixNeq(Int, Int)"
257
257
 
258
- extern pure def infixEq(x: Char, y: Char): Bool =
258
+ extern def infixEq(x: Char, y: Char) at {}: Bool =
259
259
  js "${x} === ${y}"
260
260
  chez "(equal? ${x} ${y})"
261
261
  llvm """
@@ -266,7 +266,7 @@ extern pure def infixEq(x: Char, y: Char): Bool =
266
266
  """
267
267
  vm "effekt::infixEq(Char, Char)"
268
268
 
269
- extern pure def infixNeq(x: Char, y: Char): Bool =
269
+ extern def infixNeq(x: Char, y: Char) at {}: Bool =
270
270
  js "${x} !== ${y}"
271
271
  chez "(not (equal? ${x} ${y}))"
272
272
  llvm """
@@ -276,7 +276,7 @@ extern pure def infixNeq(x: Char, y: Char): Bool =
276
276
  ret %Pos %adt_boolean
277
277
  """
278
278
 
279
- extern pure def infixEq(x: String, y: String): Bool =
279
+ extern def infixEq(x: String, y: String) at {}: Bool =
280
280
  js "${x} === ${y}"
281
281
  chez "(equal? ${x} ${y})"
282
282
  llvm """
@@ -287,7 +287,7 @@ extern pure def infixEq(x: String, y: String): Bool =
287
287
 
288
288
  def infixNeq(x: String, y: String): Bool = not(x == y)
289
289
 
290
- extern pure def infixEq(x: Bool, y: Bool): Bool =
290
+ extern def infixEq(x: Bool, y: Bool) at {}: Bool =
291
291
  js "${x} === ${y}"
292
292
  chez "(equal? ${x} ${y})"
293
293
  llvm """
@@ -300,7 +300,7 @@ extern pure def infixEq(x: Bool, y: Bool): Bool =
300
300
  """
301
301
  vm "effekt::infixEq(Bool, Bool)"
302
302
 
303
- extern pure def infixNeq(x: Bool, y: Bool): Bool =
303
+ extern def infixNeq(x: Bool, y: Bool) at {}: Bool =
304
304
  js "${x} !== ${y}"
305
305
  chez "(not (equal? ${x} ${y}))"
306
306
  llvm """
@@ -315,85 +315,85 @@ extern pure def infixNeq(x: Bool, y: Bool): Bool =
315
315
 
316
316
  // Math ops
317
317
  // ========
318
- extern pure def infixAdd(x: Int, y: Int): Int =
318
+ extern def infixAdd(x: Int, y: Int) at {}: Int =
319
319
  js "(${x} + ${y})"
320
320
  chez "(+ ${x} ${y})"
321
321
  llvm "%z = add %Int ${x}, ${y} ret %Int %z"
322
322
  vm "effekt::infixAdd(Int, Int)"
323
323
 
324
- extern pure def infixMul(x: Int, y: Int): Int =
324
+ extern def infixMul(x: Int, y: Int) at {}: Int =
325
325
  js "(${x} * ${y})"
326
326
  chez "(* ${x} ${y})"
327
327
  llvm "%z = mul %Int ${x}, ${y} ret %Int %z"
328
328
  vm "effekt::infixMul(Int, Int)"
329
329
 
330
- extern pure def infixDiv(x: Int, y: Int): Int =
330
+ extern def infixDiv(x: Int, y: Int) at {}: Int =
331
331
  js "Math.floor(${x} / ${y})"
332
332
  chez "(floor (/ ${x} ${y}))"
333
333
  llvm "%z = sdiv %Int ${x}, ${y} ret %Int %z"
334
334
  vm "effekt::infixDiv(Int, Int)"
335
335
 
336
- extern pure def infixSub(x: Int, y: Int): Int =
336
+ extern def infixSub(x: Int, y: Int) at {}: Int =
337
337
  js "(${x} - ${y})"
338
338
  chez "(- ${x} ${y})"
339
339
  llvm "%z = sub %Int ${x}, ${y} ret %Int %z"
340
340
  vm "effekt::infixSub(Int, Int)"
341
341
 
342
- extern pure def mod(x: Int, y: Int): Int =
342
+ extern def mod(x: Int, y: Int) at {}: Int =
343
343
  js "(${x} % ${y})"
344
344
  chez "(modulo ${x} ${y})"
345
345
  llvm "%z = srem %Int ${x}, ${y} ret %Int %z"
346
346
  vm "effekt::mod(Int, Int)"
347
347
 
348
- extern pure def infixAdd(x: Double, y: Double): Double =
348
+ extern def infixAdd(x: Double, y: Double) at {}: Double =
349
349
  js "(${x} + ${y})"
350
350
  chez "(+ ${x} ${y})"
351
351
  llvm "%z = fadd %Double ${x}, ${y} ret %Double %z"
352
352
  vm "effekt::infixAdd(Double, Double)"
353
353
 
354
- extern pure def infixMul(x: Double, y: Double): Double =
354
+ extern def infixMul(x: Double, y: Double) at {}: Double =
355
355
  js "(${x} * ${y})"
356
356
  chez "(* ${x} ${y})"
357
357
  llvm "%z = fmul %Double ${x}, ${y} ret %Double %z"
358
358
  vm "effekt::infixMul(Double, Double)"
359
359
 
360
- extern pure def infixSub(x: Double, y: Double): Double =
360
+ extern def infixSub(x: Double, y: Double) at {}: Double =
361
361
  js "(${x} - ${y})"
362
362
  chez "(- ${x} ${y})"
363
363
  llvm "%z = fsub %Double ${x}, ${y} ret %Double %z"
364
364
  vm "effekt::infixSub(Double, Double)"
365
365
 
366
- extern pure def infixDiv(x: Double, y: Double): Double =
366
+ extern def infixDiv(x: Double, y: Double) at {}: Double =
367
367
  js "(${x} / ${y})"
368
368
  chez "(fl/ ${x} ${y})"
369
369
  llvm "%z = fdiv %Double ${x}, ${y} ret %Double %z"
370
370
  vm "effekt::infixDiv(Double, Double)"
371
371
 
372
- extern pure def cos(x: Double): Double =
372
+ extern def cos(x: Double) at {}: Double =
373
373
  js "Math.cos(${x})"
374
374
  chez "(cos ${x})"
375
375
  vm "effekt::cos(Double)"
376
376
  llvm "%z = call %Double @llvm.cos.f64(double ${x}) ret %Double %z"
377
377
 
378
- extern pure def sin(x: Double): Double =
378
+ extern def sin(x: Double) at {}: Double =
379
379
  js "Math.sin(${x})"
380
380
  chez "(sin ${x})"
381
381
  vm "effekt::sin(Double)"
382
382
  llvm "%z = call %Double @llvm.sin.f64(double ${x}) ret %Double %z"
383
383
 
384
- extern pure def atan(x: Double): Double =
384
+ extern def atan(x: Double) at {}: Double =
385
385
  js "Math.atan(${x})"
386
386
  chez "(atan ${x})"
387
387
  vm "effekt::atan(Double)"
388
388
  llvm "%z = call %Double @atan(double ${x}) ret %Double %z"
389
389
 
390
- extern pure def tan(x: Double): Double =
390
+ extern def tan(x: Double) at {}: Double =
391
391
  js "Math.tan(${x})"
392
392
  chez "(tan ${x})"
393
393
  vm "effekt::tan(Double)"
394
394
  llvm "%z = call %Double @tan(double ${x}) ret %Double %z"
395
395
 
396
- extern pure def sqrt(x: Double): Double =
396
+ extern def sqrt(x: Double) at {}: Double =
397
397
  js "Math.sqrt(${x})"
398
398
  chez "(sqrt ${x})"
399
399
  llvm "%z = call %Double @llvm.sqrt.f64(double ${x}) ret %Double %z"
@@ -404,24 +404,27 @@ def square(x: Double): Double = x * x
404
404
  def neg(n: Double): Double =
405
405
  0.0 - n
406
406
 
407
+ def min(n: Double, m: Double): Double =
408
+ if (n < m) n else m
409
+
407
410
  def max(n: Double, m: Double): Double =
408
411
  if (n > m) n else m
409
412
 
410
413
  def abs(n: Double): Double =
411
414
  max(n, neg(n))
412
415
 
413
- extern pure def log(x: Double): Double =
416
+ extern def log(x: Double) at {}: Double =
414
417
  js "Math.log(${x})"
415
418
  chez "(log ${x})"
416
419
  vm "effekt::log(Double)"
417
420
  llvm "%z = call %Double @llvm.log.f64(double ${x}) ret %Double %z"
418
421
 
419
- extern pure def log1p(x: Double): Double =
422
+ extern def log1p(x: Double) at {}: Double =
420
423
  js "Math.log1p(${x})"
421
424
  chez "(log (+ ${x} 1))"
422
425
  llvm "%z = call %Double @log1p(double ${x}) ret %Double %z"
423
426
 
424
- extern pure def exp(x: Double): Double =
427
+ extern def exp(x: Double) at {}: Double =
425
428
  js "Math.exp(${x})"
426
429
  chez "(exp ${x})"
427
430
  vm "effekt::exp(Double)"
@@ -440,14 +443,14 @@ def pow(base: Double, exponent: Int): Double = {
440
443
  }
441
444
  }
442
445
 
443
- extern pure def pow(base: Double, exponent: Double): Double =
446
+ extern def pow(base: Double, exponent: Double) at {}: Double =
444
447
  js "Math.pow(${base}, ${exponent})"
445
448
  chez "(expt ${base} ${exponent})"
446
449
  vm "effekt::pow(Double, Double)"
447
450
  llvm "%z = call %Double @llvm.pow.f64(double ${base}, double ${exponent}) ret %Double %z"
448
451
 
449
452
  // since we do not have "extern val", yet
450
- extern pure def _pi(): Double =
453
+ extern def _pi() at {}: Double =
451
454
  js "Math.PI"
452
455
  chez "(* 4 (atan 1))"
453
456
  vm "effekt::pi()"
@@ -455,20 +458,20 @@ extern pure def _pi(): Double =
455
458
 
456
459
  val PI: Double = _pi()
457
460
 
458
- extern pure def toInt(d: Double): Int =
461
+ extern def toInt(d: Double) at {}: Int =
459
462
  js "Math.trunc(${d})"
460
463
  chez "(flonum->fixnum ${d})"
461
464
  llvm "%z = fptosi double ${d} to %Int ret %Int %z"
462
465
  vm "effekt::toInt(Double)"
463
466
 
464
- extern pure def toDouble(d: Int): Double =
467
+ extern def toDouble(d: Int) at {}: Double =
465
468
  js "${d}"
466
469
  chez "(fixnum->flonum ${d})"
467
470
  llvm "%z = sitofp i64 ${d} to double ret double %z"
468
471
  vm "effekt::toDouble(Int)"
469
472
 
470
473
 
471
- extern pure def round(d: Double): Int =
474
+ extern def round(d: Double) at {}: Int =
472
475
  js "Math.round(${d})"
473
476
  chez "(flonum->fixnum (round ${d}))"
474
477
  llvm """
@@ -482,7 +485,7 @@ def round(d: Double, digits: Int): Double = {
482
485
  round(d * factor).toDouble / factor
483
486
  }
484
487
 
485
- extern pure def floor(d: Double): Int =
488
+ extern def floor(d: Double) at {}: Int =
486
489
  js "Math.floor(${d})"
487
490
  chez "(flonum->fixnum (floor ${d}))"
488
491
  llvm """
@@ -490,7 +493,7 @@ extern pure def floor(d: Double): Int =
490
493
  %z = fptosi double %i to %Int ret %Int %z
491
494
  """
492
495
 
493
- extern pure def ceil(d: Double): Int =
496
+ extern def ceil(d: Double) at {}: Int =
494
497
  js "Math.ceil(${d})"
495
498
  chez "(flonum->fixnum (ceiling ${d}))"
496
499
  llvm """
@@ -511,7 +514,7 @@ def abs(n: Int): Int =
511
514
  max(n, neg(n))
512
515
 
513
516
 
514
- extern pure def infixLt(x: Int, y: Int): Bool =
517
+ extern def infixLt(x: Int, y: Int) at {}: Bool =
515
518
  js "(${x} < ${y})"
516
519
  chez "(< ${x} ${y})"
517
520
  llvm """
@@ -522,7 +525,7 @@ extern pure def infixLt(x: Int, y: Int): Bool =
522
525
  """
523
526
  vm "effekt::infixLt(Int, Int)"
524
527
 
525
- extern pure def infixLte(x: Int, y: Int): Bool =
528
+ extern def infixLte(x: Int, y: Int) at {}: Bool =
526
529
  js "(${x} <= ${y})"
527
530
  chez "(<= ${x} ${y})"
528
531
  llvm """
@@ -533,7 +536,7 @@ extern pure def infixLte(x: Int, y: Int): Bool =
533
536
  """
534
537
  vm "effekt::infixLte(Int, Int)"
535
538
 
536
- extern pure def infixGt(x: Int, y: Int): Bool =
539
+ extern def infixGt(x: Int, y: Int) at {}: Bool =
537
540
  js "(${x} > ${y})"
538
541
  chez "(> ${x} ${y})"
539
542
  llvm """
@@ -544,7 +547,7 @@ extern pure def infixGt(x: Int, y: Int): Bool =
544
547
  """
545
548
  vm "effekt::infixGt(Int, Int)"
546
549
 
547
- extern pure def infixGte(x: Int, y: Int): Bool =
550
+ extern def infixGte(x: Int, y: Int) at {}: Bool =
548
551
  js "(${x} >= ${y})"
549
552
  chez "(>= ${x} ${y})"
550
553
  llvm """
@@ -555,17 +558,17 @@ extern pure def infixGte(x: Int, y: Int): Bool =
555
558
  """
556
559
  vm "effekt::infixGte(Int, Int)"
557
560
 
558
- extern pure def infixEq(x: Double, y: Double): Bool =
561
+ extern def infixEq(x: Double, y: Double) at {}: Bool =
559
562
  js "${x} === ${y}"
560
563
  chez "(= ${x} ${y})"
561
564
  vm "effekt::infixEq(Double, Double)"
562
565
 
563
- extern pure def infixNeq(x: Double, y: Double): Bool =
566
+ extern def infixNeq(x: Double, y: Double) at {}: Bool =
564
567
  js "${x} !== ${y}"
565
568
  chez "(not (= ${x} ${y}))"
566
569
  vm "effekt::infixNeq(Double, Double)"
567
570
 
568
- extern pure def infixLt(x: Double, y: Double): Bool =
571
+ extern def infixLt(x: Double, y: Double) at {}: Bool =
569
572
  js "(${x} < ${y})"
570
573
  chez "(< ${x} ${y})"
571
574
  llvm """
@@ -576,12 +579,12 @@ extern pure def infixLt(x: Double, y: Double): Bool =
576
579
  """
577
580
  vm "effekt::infixLt(Double, Double)"
578
581
 
579
- extern pure def infixLte(x: Double, y: Double): Bool =
582
+ extern def infixLte(x: Double, y: Double) at {}: Bool =
580
583
  js "(${x} <= ${y})"
581
584
  chez "(<= ${x} ${y})"
582
585
  vm "effekt::infixLte(Double, Double)"
583
586
 
584
- extern pure def infixGt(x: Double, y: Double): Bool =
587
+ extern def infixGt(x: Double, y: Double) at {}: Bool =
585
588
  js "(${x} > ${y})"
586
589
  chez "(> ${x} ${y})"
587
590
  llvm """
@@ -592,32 +595,32 @@ extern pure def infixGt(x: Double, y: Double): Bool =
592
595
  """
593
596
  vm "effekt::infixGt(Double, Double)"
594
597
 
595
- extern pure def infixGte(x: Double, y: Double): Bool =
598
+ extern def infixGte(x: Double, y: Double) at {}: Bool =
596
599
  js "(${x} >= ${y})"
597
600
  chez "(>= ${x} ${y})"
598
601
  vm "effekt::infixGte(Double, Double)"
599
602
 
600
603
  // TODO do we really need those? if yes, move to string.effekt
601
- extern pure def infixLt(x: String, y: String): Bool =
604
+ extern def infixLt(x: String, y: String) at {}: Bool =
602
605
  js "(${x} < ${y})"
603
606
  chez "(string<? ${x} ${y})"
604
607
 
605
- extern pure def infixLte(x: String, y: String): Bool =
608
+ extern def infixLte(x: String, y: String) at {}: Bool =
606
609
  js "(${x} <= ${y})"
607
610
  chez "(string<=? ${x} ${y})"
608
611
 
609
- extern pure def infixGt(x: String, y: String): Bool =
612
+ extern def infixGt(x: String, y: String) at {}: Bool =
610
613
  js "(${x} > ${y})"
611
614
  chez "(string>? ${x} ${y})"
612
615
 
613
- extern pure def infixGte(x: String, y: String): Bool =
616
+ extern def infixGte(x: String, y: String) at {}: Bool =
614
617
  js "(${x} >= ${y})"
615
618
  chez "(string>=? ${x} ${y})"
616
619
 
617
620
 
618
621
  // Boolean operations
619
622
  // ==================
620
- extern pure def not(b: Bool): Bool =
623
+ extern def not(b: Bool) at {}: Bool =
621
624
  js "!${b}"
622
625
  chez "(not ${b})"
623
626
  llvm """
@@ -639,32 +642,32 @@ def infixAnd { first: => Bool } { second: => Bool }: Bool =
639
642
  // ==================
640
643
 
641
644
  /// Arithmetic left shift
642
- extern pure def bitwiseShl(x: Int, y: Int): Int =
645
+ extern def bitwiseShl(x: Int, y: Int) at {}: Int =
643
646
  js "(${x} << ${y})"
644
647
  chez "(ash ${x} ${y})"
645
648
  llvm "%z = shl %Int ${x}, ${y} ret %Int %z"
646
649
  vm "effekt::bitwiseShl(Int, Int)"
647
650
 
648
651
  /// Arithmetic right shift
649
- extern pure def bitwiseShr(x: Int, y: Int): Int =
652
+ extern def bitwiseShr(x: Int, y: Int) at {}: Int =
650
653
  js "(${x} >> ${y})"
651
654
  chez "(ash ${x} (- ${y}))"
652
655
  llvm "%z = ashr %Int ${x}, ${y} ret %Int %z"
653
656
  vm "effekt::bitwiseShr(Int, Int)"
654
657
 
655
- extern pure def bitwiseAnd(x: Int, y: Int): Int =
658
+ extern def bitwiseAnd(x: Int, y: Int) at {}: Int =
656
659
  js "(${x} & ${y})"
657
660
  chez "(logand ${x} ${y})"
658
661
  llvm "%z = and %Int ${x}, ${y} ret %Int %z"
659
662
  vm "effekt::bitwiseAnd(Int, Int)"
660
663
 
661
- extern pure def bitwiseOr(x: Int, y: Int): Int =
664
+ extern def bitwiseOr(x: Int, y: Int) at {}: Int =
662
665
  js "(${x} | ${y})"
663
666
  chez "(logior ${x} ${y})"
664
667
  llvm "%z = or %Int ${x}, ${y} ret %Int %z"
665
668
  vm "effekt::bitwiseOr(Int, Int)"
666
669
 
667
- extern pure def bitwiseXor(x: Int, y: Int): Int =
670
+ extern def bitwiseXor(x: Int, y: Int) at {}: Int =
668
671
  js "(${x} ^ ${y})"
669
672
  chez "(logxor ${x} ${y})"
670
673
  llvm "%z = xor %Int ${x}, ${y} ret %Int %z"
@@ -673,12 +676,12 @@ extern pure def bitwiseXor(x: Int, y: Int): Int =
673
676
 
674
677
  // Byte operations
675
678
  // ===============
676
- extern pure def toByte(n: Int): Byte =
679
+ extern def toByte(n: Int) at {}: Byte =
677
680
  js "${n}"
678
681
  llvm "%z = trunc %Int ${n} to %Byte ret %Byte %z"
679
682
  chez "${n}"
680
683
 
681
- extern pure def toInt(n: Byte): Int =
684
+ extern def toInt(n: Byte) at {}: Int =
682
685
  js "${n}"
683
686
  llvm "%z = zext %Byte ${n} to %Int ret %Int %z"
684
687
  vm "effekt::toInt(Byte)"
@@ -695,13 +698,13 @@ extern pure def toInt(n: Byte): Int =
695
698
  // llvm: null?
696
699
 
697
700
  /// The value used by the FFI to represent undefined values
698
- extern pure def undefined[A](): A =
701
+ extern def undefined[A]() at {}: A =
699
702
  js "undefined"
700
703
  chez "#f"
701
704
  vm "effekt::undefined()"
702
705
 
703
706
  /// Is an FFI value undefined?
704
- extern pure def isUndefined[A](value: A): Bool =
707
+ extern def isUndefined[A](value: A) at {}: Bool =
705
708
  js "(${value} === undefined || ${value} === null)"
706
709
  chez "(eq? ${value} #f)"
707
710
  vm "effekt::isUndefined[A](A)"
@@ -50,7 +50,7 @@ def wrongFormat(msg: String): Nothing / Exception[WrongFormat] =
50
50
  /**
51
51
  * A fatal runtime error that cannot be caught
52
52
  */
53
- extern io def panic(msg: String): Nothing =
53
+ extern def panic(msg: String) at io: Nothing =
54
54
  js "(function() { throw ${msg} })()"
55
55
  chez "(raise ${msg})"
56
56
  llvm """
@@ -28,18 +28,18 @@ namespace js {
28
28
 
29
29
  extern type JSConsole
30
30
 
31
- extern io def newConsole(): JSConsole =
31
+ extern def newConsole() at io: JSConsole =
32
32
  jsNode """readline.createInterface({
33
33
  input: process.stdin,
34
34
  output: process.stdout,
35
35
  })"""
36
36
 
37
- extern io def close(console: JSConsole): Unit =
37
+ extern def close(console: JSConsole) at io: Unit =
38
38
  jsNode "${console}.close()"
39
39
 
40
- extern async def readLine(console: JSConsole): String =
40
+ extern def readLine(console: JSConsole) at async: String =
41
41
  jsNode "$effekt.capture(k => ${console}.once('line', k))"
42
- extern io def writeLine(console: JSConsole, message: String): Unit =
42
+ extern def writeLine(console: JSConsole, message: String) at io: Unit =
43
43
  jsNode "${console}.output.write(${message} + '\\n')"
44
44
  }
45
45
 
@@ -456,7 +456,7 @@ namespace internal {
456
456
  }
457
457
  """
458
458
 
459
- extern pure def errorNumber(errno: Int): Int =
459
+ extern def errorNumber(errno: Int) at {}: Int =
460
460
  jsNode "errorNumber(${errno})"
461
461
  llvm """
462
462
  %z = call %Int @c_error_number(%Int ${errno})
@@ -464,3 +464,14 @@ namespace internal {
464
464
  """
465
465
 
466
466
  }
467
+
468
+ namespace internal {
469
+ def checkResult(result: Int): Int / Exception[IOError] =
470
+ if (result < 0) {
471
+ val ioError = fromNumber(internal::errorNumber(result));
472
+ do raise[IOError](ioError, message(ioError))
473
+ } else {
474
+ result
475
+ }
476
+ }
477
+