@effekt-lang/effekt 0.18.0 → 0.19.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
@@ -34,7 +34,7 @@ def emptyBuffer[T](capacity: Int): Buffer[T] at {global} = {
34
34
  }
35
35
  def arrayBuffer[T](initialCapacity: Int): Buffer[T] at {global} = {
36
36
  // TODO allocate buffer (and array) into a region r.
37
- val contents = emptyArray[T](initialCapacity)
37
+ val contents = array::allocate[T](initialCapacity)
38
38
  var head in global = 0
39
39
  var tail in global = 0
40
40
 
@@ -51,7 +51,7 @@ def arrayBuffer[T](initialCapacity: Int): Buffer[T] at {global} = {
51
51
  def read() = {
52
52
  if (buffer.empty?) None()
53
53
  else {
54
- val result: T = contents.remove(head).getOrElse { <> };
54
+ val result: T = contents.unsafeGet(head);
55
55
  head = mod(head + 1, initialCapacity)
56
56
  Some(result)
57
57
  }
@@ -59,7 +59,7 @@ def arrayBuffer[T](initialCapacity: Int): Buffer[T] at {global} = {
59
59
  def write(el: T) = {
60
60
  if (buffer.full?) <> // raise(BufferOverflow())
61
61
 
62
- contents.put(tail, el)
62
+ contents.unsafeSet(tail, el)
63
63
  tail = mod(tail + 1, initialCapacity)
64
64
  }
65
65
  }
@@ -6,7 +6,7 @@ module bytearray
6
6
  extern type ByteArray
7
7
  // = llvm "%Pos"
8
8
  // = js "Uint8Array"
9
-
9
+ // = chez "bytevector"
10
10
 
11
11
  /// Allocates a new bytearray with the given `size`, its values are undefined.
12
12
  extern global def allocate(size: Int): ByteArray =
@@ -15,6 +15,7 @@ extern global def allocate(size: Int): ByteArray =
15
15
  %arr = call %Pos @c_bytearray_new(%Int ${size})
16
16
  ret %Pos %arr
17
17
  """
18
+ chez "(make-bytevector ${size})"
18
19
 
19
20
  extern pure def size(arr: ByteArray): Int =
20
21
  js "${arr}.length"
@@ -22,6 +23,7 @@ extern pure def size(arr: ByteArray): Int =
22
23
  %size = call %Int @c_bytearray_size(%Pos ${arr})
23
24
  ret %Int %size
24
25
  """
26
+ chez "(bytevector-length ${arr})"
25
27
 
26
28
  extern global def unsafeGet(arr: ByteArray, index: Int): Byte =
27
29
  js "(${arr})[${index}]"
@@ -29,6 +31,7 @@ extern global def unsafeGet(arr: ByteArray, index: Int): Byte =
29
31
  %byte = call %Byte @c_bytearray_get(%Pos ${arr}, %Int ${index})
30
32
  ret %Byte %byte
31
33
  """
34
+ chez "(bytevector-u8-ref ${arr} ${index})"
32
35
 
33
36
  extern global def unsafeSet(arr: ByteArray, index: Int, value: Byte): Unit =
34
37
  js "bytearray$set(${arr}, ${index}, ${value})"
@@ -36,6 +39,7 @@ extern global def unsafeSet(arr: ByteArray, index: Int, value: Byte): Unit =
36
39
  %z = call %Pos @c_bytearray_set(%Pos ${arr}, %Int ${index}, %Byte ${value})
37
40
  ret %Pos %z
38
41
  """
42
+ chez "(bytevector-u8-set! ${arr} ${index} ${value})"
39
43
 
40
44
  def resize(source: ByteArray, size: Int): ByteArray = {
41
45
  val target = allocate(size)
@@ -75,6 +79,7 @@ extern pure def fromString(str: String): ByteArray =
75
79
  llvm """
76
80
  ret %Pos ${str}
77
81
  """
82
+ chez "(string->utf8 ${str})"
78
83
 
79
84
  extern pure def toString(arr: ByteArray): String =
80
85
  js "(new TextDecoder('utf-8').decode(${arr}))"
@@ -82,10 +87,68 @@ extern pure def toString(arr: ByteArray): String =
82
87
  llvm """
83
88
  ret %Pos ${arr}
84
89
  """
90
+ chez "(utf8->string ${arr})"
85
91
 
86
92
  extern js """
87
93
  function bytearray$set(bytes, index, value) {
88
94
  bytes[index] = value;
89
95
  return $effekt.unit;
90
96
  }
97
+
98
+ function bytearray$compare(arr1, arr2) {
99
+ const len = Math.min(arr1.length, arr2.length);
100
+
101
+ for (let i = 0; i < len; i++) {
102
+ if (arr1[i] !== arr2[i]) {
103
+ return arr1[i] < arr2[i] ? -1 : 1;
104
+ }
105
+ }
106
+
107
+ if (arr1.length !== arr2.length) {
108
+ return arr1.length < arr2.length ? -1 : 1;
109
+ } else {
110
+ return 0;
111
+ }
112
+ }
113
+ """
114
+
115
+ extern chez """
116
+ (define (bytearray$compare b1 b2)
117
+ (let ([len1 (bytevector-length b1)]
118
+ [len2 (bytevector-length b2)]
119
+ [minlen (min (bytevector-length b1) (bytevector-length b2))])
120
+ (let loop ([i 0])
121
+ (cond
122
+ [(= i minlen)
123
+ (cond [(< len1 len2) -1]
124
+ [(> len1 len2) 1]
125
+ [else 0])]
126
+ [(< (bytevector-u8-ref b1 i) (bytevector-u8-ref b2 i)) -1]
127
+ [(> (bytevector-u8-ref b1 i) (bytevector-u8-ref b2 i)) 1]
128
+ [else (loop (+ i 1))]))))
91
129
  """
130
+
131
+ extern pure def compareByteArrayImpl(b1: ByteArray, b2: ByteArray): Int =
132
+ js "bytearray$compare(${b1}, ${b2})"
133
+ llvm """
134
+ %x = call %Int @c_bytearray_compare(%Pos ${b1}, %Pos ${b2})
135
+ ret %Int %x
136
+ """
137
+ chez "(bytearray$compare ${b1} ${b2})"
138
+
139
+ def compareByteArray(b1: ByteArray, b2: ByteArray): Ordering = {
140
+ val ret = compareByteArrayImpl(b1, b2)
141
+ if (ret == 0) {
142
+ Equal()
143
+ } else if (ret < 0) {
144
+ Less()
145
+ } else { // ret > 0
146
+ Greater()
147
+ }
148
+ }
149
+
150
+ def compareStringBytes(left: String, right: String): Ordering = {
151
+ val l = left.fromString
152
+ val r = right.fromString
153
+ compareByteArray(l, r)
154
+ }
@@ -90,6 +90,7 @@ extern pure def show(value: Char): String =
90
90
 
91
91
  extern pure def show(value: Byte): String =
92
92
  js "'' + ${value}"
93
+ chez "(string ${value})"
93
94
  llvm """
94
95
  %z = call %Pos @c_bytearray_show_Byte(i8 ${value})
95
96
  ret %Pos %z
@@ -166,17 +167,24 @@ type Ordering {
166
167
  Greater()
167
168
  }
168
169
 
170
+ def compareInt(n: Int, m: Int) =
171
+ if (n == m) Equal()
172
+ else if (n < m) Less()
173
+ else Greater()
174
+
169
175
  extern pure def genericCompareImpl[R](x: R, y: R): Int =
170
176
  js "$effekt.compare(${x}, ${y})"
171
177
 
172
178
  /// Compares two values of the same type, returning an `Ordering`.
173
179
  /// Only available on the JavaScript backend.
174
180
  def genericCompare[R](x: R, y: R): Ordering = {
175
- genericCompareImpl(x, y) match {
176
- case -1 => Less()
177
- case 0 => Equal()
178
- case 1 => Greater()
179
- case _ => <{ "Impossible: JS comparison returned invalid value!" }>
181
+ val ret = genericCompareImpl(x, y)
182
+ if (ret == 0) {
183
+ Equal()
184
+ } else if (ret < 0) {
185
+ Less()
186
+ } else { // ret > 0
187
+ Greater()
180
188
  }
181
189
  }
182
190
 
@@ -390,7 +398,7 @@ extern pure def log(x: Double): Double =
390
398
  extern pure def log1p(x: Double): Double =
391
399
  js "Math.log1p(${x})"
392
400
  chez "(log (+ ${x} 1))"
393
- llvm "%z = call %Double @log1p(double ${x}) ret %Double %z"
401
+ llvm "%z = call %Double @log1p(double ${x}) ret %Double %z"
394
402
 
395
403
  extern pure def exp(x: Double): Double =
396
404
  js "Math.exp(${x})"
@@ -571,19 +579,19 @@ extern pure def infixGte(x: Double, y: Double): Bool =
571
579
  // TODO do we really need those? if yes, move to string.effekt
572
580
  extern pure def infixLt(x: String, y: String): Bool =
573
581
  js "(${x} < ${y})"
574
- chez "(< ${x} ${y})"
582
+ chez "(string<? ${x} ${y})"
575
583
 
576
584
  extern pure def infixLte(x: String, y: String): Bool =
577
585
  js "(${x} <= ${y})"
578
- chez "(<= ${x} ${y})"
586
+ chez "(string<=? ${x} ${y})"
579
587
 
580
588
  extern pure def infixGt(x: String, y: String): Bool =
581
589
  js "(${x} > ${y})"
582
- chez "(> ${x} ${y})"
590
+ chez "(string>? ${x} ${y})"
583
591
 
584
592
  extern pure def infixGte(x: String, y: String): Bool =
585
593
  js "(${x} >= ${y})"
586
- chez "(>= ${x} ${y})"
594
+ chez "(string>=? ${x} ${y})"
587
595
 
588
596
 
589
597
  // Boolean operations
@@ -647,10 +655,13 @@ extern pure def bitwiseXor(x: Int, y: Int): Int =
647
655
  extern pure def toByte(n: Int): Byte =
648
656
  js "${n}"
649
657
  llvm "%z = trunc %Int ${n} to %Byte ret %Byte %z"
658
+ chez "${n}"
650
659
 
651
660
  extern pure def toInt(n: Byte): Int =
652
661
  js "${n}"
653
662
  llvm "%z = zext %Byte ${n} to %Int ret %Int %z"
663
+ vm "effekt::toInt(Byte)"
664
+ chez "${n}"
654
665
 
655
666
 
656
667
  // Undefined and Null
@@ -666,11 +677,13 @@ extern pure def toInt(n: Byte): Int =
666
677
  extern pure def undefined[A](): A =
667
678
  js "undefined"
668
679
  chez "#f"
680
+ vm "effekt::undefined()"
669
681
 
670
682
  /// Is an FFI value undefined?
671
683
  extern pure def isUndefined[A](value: A): Bool =
672
684
  js "(${value} === undefined || ${value} === null)"
673
685
  chez "(eq? ${value} #f)"
686
+ vm "effekt::isUndefined[A](A)"
674
687
 
675
688
 
676
689
  // Tuples
@@ -57,14 +57,17 @@ def server(host: String, port: Int, handler: () => Unit / Socket at {io, async,
57
57
 
58
58
  namespace examples {
59
59
  def helloWorldApp(): Unit / Socket = {
60
- val request = do receive();
60
+ val request = do receive().toString;
61
61
 
62
- println("Received a request: " ++ request.toUTF8)
62
+ println("Received a request: " ++ request)
63
63
 
64
- if (request.toUTF8.startsWith("GET /")) {
65
- do send(fromUTF8("HTTP/1.1 200 OK\r\n\r\nHello from Effekt!"))
64
+ def respond(s: String): Unit / Socket =
65
+ do send(s.fromString)
66
+
67
+ if (request.startsWith("GET /")) {
68
+ respond("HTTP/1.1 200 OK\r\n\r\nHello from Effekt!")
66
69
  } else {
67
- do send("HTTP/1.1 400 Bad Request\r\n\r\n".fromUTF8)
70
+ respond("HTTP/1.1 400 Bad Request\r\n\r\n")
68
71
  }
69
72
  do end()
70
73
  }
@@ -62,7 +62,7 @@ def encodeJsonObject[R]{ body: => R / JsonObjectBuilder }: R / emit[String] = {
62
62
  do emit("{")
63
63
  def c(k: String) = {
64
64
  if (not(first)) { do emit(",") }
65
- do emit(escape(k)); do emit(":")
65
+ do emit(escape(k)); do emit(":")
66
66
  first = false
67
67
  }
68
68
  val r = encodeJson {
@@ -76,7 +76,7 @@ def encodeJsonObject[R]{ body: => R / JsonObjectBuilder }: R / emit[String] = {
76
76
  /// Main entry point for encoding json.
77
77
  /// Emits individual tokens of the resulting json.
78
78
  def encodeJson[R]{ body: => R / JsonBuilder }: R / emit[String] = {
79
- try body() with JsonBuilder {
79
+ try body() with JsonBuilder {
80
80
  def null() = { resume(do emit("null")) }
81
81
  def bool(v) = { resume(do emit( if(v){ "true" } else { "false" } )) }
82
82
  def number(n) = { resume(do emit(show(n))) }
@@ -112,7 +112,7 @@ def readDouble(): Double / Scan[Char] = {
112
112
  if (optionally { readIf('.') }) {
113
113
  var b = 0.1
114
114
  var r = pre.toDouble
115
- while (optionally[Int] { readDigit() } is Some(d)) {
115
+ while (returning::optionally[Int] { readDigit() } is Some(d)) {
116
116
  r = r + b * d.toDouble
117
117
  b = b * 0.1
118
118
  }
@@ -126,14 +126,14 @@ def readDouble(): Double / Scan[Char] = {
126
126
 
127
127
  def expectString(string: String): Unit / { Scan[Char], Exception[WrongFormat] } =
128
128
  for[Char] { string.each } { char =>
129
- expect[Unit]("Expected " ++ string) { readIf(char) }
129
+ expect("Expected " ++ string) { readIf(char) }
130
130
  }
131
131
 
132
132
  /// Read and unescape a string in ""
133
133
  def readQuotedString(): Unit / { Scan[Char], emit[Char], Exception[WrongFormat] } = {
134
134
  try {
135
135
  skipWhitespace()
136
- expect[Unit]("Expected \"") { readIf('"') }
136
+ expect("Expected \"") { readIf('"') }
137
137
  while(read[Char]() is c and c != '"') {
138
138
  c match {
139
139
  case '\\' => read[Char]() match {
@@ -191,7 +191,7 @@ def decodeJsonObject(): Unit / {Scan[Char], JsonObjectBuilder, Exception[WrongFo
191
191
  }
192
192
  do skip[Char]()
193
193
  }
194
- def decodeJsonList(): Unit / {Scan[Char], JsonBuilder, Exception[WrongFormat]} = {
194
+ def decodeJsonList(): Unit / {Scan[Char], JsonBuilder, Exception[WrongFormat]} = {
195
195
  var first = true
196
196
  expectString("[")
197
197
  with boundary
@@ -278,7 +278,7 @@ def build[R](){ body: => R / JsonBuilder }: (R, JsonValue) = {
278
278
  }
279
279
  (x, r)
280
280
  }
281
- def buildList[R](){ body: => R / JsonBuilder }: (R, List[JsonValue]) = collectList[JsonValue, R] {
281
+ def buildList[R](){ body: => R / JsonBuilder }: (R, List[JsonValue]) = returning::collectList[JsonValue, R] {
282
282
  try body() with JsonBuilder {
283
283
  def number(n) = { do emit(Number(n)); resume(()) }
284
284
  def bool(b) = { do emit(Bool(b)); resume(()) }
@@ -296,7 +296,7 @@ def buildList[R](){ body: => R / JsonBuilder }: (R, List[JsonValue]) = collectLi
296
296
  }
297
297
  }
298
298
  }
299
- def buildDict[R](){ body: => R / JsonObjectBuilder }: (R, List[(String, JsonValue)]) = collectList[(String, JsonValue), R] {
299
+ def buildDict[R](){ body: => R / JsonObjectBuilder }: (R, List[(String, JsonValue)]) = returning::collectList[(String, JsonValue), R] {
300
300
  try body() with JsonObjectBuilder {
301
301
  def field(k) = resume { {v} =>
302
302
  val x = build{v}
@@ -315,10 +315,12 @@ namespace test {
315
315
 
316
316
  // Read quoted string
317
317
  feed("\"\ta\n\ra\"") {
318
- with scanner[Char, Unit]
318
+ with scanner[Char]
319
319
  println(collectString { readQuotedString() })
320
320
  }
321
321
 
322
+ println("")
323
+
322
324
  // Parse example
323
325
  feed("""{ "a": null, "b": [true,false,false,true], "f": 12.532 }"""){
324
326
  with scanner[Char]
@@ -336,8 +338,10 @@ namespace test {
336
338
  }
337
339
  handleJsonBuilder{d}{ decodeJson() }
338
340
  }
339
- try{
340
-
341
+
342
+ println("")
343
+
344
+ try {
341
345
  // Encode example
342
346
  encodeJson {
343
347
  do dict{
@@ -352,13 +356,15 @@ namespace test {
352
356
  }
353
357
  }
354
358
  }
355
-
359
+
360
+ println("")
361
+
356
362
  // format with intermediate value
357
- val j = feed("""{
358
- "a": null,
359
- "b": [true, false, false, true], "f": 12.532
363
+ val j = feed[JsonValue]("""{
364
+ "a": null,
365
+ "b": [true, false, false, true], "f": 12.532
360
366
  } """){
361
- with scanner[Char, JsonValue]
367
+ with returning::scanner[Char, JsonValue]
362
368
  build {
363
369
  decodeJson()
364
370
  }.second
@@ -366,18 +372,20 @@ namespace test {
366
372
  encodeJson{
367
373
  unbuild(j)
368
374
  }
369
-
375
+
376
+ println("")
377
+
370
378
  // format (minify) example
371
379
  encodeJson{
372
- feed("""{
373
- "a": null,
374
- "b": [true, false, false, true], "f": 12.532
380
+ feed("""{
381
+ "a": null,
382
+ "b": [true, false, false, true], "f": 12.532
375
383
  } """){
376
- with scanner[Char, Unit]
384
+ with scanner[Char]
377
385
  decodeJson()
378
386
  }
379
387
  }
380
-
388
+
381
389
  } with emit[String] { e =>
382
390
  resume(println(e))
383
391
  }