@effekt-lang/effekt 0.60.0 → 0.62.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/chez/common/effekt_primitives.ss +3 -1
- package/libraries/common/array.effekt +11 -9
- package/libraries/common/dequeue.effekt +2 -10
- package/libraries/common/effekt.effekt +26 -30
- package/libraries/common/list.effekt +13 -12
- package/libraries/common/map.effekt +1 -1
- package/libraries/common/option.effekt +1 -8
- package/libraries/common/partial.effekt +16 -0
- package/libraries/common/random.effekt +1 -1
- package/libraries/common/stream.effekt +4 -0
- package/libraries/common/stringbuffer.effekt +30 -32
- package/libraries/common/test.effekt +12 -1
- package/libraries/js/effekt_builtins.js +4 -0
- package/libraries/llvm/bytearray.c +4 -2
- package/libraries/llvm/forward-declare-c.ll +1 -0
- package/libraries/llvm/io.c +5 -1
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +11 -7
- package/licenses/mit license - mit-license.html +47 -45
- package/licenses/the bsd license - bsd-license.html +45 -45
- package/licenses/the mit license - mit.html +46 -44
- package/package.json +1 -1
package/bin/effekt
CHANGED
|
Binary file
|
|
@@ -60,6 +60,8 @@
|
|
|
60
60
|
out))
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
(define (print_impl str)
|
|
64
|
+
(display str))
|
|
63
65
|
|
|
64
66
|
(define (println_impl str)
|
|
65
67
|
(display str)
|
|
@@ -140,4 +142,4 @@
|
|
|
140
142
|
(raise
|
|
141
143
|
(condition
|
|
142
144
|
(make-error)
|
|
143
|
-
(make-message-condition ("should not be reachable!")))))
|
|
145
|
+
(make-message-condition ("should not be reachable!")))))
|
|
@@ -624,7 +624,9 @@ def sorted[A](arr: Array[A]) { ord: (A, A) => Ordering }: Array[A] = {
|
|
|
624
624
|
// Show Instances
|
|
625
625
|
// --------------
|
|
626
626
|
|
|
627
|
-
|
|
627
|
+
// TODO: These can eventually be replaced if we ever figure out monomorphization on extern types
|
|
628
|
+
|
|
629
|
+
def showBuiltin[A](arr: Array[A]) { showA: A => String }: String = {
|
|
628
630
|
var output = "Array("
|
|
629
631
|
val lastIndex = arr.size - 1
|
|
630
632
|
|
|
@@ -636,16 +638,16 @@ def show[A](arr: Array[A]) { showA: A => String }: String = {
|
|
|
636
638
|
|
|
637
639
|
output
|
|
638
640
|
}
|
|
639
|
-
def show(l: Array[Int]): String = show(l) { e => show(e) }
|
|
640
|
-
def show(l: Array[Double]): String = show(l) { e => show(e) }
|
|
641
|
-
def show(l: Array[Bool]): String = show(l) { e => show(e) }
|
|
642
|
-
def show(l: Array[String]): String = show(l) { e => e }
|
|
643
641
|
|
|
644
|
-
def
|
|
645
|
-
def
|
|
646
|
-
def
|
|
647
|
-
def
|
|
642
|
+
def showBuiltin(l: Array[Int]): String = showBuiltin(l) { e => show(e) }
|
|
643
|
+
def showBuiltin(l: Array[Double]): String = showBuiltin(l) { e => show(e) }
|
|
644
|
+
def showBuiltin(l: Array[Bool]): String = showBuiltin(l) { e => show(e) }
|
|
645
|
+
def showBuiltin(l: Array[String]): String = showBuiltin(l) { e => e }
|
|
648
646
|
|
|
647
|
+
def println(l: Array[Int]): Unit = println(showBuiltin(l))
|
|
648
|
+
def println(l: Array[Double]): Unit = println(showBuiltin(l))
|
|
649
|
+
def println(l: Array[Bool]): Unit = println(showBuiltin(l))
|
|
650
|
+
def println(l: Array[String]): Unit = println(showBuiltin(l))
|
|
649
651
|
|
|
650
652
|
// Streaming
|
|
651
653
|
// ---------
|
|
@@ -75,18 +75,10 @@ def popBack[R](dq: Dequeue[R]): Option[(R, Dequeue[R])] = dq match {
|
|
|
75
75
|
Some((x, Dequeue(f, fs, rest, rs - 1).check))
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
// TODO: Replace when monomorphization is merged
|
|
78
79
|
|
|
79
|
-
def show[A](d: Dequeue[A]) { showA: A => String }: String = {
|
|
80
|
-
val Dequeue(front, frontSize, rear, rearSize) = d;
|
|
81
|
-
"Dequeue(" ++ show(front){showA} ++ ", " ++ show(frontSize) ++ ", " ++
|
|
82
|
-
show(rear){showA} ++ ", " ++ show(rearSize) ++ ")"
|
|
83
|
-
}
|
|
84
|
-
def show(l: Dequeue[Int]): String = show(l) { e => show(e) }
|
|
85
|
-
def show(l: Dequeue[Double]): String = show(l) { e => show(e) }
|
|
86
|
-
def show(l: Dequeue[Bool]): String = show(l) { e => show(e) }
|
|
87
|
-
def show(l: Dequeue[String]): String = show(l) { e => e }
|
|
88
80
|
|
|
89
81
|
def println(l: Dequeue[Int]): Unit = println(show(l))
|
|
90
82
|
def println(l: Dequeue[Double]): Unit = println(show(l))
|
|
91
83
|
def println(l: Dequeue[Bool]): Unit = println(show(l))
|
|
92
|
-
def println(l: Dequeue[String]): Unit = println(show(l))
|
|
84
|
+
def println(l: Dequeue[String]): Unit = println(show(l))
|
|
@@ -38,6 +38,16 @@ namespace llvm {
|
|
|
38
38
|
// Showing and debugging
|
|
39
39
|
// =====================
|
|
40
40
|
|
|
41
|
+
extern def print(value: String): Unit =
|
|
42
|
+
jsWeb "$effekt.println(${value})"
|
|
43
|
+
jsNode "$effekt.print(${value})"
|
|
44
|
+
chez "(print_impl ${value})"
|
|
45
|
+
llvm """
|
|
46
|
+
call void @c_io_print(%Pos ${value})
|
|
47
|
+
ret %Pos zeroinitializer ; Unit
|
|
48
|
+
"""
|
|
49
|
+
vm "effekt::print(String)"
|
|
50
|
+
|
|
41
51
|
extern def println(value: String): Unit =
|
|
42
52
|
js "$effekt.println(${value})"
|
|
43
53
|
chez "(println_impl ${value})"
|
|
@@ -74,7 +84,7 @@ def println(value: Double): Unit = println(value.show)
|
|
|
74
84
|
def println(value: Bool): Unit = println(value.show)
|
|
75
85
|
def println(value: Byte): Unit = println(value.show)
|
|
76
86
|
|
|
77
|
-
extern def
|
|
87
|
+
extern def showBuiltin(value: Int) at {}: String =
|
|
78
88
|
js "'' + ${value}"
|
|
79
89
|
chez "(show-number ${value})"
|
|
80
90
|
llvm """
|
|
@@ -83,9 +93,7 @@ extern def show(value: Int) at {}: String =
|
|
|
83
93
|
"""
|
|
84
94
|
vm "effekt::show(Int)"
|
|
85
95
|
|
|
86
|
-
def
|
|
87
|
-
|
|
88
|
-
extern def show(value: Double) at {}: String =
|
|
96
|
+
extern def showBuiltin(value: Double) at {}: String =
|
|
89
97
|
js "'' + ${value}"
|
|
90
98
|
chez "(show-number ${value})"
|
|
91
99
|
llvm """
|
|
@@ -94,13 +102,7 @@ extern def show(value: Double) at {}: String =
|
|
|
94
102
|
"""
|
|
95
103
|
vm "effekt::show(Double)"
|
|
96
104
|
|
|
97
|
-
def
|
|
98
|
-
value
|
|
99
|
-
|
|
100
|
-
def show(value: Bool): String =
|
|
101
|
-
if (value) "true" else "false"
|
|
102
|
-
|
|
103
|
-
extern def show(value: Char) at {}: String =
|
|
105
|
+
extern def showBuiltin(value: Char) at {}: String =
|
|
104
106
|
js "String.fromCodePoint(${value})"
|
|
105
107
|
chez "(string (integer->char ${value}))"
|
|
106
108
|
llvm """
|
|
@@ -109,22 +111,17 @@ extern def show(value: Char) at {}: String =
|
|
|
109
111
|
"""
|
|
110
112
|
vm "effekt::show(Char)"
|
|
111
113
|
|
|
112
|
-
extern def
|
|
113
|
-
js "'' + ${value}"
|
|
114
|
-
chez "(
|
|
114
|
+
extern def showBuiltin(value: Byte) at {}: String =
|
|
115
|
+
js "'0x' + ${value}.toString(16).toUpperCase().padStart(2, '0')"
|
|
116
|
+
chez "(format #f \"0x~2,'0X\" ${value})"
|
|
115
117
|
llvm """
|
|
116
|
-
%z = call %Pos @c_bytearray_show_Byte(
|
|
118
|
+
%z = call %Pos @c_bytearray_show_Byte(%Byte ${value})
|
|
117
119
|
ret %Pos %z
|
|
118
120
|
"""
|
|
119
121
|
vm "effekt::show(Byte)"
|
|
120
122
|
|
|
121
|
-
extern def genericShow[R](value: R) at {}: String =
|
|
122
|
-
js "$effekt.show(${value})"
|
|
123
|
-
chez "(show_impl ${value})"
|
|
124
|
-
|
|
125
123
|
extern def inspect[R](value: R) at io: Unit =
|
|
126
|
-
|
|
127
|
-
chez { println(genericShow(value)) }
|
|
124
|
+
default { println(show(value)) }
|
|
128
125
|
vm "effekt::inspect(Any)"
|
|
129
126
|
|
|
130
127
|
/// A fatal runtime error that cannot be caught
|
|
@@ -137,6 +134,10 @@ extern def panic(msg: String) at io: Nothing =
|
|
|
137
134
|
ret %Pos zeroinitializer ; Unit
|
|
138
135
|
"""
|
|
139
136
|
|
|
137
|
+
extern def show[R](value: R) at {}: String =
|
|
138
|
+
js "$effekt.show(${value})"
|
|
139
|
+
chez "(show_impl ${value})"
|
|
140
|
+
llvm "ret %Pos poison"
|
|
140
141
|
|
|
141
142
|
// Strings
|
|
142
143
|
// =======
|
|
@@ -223,12 +224,6 @@ def genericCompare[R](x: R, y: R): Ordering = {
|
|
|
223
224
|
}
|
|
224
225
|
}
|
|
225
226
|
|
|
226
|
-
def show(o: Ordering): String = o match {
|
|
227
|
-
case Less() => "Less()"
|
|
228
|
-
case Equal() => "Equal()"
|
|
229
|
-
case Greater() => "Greater()"
|
|
230
|
-
}
|
|
231
|
-
|
|
232
227
|
def println(o: Ordering): Unit = println(o.show)
|
|
233
228
|
|
|
234
229
|
|
|
@@ -795,9 +790,9 @@ def locally[R] { p: => R } : R = p()
|
|
|
795
790
|
//
|
|
796
791
|
// "foo ${42} bar ${43}"
|
|
797
792
|
//
|
|
798
|
-
// to the following stream of `
|
|
793
|
+
// to the following stream of `write`s and `splice[Int]`s:
|
|
799
794
|
//
|
|
800
|
-
// do
|
|
795
|
+
// do write("foo "); do splice(42); do write(" bar "); do splice(43)
|
|
801
796
|
//
|
|
802
797
|
// The stream is wrapped into a handler function, which defaults to `stringbuffer::s`
|
|
803
798
|
//
|
|
@@ -805,7 +800,8 @@ def locally[R] { p: => R } : R = p()
|
|
|
805
800
|
//
|
|
806
801
|
// but can be specified by prefixing the string interpolation `custom"..."`.
|
|
807
802
|
|
|
808
|
-
effect
|
|
803
|
+
effect write(s: String): Unit
|
|
804
|
+
|
|
809
805
|
effect splice[A](x: A): Unit
|
|
810
806
|
|
|
811
807
|
|
|
@@ -74,6 +74,16 @@ def tail[A](l: List[A]): List[A] / Exception[MissingValue] = l match {
|
|
|
74
74
|
case Cons(a, rest) => rest
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/// Return all elements of a given list except the last element.
|
|
78
|
+
/// Throws a `MissingValue` exception if it's empty.
|
|
79
|
+
///
|
|
80
|
+
/// O(n)
|
|
81
|
+
def init[A](l: List[A]): List[A] / Exception[MissingValue] = l match {
|
|
82
|
+
case Nil() => do raise(MissingValue(), "Trying to get the beginning of an empty list")
|
|
83
|
+
case Cons(a, Nil()) => Nil()
|
|
84
|
+
case Cons(a, as) => Cons(a, as.init)
|
|
85
|
+
}
|
|
86
|
+
|
|
77
87
|
/// Return the first element of a given list.
|
|
78
88
|
/// Returns `None()` if it's empty.
|
|
79
89
|
///
|
|
@@ -914,24 +924,15 @@ def isSortedBy[A](list: List[A]) { lessOrEqual: (A, A) => Bool }: Bool = {
|
|
|
914
924
|
// Show Instances
|
|
915
925
|
// --------------
|
|
916
926
|
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
case Nil() => "Nil()"
|
|
920
|
-
case Cons(x, xs) => "Cons(" ++ showA(x) ++ ", " ++ go(xs) ++ ")"
|
|
921
|
-
}
|
|
922
|
-
go(l)
|
|
923
|
-
}
|
|
924
|
-
def show(l: List[Int]): String = show(l) { e => show(e) }
|
|
925
|
-
def show(l: List[Double]): String = show(l) { e => show(e) }
|
|
926
|
-
def show(l: List[Bool]): String = show(l) { e => show(e) }
|
|
927
|
-
def show(l: List[String]): String = show(l) { e => e }
|
|
927
|
+
// TODO: Get rid of these after monomorphization is merged
|
|
928
|
+
|
|
928
929
|
|
|
929
930
|
def println(l: List[Int]): Unit = println(show(l))
|
|
930
931
|
def println(l: List[Double]): Unit = println(show(l))
|
|
932
|
+
def println(l: List[Char]): Unit = println(show(l))
|
|
931
933
|
def println(l: List[Bool]): Unit = println(show(l))
|
|
932
934
|
def println(l: List[String]): Unit = println(show(l))
|
|
933
935
|
|
|
934
|
-
|
|
935
936
|
// Streaming
|
|
936
937
|
// ---------
|
|
937
938
|
|
|
@@ -969,7 +969,7 @@ namespace internal {
|
|
|
969
969
|
t match {
|
|
970
970
|
case Tip() => ""
|
|
971
971
|
case Bin(_, k, v, l, r) =>
|
|
972
|
-
val pair = k.
|
|
972
|
+
val pair = k.show ++ " → " ++ v.show
|
|
973
973
|
val currentLine = prefix ++ (if (isTail) "└── " else "├── ") ++ pair ++ "\n"
|
|
974
974
|
|
|
975
975
|
val newPrefix = prefix ++ (if (isTail) " " else "│ ")
|
|
@@ -59,14 +59,7 @@ def undefinedToOption[A](value: A): Option[A] =
|
|
|
59
59
|
// Show Instances
|
|
60
60
|
// --------------
|
|
61
61
|
|
|
62
|
-
def show[A](o: Option[A]) { showA: A => String }: String = o match {
|
|
63
|
-
case None() => "None()"
|
|
64
|
-
case Some(v) => "Some(" ++ showA(v) ++ ")"
|
|
65
|
-
}
|
|
66
|
-
def show(o: Option[Int]): String = show(o) { e => show(e) }
|
|
67
|
-
def show(o: Option[Double]): String = show(o) { e => show(e) }
|
|
68
|
-
def show(o: Option[Bool]): String = show(o) { e => show(e) }
|
|
69
62
|
|
|
70
63
|
def println(o: Option[Int]): Unit = println(show(o))
|
|
71
64
|
def println(o: Option[Double]): Unit = println(show(o))
|
|
72
|
-
def println(o: Option[Bool]): Unit = println(show(o))
|
|
65
|
+
def println(o: Option[Bool]): Unit = println(show(o))
|
|
@@ -46,3 +46,19 @@ def suchThat[A](value: A){ predicate: A => Bool }: Option[A] =
|
|
|
46
46
|
|
|
47
47
|
def getOrFail[A](option: Option[A]): A / fail =
|
|
48
48
|
option.getOrElse { do fail() }
|
|
49
|
+
|
|
50
|
+
namespace returning {
|
|
51
|
+
|
|
52
|
+
def exhaustively[R](init: R) { program: () => R / fail }: R =
|
|
53
|
+
var res = init
|
|
54
|
+
try {
|
|
55
|
+
def go(): R = {
|
|
56
|
+
res = program()
|
|
57
|
+
go()
|
|
58
|
+
}
|
|
59
|
+
go()
|
|
60
|
+
} with fail {
|
|
61
|
+
res
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
}
|
|
@@ -51,7 +51,7 @@ def minstd(seed: Int): Unit / emit[Byte] = {
|
|
|
51
51
|
///
|
|
52
52
|
/// Implementation is similar to `stream::source`, specialized for bytes and the `random` effect.
|
|
53
53
|
def minstd(seed: Int) { randomnessReader: () => Unit / random }: Unit = {
|
|
54
|
-
var next = box {
|
|
54
|
+
var next = box { 0xFF } // sentinel value
|
|
55
55
|
next = box {
|
|
56
56
|
try {
|
|
57
57
|
minstd(seed)
|
|
@@ -192,6 +192,10 @@ def countIf[A] { shouldCount: A => Bool } { stream: () => Unit / emit[A] }: Int
|
|
|
192
192
|
count
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
/// Count the number of emitted values.
|
|
196
|
+
def count[A] { stream: () => Unit / emit[A] }: Int =
|
|
197
|
+
countIf[A] { _ => true } {stream}
|
|
198
|
+
|
|
195
199
|
def source[A] { stream: () => Unit / emit[A] } { reader: () => Unit / read[A] }: Unit =
|
|
196
200
|
returning::source[A, Unit]{stream}{reader}
|
|
197
201
|
|
|
@@ -3,60 +3,58 @@ module stringbuffer
|
|
|
3
3
|
import effekt
|
|
4
4
|
import bytearray
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
6
|
+
effect flush(): String
|
|
7
|
+
|
|
8
|
+
def stringBuffer { program: () => Unit / write }: String =
|
|
9
|
+
flushableStringBuffer { program(); do flush() }
|
|
10
10
|
|
|
11
|
-
def
|
|
11
|
+
def flushableStringBuffer[A] { program: () => A / { write, flush } }: A = {
|
|
12
12
|
val initialCapacity = 128
|
|
13
13
|
var buffer = bytearray::allocate(initialCapacity)
|
|
14
14
|
// next free index to write to
|
|
15
|
-
var
|
|
15
|
+
var position = 0
|
|
16
16
|
|
|
17
|
-
def ensureCapacity(
|
|
18
|
-
val
|
|
19
|
-
if (
|
|
17
|
+
def ensureCapacity(required: Int): Unit = {
|
|
18
|
+
val capacity = buffer.size - position
|
|
19
|
+
if (required <= capacity) ()
|
|
20
20
|
else {
|
|
21
21
|
// Double the capacity while ensuring the required capacity
|
|
22
|
-
val newSize = max(buffer.size * 2, buffer.size +
|
|
22
|
+
val newSize = max(buffer.size * 2, buffer.size + required)
|
|
23
23
|
buffer = buffer.resize(newSize)
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
try {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
resume(())
|
|
37
|
-
}
|
|
38
|
-
def flush() = {
|
|
39
|
-
// resize (& copy) buffer to strip trailing zeros that otherwise would be converted into 0x00 characters
|
|
40
|
-
val str = bytearray::resize(buffer, pos).toString()
|
|
41
|
-
// NOTE: Keep the `buffer` as-is (no wipe, no realloc),
|
|
42
|
-
// just reset the `pos` in case we want to use it again.
|
|
43
|
-
pos = 0
|
|
44
|
-
resume(str)
|
|
27
|
+
try {
|
|
28
|
+
program()
|
|
29
|
+
} with write { string =>
|
|
30
|
+
val bytes = fromString(string)
|
|
31
|
+
ensureCapacity(bytes.size)
|
|
32
|
+
bytes.foreach { b =>
|
|
33
|
+
buffer.set(position, b)
|
|
34
|
+
position = position + 1
|
|
45
35
|
}
|
|
36
|
+
resume(())
|
|
37
|
+
} with flush {
|
|
38
|
+
val string = buffer.resize(position).toString()
|
|
39
|
+
position = 0
|
|
40
|
+
resume(string)
|
|
46
41
|
}
|
|
47
42
|
}
|
|
48
43
|
|
|
44
|
+
def splicing[T] { writer: T => Unit } { program: () => Unit / splice[T] }: Unit =
|
|
45
|
+
try { program() } with splice[T] { t => resume(writer(t)) }
|
|
46
|
+
|
|
47
|
+
|
|
49
48
|
/// Handler for string interpolation using a string buffer
|
|
50
|
-
def s {
|
|
49
|
+
def s { program: () => Unit / { write, splice[String] } }: String =
|
|
51
50
|
stringBuffer {
|
|
52
|
-
try {
|
|
51
|
+
try { program() }
|
|
53
52
|
with splice[String] { x => resume(do write(x)) }
|
|
54
|
-
with literal { s => resume(do write(s)) }
|
|
55
53
|
}
|
|
56
54
|
|
|
57
55
|
namespace examples {
|
|
58
56
|
def main() = {
|
|
59
|
-
with
|
|
57
|
+
with flushableStringBuffer
|
|
60
58
|
|
|
61
59
|
do write("hello")
|
|
62
60
|
do write(", world")
|
|
@@ -46,7 +46,7 @@ def assertEqual[A](obtained: A, expected: A, msg: String): Unit / Assertion =
|
|
|
46
46
|
assertEqual(obtained, expected, msg) { (x, y) => x.equals(y) }
|
|
47
47
|
|
|
48
48
|
def assertEqual[A](obtained: A, expected: A): Unit / { Assertion, Formatted } =
|
|
49
|
-
assertEqual(obtained, expected) { (x, y) => x.equals(y) } { x => x.
|
|
49
|
+
assertEqual(obtained, expected) { (x, y) => x.equals(y) } { x => x.show }
|
|
50
50
|
|
|
51
51
|
def assertEqual[A](obtained: A, expected: A, msg: String) { equals: (A, A) => Bool }: Unit / Assertion =
|
|
52
52
|
do assert(equals(obtained, expected), msg)
|
|
@@ -56,6 +56,17 @@ def assertEqual[A](obtained: A, expected: A) { equals: (A, A) => Bool } { show:
|
|
|
56
56
|
// NOTE: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
57
57
|
// Here's an accidental capture! Can we prevent this somehow nicely?
|
|
58
58
|
|
|
59
|
+
def assertNotThrown[E](ex: on[E]) { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
60
|
+
ex.default { do assert(false, "Unexpected Exception") } {body}
|
|
61
|
+
|
|
62
|
+
def assertNoThrow[E] { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
63
|
+
on[E].default{ do assert(false, "Unexpected Exception") } {body}
|
|
64
|
+
|
|
65
|
+
def assertThrown[E](ex: on[E]) { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
66
|
+
do assert(ex.default { true } { body(); false }, "Expected Exception, but exited normally")
|
|
67
|
+
|
|
68
|
+
def assertThrows[E] { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
69
|
+
do assert(on[E].default { true } { body(); false }, "Expected Exception, but exited normally")
|
|
59
70
|
|
|
60
71
|
interface Test {
|
|
61
72
|
def success(name: String, duration: Int): Unit
|
|
@@ -54,6 +54,10 @@ $effekt.println = function println$impl(str) {
|
|
|
54
54
|
console.log(str); return $effekt.unit;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
$effekt.print = function println$impl(str) {
|
|
58
|
+
process.stdout.write(str); return $effekt.unit;
|
|
59
|
+
}
|
|
60
|
+
|
|
57
61
|
$effekt.unit = { __unit: true }
|
|
58
62
|
|
|
59
63
|
$effekt.unreachable = function() { throw "should not be reachable!" }
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
#define EFFEKT_BYTEARRAY_C
|
|
3
3
|
|
|
4
4
|
#include <string.h> // For memcopy
|
|
5
|
+
#include <stdint.h>
|
|
6
|
+
#include <inttypes.h>
|
|
5
7
|
|
|
6
8
|
/** We represent bytearrays like positive types.
|
|
7
9
|
*
|
|
@@ -115,8 +117,8 @@ struct Pos c_bytearray_show_Char(const uint64_t n) {
|
|
|
115
117
|
|
|
116
118
|
// TODO do this in Effekt
|
|
117
119
|
struct Pos c_bytearray_show_Byte(const Byte n) {
|
|
118
|
-
char str[
|
|
119
|
-
snprintf(str, sizeof
|
|
120
|
+
char str[5]; // |"0x" ++ <2 hex digits> ++ '\0'| = 5
|
|
121
|
+
snprintf(str, sizeof str, "0x%02" PRIX8, (uint8_t)n);
|
|
120
122
|
return c_bytearray_from_nullterminated_string(str);
|
|
121
123
|
}
|
|
122
124
|
|
package/libraries/llvm/io.c
CHANGED
|
@@ -7,11 +7,15 @@
|
|
|
7
7
|
// Println and Readln and Random
|
|
8
8
|
// -----------------------------
|
|
9
9
|
|
|
10
|
-
void
|
|
10
|
+
void c_io_print(String text) {
|
|
11
11
|
for (uint64_t j = 0; j < text.tag; ++j) {
|
|
12
12
|
putchar(c_bytearray_data(text)[j]);
|
|
13
13
|
};
|
|
14
14
|
erasePositive(text);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
void c_io_println(String text) {
|
|
18
|
+
c_io_print(text);
|
|
15
19
|
putchar('\n');
|
|
16
20
|
}
|
|
17
21
|
|