@effekt-lang/effekt 0.3.0 → 0.4.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 +11 -16
- package/libraries/common/bench.effekt +32 -6
- package/libraries/common/effekt.effekt +30 -69
- package/libraries/common/exception.effekt +0 -1
- package/libraries/common/io/console.effekt +32 -36
- package/libraries/common/io/error.effekt +111 -2
- package/libraries/common/io/filesystem.effekt +274 -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 +18 -0
- package/libraries/common/process.effekt +0 -1
- package/libraries/common/ref.effekt +4 -7
- package/libraries/common/string/tty.effekt +66 -0
- package/libraries/common/string.effekt +0 -34
- 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 +19 -19
- package/licenses/the bsd license - bsd-license.html +19 -19
- package/licenses/the mit license - mit.html +20 -20
- 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
package/README.md
CHANGED
|
@@ -11,26 +11,14 @@ aims to be significantly more lightweight in its concepts.
|
|
|
11
11
|
Also, Effekt comes with no warranty and there are (probably) many bugs -- If this does not discourage you, feel free to
|
|
12
12
|
play with it and give us your feedback :)
|
|
13
13
|
|
|
14
|
-
##
|
|
15
|
-
|
|
16
|
-
You need to have Java (>= 11) and Node (>= 12) and npm installed.
|
|
17
|
-
|
|
18
|
-
The recommended way of installing Effekt is by running:
|
|
14
|
+
## Examples
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
npm install -g https://github.com/effekt-lang/effekt/releases/latest/download/effekt.tgz
|
|
22
|
-
```
|
|
16
|
+
If you are looking for examples of the Effekt language, we invite you to look at the [casestudies](https://github.com/effekt-lang/effekt/tree/master/examples/casestudies) and the [language tour](https://effekt-lang.org/tour).
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
npm install -g effekt.tgz
|
|
28
|
-
```
|
|
18
|
+
## Installation
|
|
29
19
|
|
|
30
|
-
|
|
20
|
+
Please navigate to the [getting-started guide](https://effekt-lang.org/docs/getting-started#installing-effekt) on our [website](https://effekt-lang.org) for detailed instructions of how to install Effekt.
|
|
31
21
|
|
|
32
|
-
|
|
33
|
-
> effekt
|
|
34
|
-
```
|
|
22
|
+
## Contributing
|
|
35
23
|
|
|
36
|
-
|
|
24
|
+
Thanks for considering to contribute to the Effekt compiler! For setting up your local environment, please check out our [contributing guide](https://effekt-lang.org/contributing.html) on the [website](https://effekt-lang.org).
|
package/bin/effekt
CHANGED
|
Binary file
|
|
@@ -3,7 +3,6 @@ module args
|
|
|
3
3
|
extern io def commandLineArgs(): List[String] =
|
|
4
4
|
js { js::commandLineArgs() }
|
|
5
5
|
chez { chez::commandLineArgs() }
|
|
6
|
-
ml { ml::commandLineArgs() }
|
|
7
6
|
llvm { llvm::commandLineArgs() }
|
|
8
7
|
|
|
9
8
|
namespace js {
|
|
@@ -46,32 +45,6 @@ namespace chez {
|
|
|
46
45
|
def commandLineArgs(): List[String] = nativeArgs().toList
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
namespace ml {
|
|
50
|
-
|
|
51
|
-
// MLList[String]
|
|
52
|
-
// we inline these from mllist to not have a dependency
|
|
53
|
-
extern type Args
|
|
54
|
-
|
|
55
|
-
extern io def nativeArgs(): Args =
|
|
56
|
-
ml "CommandLine.arguments ()"
|
|
57
|
-
|
|
58
|
-
extern pure def isEmpty(args: Args): Bool =
|
|
59
|
-
ml "null ${args}"
|
|
60
|
-
|
|
61
|
-
extern io def first(a: Args): String =
|
|
62
|
-
ml "hd ${a}"
|
|
63
|
-
|
|
64
|
-
extern io def rest(a: Args): Args =
|
|
65
|
-
ml "tl ${a}"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def commandLineArgs(): List[String] = {
|
|
69
|
-
def toList(args: Args): List[String] =
|
|
70
|
-
if (args.isEmpty) Nil() else Cons(args.first, args.rest.toList)
|
|
71
|
-
nativeArgs().toList
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
48
|
namespace llvm {
|
|
76
49
|
extern io def argCount(): Int =
|
|
77
50
|
llvm """
|
|
@@ -24,15 +24,13 @@ extern global def allocate[T](size: Int): Array[T] =
|
|
|
24
24
|
/**
|
|
25
25
|
* Creates a new Array of size `size` filled with the value `init`
|
|
26
26
|
*/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
arr
|
|
35
|
-
}
|
|
27
|
+
def array[T](size: Int, init: T): Array[T] = {
|
|
28
|
+
val arr = allocate[T](size);
|
|
29
|
+
each(0, size) { i =>
|
|
30
|
+
unsafeSet(arr, i, init)
|
|
31
|
+
};
|
|
32
|
+
arr
|
|
33
|
+
}
|
|
36
34
|
|
|
37
35
|
/**
|
|
38
36
|
* Converts a List `list` to an Array
|
|
@@ -53,7 +51,6 @@ def fromList[T](list: List[T]): Array[T] = {
|
|
|
53
51
|
extern pure def size[T](arr: Array[T]): Int =
|
|
54
52
|
js "${arr}.length"
|
|
55
53
|
chez "(vector-length ${arr})"
|
|
56
|
-
ml "Array.length ${arr}"
|
|
57
54
|
llvm """
|
|
58
55
|
%z = call %Int @c_array_size(%Pos ${arr})
|
|
59
56
|
ret %Int %z
|
|
@@ -68,17 +65,16 @@ extern pure def size[T](arr: Array[T]): Int =
|
|
|
68
65
|
extern global def unsafeGet[T](arr: Array[T], index: Int): T =
|
|
69
66
|
js "${arr}[${index}]"
|
|
70
67
|
chez "(vector-ref ${arr} ${index})"
|
|
71
|
-
ml "Array.sub (${arr}, ${index})"
|
|
72
68
|
llvm """
|
|
73
69
|
%z = call %Pos @c_array_get(%Pos ${arr}, %Int ${index})
|
|
74
70
|
ret %Pos %z
|
|
75
71
|
"""
|
|
76
72
|
|
|
77
73
|
extern js """
|
|
78
|
-
function array$set(arr, index, value) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
74
|
+
function array$set(arr, index, value) {
|
|
75
|
+
arr[index] = value;
|
|
76
|
+
return $effekt.unit
|
|
77
|
+
}
|
|
82
78
|
"""
|
|
83
79
|
|
|
84
80
|
/**
|
|
@@ -90,7 +86,6 @@ function array$set(arr, index, value) {
|
|
|
90
86
|
extern global def unsafeSet[T](arr: Array[T], index: Int, value: T): Unit =
|
|
91
87
|
js "array$set(${arr}, ${index}, ${value})"
|
|
92
88
|
chez "(begin (vector-set! ${arr} ${index} ${value}) #f)"
|
|
93
|
-
ml "Array.update (${arr}, ${index}, ${value})"
|
|
94
89
|
llvm """
|
|
95
90
|
%z = call %Pos @c_array_set(%Pos ${arr}, %Int ${index}, %Pos ${value})
|
|
96
91
|
ret %Pos %z
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
module bench
|
|
2
2
|
|
|
3
|
+
type Nanos = Int
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* The current time (since UNIX Epoch) in nanoseconds.
|
|
5
7
|
*
|
|
6
8
|
* The actual precision varies across the different backends.
|
|
7
9
|
* - js: Milliseconds
|
|
8
10
|
* - chez: Microseconds
|
|
9
|
-
* - ml: Microseconds
|
|
10
11
|
*/
|
|
11
|
-
extern io def timestamp():
|
|
12
|
+
extern io def timestamp(): Nanos =
|
|
12
13
|
js "Date.now() * 1000000"
|
|
13
14
|
chez "(timestamp)"
|
|
14
|
-
ml "IntInf.toInt (Time.toNanoseconds (Time.now ()))"
|
|
15
15
|
llvm """
|
|
16
16
|
%time_ptr = alloca { i64, i64 }
|
|
17
17
|
call i32 @clock_gettime(i32 0, ptr %time_ptr)
|
|
@@ -27,24 +27,35 @@ extern llvm """
|
|
|
27
27
|
declare i32 @clock_gettime(i32, ptr)
|
|
28
28
|
"""
|
|
29
29
|
|
|
30
|
+
// This should not be needed when using NodeJS 16.x or newer.
|
|
31
|
+
extern jsNode """
|
|
32
|
+
const { performance } = require('node:perf_hooks');
|
|
33
|
+
"""
|
|
34
|
+
|
|
30
35
|
/**
|
|
31
36
|
* High-precision timestamp in nanoseconds that should be for measurements.
|
|
32
37
|
*
|
|
33
38
|
* This timestamp should only be used for **relative** measurements,
|
|
34
39
|
* as gives no guarantees on the absolute time (unlike a UNIX timestamp).
|
|
35
40
|
*/
|
|
36
|
-
extern io def relativeTimestamp():
|
|
41
|
+
extern io def relativeTimestamp(): Nanos =
|
|
37
42
|
js "Math.round(performance.now() * 1000000)"
|
|
38
43
|
default { timestamp() }
|
|
39
44
|
|
|
45
|
+
type Duration = Int
|
|
46
|
+
|
|
47
|
+
namespace Duration {
|
|
48
|
+
def diff(fromNanos: Nanos, toNanos: Nanos): Duration = toNanos - fromNanos
|
|
49
|
+
}
|
|
50
|
+
|
|
40
51
|
/**
|
|
41
52
|
* Runs the block and returns the time in nanoseconds
|
|
42
53
|
*/
|
|
43
|
-
def timed { block: => Unit }:
|
|
54
|
+
def timed { block: => Unit }: Duration = {
|
|
44
55
|
val before = relativeTimestamp()
|
|
45
56
|
block()
|
|
46
57
|
val after = relativeTimestamp()
|
|
47
|
-
after
|
|
58
|
+
Duration::diff(before, after)
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
def measure(warmup: Int, iterations: Int) { block: => Unit }: Unit = {
|
|
@@ -58,3 +69,18 @@ def measure(warmup: Int, iterations: Int) { block: => Unit }: Unit = {
|
|
|
58
69
|
run(warmup, false)
|
|
59
70
|
run(iterations, true)
|
|
60
71
|
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Takes a duration in nanoseconds and formats it in milliseconds with precision of two decimal digits.
|
|
75
|
+
*/
|
|
76
|
+
def formatMs(nanos: Nanos): String = {
|
|
77
|
+
val micros = nanos / 1000000
|
|
78
|
+
val sub = (nanos.mod(1000000).toDouble / 10000.0).round
|
|
79
|
+
|
|
80
|
+
if (sub == 100) {
|
|
81
|
+
// overflow because of rounding
|
|
82
|
+
(micros + 1).show ++ ".0ms"
|
|
83
|
+
} else {
|
|
84
|
+
micros.show ++ "." ++ sub.show ++ "ms"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -30,10 +30,6 @@ namespace chez {
|
|
|
30
30
|
extern include chezMonadic "../chez/monadic/effekt.ss"
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
namespace ml {
|
|
34
|
-
extern include ml "../ml/effekt.sml"
|
|
35
|
-
}
|
|
36
|
-
|
|
37
33
|
namespace llvm {
|
|
38
34
|
extern include llvm "../llvm/rts.ll"
|
|
39
35
|
extern include llvm "../llvm/forward-declare-c.ll"
|
|
@@ -49,10 +45,6 @@ extern def println(value: String): Unit =
|
|
|
49
45
|
call void @c_io_println_String(%Pos ${value})
|
|
50
46
|
ret %Pos zeroinitializer ; Unit
|
|
51
47
|
"""
|
|
52
|
-
ml { print(value); print("\n") }
|
|
53
|
-
|
|
54
|
-
extern io def print(value: String): Unit =
|
|
55
|
-
ml "print ${value}"
|
|
56
48
|
|
|
57
49
|
def println(value: Int): Unit = println(value.show)
|
|
58
50
|
def println(value: Unit): Unit = println(value.show)
|
|
@@ -63,7 +55,6 @@ def println(value: Byte): Unit = println(value.show)
|
|
|
63
55
|
extern pure def show(value: Int): String =
|
|
64
56
|
js "'' + ${value}"
|
|
65
57
|
chez "(show-number ${value})"
|
|
66
|
-
ml "show'int ${value}"
|
|
67
58
|
llvm """
|
|
68
59
|
%z = call %Pos @c_buffer_show_Int(%Int ${value})
|
|
69
60
|
ret %Pos %z
|
|
@@ -74,7 +65,6 @@ def show(value: Unit): String = "()"
|
|
|
74
65
|
extern pure def show(value: Double): String =
|
|
75
66
|
js "'' + ${value}"
|
|
76
67
|
chez "(show-number ${value})"
|
|
77
|
-
ml "show'real ${value}"
|
|
78
68
|
llvm """
|
|
79
69
|
%z = call %Pos @c_buffer_show_Double(%Double ${value})
|
|
80
70
|
ret %Pos %z
|
|
@@ -89,7 +79,6 @@ def show(value: Bool): String =
|
|
|
89
79
|
extern pure def show(value: Char): String =
|
|
90
80
|
js "String.fromCodePoint(${value})"
|
|
91
81
|
chez "(string (integer->char ${value}))"
|
|
92
|
-
ml "str (chr ${value})"
|
|
93
82
|
llvm """
|
|
94
83
|
%z = call %Pos @c_buffer_show_Char(%Int ${value})
|
|
95
84
|
ret %Pos %z
|
|
@@ -115,7 +104,6 @@ extern io def inspect[R](value: R): Unit =
|
|
|
115
104
|
extern pure def infixConcat(s1: String, s2: String): String =
|
|
116
105
|
js "((${s1}) + (${s2}))"
|
|
117
106
|
chez "(string-append ${s1} ${s2})"
|
|
118
|
-
ml "${s1} ^ ${s2}"
|
|
119
107
|
llvm """
|
|
120
108
|
%spz = call %Pos @c_buffer_concatenate(%Pos ${s1}, %Pos ${s2})
|
|
121
109
|
ret %Pos %spz
|
|
@@ -124,7 +112,6 @@ extern pure def infixConcat(s1: String, s2: String): String =
|
|
|
124
112
|
extern pure def length(str: String): Int =
|
|
125
113
|
js "${str}.length"
|
|
126
114
|
chez "(string-length ${str})"
|
|
127
|
-
ml "String.size ${str}"
|
|
128
115
|
llvm """
|
|
129
116
|
%x = call %Int @c_buffer_length(%Pos ${str})
|
|
130
117
|
call void @erasePositive(%Pos ${str})
|
|
@@ -134,7 +121,6 @@ extern pure def length(str: String): Int =
|
|
|
134
121
|
extern pure def unsafeSubstring(str: String, from: Int, to: Int): String =
|
|
135
122
|
js "${str}.substring(${from}, ${to})"
|
|
136
123
|
chez "(substring ${str} ${from} ${to})" // potentially raises: "Exception in substring: ..."
|
|
137
|
-
ml "String.extract (${str}, ${from}, SOME (${to} - ${from}))"
|
|
138
124
|
llvm """
|
|
139
125
|
%x = call %Pos @c_buffer_substring(%Pos ${str}, i64 ${from}, i64 ${to})
|
|
140
126
|
ret %Pos %x
|
|
@@ -147,7 +133,6 @@ extern pure def unsafeSubstring(str: String, from: Int, to: Int): String =
|
|
|
147
133
|
extern io def random(): Double =
|
|
148
134
|
js "Math.random()"
|
|
149
135
|
chez "(random 1.0)"
|
|
150
|
-
ml "mlRandomReal ()"
|
|
151
136
|
|
|
152
137
|
// References and state
|
|
153
138
|
// ====================
|
|
@@ -203,7 +188,6 @@ def println(o: Ordering): Unit = println(o.show)
|
|
|
203
188
|
extern pure def equals[R](x: R, y: R): Bool =
|
|
204
189
|
js "$effekt.equals(${x}, ${y})"
|
|
205
190
|
chez "(equal? ${x} ${y})"
|
|
206
|
-
ml "${x} = ${y}"
|
|
207
191
|
|
|
208
192
|
def differsFrom[R](x: R, y: R): Bool =
|
|
209
193
|
not(equals(x, y))
|
|
@@ -212,12 +196,10 @@ def differsFrom[R](x: R, y: R): Bool =
|
|
|
212
196
|
extern pure def infixEq(x: Unit, y: Unit): Bool =
|
|
213
197
|
js "true"
|
|
214
198
|
chez "#t"
|
|
215
|
-
ml "true"
|
|
216
199
|
|
|
217
200
|
extern pure def infixEq(x: Int, y: Int): Bool =
|
|
218
201
|
js "${x} === ${y}"
|
|
219
202
|
chez "(equal? ${x} ${y})"
|
|
220
|
-
ml "${x} = ${y}"
|
|
221
203
|
llvm """
|
|
222
204
|
%z = icmp eq %Int ${x}, ${y}
|
|
223
205
|
%fat_z = zext i1 %z to i64
|
|
@@ -228,7 +210,6 @@ extern pure def infixEq(x: Int, y: Int): Bool =
|
|
|
228
210
|
extern pure def infixNeq(x: Int, y: Int): Bool =
|
|
229
211
|
js "${x} !== ${y}"
|
|
230
212
|
chez "(not (equal? ${x} ${y}))"
|
|
231
|
-
ml "${x} <> ${y}"
|
|
232
213
|
llvm """
|
|
233
214
|
%z = icmp ne %Int ${x}, ${y}
|
|
234
215
|
%fat_z = zext i1 %z to i64
|
|
@@ -239,7 +220,6 @@ extern pure def infixNeq(x: Int, y: Int): Bool =
|
|
|
239
220
|
extern pure def infixEq(x: Char, y: Char): Bool =
|
|
240
221
|
js "${x} === ${y}"
|
|
241
222
|
chez "(equal? ${x} ${y})"
|
|
242
|
-
ml "${x} = ${y}"
|
|
243
223
|
llvm """
|
|
244
224
|
%z = icmp eq %Int ${x}, ${y}
|
|
245
225
|
%fat_z = zext i1 %z to i64
|
|
@@ -250,7 +230,6 @@ extern pure def infixEq(x: Char, y: Char): Bool =
|
|
|
250
230
|
extern pure def infixNeq(x: Char, y: Char): Bool =
|
|
251
231
|
js "${x} !== ${y}"
|
|
252
232
|
chez "(not (equal? ${x} ${y}))"
|
|
253
|
-
ml "${x} <> ${y}"
|
|
254
233
|
llvm """
|
|
255
234
|
%z = icmp ne %Int ${x}, ${y}
|
|
256
235
|
%fat_z = zext i1 %z to i64
|
|
@@ -261,7 +240,6 @@ extern pure def infixNeq(x: Char, y: Char): Bool =
|
|
|
261
240
|
extern pure def infixEq(x: String, y: String): Bool =
|
|
262
241
|
js "${x} === ${y}"
|
|
263
242
|
chez "(equal? ${x} ${y})"
|
|
264
|
-
ml "${x} = ${y}"
|
|
265
243
|
llvm """
|
|
266
244
|
%res = call %Pos @c_buffer_eq(%Pos ${x}, %Pos ${y})
|
|
267
245
|
ret %Pos %res
|
|
@@ -272,7 +250,6 @@ def infixNeq(x: String, y: String): Bool = not(x == y)
|
|
|
272
250
|
extern pure def infixEq(x: Bool, y: Bool): Bool =
|
|
273
251
|
js "${x} === ${y}"
|
|
274
252
|
chez "(equal? ${x} ${y})"
|
|
275
|
-
ml "${x} = ${y}"
|
|
276
253
|
llvm """
|
|
277
254
|
%slim_x = extractvalue %Pos ${x}, 0
|
|
278
255
|
%slim_y = extractvalue %Pos ${y}, 0
|
|
@@ -285,7 +262,6 @@ extern pure def infixEq(x: Bool, y: Bool): Bool =
|
|
|
285
262
|
extern pure def infixNeq(x: Bool, y: Bool): Bool =
|
|
286
263
|
js "${x} !== ${y}"
|
|
287
264
|
chez "(not (equal? ${x} ${y}))"
|
|
288
|
-
ml "${x} <> ${y}"
|
|
289
265
|
llvm """
|
|
290
266
|
%slim_x = extractvalue %Pos ${x}, 0
|
|
291
267
|
%slim_y = extractvalue %Pos ${y}, 0
|
|
@@ -301,87 +277,69 @@ extern pure def infixNeq(x: Bool, y: Bool): Bool =
|
|
|
301
277
|
extern pure def infixAdd(x: Int, y: Int): Int =
|
|
302
278
|
js "(${x} + ${y})"
|
|
303
279
|
chez "(+ ${x} ${y})"
|
|
304
|
-
ml "(${x}: int) + ${y}"
|
|
305
280
|
llvm "%z = add %Int ${x}, ${y} ret %Int %z"
|
|
306
281
|
|
|
307
282
|
extern pure def infixMul(x: Int, y: Int): Int =
|
|
308
283
|
js "(${x} * ${y})"
|
|
309
284
|
chez "(* ${x} ${y})"
|
|
310
|
-
ml "(${x}: int) * ${y}"
|
|
311
285
|
llvm "%z = mul %Int ${x}, ${y} ret %Int %z"
|
|
312
286
|
|
|
313
287
|
extern pure def infixDiv(x: Int, y: Int): Int =
|
|
314
288
|
js "Math.floor(${x} / ${y})"
|
|
315
289
|
chez "(floor (/ ${x} ${y}))"
|
|
316
|
-
ml "(${x}: int) div ${y}"
|
|
317
290
|
llvm "%z = sdiv %Int ${x}, ${y} ret %Int %z"
|
|
318
291
|
|
|
319
292
|
extern pure def infixSub(x: Int, y: Int): Int =
|
|
320
293
|
js "(${x} - ${y})"
|
|
321
294
|
chez "(- ${x} ${y})"
|
|
322
|
-
ml "(${x}: int) - ${y}"
|
|
323
295
|
llvm "%z = sub %Int ${x}, ${y} ret %Int %z"
|
|
324
296
|
|
|
325
297
|
extern pure def mod(x: Int, y: Int): Int =
|
|
326
298
|
js "(${x} % ${y})"
|
|
327
299
|
chez "(modulo ${x} ${y})"
|
|
328
|
-
ml "(${x}: int) mod ${y}"
|
|
329
300
|
llvm "%z = srem %Int ${x}, ${y} ret %Int %z"
|
|
330
301
|
|
|
331
302
|
extern pure def infixAdd(x: Double, y: Double): Double =
|
|
332
303
|
js "(${x} + ${y})"
|
|
333
304
|
chez "(+ ${x} ${y})"
|
|
334
|
-
ml "(${x}: real) + ${y}"
|
|
335
305
|
llvm "%z = fadd %Double ${x}, ${y} ret %Double %z"
|
|
336
306
|
|
|
337
307
|
extern pure def infixMul(x: Double, y: Double): Double =
|
|
338
308
|
js "(${x} * ${y})"
|
|
339
309
|
chez "(* ${x} ${y})"
|
|
340
|
-
ml "(${x}: real) * ${y}"
|
|
341
310
|
llvm "%z = fmul %Double ${x}, ${y} ret %Double %z"
|
|
342
311
|
|
|
343
312
|
extern pure def infixSub(x: Double, y: Double): Double =
|
|
344
313
|
js "(${x} - ${y})"
|
|
345
314
|
chez "(- ${x} ${y})"
|
|
346
|
-
ml "(${x}: real) - ${y}"
|
|
347
315
|
llvm "%z = fsub %Double ${x}, ${y} ret %Double %z"
|
|
348
316
|
|
|
349
317
|
extern pure def infixDiv(x: Double, y: Double): Double =
|
|
350
318
|
js "(${x} / ${y})"
|
|
351
319
|
chez "(/ ${x} ${y})"
|
|
352
|
-
ml "(${x}: real) / ${y}"
|
|
353
320
|
llvm "%z = fdiv %Double ${x}, ${y} ret %Double %z"
|
|
354
321
|
|
|
355
322
|
extern pure def cos(x: Double): Double =
|
|
356
323
|
js "Math.cos(${x})"
|
|
357
324
|
chez "(cos ${x})"
|
|
358
|
-
ml "Math.cos ${x}"
|
|
359
325
|
|
|
360
326
|
extern pure def sin(x: Double): Double =
|
|
361
327
|
js "Math.sin(${x})"
|
|
362
328
|
chez "(sin ${x})"
|
|
363
|
-
ml "Math.sin ${x}"
|
|
364
329
|
|
|
365
330
|
extern pure def atan(x: Double): Double =
|
|
366
331
|
js "Math.atan(${x})"
|
|
367
332
|
chez "(atan ${x})"
|
|
368
|
-
ml "Math.atan ${x}"
|
|
369
333
|
|
|
370
334
|
extern pure def tan(x: Double): Double =
|
|
371
335
|
js "Math.tan(${x})"
|
|
372
336
|
chez "(tan ${x})"
|
|
373
|
-
ml "Math.tan ${x}"
|
|
374
337
|
|
|
375
338
|
extern pure def sqrt(x: Double): Double =
|
|
376
339
|
js "Math.sqrt(${x})"
|
|
377
340
|
chez "(sqrt ${x})"
|
|
378
|
-
ml "Math.sqrt ${x}"
|
|
379
341
|
llvm "%z = call %Double @llvm.sqrt.f64(double ${x}) ret %Double %z"
|
|
380
342
|
|
|
381
|
-
extern llvm """
|
|
382
|
-
declare double @llvm.sqrt.f64(double %x)
|
|
383
|
-
"""
|
|
384
|
-
|
|
385
343
|
def square(x: Double): Double = x * x
|
|
386
344
|
|
|
387
345
|
def neg(n: Double): Double =
|
|
@@ -396,52 +354,73 @@ def abs(n: Double): Double =
|
|
|
396
354
|
extern pure def log(x: Double): Double =
|
|
397
355
|
js "Math.log(${x})"
|
|
398
356
|
chez "(log ${x})"
|
|
399
|
-
ml "Math.ln ${x}"
|
|
400
357
|
|
|
401
358
|
extern pure def log1p(x: Double): Double =
|
|
402
359
|
js "Math.log1p(${x})"
|
|
403
360
|
chez "(log (+ ${x} 1))"
|
|
404
|
-
ml "Math.ln (${x} + 1.0)"
|
|
405
361
|
|
|
406
362
|
extern pure def exp(x: Double): Double =
|
|
407
363
|
js "Math.exp(${x})"
|
|
408
364
|
chez "(exp ${x})"
|
|
409
|
-
|
|
365
|
+
|
|
366
|
+
def pow(base: Double, exponent: Int): Double = {
|
|
367
|
+
def loop(base: Double, exponent: Int, acc: Double): Double = {
|
|
368
|
+
if (exponent == 0) acc
|
|
369
|
+
else if (exponent.mod(2) == 0) loop(base * base, exponent / 2, acc) // even exponent
|
|
370
|
+
else loop(base, exponent - 1, acc * base) // odd exponent
|
|
371
|
+
}
|
|
372
|
+
loop(base, exponent, 1.0)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
extern pure def pow(base: Double, exponent: Double): Double =
|
|
376
|
+
js "Math.pow(${base}, ${exponent})"
|
|
377
|
+
chez "(expt ${base} ${exponent})"
|
|
410
378
|
|
|
411
379
|
// since we do not have "extern val", yet
|
|
412
380
|
extern pure def _pi(): Double =
|
|
413
381
|
js "Math.PI"
|
|
414
382
|
chez "(* 4 (atan 1))"
|
|
415
|
-
ml "Math.pi"
|
|
416
383
|
|
|
417
384
|
val PI: Double = _pi()
|
|
418
385
|
|
|
419
386
|
extern pure def toInt(d: Double): Int =
|
|
420
387
|
js "Math.trunc(${d})"
|
|
421
388
|
chez "(flonum->fixnum ${d})"
|
|
422
|
-
ml "Real.trunc ${d}"
|
|
423
389
|
llvm "%z = fptosi double ${d} to %Int ret %Int %z"
|
|
424
390
|
|
|
425
391
|
extern pure def toDouble(d: Int): Double =
|
|
426
392
|
js "${d}"
|
|
427
393
|
chez "${d}"
|
|
428
|
-
ml "Real.fromInt ${d}"
|
|
429
394
|
llvm "%z = sitofp i64 ${d} to double ret double %z"
|
|
430
395
|
|
|
431
396
|
extern pure def round(d: Double): Int =
|
|
432
397
|
js "Math.round(${d})"
|
|
433
398
|
chez "(round ${d})"
|
|
434
|
-
|
|
399
|
+
llvm """
|
|
400
|
+
%i = call %Double @llvm.round.f64(double ${d})
|
|
401
|
+
%z = fptosi double %i to %Int ret %Int %z
|
|
402
|
+
"""
|
|
403
|
+
|
|
404
|
+
def round(d: Double, digits: Int): Double = {
|
|
405
|
+
val factor = pow(10.0, digits)
|
|
406
|
+
round(d * factor).toDouble / factor
|
|
407
|
+
}
|
|
435
408
|
|
|
436
409
|
extern pure def floor(d: Double): Int =
|
|
437
410
|
js "Math.floor(${d})"
|
|
438
411
|
chez "(flonum->fixnum (floor ${d}))"
|
|
439
|
-
|
|
412
|
+
llvm """
|
|
413
|
+
%i = call %Double @llvm.floor.f64(double ${d})
|
|
414
|
+
%z = fptosi double %i to %Int ret %Int %z
|
|
415
|
+
"""
|
|
440
416
|
|
|
441
417
|
extern pure def ceil(d: Double): Int =
|
|
442
418
|
js "Math.ceil(${d})"
|
|
443
419
|
chez "(flonum->fixnum (ceiling ${d}))"
|
|
444
|
-
|
|
420
|
+
llvm """
|
|
421
|
+
%i = call %Double @llvm.ceil.f64(double ${d})
|
|
422
|
+
%z = fptosi double %i to %Int ret %Int %z
|
|
423
|
+
"""
|
|
445
424
|
|
|
446
425
|
def min(n: Int, m: Int): Int =
|
|
447
426
|
if (n < m) n else m
|
|
@@ -459,7 +438,6 @@ def abs(n: Int): Int =
|
|
|
459
438
|
extern pure def infixLt(x: Int, y: Int): Bool =
|
|
460
439
|
js "(${x} < ${y})"
|
|
461
440
|
chez "(< ${x} ${y})"
|
|
462
|
-
ml "(${x}: int) < ${y}"
|
|
463
441
|
llvm """
|
|
464
442
|
%z = icmp slt %Int ${x}, ${y}
|
|
465
443
|
%fat_z = zext i1 %z to i64
|
|
@@ -470,7 +448,6 @@ extern pure def infixLt(x: Int, y: Int): Bool =
|
|
|
470
448
|
extern pure def infixLte(x: Int, y: Int): Bool =
|
|
471
449
|
js "(${x} <= ${y})"
|
|
472
450
|
chez "(<= ${x} ${y})"
|
|
473
|
-
ml "(${x}: int) <= ${y}"
|
|
474
451
|
llvm """
|
|
475
452
|
%z = icmp sle %Int ${x}, ${y}
|
|
476
453
|
%fat_z = zext i1 %z to i64
|
|
@@ -481,7 +458,6 @@ extern pure def infixLte(x: Int, y: Int): Bool =
|
|
|
481
458
|
extern pure def infixGt(x: Int, y: Int): Bool =
|
|
482
459
|
js "(${x} > ${y})"
|
|
483
460
|
chez "(> ${x} ${y})"
|
|
484
|
-
ml "(${x}: int) > ${y}"
|
|
485
461
|
llvm """
|
|
486
462
|
%z = icmp sgt %Int ${x}, ${y}
|
|
487
463
|
%fat_z = zext i1 %z to i64
|
|
@@ -492,7 +468,6 @@ extern pure def infixGt(x: Int, y: Int): Bool =
|
|
|
492
468
|
extern pure def infixGte(x: Int, y: Int): Bool =
|
|
493
469
|
js "(${x} >= ${y})"
|
|
494
470
|
chez "(>= ${x} ${y})"
|
|
495
|
-
ml "(${x}: int) >= ${y}"
|
|
496
471
|
llvm """
|
|
497
472
|
%z = icmp sge %Int ${x}, ${y}
|
|
498
473
|
%fat_z = zext i1 %z to i64
|
|
@@ -503,17 +478,14 @@ extern pure def infixGte(x: Int, y: Int): Bool =
|
|
|
503
478
|
extern pure def infixEq(x: Double, y: Double): Bool =
|
|
504
479
|
js "${x} === ${y}"
|
|
505
480
|
chez "(= ${x} ${y})"
|
|
506
|
-
ml "(${x}: real) = ${y}"
|
|
507
481
|
|
|
508
482
|
extern pure def infixNeq(x: Double, y: Double): Bool =
|
|
509
483
|
js "${x} !== ${y}"
|
|
510
484
|
chez "(not (= ${x} ${y}))"
|
|
511
|
-
ml "(${x}: real) <> ${y}"
|
|
512
485
|
|
|
513
486
|
extern pure def infixLt(x: Double, y: Double): Bool =
|
|
514
487
|
js "(${x} < ${y})"
|
|
515
488
|
chez "(< ${x} ${y})"
|
|
516
|
-
ml "(${x}: real) < ${y}"
|
|
517
489
|
llvm """
|
|
518
490
|
%z = fcmp olt %Double ${x}, ${y}
|
|
519
491
|
%fat_z = zext i1 %z to i64
|
|
@@ -524,12 +496,10 @@ extern pure def infixLt(x: Double, y: Double): Bool =
|
|
|
524
496
|
extern pure def infixLte(x: Double, y: Double): Bool =
|
|
525
497
|
js "(${x} <= ${y})"
|
|
526
498
|
chez "(<= ${x} ${y})"
|
|
527
|
-
ml "(${x}: real) <= ${y}"
|
|
528
499
|
|
|
529
500
|
extern pure def infixGt(x: Double, y: Double): Bool =
|
|
530
501
|
js "(${x} > ${y})"
|
|
531
502
|
chez "(> ${x} ${y})"
|
|
532
|
-
ml "(${x}: real) > ${y}"
|
|
533
503
|
llvm """
|
|
534
504
|
%z = fcmp ogt %Double ${x}, ${y}
|
|
535
505
|
%fat_z = zext i1 %z to i64
|
|
@@ -540,28 +510,23 @@ extern pure def infixGt(x: Double, y: Double): Bool =
|
|
|
540
510
|
extern pure def infixGte(x: Double, y: Double): Bool =
|
|
541
511
|
js "(${x} >= ${y})"
|
|
542
512
|
chez "(>= ${x} ${y})"
|
|
543
|
-
ml "(${x}: real) >= ${y}"
|
|
544
513
|
|
|
545
514
|
// TODO do we really need those? if yes, move to string.effekt
|
|
546
515
|
extern pure def infixLt(x: String, y: String): Bool =
|
|
547
516
|
js "(${x} < ${y})"
|
|
548
517
|
chez "(< ${x} ${y})"
|
|
549
|
-
ml "(${x}: string) < ${y}"
|
|
550
518
|
|
|
551
519
|
extern pure def infixLte(x: String, y: String): Bool =
|
|
552
520
|
js "(${x} <= ${y})"
|
|
553
521
|
chez "(<= ${x} ${y})"
|
|
554
|
-
ml "(${x}: string) <= ${y}"
|
|
555
522
|
|
|
556
523
|
extern pure def infixGt(x: String, y: String): Bool =
|
|
557
524
|
js "(${x} > ${y})"
|
|
558
525
|
chez "(> ${x} ${y})"
|
|
559
|
-
ml "(${x}: string) > ${y}"
|
|
560
526
|
|
|
561
527
|
extern pure def infixGte(x: String, y: String): Bool =
|
|
562
528
|
js "(${x} >= ${y})"
|
|
563
529
|
chez "(>= ${x} ${y})"
|
|
564
|
-
ml "(${x}: string) >= ${y}"
|
|
565
530
|
|
|
566
531
|
|
|
567
532
|
// Boolean operations
|
|
@@ -569,7 +534,6 @@ extern pure def infixGte(x: String, y: String): Bool =
|
|
|
569
534
|
extern pure def not(b: Bool): Bool =
|
|
570
535
|
js "!${b}"
|
|
571
536
|
chez "(not ${b})"
|
|
572
|
-
ml "not ${b}"
|
|
573
537
|
llvm """
|
|
574
538
|
%p = extractvalue %Pos ${b}, 0
|
|
575
539
|
%q = xor i64 1, %p
|
|
@@ -620,7 +584,6 @@ extern pure def toInt(n: Byte): Int =
|
|
|
620
584
|
//
|
|
621
585
|
// js: undefined || null
|
|
622
586
|
// chez: #f
|
|
623
|
-
// ml: NONE (of option 'a)
|
|
624
587
|
// llvm: null?
|
|
625
588
|
|
|
626
589
|
/**
|
|
@@ -629,7 +592,6 @@ extern pure def toInt(n: Byte): Int =
|
|
|
629
592
|
extern pure def undefined[A](): A =
|
|
630
593
|
js "undefined"
|
|
631
594
|
chez "#f"
|
|
632
|
-
ml "NONE"
|
|
633
595
|
|
|
634
596
|
/**
|
|
635
597
|
* Is an FFI value undefined?
|
|
@@ -637,7 +599,6 @@ extern pure def undefined[A](): A =
|
|
|
637
599
|
extern pure def isUndefined[A](value: A): Bool =
|
|
638
600
|
js "(${value} === undefined || ${value} === null)"
|
|
639
601
|
chez "(eq? ${value} #f)"
|
|
640
|
-
ml "Option.isSome ${value}"
|
|
641
602
|
|
|
642
603
|
|
|
643
604
|
// Tuples
|
|
@@ -53,7 +53,6 @@ def wrongFormat(msg: String): Nothing / Exception[WrongFormat] =
|
|
|
53
53
|
extern io def panic[R](msg: String): R =
|
|
54
54
|
js "(function() { throw ${msg} })()"
|
|
55
55
|
chez "(raise ${msg})"
|
|
56
|
-
ml "raise Fail ${msg}"
|
|
57
56
|
llvm """
|
|
58
57
|
call void @c_io_println_String(%Pos ${msg})
|
|
59
58
|
call void @exit(i32 1)
|