@@ -5,6 +5,7 @@ import effekt
5
5
import exception
6
6
import option
7
7
import result
8
+ import stream
8
9
9
10
10
11
/// Checks if the given character is an ASCII whitespace
@@ -175,3 +176,89 @@ def utf16UnitCount(codepoint: Char): Int = codepoint match {
175
176
extern def charWidth(c: Char) at {}: Int =
176
177
// JavaScript strings are UTF-16 where every unicode character after 0xffff takes two units
177
178
js "(${c} > 0xffff) ? 2 : 1"
179
+
180
+
181
+ def writeLine { body: () => Unit / emit[Char] }: Unit / emit[Char] =
182
+ returning::writeLine[Unit]{body}
183
+
184
+ def readLine { body: () => Unit / read[Char] }: Unit / {read[Char], stop} =
185
+ returning::readLine[Unit]{body}
186
+
187
+ namespace returning {
188
+ def writeLine[R] { body: () => R / emit[Char] }: R / emit[Char] = {
189
+ val result = body()
190
+ do emit('\n')
191
+ return result
192
+ }
193
+
194
+ def readLine[R] { body: () => R / read[Char] }: R / {read[Char], stop} = {
195
+ var stopped = false
196
+ try {
197
+ body()
198
+ } with read[Char] {
199
+ if(stopped){
200
+ resume { do stop() }
201
+ } else {
202
+ do read[Char] match {
203
+ case '\n' => stopped = true; resume { do stop() }
204
+ case char => resume { return char }
205
+ }
206
+ }
207
+ }
208
+ }
209
+ }
210
+
211
+ def decodeChar(): Char / {read[Byte], stop} = {
212
+ val b = do read().toInt
213
+ if (b < 128) {
214
+ b.toChar
215
+ } else if (b < 224) {
216
+ val part1 = bitwiseShl(bitwiseAnd(b, 31), 6)
217
+ val part2 = bitwiseAnd(do read().toInt, 63)
218
+ bitwiseOr(part1, part2).toChar
219
+ } else if (b < 240) {
220
+ val part1 = bitwiseShl(bitwiseAnd(b, 15), 12)
221
+ val part2 = bitwiseShl(bitwiseAnd(do read().toInt, 63), 6)
222
+ val part3 = bitwiseAnd(do read().toInt, 63)
223
+ bitwiseOr(bitwiseOr(part1, part2), part3).toChar
224
+ } else {
225
+ val part1 = bitwiseShl(bitwiseAnd(b, 7), 18)
226
+ val part2 = bitwiseShl(bitwiseAnd(do read().toInt, 63), 12)
227
+ val part3 = bitwiseShl(bitwiseAnd(do read().toInt, 63), 6)
228
+ val part4 = bitwiseAnd(do read().toInt, 63)
229
+ bitwiseOr(bitwiseOr(bitwiseOr(part1, part2), part3), part4).toChar
230
+ }
231
+ }
232
+
233
+ def encodeChar(char: Char): Unit / emit[Byte] = {
234
+ val code = char.toInt
235
+ if (code < 128) {
236
+ do emit(code.toByte)
237
+ } else if (code < 2048) {
238
+ do emit(bitwiseOr(192, bitwiseShr(code, 6)).toByte)
239
+ do emit(bitwiseOr(128, bitwiseAnd(code, 63)).toByte)
240
+ } else if (code < 65536) {
241
+ do emit(bitwiseOr(224, bitwiseShr(code, 12)).toByte)
242
+ do emit(bitwiseOr(128, bitwiseAnd(bitwiseShr(code, 6), 63)).toByte)
243
+ do emit(bitwiseOr(128, bitwiseAnd(code, 63)).toByte)
244
+ } else {
245
+ do emit(bitwiseOr(240, bitwiseShr(code, 18)).toByte)
246
+ do emit(bitwiseOr(128, bitwiseAnd(bitwiseShr(code, 12), 63)).toByte)
247
+ do emit(bitwiseOr(128, bitwiseAnd(bitwiseShr(code, 6), 63)).toByte)
248
+ do emit(bitwiseOr(128, bitwiseAnd(code, 63)).toByte)
249
+ }
250
+ }
251
+
252
+ def decodeUTF8[R] { reader: () => R / read[Char] }: R / read[Byte] =
253
+ try {
254
+ reader()
255
+ } with read[Char] {
256
+ resume { decodeChar() }
257
+ }
258
+
259
+ def encodeUTF8[R] { stream: () => R / emit[Char] }: R / emit[Byte] =
260
+ try {
261
+ stream()
262
+ } with emit[Char] { char =>
263
+ resume(encodeChar(char))
264
+ }
0 commit comments