@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.
Files changed (44) hide show
  1. package/README.md +6 -18
  2. package/bin/effekt +0 -0
  3. package/libraries/common/args.effekt +0 -27
  4. package/libraries/common/array.effekt +34 -63
  5. package/libraries/common/bench.effekt +40 -22
  6. package/libraries/common/buffer.effekt +8 -20
  7. package/libraries/common/bytes.effekt +5 -15
  8. package/libraries/common/dequeue.effekt +5 -5
  9. package/libraries/common/effekt.effekt +51 -92
  10. package/libraries/common/exception.effekt +0 -1
  11. package/libraries/common/io/console.effekt +30 -36
  12. package/libraries/common/io/error.effekt +131 -30
  13. package/libraries/common/io/filesystem.effekt +262 -0
  14. package/libraries/common/io/network.effekt +30 -54
  15. package/libraries/common/io/time.effekt +9 -12
  16. package/libraries/common/io.effekt +54 -124
  17. package/libraries/common/list.effekt +345 -327
  18. package/libraries/common/process.effekt +0 -1
  19. package/libraries/common/queue.effekt +1 -3
  20. package/libraries/common/ref.effekt +11 -24
  21. package/libraries/common/result.effekt +6 -14
  22. package/libraries/common/seq.effekt +28 -49
  23. package/libraries/common/string/tty.effekt +66 -0
  24. package/libraries/common/string.effekt +7 -49
  25. package/libraries/common/test.effekt +96 -34
  26. package/libraries/js/unsafe/cont.effekt +1 -1
  27. package/libraries/llvm/io.c +258 -378
  28. package/libraries/llvm/main.c +3 -0
  29. package/libraries/llvm/rts.ll +57 -38
  30. package/libraries/llvm/types.c +10 -1
  31. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +4 -4
  32. package/licenses/mit license - mit-license.html +21 -20
  33. package/licenses/the bsd license - bsd-license.html +20 -21
  34. package/licenses/the mit license - mit.html +22 -21
  35. package/package.json +1 -1
  36. package/libraries/chez/lift/effekt.ss +0 -118
  37. package/libraries/common/io/files.effekt +0 -282
  38. package/libraries/js/io.js +0 -143
  39. package/libraries/llvm/io.ll +0 -19
  40. package/libraries/ml/effekt.sml +0 -65
  41. package/libraries/ml/internal/mllist.effekt +0 -9
  42. package/libraries/ml/internal/mloption.effekt +0 -18
  43. package/libraries/ml/random.effekt +0 -85
  44. 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
- extern include llvm "../llvm/io.ll"
7
- extern include js "../js/io.js"
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 "{promise: Promise, resolve: ƒ}"
45
- // = llvm "Promise"
42
+ // = js "{resolve: ƒ, promise: Promise}"
43
+ // = llvm "{tag: 0, obj: Promise*}"
46
44
 
47
- interface Promises {
48
- def promise[T](p: Task[T]): Promise[T]
49
- def await[T](p: Promise[T]): T
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
  }