@effekt-lang/effekt 0.15.0 → 0.17.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 +0 -0
- package/libraries/common/args.effekt +1 -0
- package/libraries/common/array.effekt +4 -0
- package/libraries/common/effekt.effekt +54 -3
- package/libraries/common/io/filesystem.effekt +2 -0
- package/libraries/common/io.effekt +2 -1
- package/libraries/common/ref.effekt +3 -0
- package/libraries/llvm/array.c +5 -1
- package/libraries/llvm/bytearray.c +24 -18
- package/libraries/llvm/io.c +5 -5
- package/libraries/llvm/main.c +0 -1
- package/libraries/llvm/ref.c +2 -0
- package/libraries/llvm/rts.ll +20 -0
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/licenses/mit license - mit-license.html +26 -23
- package/licenses/the bsd license - bsd-license.html +27 -24
- package/licenses/the mit license - mit.html +27 -22
- package/package.json +1 -1
- package/libraries/llvm/sanity.c +0 -16
package/bin/effekt
CHANGED
|
Binary file
|
|
@@ -16,6 +16,7 @@ extern global def allocate[T](size: Int): Array[T] =
|
|
|
16
16
|
%z = call %Pos @c_array_new(%Int ${size})
|
|
17
17
|
ret %Pos %z
|
|
18
18
|
"""
|
|
19
|
+
vm "array::allocate(Int)"
|
|
19
20
|
|
|
20
21
|
/// Creates a new Array of size `size` filled with the value `init`
|
|
21
22
|
def array[T](size: Int, init: T): Array[T] = {
|
|
@@ -45,6 +46,7 @@ extern pure def size[T](arr: Array[T]): Int =
|
|
|
45
46
|
%z = call %Int @c_array_size(%Pos ${arr})
|
|
46
47
|
ret %Int %z
|
|
47
48
|
"""
|
|
49
|
+
vm "array::size[T](Array[T])"
|
|
48
50
|
|
|
49
51
|
/// Gets the element of the `arr` at given `index` in constant time.
|
|
50
52
|
/// Unchecked Precondition: `index` is in bounds (0 ≤ index < arr.size)
|
|
@@ -57,6 +59,7 @@ extern global def unsafeGet[T](arr: Array[T], index: Int): T =
|
|
|
57
59
|
%z = call %Pos @c_array_get(%Pos ${arr}, %Int ${index})
|
|
58
60
|
ret %Pos %z
|
|
59
61
|
"""
|
|
62
|
+
vm "array::unsafeGet[T](Array[T], Int)"
|
|
60
63
|
|
|
61
64
|
extern js """
|
|
62
65
|
function array$set(arr, index, value) {
|
|
@@ -76,6 +79,7 @@ extern global def unsafeSet[T](arr: Array[T], index: Int, value: T): Unit =
|
|
|
76
79
|
%z = call %Pos @c_array_set(%Pos ${arr}, %Int ${index}, %Pos ${value})
|
|
77
80
|
ret %Pos %z
|
|
78
81
|
"""
|
|
82
|
+
vm "array::unsafeSet[T](Array[T], Int, T)"
|
|
79
83
|
|
|
80
84
|
|
|
81
85
|
|
|
@@ -45,6 +45,7 @@ extern def println(value: String): Unit =
|
|
|
45
45
|
call void @c_io_println_String(%Pos ${value})
|
|
46
46
|
ret %Pos zeroinitializer ; Unit
|
|
47
47
|
"""
|
|
48
|
+
vm "effekt::println(String)"
|
|
48
49
|
|
|
49
50
|
def println(value: Int): Unit = println(value.show)
|
|
50
51
|
def println(value: Unit): Unit = println(value.show)
|
|
@@ -59,6 +60,7 @@ extern pure def show(value: Int): String =
|
|
|
59
60
|
%z = call %Pos @c_bytearray_show_Int(%Int ${value})
|
|
60
61
|
ret %Pos %z
|
|
61
62
|
"""
|
|
63
|
+
vm "effekt::show(Int)"
|
|
62
64
|
|
|
63
65
|
def show(value: Unit): String = "()"
|
|
64
66
|
|
|
@@ -69,6 +71,7 @@ extern pure def show(value: Double): String =
|
|
|
69
71
|
%z = call %Pos @c_bytearray_show_Double(%Double ${value})
|
|
70
72
|
ret %Pos %z
|
|
71
73
|
"""
|
|
74
|
+
vm "effekt::show(Double)"
|
|
72
75
|
|
|
73
76
|
def show(value: String): String =
|
|
74
77
|
value
|
|
@@ -83,6 +86,7 @@ extern pure def show(value: Char): String =
|
|
|
83
86
|
%z = call %Pos @c_bytearray_show_Char(%Int ${value})
|
|
84
87
|
ret %Pos %z
|
|
85
88
|
"""
|
|
89
|
+
vm "effekt::show(Char)"
|
|
86
90
|
|
|
87
91
|
extern pure def show(value: Byte): String =
|
|
88
92
|
js "'' + ${value}"
|
|
@@ -90,6 +94,7 @@ extern pure def show(value: Byte): String =
|
|
|
90
94
|
%z = call %Pos @c_bytearray_show_Byte(i8 ${value})
|
|
91
95
|
ret %Pos %z
|
|
92
96
|
"""
|
|
97
|
+
vm "effekt::show(Byte)"
|
|
93
98
|
|
|
94
99
|
extern pure def genericShow[R](value: R): String =
|
|
95
100
|
js "$effekt.show(${value})"
|
|
@@ -98,6 +103,7 @@ extern pure def genericShow[R](value: R): String =
|
|
|
98
103
|
extern io def inspect[R](value: R): Unit =
|
|
99
104
|
js { println(genericShow(value)) }
|
|
100
105
|
chez { println(genericShow(value)) }
|
|
106
|
+
vm "effekt::inspect(Any)"
|
|
101
107
|
|
|
102
108
|
|
|
103
109
|
// Strings
|
|
@@ -109,15 +115,16 @@ extern pure def infixConcat(s1: String, s2: String): String =
|
|
|
109
115
|
%spz = call %Pos @c_bytearray_concatenate(%Pos ${s1}, %Pos ${s2})
|
|
110
116
|
ret %Pos %spz
|
|
111
117
|
"""
|
|
118
|
+
vm "effekt::infixConcat(String, String)"
|
|
112
119
|
|
|
113
120
|
extern pure def length(str: String): Int =
|
|
114
121
|
js "${str}.length"
|
|
115
122
|
chez "(string-length ${str})"
|
|
116
123
|
llvm """
|
|
117
124
|
%x = call %Int @c_bytearray_size(%Pos ${str})
|
|
118
|
-
call void @erasePositive(%Pos ${str})
|
|
119
125
|
ret %Int %x
|
|
120
126
|
"""
|
|
127
|
+
vm "effekt::length(String)"
|
|
121
128
|
|
|
122
129
|
extern pure def unsafeSubstring(str: String, from: Int, to: Int): String =
|
|
123
130
|
js "${str}.substring(${from}, ${to})"
|
|
@@ -126,6 +133,7 @@ extern pure def unsafeSubstring(str: String, from: Int, to: Int): String =
|
|
|
126
133
|
%x = call %Pos @c_bytearray_substring(%Pos ${str}, i64 ${from}, i64 ${to})
|
|
127
134
|
ret %Pos %x
|
|
128
135
|
"""
|
|
136
|
+
vm "effekt::substring(String, Int, Int)"
|
|
129
137
|
|
|
130
138
|
|
|
131
139
|
// Side effecting ops
|
|
@@ -134,6 +142,7 @@ extern pure def unsafeSubstring(str: String, from: Int, to: Int): String =
|
|
|
134
142
|
extern io def random(): Double =
|
|
135
143
|
js "Math.random()"
|
|
136
144
|
chez "(random 1.0)"
|
|
145
|
+
vm "effekt::random()"
|
|
137
146
|
|
|
138
147
|
// References and state
|
|
139
148
|
// ====================
|
|
@@ -193,8 +202,7 @@ def differsFrom[R](x: R, y: R): Bool =
|
|
|
193
202
|
|
|
194
203
|
// TODO fix this in the pattern matching compiler
|
|
195
204
|
extern pure def infixEq(x: Unit, y: Unit): Bool =
|
|
196
|
-
|
|
197
|
-
chez "#t"
|
|
205
|
+
default { true }
|
|
198
206
|
|
|
199
207
|
extern pure def infixEq(x: Int, y: Int): Bool =
|
|
200
208
|
js "${x} === ${y}"
|
|
@@ -205,6 +213,7 @@ extern pure def infixEq(x: Int, y: Int): Bool =
|
|
|
205
213
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
206
214
|
ret %Pos %adt_boolean
|
|
207
215
|
"""
|
|
216
|
+
vm "effekt::infixEq(Int, Int)"
|
|
208
217
|
|
|
209
218
|
extern pure def infixNeq(x: Int, y: Int): Bool =
|
|
210
219
|
js "${x} !== ${y}"
|
|
@@ -215,6 +224,7 @@ extern pure def infixNeq(x: Int, y: Int): Bool =
|
|
|
215
224
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
216
225
|
ret %Pos %adt_boolean
|
|
217
226
|
"""
|
|
227
|
+
vm "effekt::infixNeq(Int, Int)"
|
|
218
228
|
|
|
219
229
|
extern pure def infixEq(x: Char, y: Char): Bool =
|
|
220
230
|
js "${x} === ${y}"
|
|
@@ -225,6 +235,7 @@ extern pure def infixEq(x: Char, y: Char): Bool =
|
|
|
225
235
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
226
236
|
ret %Pos %adt_boolean
|
|
227
237
|
"""
|
|
238
|
+
vm "effekt::infixEq(Char, Char)"
|
|
228
239
|
|
|
229
240
|
extern pure def infixNeq(x: Char, y: Char): Bool =
|
|
230
241
|
js "${x} !== ${y}"
|
|
@@ -243,6 +254,7 @@ extern pure def infixEq(x: String, y: String): Bool =
|
|
|
243
254
|
%res = call %Pos @c_bytearray_equal(%Pos ${x}, %Pos ${y})
|
|
244
255
|
ret %Pos %res
|
|
245
256
|
"""
|
|
257
|
+
vm "effekt::infixEq(String, String)"
|
|
246
258
|
|
|
247
259
|
def infixNeq(x: String, y: String): Bool = not(x == y)
|
|
248
260
|
|
|
@@ -257,6 +269,7 @@ extern pure def infixEq(x: Bool, y: Bool): Bool =
|
|
|
257
269
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
258
270
|
ret %Pos %adt_boolean
|
|
259
271
|
"""
|
|
272
|
+
vm "effekt::infixEq(Bool, Bool)"
|
|
260
273
|
|
|
261
274
|
extern pure def infixNeq(x: Bool, y: Bool): Bool =
|
|
262
275
|
js "${x} !== ${y}"
|
|
@@ -277,67 +290,81 @@ extern pure def infixAdd(x: Int, y: Int): Int =
|
|
|
277
290
|
js "(${x} + ${y})"
|
|
278
291
|
chez "(+ ${x} ${y})"
|
|
279
292
|
llvm "%z = add %Int ${x}, ${y} ret %Int %z"
|
|
293
|
+
vm "effekt::infixAdd(Int, Int)"
|
|
280
294
|
|
|
281
295
|
extern pure def infixMul(x: Int, y: Int): Int =
|
|
282
296
|
js "(${x} * ${y})"
|
|
283
297
|
chez "(* ${x} ${y})"
|
|
284
298
|
llvm "%z = mul %Int ${x}, ${y} ret %Int %z"
|
|
299
|
+
vm "effekt::infixMul(Int, Int)"
|
|
285
300
|
|
|
286
301
|
extern pure def infixDiv(x: Int, y: Int): Int =
|
|
287
302
|
js "Math.floor(${x} / ${y})"
|
|
288
303
|
chez "(floor (/ ${x} ${y}))"
|
|
289
304
|
llvm "%z = sdiv %Int ${x}, ${y} ret %Int %z"
|
|
305
|
+
vm "effekt::infixDiv(Int, Int)"
|
|
290
306
|
|
|
291
307
|
extern pure def infixSub(x: Int, y: Int): Int =
|
|
292
308
|
js "(${x} - ${y})"
|
|
293
309
|
chez "(- ${x} ${y})"
|
|
294
310
|
llvm "%z = sub %Int ${x}, ${y} ret %Int %z"
|
|
311
|
+
vm "effekt::infixSub(Int, Int)"
|
|
295
312
|
|
|
296
313
|
extern pure def mod(x: Int, y: Int): Int =
|
|
297
314
|
js "(${x} % ${y})"
|
|
298
315
|
chez "(modulo ${x} ${y})"
|
|
299
316
|
llvm "%z = srem %Int ${x}, ${y} ret %Int %z"
|
|
317
|
+
vm "effekt::mod(Int, Int)"
|
|
300
318
|
|
|
301
319
|
extern pure def infixAdd(x: Double, y: Double): Double =
|
|
302
320
|
js "(${x} + ${y})"
|
|
303
321
|
chez "(+ ${x} ${y})"
|
|
304
322
|
llvm "%z = fadd %Double ${x}, ${y} ret %Double %z"
|
|
323
|
+
vm "effekt::infixAdd(Double, Double)"
|
|
305
324
|
|
|
306
325
|
extern pure def infixMul(x: Double, y: Double): Double =
|
|
307
326
|
js "(${x} * ${y})"
|
|
308
327
|
chez "(* ${x} ${y})"
|
|
309
328
|
llvm "%z = fmul %Double ${x}, ${y} ret %Double %z"
|
|
329
|
+
vm "effekt::infixMul(Double, Double)"
|
|
310
330
|
|
|
311
331
|
extern pure def infixSub(x: Double, y: Double): Double =
|
|
312
332
|
js "(${x} - ${y})"
|
|
313
333
|
chez "(- ${x} ${y})"
|
|
314
334
|
llvm "%z = fsub %Double ${x}, ${y} ret %Double %z"
|
|
335
|
+
vm "effekt::infixSub(Double, Double)"
|
|
315
336
|
|
|
316
337
|
extern pure def infixDiv(x: Double, y: Double): Double =
|
|
317
338
|
js "(${x} / ${y})"
|
|
318
339
|
chez "(/ ${x} ${y})"
|
|
319
340
|
llvm "%z = fdiv %Double ${x}, ${y} ret %Double %z"
|
|
341
|
+
vm "effekt::infixDiv(Double, Double)"
|
|
320
342
|
|
|
321
343
|
extern pure def cos(x: Double): Double =
|
|
322
344
|
js "Math.cos(${x})"
|
|
323
345
|
chez "(cos ${x})"
|
|
346
|
+
vm "effekt::cos(Double)"
|
|
324
347
|
|
|
325
348
|
extern pure def sin(x: Double): Double =
|
|
326
349
|
js "Math.sin(${x})"
|
|
327
350
|
chez "(sin ${x})"
|
|
351
|
+
vm "effekt::sin(Double)"
|
|
328
352
|
|
|
329
353
|
extern pure def atan(x: Double): Double =
|
|
330
354
|
js "Math.atan(${x})"
|
|
331
355
|
chez "(atan ${x})"
|
|
356
|
+
vm "effekt::atan(Double)"
|
|
332
357
|
|
|
333
358
|
extern pure def tan(x: Double): Double =
|
|
334
359
|
js "Math.tan(${x})"
|
|
335
360
|
chez "(tan ${x})"
|
|
361
|
+
vm "effekt::tan(Double)"
|
|
336
362
|
|
|
337
363
|
extern pure def sqrt(x: Double): Double =
|
|
338
364
|
js "Math.sqrt(${x})"
|
|
339
365
|
chez "(sqrt ${x})"
|
|
340
366
|
llvm "%z = call %Double @llvm.sqrt.f64(double ${x}) ret %Double %z"
|
|
367
|
+
vm "effekt::sqrt(Double)"
|
|
341
368
|
|
|
342
369
|
def square(x: Double): Double = x * x
|
|
343
370
|
|
|
@@ -353,6 +380,7 @@ def abs(n: Double): Double =
|
|
|
353
380
|
extern pure def log(x: Double): Double =
|
|
354
381
|
js "Math.log(${x})"
|
|
355
382
|
chez "(log ${x})"
|
|
383
|
+
vm "effekt::log(Double)"
|
|
356
384
|
|
|
357
385
|
extern pure def log1p(x: Double): Double =
|
|
358
386
|
js "Math.log1p(${x})"
|
|
@@ -361,6 +389,7 @@ extern pure def log1p(x: Double): Double =
|
|
|
361
389
|
extern pure def exp(x: Double): Double =
|
|
362
390
|
js "Math.exp(${x})"
|
|
363
391
|
chez "(exp ${x})"
|
|
392
|
+
vm "effekt::exp(Double)"
|
|
364
393
|
|
|
365
394
|
def pow(base: Double, exponent: Int): Double = {
|
|
366
395
|
def loop(base: Double, exponent: Int, acc: Double): Double = {
|
|
@@ -378,11 +407,13 @@ def pow(base: Double, exponent: Int): Double = {
|
|
|
378
407
|
extern pure def pow(base: Double, exponent: Double): Double =
|
|
379
408
|
js "Math.pow(${base}, ${exponent})"
|
|
380
409
|
chez "(expt ${base} ${exponent})"
|
|
410
|
+
vm "effekt::pow(Double, Double)"
|
|
381
411
|
|
|
382
412
|
// since we do not have "extern val", yet
|
|
383
413
|
extern pure def _pi(): Double =
|
|
384
414
|
js "Math.PI"
|
|
385
415
|
chez "(* 4 (atan 1))"
|
|
416
|
+
vm "effekt::pi()"
|
|
386
417
|
|
|
387
418
|
val PI: Double = _pi()
|
|
388
419
|
|
|
@@ -390,11 +421,14 @@ extern pure def toInt(d: Double): Int =
|
|
|
390
421
|
js "Math.trunc(${d})"
|
|
391
422
|
chez "(flonum->fixnum ${d})"
|
|
392
423
|
llvm "%z = fptosi double ${d} to %Int ret %Int %z"
|
|
424
|
+
vm "effekt::toInt(Double)"
|
|
393
425
|
|
|
394
426
|
extern pure def toDouble(d: Int): Double =
|
|
395
427
|
js "${d}"
|
|
396
428
|
chez "${d}"
|
|
397
429
|
llvm "%z = sitofp i64 ${d} to double ret double %z"
|
|
430
|
+
vm "effekt::toDouble(Int)"
|
|
431
|
+
|
|
398
432
|
|
|
399
433
|
extern pure def round(d: Double): Int =
|
|
400
434
|
js "Math.round(${d})"
|
|
@@ -403,6 +437,7 @@ extern pure def round(d: Double): Int =
|
|
|
403
437
|
%i = call %Double @llvm.round.f64(double ${d})
|
|
404
438
|
%z = fptosi double %i to %Int ret %Int %z
|
|
405
439
|
"""
|
|
440
|
+
vm "effekt::round(Double)"
|
|
406
441
|
|
|
407
442
|
def round(d: Double, digits: Int): Double = {
|
|
408
443
|
val factor = pow(10.0, digits)
|
|
@@ -447,6 +482,7 @@ extern pure def infixLt(x: Int, y: Int): Bool =
|
|
|
447
482
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
448
483
|
ret %Pos %adt_boolean
|
|
449
484
|
"""
|
|
485
|
+
vm "effekt::infixLt(Int, Int)"
|
|
450
486
|
|
|
451
487
|
extern pure def infixLte(x: Int, y: Int): Bool =
|
|
452
488
|
js "(${x} <= ${y})"
|
|
@@ -457,6 +493,7 @@ extern pure def infixLte(x: Int, y: Int): Bool =
|
|
|
457
493
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
458
494
|
ret %Pos %adt_boolean
|
|
459
495
|
"""
|
|
496
|
+
vm "effekt::infixLte(Int, Int)"
|
|
460
497
|
|
|
461
498
|
extern pure def infixGt(x: Int, y: Int): Bool =
|
|
462
499
|
js "(${x} > ${y})"
|
|
@@ -467,6 +504,7 @@ extern pure def infixGt(x: Int, y: Int): Bool =
|
|
|
467
504
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
468
505
|
ret %Pos %adt_boolean
|
|
469
506
|
"""
|
|
507
|
+
vm "effekt::infixGt(Int, Int)"
|
|
470
508
|
|
|
471
509
|
extern pure def infixGte(x: Int, y: Int): Bool =
|
|
472
510
|
js "(${x} >= ${y})"
|
|
@@ -477,14 +515,17 @@ extern pure def infixGte(x: Int, y: Int): Bool =
|
|
|
477
515
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
478
516
|
ret %Pos %adt_boolean
|
|
479
517
|
"""
|
|
518
|
+
vm "effekt::infixGte(Int, Int)"
|
|
480
519
|
|
|
481
520
|
extern pure def infixEq(x: Double, y: Double): Bool =
|
|
482
521
|
js "${x} === ${y}"
|
|
483
522
|
chez "(= ${x} ${y})"
|
|
523
|
+
vm "effekt::infixEq(Double, Double)"
|
|
484
524
|
|
|
485
525
|
extern pure def infixNeq(x: Double, y: Double): Bool =
|
|
486
526
|
js "${x} !== ${y}"
|
|
487
527
|
chez "(not (= ${x} ${y}))"
|
|
528
|
+
vm "effekt::infixNeq(Double, Double)"
|
|
488
529
|
|
|
489
530
|
extern pure def infixLt(x: Double, y: Double): Bool =
|
|
490
531
|
js "(${x} < ${y})"
|
|
@@ -495,10 +536,12 @@ extern pure def infixLt(x: Double, y: Double): Bool =
|
|
|
495
536
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
496
537
|
ret %Pos %adt_boolean
|
|
497
538
|
"""
|
|
539
|
+
vm "effekt::infixLt(Double, Double)"
|
|
498
540
|
|
|
499
541
|
extern pure def infixLte(x: Double, y: Double): Bool =
|
|
500
542
|
js "(${x} <= ${y})"
|
|
501
543
|
chez "(<= ${x} ${y})"
|
|
544
|
+
vm "effekt::infixLte(Double, Double)"
|
|
502
545
|
|
|
503
546
|
extern pure def infixGt(x: Double, y: Double): Bool =
|
|
504
547
|
js "(${x} > ${y})"
|
|
@@ -509,10 +552,12 @@ extern pure def infixGt(x: Double, y: Double): Bool =
|
|
|
509
552
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
510
553
|
ret %Pos %adt_boolean
|
|
511
554
|
"""
|
|
555
|
+
vm "effekt::infixGt(Double, Double)"
|
|
512
556
|
|
|
513
557
|
extern pure def infixGte(x: Double, y: Double): Bool =
|
|
514
558
|
js "(${x} >= ${y})"
|
|
515
559
|
chez "(>= ${x} ${y})"
|
|
560
|
+
vm "effekt::infixGte(Double, Double)"
|
|
516
561
|
|
|
517
562
|
// TODO do we really need those? if yes, move to string.effekt
|
|
518
563
|
extern pure def infixLt(x: String, y: String): Bool =
|
|
@@ -543,6 +588,7 @@ extern pure def not(b: Bool): Bool =
|
|
|
543
588
|
%adt_q = insertvalue %Pos zeroinitializer, i64 %q, 0
|
|
544
589
|
ret %Pos %adt_q
|
|
545
590
|
"""
|
|
591
|
+
vm "effekt::not(Bool)"
|
|
546
592
|
|
|
547
593
|
def infixOr { first: => Bool } { second: => Bool }: Bool =
|
|
548
594
|
if (first()) true else second()
|
|
@@ -559,27 +605,32 @@ extern pure def bitwiseShl(x: Int, y: Int): Int =
|
|
|
559
605
|
js "(${x} << ${y})"
|
|
560
606
|
chez "(ash ${x} ${y})"
|
|
561
607
|
llvm "%z = shl %Int ${x}, ${y} ret %Int %z"
|
|
608
|
+
vm "effekt::bitwiseShl(Int, Int)"
|
|
562
609
|
|
|
563
610
|
/// Arithmetic right shift
|
|
564
611
|
extern pure def bitwiseShr(x: Int, y: Int): Int =
|
|
565
612
|
js "(${x} >> ${y})"
|
|
566
613
|
chez "(ash ${x} (- ${y}))"
|
|
567
614
|
llvm "%z = ashr %Int ${x}, ${y} ret %Int %z"
|
|
615
|
+
vm "effekt::bitwiseShr(Int, Int)"
|
|
568
616
|
|
|
569
617
|
extern pure def bitwiseAnd(x: Int, y: Int): Int =
|
|
570
618
|
js "(${x} & ${y})"
|
|
571
619
|
chez "(logand ${x} ${y})"
|
|
572
620
|
llvm "%z = and %Int ${x}, ${y} ret %Int %z"
|
|
621
|
+
vm "effekt::bitwiseAnd(Int, Int)"
|
|
573
622
|
|
|
574
623
|
extern pure def bitwiseOr(x: Int, y: Int): Int =
|
|
575
624
|
js "(${x} | ${y})"
|
|
576
625
|
chez "(logior ${x} ${y})"
|
|
577
626
|
llvm "%z = or %Int ${x}, ${y} ret %Int %z"
|
|
627
|
+
vm "effekt::bitwiseOr(Int, Int)"
|
|
578
628
|
|
|
579
629
|
extern pure def bitwiseXor(x: Int, y: Int): Int =
|
|
580
630
|
js "(${x} ^ ${y})"
|
|
581
631
|
chez "(logxor ${x} ${y})"
|
|
582
632
|
llvm "%z = xor %Int ${x}, ${y} ret %Int %z"
|
|
633
|
+
vm "effekt::bitwiseXor(Int, Int)"
|
|
583
634
|
|
|
584
635
|
|
|
585
636
|
// Byte operations
|
|
@@ -198,6 +198,7 @@ namespace internal {
|
|
|
198
198
|
ret void
|
|
199
199
|
"""
|
|
200
200
|
|
|
201
|
+
/// The buffer must be kept alive by using it after the call
|
|
201
202
|
extern async def read(file: Int, buffer: ByteArray, offset: Int, size: Int, position: Int): Int =
|
|
202
203
|
jsNode "$effekt.capture(callback => read(${file}, ${buffer}, ${offset}, ${size}, ${position}, callback))"
|
|
203
204
|
llvm """
|
|
@@ -205,6 +206,7 @@ namespace internal {
|
|
|
205
206
|
ret void
|
|
206
207
|
"""
|
|
207
208
|
|
|
209
|
+
/// The buffer must be kept alive by using it after the call
|
|
208
210
|
extern async def write(file: Int, buffer: ByteArray, offset: Int, size: Int, position: Int): Int =
|
|
209
211
|
jsNode "$effekt.capture(callback => write(${file}, ${buffer}, ${offset}, ${size}, ${position}, callback))"
|
|
210
212
|
llvm """
|
|
@@ -16,7 +16,8 @@ extern async def spawn(task: Task[Unit]): Unit =
|
|
|
16
16
|
js "$effekt.capture(k => { setTimeout(() => k($effekt.unit), 0); return $effekt.run(${task}) })"
|
|
17
17
|
llvm """
|
|
18
18
|
call void @c_yield(%Stack %stack)
|
|
19
|
-
call
|
|
19
|
+
%unboxed = call ccc %Neg @unbox(%Pos ${task})
|
|
20
|
+
call void @run(%Neg %unboxed)
|
|
20
21
|
ret void
|
|
21
22
|
"""
|
|
22
23
|
|
|
@@ -30,6 +30,7 @@ extern global def ref[T](init: T): Ref[T] =
|
|
|
30
30
|
%z = call %Pos @c_ref_fresh(%Pos ${init})
|
|
31
31
|
ret %Pos %z
|
|
32
32
|
"""
|
|
33
|
+
vm "ref::ref[T](T)"
|
|
33
34
|
|
|
34
35
|
/// Gets the referenced element of the `ref` in constant time.
|
|
35
36
|
extern global def get[T](ref: Ref[T]): T =
|
|
@@ -39,6 +40,7 @@ extern global def get[T](ref: Ref[T]): T =
|
|
|
39
40
|
%z = call %Pos @c_ref_get(%Pos ${ref})
|
|
40
41
|
ret %Pos %z
|
|
41
42
|
"""
|
|
43
|
+
vm "ref::get[T](Ref[T])"
|
|
42
44
|
|
|
43
45
|
/// Sets the referenced element of the `ref` to `value` in constant time.
|
|
44
46
|
extern global def set[T](ref: Ref[T], value: T): Unit =
|
|
@@ -48,3 +50,4 @@ extern global def set[T](ref: Ref[T], value: T): Unit =
|
|
|
48
50
|
%z = call %Pos @c_ref_set(%Pos ${ref}, %Pos ${value})
|
|
49
51
|
ret %Pos %z
|
|
50
52
|
"""
|
|
53
|
+
vm "ref::set[T](Ref[T], T)"
|
package/libraries/llvm/array.c
CHANGED
|
@@ -32,13 +32,16 @@ struct Pos c_array_new(const Int size) {
|
|
|
32
32
|
|
|
33
33
|
Int c_array_size(const struct Pos arr) {
|
|
34
34
|
uint64_t *sizePtr = arr.obj + sizeof(struct Header);
|
|
35
|
-
|
|
35
|
+
uint64_t size = *sizePtr;
|
|
36
|
+
erasePositive(arr);
|
|
37
|
+
return size;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
struct Pos c_array_get(const struct Pos arr, const Int index) {
|
|
39
41
|
struct Pos *dataPtr = arr.obj + sizeof(struct Header) + sizeof(uint64_t);
|
|
40
42
|
struct Pos element = dataPtr[index];
|
|
41
43
|
sharePositive(element);
|
|
44
|
+
erasePositive(arr);
|
|
42
45
|
return element;
|
|
43
46
|
}
|
|
44
47
|
|
|
@@ -47,6 +50,7 @@ struct Pos c_array_set(const struct Pos arr, const Int index, const struct Pos v
|
|
|
47
50
|
struct Pos element = dataPtr[index];
|
|
48
51
|
erasePositive(element);
|
|
49
52
|
dataPtr[index] = value;
|
|
53
|
+
erasePositive(arr);
|
|
50
54
|
return Unit;
|
|
51
55
|
}
|
|
52
56
|
|
|
@@ -29,30 +29,34 @@ struct Pos c_bytearray_new(const Int size) {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
Int c_bytearray_size(const struct Pos arr) {
|
|
32
|
+
erasePositive(arr);
|
|
32
33
|
return arr.tag;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
uint8_t* c_bytearray_data(const struct Pos arr) {
|
|
36
|
-
return arr.obj + sizeof(struct Header);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
36
|
Byte c_bytearray_get(const struct Pos arr, const Int index) {
|
|
40
37
|
Byte *dataPtr = arr.obj + sizeof(struct Header);
|
|
41
38
|
Byte element = dataPtr[index];
|
|
39
|
+
erasePositive(arr);
|
|
42
40
|
return element;
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
struct Pos c_bytearray_set(const struct Pos arr, const Int index, const Byte value) {
|
|
46
44
|
Byte *dataPtr = arr.obj + sizeof(struct Header);
|
|
47
45
|
dataPtr[index] = value;
|
|
46
|
+
erasePositive(arr);
|
|
48
47
|
return Unit;
|
|
49
48
|
}
|
|
50
49
|
|
|
50
|
+
// Internal Operations
|
|
51
|
+
|
|
52
|
+
uint8_t* c_bytearray_data(const struct Pos arr) {
|
|
53
|
+
uint8_t *data = arr.obj + sizeof(struct Header);
|
|
54
|
+
return data;
|
|
55
|
+
}
|
|
56
|
+
|
|
51
57
|
struct Pos c_bytearray_construct(const uint64_t n, const uint8_t *data) {
|
|
52
58
|
struct Pos arr = c_bytearray_new(n);
|
|
53
|
-
|
|
54
59
|
memcpy(c_bytearray_data(arr), data, n);
|
|
55
|
-
|
|
56
60
|
return arr;
|
|
57
61
|
}
|
|
58
62
|
|
|
@@ -66,7 +70,7 @@ struct Pos c_bytearray_from_nullterminated_string(const char *data) {
|
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
char* c_bytearray_into_nullterminated_string(const struct Pos arr) {
|
|
69
|
-
uint64_t size =
|
|
73
|
+
uint64_t size = arr.tag;
|
|
70
74
|
|
|
71
75
|
char* result = (char*)malloc(size + 1);
|
|
72
76
|
|
|
@@ -125,12 +129,14 @@ struct Pos c_bytearray_show_Double(const Double x) {
|
|
|
125
129
|
|
|
126
130
|
// TODO do this in Effekt
|
|
127
131
|
struct Pos c_bytearray_concatenate(const struct Pos left, const struct Pos right) {
|
|
128
|
-
|
|
129
|
-
|
|
132
|
+
uint64_t left_size = left.tag;
|
|
133
|
+
uint64_t right_size = right.tag;
|
|
134
|
+
const struct Pos concatenated = c_bytearray_new(left_size + right_size);
|
|
135
|
+
for (uint64_t j = 0; j < concatenated.tag; ++j)
|
|
130
136
|
c_bytearray_data(concatenated)[j]
|
|
131
|
-
= j <
|
|
137
|
+
= j < left_size
|
|
132
138
|
? c_bytearray_data(left)[j]
|
|
133
|
-
: c_bytearray_data(right)[j -
|
|
139
|
+
: c_bytearray_data(right)[j - left_size];
|
|
134
140
|
|
|
135
141
|
erasePositive(left);
|
|
136
142
|
erasePositive(right);
|
|
@@ -139,8 +145,8 @@ struct Pos c_bytearray_concatenate(const struct Pos left, const struct Pos right
|
|
|
139
145
|
|
|
140
146
|
// TODO do this in Effekt
|
|
141
147
|
struct Pos c_bytearray_equal(const struct Pos left, const struct Pos right) {
|
|
142
|
-
uint64_t left_size =
|
|
143
|
-
uint64_t right_size =
|
|
148
|
+
uint64_t left_size = left.tag;
|
|
149
|
+
uint64_t right_size = right.tag;
|
|
144
150
|
if (left_size != right_size) {
|
|
145
151
|
erasePositive(left);
|
|
146
152
|
erasePositive(right);
|
|
@@ -161,7 +167,7 @@ struct Pos c_bytearray_equal(const struct Pos left, const struct Pos right) {
|
|
|
161
167
|
// TODO deprecate
|
|
162
168
|
struct Pos c_bytearray_substring(const struct Pos str, uint64_t start, uint64_t end) {
|
|
163
169
|
const struct Pos substr = c_bytearray_new(end - start);
|
|
164
|
-
for (
|
|
170
|
+
for (uint64_t j = 0; j < substr.tag; ++j) {
|
|
165
171
|
c_bytearray_data(substr)[j] = c_bytearray_data(str)[start+j];
|
|
166
172
|
}
|
|
167
173
|
erasePositive(str);
|
|
@@ -174,27 +180,27 @@ uint32_t c_bytearray_character_at(const struct Pos str, const uint64_t index) {
|
|
|
174
180
|
uint8_t first_byte = bytes[index];
|
|
175
181
|
uint32_t character = 0;
|
|
176
182
|
|
|
177
|
-
uint32_t
|
|
183
|
+
uint32_t size = str.tag;
|
|
178
184
|
|
|
179
185
|
if (first_byte < 0x80) {
|
|
180
186
|
// Single-byte character (0xxxxxxx)
|
|
181
187
|
character = first_byte;
|
|
182
188
|
} else if ((first_byte & 0xE0) == 0xC0) {
|
|
183
189
|
// Two-byte character (110xxxxx 10xxxxxx)
|
|
184
|
-
if (index + 1 <
|
|
190
|
+
if (index + 1 < size) {
|
|
185
191
|
character = ((first_byte & 0x1F) << 6) |
|
|
186
192
|
(bytes[index + 1] & 0x3F);
|
|
187
193
|
}
|
|
188
194
|
} else if ((first_byte & 0xF0) == 0xE0) {
|
|
189
195
|
// Three-byte character (1110xxxx 10xxxxxx 10xxxxxx)
|
|
190
|
-
if (index + 2 <
|
|
196
|
+
if (index + 2 < size) {
|
|
191
197
|
character = ((first_byte & 0x0F) << 12) |
|
|
192
198
|
((bytes[index + 1] & 0x3F) << 6) |
|
|
193
199
|
(bytes[index + 2] & 0x3F);
|
|
194
200
|
}
|
|
195
201
|
} else if ((first_byte & 0xF8) == 0xF0) {
|
|
196
202
|
// Four-byte character (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)
|
|
197
|
-
if (index + 3 <
|
|
203
|
+
if (index + 3 < size) {
|
|
198
204
|
character = ((first_byte & 0x07) << 18) |
|
|
199
205
|
((bytes[index + 1] & 0x3F) << 12) |
|
|
200
206
|
((bytes[index + 2] & 0x3F) << 6) |
|
package/libraries/llvm/io.c
CHANGED
|
@@ -20,7 +20,7 @@ void c_io_println_Double(const Double x) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
void c_io_println_String(String text) {
|
|
23
|
-
for (
|
|
23
|
+
for (uint64_t j = 0; j < text.tag; ++j)
|
|
24
24
|
putchar(c_bytearray_data(text)[j]);
|
|
25
25
|
erasePositive(text);
|
|
26
26
|
putchar('\n');
|
|
@@ -126,8 +126,8 @@ void c_fs_open(String path, struct Pos mode, Stack stack) {
|
|
|
126
126
|
void c_fs_read(Int file, struct Pos buffer, Int offset, Int size, Int position, Stack stack) {
|
|
127
127
|
|
|
128
128
|
uv_buf_t buf = uv_buf_init((char*)(c_bytearray_data(buffer) + offset), size);
|
|
129
|
-
|
|
130
|
-
// TODO
|
|
129
|
+
erasePositive(buffer);
|
|
130
|
+
// TODO panic if this was the last reference
|
|
131
131
|
|
|
132
132
|
uv_fs_t* request = malloc(sizeof(uv_fs_t));
|
|
133
133
|
request->data = stack;
|
|
@@ -144,8 +144,8 @@ void c_fs_read(Int file, struct Pos buffer, Int offset, Int size, Int position,
|
|
|
144
144
|
void c_fs_write(Int file, struct Pos buffer, Int offset, Int size, Int position, Stack stack) {
|
|
145
145
|
|
|
146
146
|
uv_buf_t buf = uv_buf_init((char*)(c_bytearray_data(buffer) + offset), size);
|
|
147
|
-
|
|
148
|
-
// TODO
|
|
147
|
+
erasePositive(buffer);
|
|
148
|
+
// TODO panic if this was the last reference
|
|
149
149
|
|
|
150
150
|
uv_fs_t* request = malloc(sizeof(uv_fs_t));
|
|
151
151
|
request->data = stack;
|
package/libraries/llvm/main.c
CHANGED
package/libraries/llvm/ref.c
CHANGED
|
@@ -31,6 +31,7 @@ struct Pos c_ref_get(const struct Pos ref) {
|
|
|
31
31
|
struct Pos *fieldPtr = ref.obj + sizeof(struct Header);
|
|
32
32
|
struct Pos element = *fieldPtr;
|
|
33
33
|
sharePositive(element);
|
|
34
|
+
erasePositive(ref);
|
|
34
35
|
return element;
|
|
35
36
|
}
|
|
36
37
|
|
|
@@ -39,6 +40,7 @@ struct Pos c_ref_set(const struct Pos ref, const struct Pos value) {
|
|
|
39
40
|
struct Pos element = *fieldPtr;
|
|
40
41
|
erasePositive(element);
|
|
41
42
|
*fieldPtr = value;
|
|
43
|
+
erasePositive(ref);
|
|
42
44
|
return Unit;
|
|
43
45
|
}
|
|
44
46
|
|
package/libraries/llvm/rts.ll
CHANGED
|
@@ -114,6 +114,26 @@ declare void @exit(i64)
|
|
|
114
114
|
declare void @llvm.assume(i1)
|
|
115
115
|
|
|
116
116
|
|
|
117
|
+
; Boxing (externs functions, hence ccc)
|
|
118
|
+
define ccc %Pos @box(%Neg %input) {
|
|
119
|
+
%vtable = extractvalue %Neg %input, 0
|
|
120
|
+
%heap_obj = extractvalue %Neg %input, 1
|
|
121
|
+
%vtable_as_int = ptrtoint ptr %vtable to i64
|
|
122
|
+
%pos_result = insertvalue %Pos undef, i64 %vtable_as_int, 0
|
|
123
|
+
%pos_result_with_heap = insertvalue %Pos %pos_result, ptr %heap_obj, 1
|
|
124
|
+
ret %Pos %pos_result_with_heap
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
define ccc %Neg @unbox(%Pos %input) {
|
|
128
|
+
%tag = extractvalue %Pos %input, 0
|
|
129
|
+
%heap_obj = extractvalue %Pos %input, 1
|
|
130
|
+
%vtable = inttoptr i64 %tag to ptr
|
|
131
|
+
%neg_result = insertvalue %Neg undef, ptr %vtable, 0
|
|
132
|
+
%neg_result_with_heap = insertvalue %Neg %neg_result, ptr %heap_obj, 1
|
|
133
|
+
ret %Neg %neg_result_with_heap
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
117
137
|
; Prompts
|
|
118
138
|
|
|
119
139
|
define private %Prompt @currentPrompt(%Stack %stack) {
|