@effekt-lang/effekt 0.2.2 → 0.3.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/bin/effekt.sh +1 -1
- package/libraries/chez/common/effekt_primitives.ss +10 -2
- package/libraries/chez/common/immutable/cslist.effekt +13 -7
- package/libraries/chez/common/mutable/dict.effekt +8 -10
- package/libraries/chez/common/text/regex.effekt +7 -9
- package/libraries/common/args.effekt +95 -0
- package/libraries/common/array.effekt +225 -0
- package/libraries/common/bench.effekt +60 -0
- package/libraries/common/buffer.effekt +123 -0
- package/libraries/common/bytes.effekt +125 -0
- package/libraries/{chez/common/immutable → common}/dequeue.effekt +18 -4
- package/libraries/common/effekt.effekt +764 -0
- package/libraries/common/exception.effekt +122 -0
- package/libraries/common/io/console.effekt +66 -0
- package/libraries/common/io/error.effekt +365 -0
- package/libraries/common/io/files.effekt +282 -0
- package/libraries/common/io/network.effekt +105 -0
- package/libraries/common/io/time.effekt +15 -0
- package/libraries/common/io.effekt +158 -0
- package/libraries/{llvm/immutable → common}/list.effekt +83 -74
- package/libraries/common/option.effekt +72 -0
- package/libraries/common/process.effekt +10 -0
- package/libraries/common/queue.effekt +140 -0
- package/libraries/common/ref.effekt +63 -0
- package/libraries/common/result.effekt +45 -0
- package/libraries/{ml/immutable → common}/seq.effekt +30 -19
- package/libraries/common/string.effekt +395 -0
- package/libraries/common/test.effekt +98 -0
- package/libraries/js/effekt_builtins.js +37 -6
- package/libraries/js/io.js +143 -0
- package/libraries/js/mutable/map.effekt +8 -9
- package/libraries/js/text/regex.effekt +7 -8
- package/libraries/js/unsafe/cont.effekt +2 -2
- package/libraries/js/web/dom.effekt +13 -13
- package/libraries/llvm/array.c +53 -0
- package/libraries/llvm/buffer.c +181 -76
- package/libraries/llvm/forward-declare-c.ll +27 -8
- package/libraries/llvm/io.c +543 -1
- package/libraries/llvm/io.ll +19 -0
- package/libraries/llvm/main.c +3 -1
- package/libraries/llvm/ref.c +45 -0
- package/libraries/llvm/rts.ll +496 -354
- package/libraries/llvm/types.c +23 -0
- package/libraries/ml/effekt.sml +2 -0
- package/libraries/ml/internal/mllist.effekt +9 -0
- package/libraries/ml/internal/mloption.effekt +18 -0
- package/libraries/ml/random.effekt +9 -9
- package/libraries/ml/text/regex.effekt +14 -19
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/licenses/mit license - mit-license.html +527 -57
- package/licenses/the bsd license - bsd-license.html +530 -55
- package/licenses/the mit license - mit.html +528 -58
- package/package.json +2 -2
- package/libraries/chez/callcc/effekt.effekt +0 -221
- package/libraries/chez/common/effekt_matching.ss +0 -100
- package/libraries/chez/common/immutable/list.effekt +0 -643
- package/libraries/chez/common/immutable/option.effekt +0 -39
- package/libraries/chez/common/immutable/result.effekt +0 -29
- package/libraries/chez/common/io/args.effekt +0 -20
- package/libraries/chez/common/mutable/array.effekt +0 -27
- package/libraries/chez/common/mutable/heap.effekt +0 -12
- package/libraries/chez/common/test.effekt +0 -59
- package/libraries/chez/common/text/string.effekt +0 -46
- package/libraries/chez/lift/effekt.effekt +0 -217
- package/libraries/chez/monadic/effekt.effekt +0 -218
- package/libraries/js/effekt.effekt +0 -284
- package/libraries/js/effekt_matching.js +0 -79
- package/libraries/js/immutable/dequeue.effekt +0 -78
- package/libraries/js/immutable/list.effekt +0 -643
- package/libraries/js/immutable/option.effekt +0 -49
- package/libraries/js/immutable/result.effekt +0 -29
- package/libraries/js/io/args.effekt +0 -9
- package/libraries/js/io/async.effekt +0 -28
- package/libraries/js/io/async.js +0 -2
- package/libraries/js/io/file.effekt +0 -50
- package/libraries/js/io/file_include.js +0 -13
- package/libraries/js/mutable/array.effekt +0 -98
- package/libraries/js/mutable/heap.effekt +0 -32
- package/libraries/js/test.effekt +0 -59
- package/libraries/js/text/string.effekt +0 -64
- package/libraries/llvm/effekt.effekt +0 -243
- package/libraries/llvm/immutable/option.effekt +0 -53
- package/libraries/llvm/immutable/result.effekt +0 -29
- package/libraries/llvm/io/args.effekt +0 -24
- package/libraries/llvm/text/string.effekt +0 -179
- package/libraries/ml/effekt.effekt +0 -267
- package/libraries/ml/immutable/dequeue.effekt +0 -81
- package/libraries/ml/immutable/list.effekt +0 -674
- package/libraries/ml/immutable/option.effekt +0 -53
- package/libraries/ml/immutable/result.effekt +0 -29
- package/libraries/ml/internal/option.effekt +0 -18
- package/libraries/ml/io/args.effekt +0 -41
- package/libraries/ml/mutable/array.effekt +0 -43
- package/libraries/ml/test.effekt +0 -60
- package/libraries/ml/text/string.effekt +0 -81
|
@@ -0,0 +1,764 @@
|
|
|
1
|
+
module effekt
|
|
2
|
+
|
|
3
|
+
namespace js {
|
|
4
|
+
// Runtime
|
|
5
|
+
extern include js "../js/effekt_runtime.js"
|
|
6
|
+
|
|
7
|
+
// Builtins
|
|
8
|
+
extern include js "../js/effekt_builtins.js"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
namespace chez {
|
|
12
|
+
|
|
13
|
+
// All Chez Scheme backends
|
|
14
|
+
// ------------------------
|
|
15
|
+
extern include chez "../chez/common/effekt_primitives.ss"
|
|
16
|
+
|
|
17
|
+
// call/cc based implementation
|
|
18
|
+
// ----------------------------
|
|
19
|
+
extern include chezCallCC "../chez/callcc/seq0.ss"
|
|
20
|
+
extern include chezCallCC "../chez/callcc/tail0.ss"
|
|
21
|
+
extern include chezCallCC "../chez/callcc/effekt.ss"
|
|
22
|
+
|
|
23
|
+
// CPS implementation
|
|
24
|
+
// ------------------
|
|
25
|
+
extern include chezLift "../chez/lift/effekt.ss"
|
|
26
|
+
|
|
27
|
+
// Monadic implementation
|
|
28
|
+
// ----------------------
|
|
29
|
+
extern include chezMonadic "../chez/monadic/seq0.ss"
|
|
30
|
+
extern include chezMonadic "../chez/monadic/effekt.ss"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
namespace ml {
|
|
34
|
+
extern include ml "../ml/effekt.sml"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
namespace llvm {
|
|
38
|
+
extern include llvm "../llvm/rts.ll"
|
|
39
|
+
extern include llvm "../llvm/forward-declare-c.ll"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Showing and debugging
|
|
43
|
+
// =====================
|
|
44
|
+
|
|
45
|
+
extern def println(value: String): Unit =
|
|
46
|
+
js "$effekt.println(${value})"
|
|
47
|
+
chez "(println_impl ${value})"
|
|
48
|
+
llvm """
|
|
49
|
+
call void @c_io_println_String(%Pos ${value})
|
|
50
|
+
ret %Pos zeroinitializer ; Unit
|
|
51
|
+
"""
|
|
52
|
+
ml { print(value); print("\n") }
|
|
53
|
+
|
|
54
|
+
extern io def print(value: String): Unit =
|
|
55
|
+
ml "print ${value}"
|
|
56
|
+
|
|
57
|
+
def println(value: Int): Unit = println(value.show)
|
|
58
|
+
def println(value: Unit): Unit = println(value.show)
|
|
59
|
+
def println(value: Double): Unit = println(value.show)
|
|
60
|
+
def println(value: Bool): Unit = println(value.show)
|
|
61
|
+
def println(value: Byte): Unit = println(value.show)
|
|
62
|
+
|
|
63
|
+
extern pure def show(value: Int): String =
|
|
64
|
+
js "'' + ${value}"
|
|
65
|
+
chez "(show-number ${value})"
|
|
66
|
+
ml "show'int ${value}"
|
|
67
|
+
llvm """
|
|
68
|
+
%z = call %Pos @c_buffer_show_Int(%Int ${value})
|
|
69
|
+
ret %Pos %z
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
def show(value: Unit): String = "()"
|
|
73
|
+
|
|
74
|
+
extern pure def show(value: Double): String =
|
|
75
|
+
js "'' + ${value}"
|
|
76
|
+
chez "(show-number ${value})"
|
|
77
|
+
ml "show'real ${value}"
|
|
78
|
+
llvm """
|
|
79
|
+
%z = call %Pos @c_buffer_show_Double(%Double ${value})
|
|
80
|
+
ret %Pos %z
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
def show(value: String): String =
|
|
84
|
+
value
|
|
85
|
+
|
|
86
|
+
def show(value: Bool): String =
|
|
87
|
+
if (value) "true" else "false"
|
|
88
|
+
|
|
89
|
+
extern pure def show(value: Char): String =
|
|
90
|
+
js "String.fromCodePoint(${value})"
|
|
91
|
+
chez "(string (integer->char ${value}))"
|
|
92
|
+
ml "str (chr ${value})"
|
|
93
|
+
llvm """
|
|
94
|
+
%z = call %Pos @c_buffer_show_Char(%Int ${value})
|
|
95
|
+
ret %Pos %z
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
extern pure def show(value: Byte): String =
|
|
99
|
+
llvm """
|
|
100
|
+
%z = call %Pos @c_buffer_show_Byte(i8 ${value})
|
|
101
|
+
ret %Pos %z
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
extern pure def genericShow[R](value: R): String =
|
|
105
|
+
js "$effekt.show(${value})"
|
|
106
|
+
chez "(show_impl ${value})"
|
|
107
|
+
|
|
108
|
+
extern io def inspect[R](value: R): Unit =
|
|
109
|
+
js { println(genericShow(value)) }
|
|
110
|
+
chez { println(genericShow(value)) }
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
// Strings
|
|
114
|
+
// =======
|
|
115
|
+
extern pure def infixConcat(s1: String, s2: String): String =
|
|
116
|
+
js "((${s1}) + (${s2}))"
|
|
117
|
+
chez "(string-append ${s1} ${s2})"
|
|
118
|
+
ml "${s1} ^ ${s2}"
|
|
119
|
+
llvm """
|
|
120
|
+
%spz = call %Pos @c_buffer_concatenate(%Pos ${s1}, %Pos ${s2})
|
|
121
|
+
ret %Pos %spz
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
extern pure def length(str: String): Int =
|
|
125
|
+
js "${str}.length"
|
|
126
|
+
chez "(string-length ${str})"
|
|
127
|
+
ml "String.size ${str}"
|
|
128
|
+
llvm """
|
|
129
|
+
%x = call %Int @c_buffer_length(%Pos ${str})
|
|
130
|
+
call void @erasePositive(%Pos ${str})
|
|
131
|
+
ret %Int %x
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
extern pure def unsafeSubstring(str: String, from: Int, to: Int): String =
|
|
135
|
+
js "${str}.substring(${from}, ${to})"
|
|
136
|
+
chez "(substring ${str} ${from} ${to})" // potentially raises: "Exception in substring: ..."
|
|
137
|
+
ml "String.extract (${str}, ${from}, SOME (${to} - ${from}))"
|
|
138
|
+
llvm """
|
|
139
|
+
%x = call %Pos @c_buffer_substring(%Pos ${str}, i64 ${from}, i64 ${to})
|
|
140
|
+
ret %Pos %x
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
// Side effecting ops
|
|
145
|
+
// ==================
|
|
146
|
+
|
|
147
|
+
extern io def random(): Double =
|
|
148
|
+
js "Math.random()"
|
|
149
|
+
chez "(random 1.0)"
|
|
150
|
+
ml "mlRandomReal ()"
|
|
151
|
+
|
|
152
|
+
// References and state
|
|
153
|
+
// ====================
|
|
154
|
+
// the following type is defined in builtins.scala
|
|
155
|
+
// interface Ref[T] { def get(): T; def put(t: T): Unit }
|
|
156
|
+
// extern io def freshIn[T](t: T) {r: Region}: Ref[T] at {r} = js "r.fresh(${t})"
|
|
157
|
+
// extern io def freshGlobal[T](t: T): Ref[T] at {global} = js "$effekt.fresh(${t})"
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
// Equality
|
|
161
|
+
// ========
|
|
162
|
+
/**
|
|
163
|
+
* Result of comparison between two objects according to some order:
|
|
164
|
+
*
|
|
165
|
+
* - `Less()` means that the first object is *before* the first in the order,
|
|
166
|
+
* - `Equal()` means that the two objects are the same in the order,
|
|
167
|
+
* - and `Greater()` means that the second object is *before* the first in the order.
|
|
168
|
+
*/
|
|
169
|
+
type Ordering {
|
|
170
|
+
Less();
|
|
171
|
+
Equal();
|
|
172
|
+
Greater()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
extern pure def genericCompareImpl[R](x: R, y: R): Int =
|
|
176
|
+
js "$effekt.compare(${x}, ${y})"
|
|
177
|
+
|
|
178
|
+
// Compares two values of the same type, returning an `Ordering`.
|
|
179
|
+
def genericCompare[R](x: R, y: R): Ordering = {
|
|
180
|
+
genericCompareImpl(x, y) match {
|
|
181
|
+
case -1 => Less()
|
|
182
|
+
case 0 => Equal()
|
|
183
|
+
case 1 => Greater()
|
|
184
|
+
case _ => <{ "Impossible: JS comparison returned invalid value!" }>
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
def show(o: Ordering): String = o match {
|
|
189
|
+
case Less() => "Less()"
|
|
190
|
+
case Equal() => "Equal()"
|
|
191
|
+
case Greater() => "Greater()"
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
def println(o: Ordering): Unit = println(o.show)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
// Comparison ops
|
|
198
|
+
// ==============
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Structural equality: Not available in the LLVM backend
|
|
202
|
+
*/
|
|
203
|
+
extern pure def equals[R](x: R, y: R): Bool =
|
|
204
|
+
js "$effekt.equals(${x}, ${y})"
|
|
205
|
+
chez "(equal? ${x} ${y})"
|
|
206
|
+
ml "${x} = ${y}"
|
|
207
|
+
|
|
208
|
+
def differsFrom[R](x: R, y: R): Bool =
|
|
209
|
+
not(equals(x, y))
|
|
210
|
+
|
|
211
|
+
// TODO fix this in the pattern matching compiler
|
|
212
|
+
extern pure def infixEq(x: Unit, y: Unit): Bool =
|
|
213
|
+
js "true"
|
|
214
|
+
chez "#t"
|
|
215
|
+
ml "true"
|
|
216
|
+
|
|
217
|
+
extern pure def infixEq(x: Int, y: Int): Bool =
|
|
218
|
+
js "${x} === ${y}"
|
|
219
|
+
chez "(equal? ${x} ${y})"
|
|
220
|
+
ml "${x} = ${y}"
|
|
221
|
+
llvm """
|
|
222
|
+
%z = icmp eq %Int ${x}, ${y}
|
|
223
|
+
%fat_z = zext i1 %z to i64
|
|
224
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
225
|
+
ret %Pos %adt_boolean
|
|
226
|
+
"""
|
|
227
|
+
|
|
228
|
+
extern pure def infixNeq(x: Int, y: Int): Bool =
|
|
229
|
+
js "${x} !== ${y}"
|
|
230
|
+
chez "(not (equal? ${x} ${y}))"
|
|
231
|
+
ml "${x} <> ${y}"
|
|
232
|
+
llvm """
|
|
233
|
+
%z = icmp ne %Int ${x}, ${y}
|
|
234
|
+
%fat_z = zext i1 %z to i64
|
|
235
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
236
|
+
ret %Pos %adt_boolean
|
|
237
|
+
"""
|
|
238
|
+
|
|
239
|
+
extern pure def infixEq(x: Char, y: Char): Bool =
|
|
240
|
+
js "${x} === ${y}"
|
|
241
|
+
chez "(equal? ${x} ${y})"
|
|
242
|
+
ml "${x} = ${y}"
|
|
243
|
+
llvm """
|
|
244
|
+
%z = icmp eq %Int ${x}, ${y}
|
|
245
|
+
%fat_z = zext i1 %z to i64
|
|
246
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
247
|
+
ret %Pos %adt_boolean
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
extern pure def infixNeq(x: Char, y: Char): Bool =
|
|
251
|
+
js "${x} !== ${y}"
|
|
252
|
+
chez "(not (equal? ${x} ${y}))"
|
|
253
|
+
ml "${x} <> ${y}"
|
|
254
|
+
llvm """
|
|
255
|
+
%z = icmp ne %Int ${x}, ${y}
|
|
256
|
+
%fat_z = zext i1 %z to i64
|
|
257
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
258
|
+
ret %Pos %adt_boolean
|
|
259
|
+
"""
|
|
260
|
+
|
|
261
|
+
extern pure def infixEq(x: String, y: String): Bool =
|
|
262
|
+
js "${x} === ${y}"
|
|
263
|
+
chez "(equal? ${x} ${y})"
|
|
264
|
+
ml "${x} = ${y}"
|
|
265
|
+
llvm """
|
|
266
|
+
%res = call %Pos @c_buffer_eq(%Pos ${x}, %Pos ${y})
|
|
267
|
+
ret %Pos %res
|
|
268
|
+
"""
|
|
269
|
+
|
|
270
|
+
def infixNeq(x: String, y: String): Bool = not(x == y)
|
|
271
|
+
|
|
272
|
+
extern pure def infixEq(x: Bool, y: Bool): Bool =
|
|
273
|
+
js "${x} === ${y}"
|
|
274
|
+
chez "(equal? ${x} ${y})"
|
|
275
|
+
ml "${x} = ${y}"
|
|
276
|
+
llvm """
|
|
277
|
+
%slim_x = extractvalue %Pos ${x}, 0
|
|
278
|
+
%slim_y = extractvalue %Pos ${y}, 0
|
|
279
|
+
%slim_z = icmp eq i64 %slim_x, %slim_y
|
|
280
|
+
%fat_z = zext i1 %slim_z to i64
|
|
281
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
282
|
+
ret %Pos %adt_boolean
|
|
283
|
+
"""
|
|
284
|
+
|
|
285
|
+
extern pure def infixNeq(x: Bool, y: Bool): Bool =
|
|
286
|
+
js "${x} !== ${y}"
|
|
287
|
+
chez "(not (equal? ${x} ${y}))"
|
|
288
|
+
ml "${x} <> ${y}"
|
|
289
|
+
llvm """
|
|
290
|
+
%slim_x = extractvalue %Pos ${x}, 0
|
|
291
|
+
%slim_y = extractvalue %Pos ${y}, 0
|
|
292
|
+
%slim_z = icmp ne i64 %slim_x, %slim_y
|
|
293
|
+
%fat_z = zext i1 %slim_z to i64
|
|
294
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
295
|
+
ret %Pos %adt_boolean
|
|
296
|
+
"""
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
// Math ops
|
|
300
|
+
// ========
|
|
301
|
+
extern pure def infixAdd(x: Int, y: Int): Int =
|
|
302
|
+
js "(${x} + ${y})"
|
|
303
|
+
chez "(+ ${x} ${y})"
|
|
304
|
+
ml "(${x}: int) + ${y}"
|
|
305
|
+
llvm "%z = add %Int ${x}, ${y} ret %Int %z"
|
|
306
|
+
|
|
307
|
+
extern pure def infixMul(x: Int, y: Int): Int =
|
|
308
|
+
js "(${x} * ${y})"
|
|
309
|
+
chez "(* ${x} ${y})"
|
|
310
|
+
ml "(${x}: int) * ${y}"
|
|
311
|
+
llvm "%z = mul %Int ${x}, ${y} ret %Int %z"
|
|
312
|
+
|
|
313
|
+
extern pure def infixDiv(x: Int, y: Int): Int =
|
|
314
|
+
js "Math.floor(${x} / ${y})"
|
|
315
|
+
chez "(floor (/ ${x} ${y}))"
|
|
316
|
+
ml "(${x}: int) div ${y}"
|
|
317
|
+
llvm "%z = sdiv %Int ${x}, ${y} ret %Int %z"
|
|
318
|
+
|
|
319
|
+
extern pure def infixSub(x: Int, y: Int): Int =
|
|
320
|
+
js "(${x} - ${y})"
|
|
321
|
+
chez "(- ${x} ${y})"
|
|
322
|
+
ml "(${x}: int) - ${y}"
|
|
323
|
+
llvm "%z = sub %Int ${x}, ${y} ret %Int %z"
|
|
324
|
+
|
|
325
|
+
extern pure def mod(x: Int, y: Int): Int =
|
|
326
|
+
js "(${x} % ${y})"
|
|
327
|
+
chez "(modulo ${x} ${y})"
|
|
328
|
+
ml "(${x}: int) mod ${y}"
|
|
329
|
+
llvm "%z = srem %Int ${x}, ${y} ret %Int %z"
|
|
330
|
+
|
|
331
|
+
extern pure def infixAdd(x: Double, y: Double): Double =
|
|
332
|
+
js "(${x} + ${y})"
|
|
333
|
+
chez "(+ ${x} ${y})"
|
|
334
|
+
ml "(${x}: real) + ${y}"
|
|
335
|
+
llvm "%z = fadd %Double ${x}, ${y} ret %Double %z"
|
|
336
|
+
|
|
337
|
+
extern pure def infixMul(x: Double, y: Double): Double =
|
|
338
|
+
js "(${x} * ${y})"
|
|
339
|
+
chez "(* ${x} ${y})"
|
|
340
|
+
ml "(${x}: real) * ${y}"
|
|
341
|
+
llvm "%z = fmul %Double ${x}, ${y} ret %Double %z"
|
|
342
|
+
|
|
343
|
+
extern pure def infixSub(x: Double, y: Double): Double =
|
|
344
|
+
js "(${x} - ${y})"
|
|
345
|
+
chez "(- ${x} ${y})"
|
|
346
|
+
ml "(${x}: real) - ${y}"
|
|
347
|
+
llvm "%z = fsub %Double ${x}, ${y} ret %Double %z"
|
|
348
|
+
|
|
349
|
+
extern pure def infixDiv(x: Double, y: Double): Double =
|
|
350
|
+
js "(${x} / ${y})"
|
|
351
|
+
chez "(/ ${x} ${y})"
|
|
352
|
+
ml "(${x}: real) / ${y}"
|
|
353
|
+
llvm "%z = fdiv %Double ${x}, ${y} ret %Double %z"
|
|
354
|
+
|
|
355
|
+
extern pure def cos(x: Double): Double =
|
|
356
|
+
js "Math.cos(${x})"
|
|
357
|
+
chez "(cos ${x})"
|
|
358
|
+
ml "Math.cos ${x}"
|
|
359
|
+
|
|
360
|
+
extern pure def sin(x: Double): Double =
|
|
361
|
+
js "Math.sin(${x})"
|
|
362
|
+
chez "(sin ${x})"
|
|
363
|
+
ml "Math.sin ${x}"
|
|
364
|
+
|
|
365
|
+
extern pure def atan(x: Double): Double =
|
|
366
|
+
js "Math.atan(${x})"
|
|
367
|
+
chez "(atan ${x})"
|
|
368
|
+
ml "Math.atan ${x}"
|
|
369
|
+
|
|
370
|
+
extern pure def tan(x: Double): Double =
|
|
371
|
+
js "Math.tan(${x})"
|
|
372
|
+
chez "(tan ${x})"
|
|
373
|
+
ml "Math.tan ${x}"
|
|
374
|
+
|
|
375
|
+
extern pure def sqrt(x: Double): Double =
|
|
376
|
+
js "Math.sqrt(${x})"
|
|
377
|
+
chez "(sqrt ${x})"
|
|
378
|
+
ml "Math.sqrt ${x}"
|
|
379
|
+
llvm "%z = call %Double @llvm.sqrt.f64(double ${x}) ret %Double %z"
|
|
380
|
+
|
|
381
|
+
extern llvm """
|
|
382
|
+
declare double @llvm.sqrt.f64(double %x)
|
|
383
|
+
"""
|
|
384
|
+
|
|
385
|
+
def square(x: Double): Double = x * x
|
|
386
|
+
|
|
387
|
+
def neg(n: Double): Double =
|
|
388
|
+
0.0 - n
|
|
389
|
+
|
|
390
|
+
def max(n: Double, m: Double): Double =
|
|
391
|
+
if (n > m) n else m
|
|
392
|
+
|
|
393
|
+
def abs(n: Double): Double =
|
|
394
|
+
max(n, neg(n))
|
|
395
|
+
|
|
396
|
+
extern pure def log(x: Double): Double =
|
|
397
|
+
js "Math.log(${x})"
|
|
398
|
+
chez "(log ${x})"
|
|
399
|
+
ml "Math.ln ${x}"
|
|
400
|
+
|
|
401
|
+
extern pure def log1p(x: Double): Double =
|
|
402
|
+
js "Math.log1p(${x})"
|
|
403
|
+
chez "(log (+ ${x} 1))"
|
|
404
|
+
ml "Math.ln (${x} + 1.0)"
|
|
405
|
+
|
|
406
|
+
extern pure def exp(x: Double): Double =
|
|
407
|
+
js "Math.exp(${x})"
|
|
408
|
+
chez "(exp ${x})"
|
|
409
|
+
ml "Math.exp ${x}"
|
|
410
|
+
|
|
411
|
+
// since we do not have "extern val", yet
|
|
412
|
+
extern pure def _pi(): Double =
|
|
413
|
+
js "Math.PI"
|
|
414
|
+
chez "(* 4 (atan 1))"
|
|
415
|
+
ml "Math.pi"
|
|
416
|
+
|
|
417
|
+
val PI: Double = _pi()
|
|
418
|
+
|
|
419
|
+
extern pure def toInt(d: Double): Int =
|
|
420
|
+
js "Math.trunc(${d})"
|
|
421
|
+
chez "(flonum->fixnum ${d})"
|
|
422
|
+
ml "Real.trunc ${d}"
|
|
423
|
+
llvm "%z = fptosi double ${d} to %Int ret %Int %z"
|
|
424
|
+
|
|
425
|
+
extern pure def toDouble(d: Int): Double =
|
|
426
|
+
js "${d}"
|
|
427
|
+
chez "${d}"
|
|
428
|
+
ml "Real.fromInt ${d}"
|
|
429
|
+
llvm "%z = sitofp i64 ${d} to double ret double %z"
|
|
430
|
+
|
|
431
|
+
extern pure def round(d: Double): Int =
|
|
432
|
+
js "Math.round(${d})"
|
|
433
|
+
chez "(round ${d})"
|
|
434
|
+
ml "Real.round ${d}"
|
|
435
|
+
|
|
436
|
+
extern pure def floor(d: Double): Int =
|
|
437
|
+
js "Math.floor(${d})"
|
|
438
|
+
chez "(flonum->fixnum (floor ${d}))"
|
|
439
|
+
ml "Real.floor ${d}"
|
|
440
|
+
|
|
441
|
+
extern pure def ceil(d: Double): Int =
|
|
442
|
+
js "Math.ceil(${d})"
|
|
443
|
+
chez "(flonum->fixnum (ceiling ${d}))"
|
|
444
|
+
ml "Real.ceil ${d}"
|
|
445
|
+
|
|
446
|
+
def min(n: Int, m: Int): Int =
|
|
447
|
+
if (n < m) n else m
|
|
448
|
+
|
|
449
|
+
def max(n: Int, m: Int): Int =
|
|
450
|
+
if (n > m) n else m
|
|
451
|
+
|
|
452
|
+
def neg(n: Int): Int =
|
|
453
|
+
0 - n
|
|
454
|
+
|
|
455
|
+
def abs(n: Int): Int =
|
|
456
|
+
max(n, neg(n))
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
extern pure def infixLt(x: Int, y: Int): Bool =
|
|
460
|
+
js "(${x} < ${y})"
|
|
461
|
+
chez "(< ${x} ${y})"
|
|
462
|
+
ml "(${x}: int) < ${y}"
|
|
463
|
+
llvm """
|
|
464
|
+
%z = icmp slt %Int ${x}, ${y}
|
|
465
|
+
%fat_z = zext i1 %z to i64
|
|
466
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
467
|
+
ret %Pos %adt_boolean
|
|
468
|
+
"""
|
|
469
|
+
|
|
470
|
+
extern pure def infixLte(x: Int, y: Int): Bool =
|
|
471
|
+
js "(${x} <= ${y})"
|
|
472
|
+
chez "(<= ${x} ${y})"
|
|
473
|
+
ml "(${x}: int) <= ${y}"
|
|
474
|
+
llvm """
|
|
475
|
+
%z = icmp sle %Int ${x}, ${y}
|
|
476
|
+
%fat_z = zext i1 %z to i64
|
|
477
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
478
|
+
ret %Pos %adt_boolean
|
|
479
|
+
"""
|
|
480
|
+
|
|
481
|
+
extern pure def infixGt(x: Int, y: Int): Bool =
|
|
482
|
+
js "(${x} > ${y})"
|
|
483
|
+
chez "(> ${x} ${y})"
|
|
484
|
+
ml "(${x}: int) > ${y}"
|
|
485
|
+
llvm """
|
|
486
|
+
%z = icmp sgt %Int ${x}, ${y}
|
|
487
|
+
%fat_z = zext i1 %z to i64
|
|
488
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
489
|
+
ret %Pos %adt_boolean
|
|
490
|
+
"""
|
|
491
|
+
|
|
492
|
+
extern pure def infixGte(x: Int, y: Int): Bool =
|
|
493
|
+
js "(${x} >= ${y})"
|
|
494
|
+
chez "(>= ${x} ${y})"
|
|
495
|
+
ml "(${x}: int) >= ${y}"
|
|
496
|
+
llvm """
|
|
497
|
+
%z = icmp sge %Int ${x}, ${y}
|
|
498
|
+
%fat_z = zext i1 %z to i64
|
|
499
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
500
|
+
ret %Pos %adt_boolean
|
|
501
|
+
"""
|
|
502
|
+
|
|
503
|
+
extern pure def infixEq(x: Double, y: Double): Bool =
|
|
504
|
+
js "${x} === ${y}"
|
|
505
|
+
chez "(= ${x} ${y})"
|
|
506
|
+
ml "(${x}: real) = ${y}"
|
|
507
|
+
|
|
508
|
+
extern pure def infixNeq(x: Double, y: Double): Bool =
|
|
509
|
+
js "${x} !== ${y}"
|
|
510
|
+
chez "(not (= ${x} ${y}))"
|
|
511
|
+
ml "(${x}: real) <> ${y}"
|
|
512
|
+
|
|
513
|
+
extern pure def infixLt(x: Double, y: Double): Bool =
|
|
514
|
+
js "(${x} < ${y})"
|
|
515
|
+
chez "(< ${x} ${y})"
|
|
516
|
+
ml "(${x}: real) < ${y}"
|
|
517
|
+
llvm """
|
|
518
|
+
%z = fcmp olt %Double ${x}, ${y}
|
|
519
|
+
%fat_z = zext i1 %z to i64
|
|
520
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
521
|
+
ret %Pos %adt_boolean
|
|
522
|
+
"""
|
|
523
|
+
|
|
524
|
+
extern pure def infixLte(x: Double, y: Double): Bool =
|
|
525
|
+
js "(${x} <= ${y})"
|
|
526
|
+
chez "(<= ${x} ${y})"
|
|
527
|
+
ml "(${x}: real) <= ${y}"
|
|
528
|
+
|
|
529
|
+
extern pure def infixGt(x: Double, y: Double): Bool =
|
|
530
|
+
js "(${x} > ${y})"
|
|
531
|
+
chez "(> ${x} ${y})"
|
|
532
|
+
ml "(${x}: real) > ${y}"
|
|
533
|
+
llvm """
|
|
534
|
+
%z = fcmp ogt %Double ${x}, ${y}
|
|
535
|
+
%fat_z = zext i1 %z to i64
|
|
536
|
+
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
537
|
+
ret %Pos %adt_boolean
|
|
538
|
+
"""
|
|
539
|
+
|
|
540
|
+
extern pure def infixGte(x: Double, y: Double): Bool =
|
|
541
|
+
js "(${x} >= ${y})"
|
|
542
|
+
chez "(>= ${x} ${y})"
|
|
543
|
+
ml "(${x}: real) >= ${y}"
|
|
544
|
+
|
|
545
|
+
// TODO do we really need those? if yes, move to string.effekt
|
|
546
|
+
extern pure def infixLt(x: String, y: String): Bool =
|
|
547
|
+
js "(${x} < ${y})"
|
|
548
|
+
chez "(< ${x} ${y})"
|
|
549
|
+
ml "(${x}: string) < ${y}"
|
|
550
|
+
|
|
551
|
+
extern pure def infixLte(x: String, y: String): Bool =
|
|
552
|
+
js "(${x} <= ${y})"
|
|
553
|
+
chez "(<= ${x} ${y})"
|
|
554
|
+
ml "(${x}: string) <= ${y}"
|
|
555
|
+
|
|
556
|
+
extern pure def infixGt(x: String, y: String): Bool =
|
|
557
|
+
js "(${x} > ${y})"
|
|
558
|
+
chez "(> ${x} ${y})"
|
|
559
|
+
ml "(${x}: string) > ${y}"
|
|
560
|
+
|
|
561
|
+
extern pure def infixGte(x: String, y: String): Bool =
|
|
562
|
+
js "(${x} >= ${y})"
|
|
563
|
+
chez "(>= ${x} ${y})"
|
|
564
|
+
ml "(${x}: string) >= ${y}"
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
// Boolean operations
|
|
568
|
+
// ==================
|
|
569
|
+
extern pure def not(b: Bool): Bool =
|
|
570
|
+
js "!${b}"
|
|
571
|
+
chez "(not ${b})"
|
|
572
|
+
ml "not ${b}"
|
|
573
|
+
llvm """
|
|
574
|
+
%p = extractvalue %Pos ${b}, 0
|
|
575
|
+
%q = xor i64 1, %p
|
|
576
|
+
%adt_q = insertvalue %Pos zeroinitializer, i64 %q, 0
|
|
577
|
+
ret %Pos %adt_q
|
|
578
|
+
"""
|
|
579
|
+
|
|
580
|
+
def infixOr { first: => Bool } { second: => Bool }: Bool =
|
|
581
|
+
if (first()) true else second()
|
|
582
|
+
|
|
583
|
+
def infixAnd { first: => Bool } { second: => Bool }: Bool =
|
|
584
|
+
if (first()) second() else false
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
// Bitwise operations
|
|
588
|
+
// ==================
|
|
589
|
+
extern pure def bitwiseShl(x: Int, y: Int): Int =
|
|
590
|
+
js "(${x} << ${y})"
|
|
591
|
+
chez "(ash ${x} ${y})"
|
|
592
|
+
llvm "%z = shl %Int ${x}, ${y} ret %Int %z"
|
|
593
|
+
|
|
594
|
+
extern pure def bitwiseAnd(x: Int, y: Int): Int =
|
|
595
|
+
js "(${x} & ${y})"
|
|
596
|
+
chez "(logand ${x} ${y})"
|
|
597
|
+
llvm "%z = and %Int ${x}, ${y} ret %Int %z"
|
|
598
|
+
|
|
599
|
+
extern pure def bitwiseXor(x: Int, y: Int): Int =
|
|
600
|
+
js "(${x} ^ ${y})"
|
|
601
|
+
chez "(logxor ${x} ${y})"
|
|
602
|
+
llvm "%z = xor %Int ${x}, ${y} ret %Int %z"
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
// Byte operations
|
|
606
|
+
// ===============
|
|
607
|
+
extern pure def toByte(n: Int): Byte =
|
|
608
|
+
js "${n}"
|
|
609
|
+
llvm "%z = trunc %Int ${n} to %Byte ret %Byte %z"
|
|
610
|
+
|
|
611
|
+
extern pure def toInt(n: Byte): Int =
|
|
612
|
+
js "${n}"
|
|
613
|
+
llvm "%z = zext %Byte ${n} to %Int ret %Int %z"
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
// Undefined and Null
|
|
617
|
+
// ==================
|
|
618
|
+
// Should only be used for interop with FFI, since values in Effekt
|
|
619
|
+
// should not be undefined.
|
|
620
|
+
//
|
|
621
|
+
// js: undefined || null
|
|
622
|
+
// chez: #f
|
|
623
|
+
// ml: NONE (of option 'a)
|
|
624
|
+
// llvm: null?
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* The value used by the FFI to represent undefined values
|
|
628
|
+
*/
|
|
629
|
+
extern pure def undefined[A](): A =
|
|
630
|
+
js "undefined"
|
|
631
|
+
chez "#f"
|
|
632
|
+
ml "NONE"
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Is an FFI value undefined?
|
|
636
|
+
*/
|
|
637
|
+
extern pure def isUndefined[A](value: A): Bool =
|
|
638
|
+
js "(${value} === undefined || ${value} === null)"
|
|
639
|
+
chez "(eq? ${value} #f)"
|
|
640
|
+
ml "Option.isSome ${value}"
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
// Tuples
|
|
644
|
+
// ======
|
|
645
|
+
record Tuple2[A, B](first: A, second: B)
|
|
646
|
+
record Tuple3[A, B, C](first: A, second: B, third: C)
|
|
647
|
+
record Tuple4[A, B, C, D](first: A, second: B, third: C, fourth: D)
|
|
648
|
+
record Tuple5[A, B, C, D, E](first: A, second: B, third: C, fourth: D, fifth: E)
|
|
649
|
+
record Tuple6[A, B, C, D, E, F](first: A, second: B, third: C, fourth: D, fifth: E, sixth: F)
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
// Control Flow
|
|
653
|
+
// ============
|
|
654
|
+
interface Control {
|
|
655
|
+
def break(): Unit
|
|
656
|
+
def continue(): Unit
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
def loop { f: () => Unit }: Unit = {
|
|
660
|
+
def go(): Unit = { f(); go() }
|
|
661
|
+
go()
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
def loop { f: {Control} => Unit }: Unit = try {
|
|
665
|
+
def go(): Unit = { f {label}; go() }
|
|
666
|
+
go()
|
|
667
|
+
} with label: Control {
|
|
668
|
+
def break() = ()
|
|
669
|
+
def continue() = loop { f }
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Calls provided action repeatedly. `start` is inclusive, `end` is not.
|
|
674
|
+
*/
|
|
675
|
+
def each(start: Int, end: Int) { action: (Int) => Unit } = {
|
|
676
|
+
def loop(i: Int): Unit =
|
|
677
|
+
if (i < end) { action(i); loop(i + 1) }
|
|
678
|
+
|
|
679
|
+
loop(start)
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Calls provided action repeatedly with support for breaking. `start` is inclusive, `end` is not.
|
|
684
|
+
*/
|
|
685
|
+
def each(start: Int, end: Int) { action: (Int) {Control} => Unit } = {
|
|
686
|
+
var i = start;
|
|
687
|
+
loop { {l} =>
|
|
688
|
+
if (i < end) { val el = i; i = i + 1; action(el){l} }
|
|
689
|
+
else { l.break() }
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
def repeat(n: Int) { action: () => Unit } = each(0, n) { n => action() }
|
|
694
|
+
|
|
695
|
+
def repeat(n: Int) { action: () {Control} => Unit } = each(0, n) { (n) {l} => action() {l} }
|
|
696
|
+
|
|
697
|
+
namespace internal {
|
|
698
|
+
namespace boxing {
|
|
699
|
+
// For boxing polymorphic values
|
|
700
|
+
extern type BoxedUnit
|
|
701
|
+
extern pure def boxUnit(u: Unit): Unit =
|
|
702
|
+
extern pure def unboxUnit(u: Unit): Unit =
|
|
703
|
+
|
|
704
|
+
extern type BoxedInt
|
|
705
|
+
extern pure def boxInt(n: Int): BoxedInt =
|
|
706
|
+
llvm """
|
|
707
|
+
%boxed1 = insertvalue %Pos zeroinitializer, i64 ${n}, 0
|
|
708
|
+
%boxed2 = insertvalue %Pos %boxed1, %Object null, 1
|
|
709
|
+
ret %Pos %boxed2
|
|
710
|
+
"""
|
|
711
|
+
extern pure def unboxInt(b: BoxedInt): Int =
|
|
712
|
+
llvm """
|
|
713
|
+
%unboxed = extractvalue %Pos ${b}, 0
|
|
714
|
+
ret %Int %unboxed
|
|
715
|
+
"""
|
|
716
|
+
|
|
717
|
+
extern type BoxedByte
|
|
718
|
+
extern pure def boxByte(n: Byte): BoxedByte =
|
|
719
|
+
llvm """
|
|
720
|
+
%extended = sext i8 ${n} to i64
|
|
721
|
+
%boxed1 = insertvalue %Pos zeroinitializer, i64 %extended, 0
|
|
722
|
+
%boxed2 = insertvalue %Pos %boxed1, %Object null, 1
|
|
723
|
+
ret %Pos %boxed2
|
|
724
|
+
"""
|
|
725
|
+
extern pure def unboxByte(b: BoxedByte): Byte =
|
|
726
|
+
llvm """
|
|
727
|
+
%unboxed = extractvalue %Pos ${b}, 0
|
|
728
|
+
%truncated = trunc i64 %unboxed to i8
|
|
729
|
+
ret i8 %truncated
|
|
730
|
+
"""
|
|
731
|
+
|
|
732
|
+
extern type BoxedChar
|
|
733
|
+
extern pure def boxChar(c: Char): BoxedChar =
|
|
734
|
+
llvm """
|
|
735
|
+
%boxed1 = insertvalue %Pos zeroinitializer, i64 ${c}, 0
|
|
736
|
+
%boxed2 = insertvalue %Pos %boxed1, %Object null, 1
|
|
737
|
+
ret %Pos %boxed2
|
|
738
|
+
"""
|
|
739
|
+
extern pure def unboxChar(b: BoxedChar): Char =
|
|
740
|
+
llvm """
|
|
741
|
+
%unboxed = extractvalue %Pos ${b}, 0
|
|
742
|
+
ret %Int %unboxed
|
|
743
|
+
"""
|
|
744
|
+
|
|
745
|
+
extern type BoxedBool
|
|
746
|
+
extern pure def boxBool(b: Bool): BoxedBool =
|
|
747
|
+
extern pure def unboxBool(b: BoxedBool): Bool =
|
|
748
|
+
|
|
749
|
+
extern type BoxedDouble
|
|
750
|
+
extern pure def boxDouble(d: Double): BoxedDouble =
|
|
751
|
+
llvm """
|
|
752
|
+
%n = bitcast double ${d} to i64
|
|
753
|
+
%boxed1 = insertvalue %Pos zeroinitializer, i64 %n, 0
|
|
754
|
+
%boxed2 = insertvalue %Pos %boxed1, %Object null, 1
|
|
755
|
+
ret %Pos %boxed2
|
|
756
|
+
"""
|
|
757
|
+
extern pure def unboxDouble(b: BoxedDouble): Double =
|
|
758
|
+
llvm """
|
|
759
|
+
%unboxed = extractvalue %Pos ${b}, 0
|
|
760
|
+
%d = bitcast i64 %unboxed to double
|
|
761
|
+
ret %Double %d
|
|
762
|
+
"""
|
|
763
|
+
}
|
|
764
|
+
}
|