@effekt-lang/effekt 0.3.0 → 0.5.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/README.md +6 -18
- package/bin/effekt +0 -0
- package/libraries/common/args.effekt +0 -27
- package/libraries/common/array.effekt +34 -63
- package/libraries/common/bench.effekt +40 -22
- package/libraries/common/buffer.effekt +8 -20
- package/libraries/common/bytes.effekt +5 -15
- package/libraries/common/dequeue.effekt +5 -5
- package/libraries/common/effekt.effekt +51 -92
- package/libraries/common/exception.effekt +0 -1
- package/libraries/common/io/console.effekt +30 -36
- package/libraries/common/io/error.effekt +131 -30
- package/libraries/common/io/filesystem.effekt +262 -0
- package/libraries/common/io/network.effekt +30 -54
- package/libraries/common/io/time.effekt +9 -12
- package/libraries/common/io.effekt +54 -124
- package/libraries/common/list.effekt +345 -327
- package/libraries/common/process.effekt +0 -1
- package/libraries/common/queue.effekt +1 -3
- package/libraries/common/ref.effekt +11 -24
- package/libraries/common/result.effekt +6 -14
- package/libraries/common/seq.effekt +28 -49
- package/libraries/common/string/tty.effekt +66 -0
- package/libraries/common/string.effekt +7 -49
- package/libraries/common/test.effekt +96 -34
- package/libraries/js/unsafe/cont.effekt +1 -1
- package/libraries/llvm/io.c +258 -378
- package/libraries/llvm/main.c +3 -0
- package/libraries/llvm/rts.ll +57 -38
- package/libraries/llvm/types.c +10 -1
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +4 -4
- package/licenses/mit license - mit-license.html +21 -20
- package/licenses/the bsd license - bsd-license.html +20 -21
- package/licenses/the mit license - mit.html +22 -21
- package/package.json +1 -1
- package/libraries/chez/lift/effekt.ss +0 -118
- package/libraries/common/io/files.effekt +0 -282
- package/libraries/js/io.js +0 -143
- package/libraries/llvm/io.ll +0 -19
- package/libraries/ml/effekt.sml +0 -65
- package/libraries/ml/internal/mllist.effekt +0 -9
- package/libraries/ml/internal/mloption.effekt +0 -18
- package/libraries/ml/random.effekt +0 -85
- package/libraries/ml/text/regex.effekt +0 -102
|
@@ -3,52 +3,71 @@ module io
|
|
|
3
3
|
import ref
|
|
4
4
|
import queue
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// Asynchronous I/O
|
|
10
|
-
// ----------------
|
|
11
|
-
|
|
12
|
-
interface AsyncIO {
|
|
13
|
-
/**
|
|
14
|
-
* Runs the provided computation and conceptually waits until it completes by
|
|
15
|
-
* calling the writer-continuation.
|
|
16
|
-
*
|
|
17
|
-
* The provided writer-continuation should only ever be called ONCE.
|
|
18
|
-
* The computation is passed as a thunk in order to prevent accidental usage of
|
|
19
|
-
* other control effects that would violate the contract of calling the writer
|
|
20
|
-
* once.
|
|
21
|
-
*/
|
|
22
|
-
def performIO[T](computation: (T => Unit at {io, global}) => Unit at {io, global}): T
|
|
23
|
-
}
|
|
6
|
+
// Event Loop
|
|
7
|
+
// ----------
|
|
24
8
|
|
|
25
|
-
|
|
26
|
-
* Run an IO computation (that uses callbacks) here.
|
|
27
|
-
*/
|
|
28
|
-
def blocking(program: () => Unit / AsyncIO at {io, global}): Unit =
|
|
29
|
-
try { program() }
|
|
30
|
-
with AsyncIO {
|
|
31
|
-
def performIO[T](computation) = computation(resume)
|
|
32
|
-
}
|
|
9
|
+
type Task[T] = () => T at {io, async, global}
|
|
33
10
|
|
|
11
|
+
extern llvm """
|
|
12
|
+
declare void @c_yield(%Stack)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
extern async def spawn(task: Task[Unit]): Unit =
|
|
16
|
+
js "$effekt.callcc(callback => { setTimeout(() => callback($effekt.unit), 0); ${task}().run()})"
|
|
17
|
+
llvm """
|
|
18
|
+
call void @c_yield(%Stack %stack)
|
|
19
|
+
call void @run(%Neg ${task})
|
|
20
|
+
ret void
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
extern async def yield(): Unit =
|
|
24
|
+
js "$effekt.callcc(callback => setTimeout(() => callback($effekt.unit), 0))"
|
|
25
|
+
llvm """
|
|
26
|
+
call void @c_yield(%Stack %stack)
|
|
27
|
+
ret void
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
extern async def abort(): Nothing =
|
|
31
|
+
js "$effekt.callcc(callback => { return })"
|
|
32
|
+
llvm """
|
|
33
|
+
call void @eraseStack(%Stack %stack)
|
|
34
|
+
ret void
|
|
35
|
+
"""
|
|
34
36
|
|
|
35
|
-
interface Concurrent {
|
|
36
|
-
def yield(): Unit
|
|
37
|
-
def abort(): Nothing
|
|
38
|
-
}
|
|
39
37
|
|
|
40
38
|
// Promises
|
|
41
39
|
// --------
|
|
42
40
|
|
|
43
41
|
extern type Promise[T]
|
|
44
|
-
// = js "{
|
|
45
|
-
// = llvm "Promise"
|
|
42
|
+
// = js "{resolve: ƒ, promise: Promise}"
|
|
43
|
+
// = llvm "{tag: 0, obj: Promise*}"
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
def promise[T](task: Task[T]): Promise[T] = {
|
|
46
|
+
val p = promise::make[T]();
|
|
47
|
+
spawn(box { p.resolve(task()) });
|
|
48
|
+
return p
|
|
50
49
|
}
|
|
51
50
|
|
|
51
|
+
extern llvm """
|
|
52
|
+
declare %Pos @c_promise_make()
|
|
53
|
+
declare void @c_promise_resolve(%Pos, %Pos)
|
|
54
|
+
declare void @c_promise_await(%Pos, %Neg)
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
extern async def await[T](promise: Promise[T]): T =
|
|
58
|
+
js "$effekt.callcc(callback => ${promise}.promise.then(res => callback(res)))"
|
|
59
|
+
llvm """
|
|
60
|
+
call void @c_promise_await(%Pos ${promise}, %Stack %stack)
|
|
61
|
+
ret void
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
extern async def resolve[T](promise: Promise[T], value: T): Unit =
|
|
65
|
+
js "$effekt.callcc(callback => { ${promise}.resolve(${value}); callback($effekt.unit)})"
|
|
66
|
+
llvm """
|
|
67
|
+
call void @c_promise_resolve(%Pos ${promise}, %Pos ${value}, %Stack %stack)
|
|
68
|
+
ret void
|
|
69
|
+
"""
|
|
70
|
+
|
|
52
71
|
namespace promise {
|
|
53
72
|
extern js """
|
|
54
73
|
function promise$make() {
|
|
@@ -63,96 +82,7 @@ namespace promise {
|
|
|
63
82
|
extern io def make[T](): Promise[T] =
|
|
64
83
|
js "promise$make()"
|
|
65
84
|
llvm """
|
|
66
|
-
; Get the default loop and run it.
|
|
67
85
|
%promise = call %Pos @c_promise_make()
|
|
68
86
|
ret %Pos %promise
|
|
69
87
|
"""
|
|
70
|
-
|
|
71
|
-
extern io def resolve[T](p: Promise[T], value: T): Unit =
|
|
72
|
-
js "${p}.resolve(${value})"
|
|
73
|
-
llvm """
|
|
74
|
-
; Get the default loop and run it.
|
|
75
|
-
call void @c_promise_resolve(%Pos ${p}, %Pos ${value})
|
|
76
|
-
ret %Pos zeroinitializer
|
|
77
|
-
"""
|
|
78
|
-
|
|
79
|
-
extern io def await[T](p: Promise[T], callback: T => Unit at {io, global}): Unit =
|
|
80
|
-
js "${p}.promise.then(res => (${callback})(res).run())"
|
|
81
|
-
llvm """
|
|
82
|
-
; Get the default loop and run it.
|
|
83
|
-
call void @c_promise_await(%Pos ${p}, %Neg ${callback})
|
|
84
|
-
ret %Pos zeroinitializer
|
|
85
|
-
"""
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// TODO we cannot add effects Files, Console, etc. to Task since modules cannot be recursive, at the moment.
|
|
90
|
-
effect IO = { AsyncIO, Concurrent, Promises }
|
|
91
|
-
|
|
92
|
-
type Task[T] = () => T / IO at {io, global}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// Event Loop
|
|
96
|
-
// ----------
|
|
97
|
-
|
|
98
|
-
def eventloop(prog: Task[Unit]) = {
|
|
99
|
-
|
|
100
|
-
def handle(p: Task[Unit]): Unit =
|
|
101
|
-
try { p() }
|
|
102
|
-
with Concurrent {
|
|
103
|
-
def yield() = eventloop::schedule(box { resume(()) })
|
|
104
|
-
def abort() = ()
|
|
105
|
-
} with AsyncIO {
|
|
106
|
-
// TODO there is a bug in our LLVM backend where eta-reducing the following will break
|
|
107
|
-
def performIO[T](computation) = computation(box { t =>
|
|
108
|
-
eventloop::schedule(box { resume(t) })
|
|
109
|
-
})
|
|
110
|
-
} with Promises {
|
|
111
|
-
def promise[T](task: Task[T]) = {
|
|
112
|
-
val p = promise::make[T]();
|
|
113
|
-
handle(box {
|
|
114
|
-
val t = task()
|
|
115
|
-
promise::resolve(p, t)
|
|
116
|
-
})
|
|
117
|
-
eventloop::schedule( box { resume(p) })
|
|
118
|
-
}
|
|
119
|
-
def await[T](p: Promise[T]) = promise::await(p, box { t => resume(t) })
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
handle(prog)
|
|
123
|
-
|
|
124
|
-
eventloop::start()
|
|
125
|
-
eventloop::stop()
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
namespace eventloop {
|
|
129
|
-
extern io def schedule(program: () => Unit at {io, global}): Unit =
|
|
130
|
-
js "setTimeout(() => (${program})().run(), 0)"
|
|
131
|
-
llvm """
|
|
132
|
-
call void @c_timer_wait(i64 0, %Neg ${program})
|
|
133
|
-
ret %Pos zeroinitializer
|
|
134
|
-
"""
|
|
135
|
-
|
|
136
|
-
extern io def start(): Unit =
|
|
137
|
-
js "$effekt.unit"
|
|
138
|
-
llvm """
|
|
139
|
-
; Get the default loop and run it.
|
|
140
|
-
%loop = call ptr @uv_default_loop()
|
|
141
|
-
%run_result = call i32 @uv_run(ptr %loop, i32 0)
|
|
142
|
-
|
|
143
|
-
; return Unit
|
|
144
|
-
ret %Pos zeroinitializer
|
|
145
|
-
"""
|
|
146
|
-
|
|
147
|
-
extern io def stop(): Unit =
|
|
148
|
-
js "$effekt.unit"
|
|
149
|
-
llvm """
|
|
150
|
-
; Get the default loop, stop and close it.
|
|
151
|
-
%loop = call ptr @uv_default_loop()
|
|
152
|
-
call void @uv_stop(ptr %loop)
|
|
153
|
-
call void @uv_loop_close(ptr %loop)
|
|
154
|
-
|
|
155
|
-
; return Unit
|
|
156
|
-
ret %Pos zeroinitializer
|
|
157
|
-
"""
|
|
158
88
|
}
|