@effekt-lang/effekt 0.2.1 → 0.2.2
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/LICENSE +21 -0
- package/README.md +36 -0
- package/bin/effekt +0 -0
- package/bin/effekt.sh +2 -0
- package/libraries/chez/THIRD-PARTY.txt +11 -0
- package/libraries/chez/callcc/datatype.ss +188 -0
- package/libraries/chez/callcc/effekt.effekt +221 -0
- package/libraries/chez/callcc/effekt.ss +31 -0
- package/libraries/chez/callcc/seq.ss +44 -0
- package/libraries/chez/callcc/seq0.ss +69 -0
- package/libraries/chez/callcc/tail.ss +76 -0
- package/libraries/chez/callcc/tail0.ss +89 -0
- package/libraries/chez/common/effekt_matching.ss +100 -0
- package/libraries/chez/common/effekt_primitives.ss +97 -0
- package/libraries/chez/common/immutable/cslist.effekt +31 -0
- package/libraries/chez/common/immutable/dequeue.effekt +78 -0
- package/libraries/chez/common/immutable/list.effekt +643 -0
- package/libraries/chez/common/immutable/option.effekt +39 -0
- package/libraries/chez/common/immutable/result.effekt +29 -0
- package/libraries/chez/common/io/args.effekt +20 -0
- package/libraries/chez/common/mutable/array.effekt +27 -0
- package/libraries/chez/common/mutable/dict.effekt +30 -0
- package/libraries/chez/common/mutable/heap.effekt +12 -0
- package/libraries/chez/common/test.effekt +59 -0
- package/libraries/chez/common/text/pregexp.scm +772 -0
- package/libraries/chez/common/text/regex.effekt +33 -0
- package/libraries/chez/common/text/string.effekt +46 -0
- package/libraries/chez/lift/effekt.effekt +217 -0
- package/libraries/chez/lift/effekt.ss +118 -0
- package/libraries/chez/monadic/effekt.effekt +218 -0
- package/libraries/chez/monadic/effekt.ss +84 -0
- package/libraries/chez/monadic/seq0.ss +76 -0
- package/libraries/js/effekt.effekt +284 -0
- package/libraries/js/effekt_builtins.js +26 -0
- package/libraries/js/effekt_matching.js +79 -0
- package/libraries/js/effekt_runtime.js +385 -0
- package/libraries/js/immutable/dequeue.effekt +78 -0
- package/libraries/js/immutable/list.effekt +643 -0
- package/libraries/js/immutable/option.effekt +49 -0
- package/libraries/js/immutable/result.effekt +29 -0
- package/libraries/js/io/args.effekt +9 -0
- package/libraries/js/io/async.effekt +28 -0
- package/libraries/js/io/async.js +2 -0
- package/libraries/js/io/file.effekt +50 -0
- package/libraries/js/io/file_include.js +13 -0
- package/libraries/js/mutable/array.effekt +98 -0
- package/libraries/js/mutable/heap.effekt +32 -0
- package/libraries/js/mutable/map.effekt +32 -0
- package/libraries/js/test.effekt +59 -0
- package/libraries/js/text/regex.effekt +34 -0
- package/libraries/js/text/string.effekt +64 -0
- package/libraries/js/unsafe/cont.effekt +11 -0
- package/libraries/js/web/dom.effekt +45 -0
- package/libraries/llvm/buffer.c +181 -0
- package/libraries/llvm/effekt.effekt +243 -0
- package/libraries/llvm/forward-declare-c.ll +24 -0
- package/libraries/llvm/hole.c +11 -0
- package/libraries/llvm/immutable/list.effekt +678 -0
- package/libraries/llvm/immutable/option.effekt +53 -0
- package/libraries/llvm/immutable/result.effekt +29 -0
- package/libraries/llvm/io/args.effekt +24 -0
- package/libraries/llvm/io.c +24 -0
- package/libraries/llvm/main.c +39 -0
- package/libraries/llvm/rts.ll +619 -0
- package/libraries/llvm/sanity.c +16 -0
- package/libraries/llvm/text/string.effekt +179 -0
- package/libraries/llvm/types.c +20 -0
- package/libraries/ml/effekt.effekt +267 -0
- package/libraries/ml/effekt.sml +63 -0
- package/libraries/ml/immutable/dequeue.effekt +81 -0
- package/libraries/ml/immutable/list.effekt +674 -0
- package/libraries/ml/immutable/option.effekt +53 -0
- package/libraries/ml/immutable/result.effekt +29 -0
- package/libraries/ml/immutable/seq.effekt +903 -0
- package/libraries/ml/internal/option.effekt +18 -0
- package/libraries/ml/io/args.effekt +41 -0
- package/libraries/ml/mutable/array.effekt +43 -0
- package/libraries/ml/random.effekt +85 -0
- package/libraries/ml/test.effekt +60 -0
- package/libraries/ml/text/regex.effekt +107 -0
- package/libraries/ml/text/string.effekt +81 -0
- package/licenses/THIRD-PARTY.txt +21 -0
- package/licenses/apache-2.0 - license-2.0.txt +202 -0
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +61 -0
- package/licenses/kiama-license.txt +373 -0
- package/licenses/kiama-readme.txt +186 -0
- package/licenses/mit license - mit-license.html +769 -0
- package/licenses/the apache software license, version 2.0 - license-2.0.txt +202 -0
- package/licenses/the bsd license - bsd-license.html +762 -0
- package/licenses/the mit license - mit.html +769 -0
- package/package.json +26 -18
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Jonathan Brachthäuser and contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Ξ Effekt
|
|
2
|
+
|
|
3
|
+
Compared to other languages with effect handlers (and support for polymorphic effects) the Effekt language
|
|
4
|
+
aims to be significantly more lightweight in its concepts.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## Disclaimer: Use at your own risk
|
|
8
|
+
|
|
9
|
+
**Effekt is a research-level language. We are actively working on it and the language (and everything else) is very likely to change.**
|
|
10
|
+
|
|
11
|
+
Also, Effekt comes with no warranty and there are (probably) many bugs -- If this does not discourage you, feel free to
|
|
12
|
+
play with it and give us your feedback :)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
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:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
npm install -g https://github.com/effekt-lang/effekt/releases/latest/download/effekt.tgz
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Alternatively, you can download the `effekt.tgz` file from [another release](https://github.com/effekt-lang/effekt/releases) and then run
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
npm install -g effekt.tgz
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This will make the `effekt` command globally available. You can start the Effekt REPL by entering:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
> effekt
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
You can find more information about the Effekt language and how to use it on the website (<https://effekt-lang.org>).
|
package/bin/effekt
ADDED
|
Binary file
|
package/bin/effekt.sh
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
The runtime of the callcc version builds on code by R. Kent Dybvig,
|
|
2
|
+
Simon L. Peyton Jones, and Amr Sabry, as presented in:
|
|
3
|
+
|
|
4
|
+
Dyvbig, R. K., Jones, S. P., & Sabry, A. (2007).
|
|
5
|
+
A monadic framework for delimited continuations.
|
|
6
|
+
Journal of Functional Programming, 17(6), 687-730.
|
|
7
|
+
|
|
8
|
+
The regular expression implementation is by Dorai Sitaram and
|
|
9
|
+
obtained from:
|
|
10
|
+
|
|
11
|
+
<https://github.com/ds26gte/pregexp/blob/master/pregexp.scm>
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
;;; datatype.ss
|
|
2
|
+
;;; Copyright (c) 2005, R. Kent Dybvig, Simon L. Peyton Jones, and Amr Sabry
|
|
3
|
+
|
|
4
|
+
;;; Code for defining datatypes, based on record subtyping.
|
|
5
|
+
|
|
6
|
+
#|
|
|
7
|
+
|
|
8
|
+
Description
|
|
9
|
+
-----------
|
|
10
|
+
|
|
11
|
+
A define-datatype form creates a new datatype with zero or more variants,
|
|
12
|
+
each with its own set of fields. It produces definitions for a predicate,
|
|
13
|
+
constructors, and a case form.
|
|
14
|
+
|
|
15
|
+
Syntax:
|
|
16
|
+
|
|
17
|
+
<datatype definition> -> (define-datatype <datatype name> <variant>*)
|
|
18
|
+
|
|
19
|
+
<datatype name> -> identifier
|
|
20
|
+
|
|
21
|
+
<variant> -> (<variant name> <field name>*)
|
|
22
|
+
<variant name> -> identifier
|
|
23
|
+
<field name> -> identifier
|
|
24
|
+
|
|
25
|
+
Products:
|
|
26
|
+
The definition
|
|
27
|
+
|
|
28
|
+
(define-datatype dtname (vname vfield ...))
|
|
29
|
+
|
|
30
|
+
produces the following set of variable definitions:
|
|
31
|
+
|
|
32
|
+
dtname? a predicate true only of datatype instances
|
|
33
|
+
variant ... a set of constructors for the different variants
|
|
34
|
+
dtname-case a case construct for the datatype
|
|
35
|
+
|
|
36
|
+
Each constructor accepts one argument for each field of the variant.
|
|
37
|
+
The case construct has the following syntax:
|
|
38
|
+
|
|
39
|
+
(dtname-case <expression> <clause> ...)
|
|
40
|
+
|
|
41
|
+
where each <clause> is of the form:
|
|
42
|
+
|
|
43
|
+
[(<variant name> <field name>*) <expression>+]
|
|
44
|
+
|
|
45
|
+
except that the last must be an else clause of the form
|
|
46
|
+
|
|
47
|
+
[else <expression>+]
|
|
48
|
+
|
|
49
|
+
if any of the datatype's variants are not represented in the set of
|
|
50
|
+
clauses. The clauses may appear in any order and the field names
|
|
51
|
+
need not be the same as those given in the datatype definition.
|
|
52
|
+
(They are instead specified positionally.)
|
|
53
|
+
|
|
54
|
+
Example:
|
|
55
|
+
|
|
56
|
+
(case-sensitive #t)
|
|
57
|
+
|
|
58
|
+
(define-datatype AST
|
|
59
|
+
(Const datum)
|
|
60
|
+
(Ref var)
|
|
61
|
+
(If tst thn els)
|
|
62
|
+
(Fun fmls body)
|
|
63
|
+
(Call exp0 args))
|
|
64
|
+
|
|
65
|
+
(define (parse x)
|
|
66
|
+
(cond
|
|
67
|
+
[(symbol? x) (Ref x)]
|
|
68
|
+
[(pair? x)
|
|
69
|
+
(case (car x)
|
|
70
|
+
[(if) (If (parse (cadr x)) (parse (caddr x)) (parse (cadddr x)))]
|
|
71
|
+
[(fun) (Fun (cadr x) (parse (caddr x)))]
|
|
72
|
+
[else (Call (parse (car x)) (map parse (cdr x)))])]
|
|
73
|
+
[else (Const x)]))
|
|
74
|
+
|
|
75
|
+
(define (ev x r)
|
|
76
|
+
(AST-case x
|
|
77
|
+
[(Ref v) (cdr (assq v r))]
|
|
78
|
+
[(Const x) x]
|
|
79
|
+
[(If tst thn els) (ev (if (ev tst r) thn els) r)]
|
|
80
|
+
[(Fun fmls body)
|
|
81
|
+
(lambda args
|
|
82
|
+
(ev body (append (map cons fmls args) r)))]
|
|
83
|
+
[(Call proc actuals)
|
|
84
|
+
(apply (ev proc r) (map (lambda (x) (ev x r)) actuals))]))
|
|
85
|
+
|
|
86
|
+
(AST? (parse #'(fun (x) x)))
|
|
87
|
+
|
|
88
|
+
(define (run x) (ev (parse x) `((- . ,-) (* . ,*) (= . ,=))))
|
|
89
|
+
|
|
90
|
+
(run '((fun (f) (f f 10))
|
|
91
|
+
(fun (f x)
|
|
92
|
+
(if (= x 0)
|
|
93
|
+
1
|
|
94
|
+
(* x (f f (- x 1))))))) ;=> 3628800
|
|
95
|
+
|
|
96
|
+
|#
|
|
97
|
+
|
|
98
|
+
(define-syntax define-datatype
|
|
99
|
+
(lambda (x)
|
|
100
|
+
(define construct-name
|
|
101
|
+
(lambda (template-identifier . args)
|
|
102
|
+
(datum->syntax-object
|
|
103
|
+
template-identifier
|
|
104
|
+
(string->symbol
|
|
105
|
+
(apply string-append
|
|
106
|
+
(map (lambda (x)
|
|
107
|
+
(if (string? x)
|
|
108
|
+
x
|
|
109
|
+
(symbol->string (syntax-object->datum x))))
|
|
110
|
+
args))))))
|
|
111
|
+
(define iota
|
|
112
|
+
(case-lambda
|
|
113
|
+
[(n) (iota 0 n)]
|
|
114
|
+
[(i n) (if (= n 0) '() (cons i (iota (+ i 1) (- n 1))))]))
|
|
115
|
+
(syntax-case x ()
|
|
116
|
+
[(_ dtname (vname field ...) ...)
|
|
117
|
+
(and (identifier? #'dtname) (andmap identifier? (syntax->list #'(vname ...))))
|
|
118
|
+
(with-syntax ([dtname? (construct-name #'dtname #'dtname "?")]
|
|
119
|
+
[dtname-case (construct-name #'dtname #'dtname "-case")]
|
|
120
|
+
[dtname-variant (construct-name #'dtname #'dtname "-variant")]
|
|
121
|
+
[((vname-field ...) ...)
|
|
122
|
+
(map (lambda (vname fields)
|
|
123
|
+
(map (lambda (field)
|
|
124
|
+
(construct-name #'dtname
|
|
125
|
+
vname "-" field))
|
|
126
|
+
fields))
|
|
127
|
+
(syntax->list #'(vname ...))
|
|
128
|
+
(map syntax->list (syntax->list #'((field ...) ...))))]
|
|
129
|
+
[(make-vname ...)
|
|
130
|
+
(map (lambda (x)
|
|
131
|
+
(construct-name #'dtname
|
|
132
|
+
"make-" x))
|
|
133
|
+
(syntax->list #'(vname ...)))]
|
|
134
|
+
[(i ...) (iota (length (syntax->list #'(vname ...))))])
|
|
135
|
+
#'(module (dtname? (dtname-case dtname-variant vname-field ... ...) vname ...)
|
|
136
|
+
(define-record dtname ((immutable variant)))
|
|
137
|
+
(module (make-vname vname-field ...)
|
|
138
|
+
(define-record vname dtname ((immutable field) ...) ()))
|
|
139
|
+
...
|
|
140
|
+
(define-syntax dtname-case
|
|
141
|
+
(lambda (x)
|
|
142
|
+
(define make-clause
|
|
143
|
+
(lambda (x)
|
|
144
|
+
(syntax-case x (vname ...)
|
|
145
|
+
[(vname (field ...) e1 e2 (... ...))
|
|
146
|
+
#'((i) (let ([field (vname-field t)] ...)
|
|
147
|
+
e1 e2 (... ...)))]
|
|
148
|
+
...)))
|
|
149
|
+
(syntax-case x (else)
|
|
150
|
+
[(__ e0
|
|
151
|
+
((v fld (... ...)) e1 e2 (... ...))
|
|
152
|
+
(... ...)
|
|
153
|
+
(else e3 e4 (... ...)))
|
|
154
|
+
(with-syntax ([(clause (... ...))
|
|
155
|
+
(map make-clause
|
|
156
|
+
#'((v (fld (... ...)) e1 e2 (... ...))
|
|
157
|
+
(... ...)))])
|
|
158
|
+
#'(let ([t e0])
|
|
159
|
+
(case (dtname-variant t)
|
|
160
|
+
clause
|
|
161
|
+
(... ...)
|
|
162
|
+
(else e3 e4 (... ...)))))]
|
|
163
|
+
[(__ e0
|
|
164
|
+
((v fld (... ...)) e1 e2 (... ...))
|
|
165
|
+
(... ...))
|
|
166
|
+
(let f ([ls1 (list #'vname ...)])
|
|
167
|
+
(or (null? ls1)
|
|
168
|
+
(and (let g ([ls2 (syntax->list #'(v (... ...)))])
|
|
169
|
+
(if (null? ls2)
|
|
170
|
+
(syntax-error x
|
|
171
|
+
(format "unhandled `~s' variant in"
|
|
172
|
+
(syntax-object->datum (car ls1))))
|
|
173
|
+
(or (literal-identifier=? (car ls1) (car ls2))
|
|
174
|
+
(g (cdr ls2)))))
|
|
175
|
+
(f (cdr ls1)))))
|
|
176
|
+
(with-syntax ([(clause (... ...))
|
|
177
|
+
(map make-clause
|
|
178
|
+
(syntax->list
|
|
179
|
+
#'((v (fld (... ...)) e1 e2 (... ...))
|
|
180
|
+
(... ...))))])
|
|
181
|
+
#'(let ([t e0])
|
|
182
|
+
(case (dtname-variant t)
|
|
183
|
+
clause
|
|
184
|
+
(... ...))))])))
|
|
185
|
+
(define vname
|
|
186
|
+
(lambda (field ...)
|
|
187
|
+
(make-vname i field ...)))
|
|
188
|
+
...))])))
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
module effekt
|
|
2
|
+
|
|
3
|
+
// shift-0 based implementation
|
|
4
|
+
extern include "../common/effekt_primitives.ss"
|
|
5
|
+
// extern include "datatype.ss"
|
|
6
|
+
extern include "seq0.ss"
|
|
7
|
+
extern include "tail0.ss"
|
|
8
|
+
extern include "effekt.ss"
|
|
9
|
+
extern include "../common/effekt_matching.ss"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def locally[R] { f: => R }: R = f()
|
|
13
|
+
|
|
14
|
+
// String ops
|
|
15
|
+
// ==========
|
|
16
|
+
extern pure def infixConcat(s1: String, s2: String): String =
|
|
17
|
+
"(string-append ${s1} ${s2})"
|
|
18
|
+
|
|
19
|
+
// TODO implement
|
|
20
|
+
extern pure def show[R](value: R): String =
|
|
21
|
+
"(show_impl ${value})"
|
|
22
|
+
|
|
23
|
+
extern io def println[R](r: R): Unit =
|
|
24
|
+
"(println_impl ${r})"
|
|
25
|
+
|
|
26
|
+
extern io def error[R](msg: String): R =
|
|
27
|
+
"(raise ${msg})"
|
|
28
|
+
|
|
29
|
+
extern io def random(): Double =
|
|
30
|
+
"(random 1.0)"
|
|
31
|
+
|
|
32
|
+
// Math ops
|
|
33
|
+
// ========
|
|
34
|
+
extern pure def infixAdd(x: Int, y: Int): Int =
|
|
35
|
+
"(+ ${x} ${y})"
|
|
36
|
+
|
|
37
|
+
extern pure def infixMul(x: Int, y: Int): Int =
|
|
38
|
+
"(* ${x} ${y})"
|
|
39
|
+
|
|
40
|
+
extern pure def infixDiv(x: Int, y: Int): Int =
|
|
41
|
+
"(floor (/ ${x} ${y}))"
|
|
42
|
+
|
|
43
|
+
extern pure def infixSub(x: Int, y: Int): Int =
|
|
44
|
+
"(- ${x} ${y})"
|
|
45
|
+
|
|
46
|
+
extern pure def mod(x: Int, y: Int): Int =
|
|
47
|
+
"(modulo ${x} ${y})"
|
|
48
|
+
|
|
49
|
+
extern pure def infixAdd(x: Double, y: Double): Double =
|
|
50
|
+
"(+ ${x} ${y})"
|
|
51
|
+
|
|
52
|
+
extern pure def infixMul(x: Double, y: Double): Double =
|
|
53
|
+
"(* ${x} ${y})"
|
|
54
|
+
|
|
55
|
+
extern pure def infixDiv(x: Double, y: Double): Double =
|
|
56
|
+
"(/ ${x} ${y})"
|
|
57
|
+
|
|
58
|
+
extern pure def infixSub(x: Double, y: Double): Double =
|
|
59
|
+
"(- ${x} ${y})"
|
|
60
|
+
|
|
61
|
+
extern pure def cos(x: Double): Double =
|
|
62
|
+
"(cos ${x})"
|
|
63
|
+
|
|
64
|
+
extern pure def sin(x: Double): Double =
|
|
65
|
+
"(sin ${x})"
|
|
66
|
+
|
|
67
|
+
extern pure def atan(x: Double): Double =
|
|
68
|
+
"(atan ${x})"
|
|
69
|
+
|
|
70
|
+
extern pure def tan(x: Double): Double =
|
|
71
|
+
"(tan ${x})"
|
|
72
|
+
|
|
73
|
+
extern pure def sqrt(x: Double): Double =
|
|
74
|
+
"(sqrt ${x})"
|
|
75
|
+
|
|
76
|
+
extern pure def square(x: Double): Double =
|
|
77
|
+
"(* ${x} ${x})"
|
|
78
|
+
|
|
79
|
+
extern pure def log(x: Double): Double =
|
|
80
|
+
"(log ${x})"
|
|
81
|
+
|
|
82
|
+
extern pure def log1p(x: Double): Double =
|
|
83
|
+
"(log (+ ${x} 1))"
|
|
84
|
+
|
|
85
|
+
extern pure def exp(x: Double): Double =
|
|
86
|
+
"(exp ${x})"
|
|
87
|
+
|
|
88
|
+
// since we do not have "extern val", yet
|
|
89
|
+
extern pure def _pi(): Double =
|
|
90
|
+
"(* 4 (atan 1))"
|
|
91
|
+
|
|
92
|
+
val PI: Double = _pi()
|
|
93
|
+
|
|
94
|
+
extern pure def toInt(d: Double): Int =
|
|
95
|
+
"(round ${d})"
|
|
96
|
+
|
|
97
|
+
extern pure def toDouble(d: Int): Double =
|
|
98
|
+
"${d}"
|
|
99
|
+
|
|
100
|
+
def min(n: Int, m: Int): Int =
|
|
101
|
+
if (n < m) n else m
|
|
102
|
+
|
|
103
|
+
def max(n: Int, m: Int): Int =
|
|
104
|
+
if (n > m) n else m
|
|
105
|
+
|
|
106
|
+
// Comparison ops
|
|
107
|
+
// ==============
|
|
108
|
+
extern pure def infixEq[R](x: R, y: R): Boolean =
|
|
109
|
+
"(equal_impl ${x} ${y})"
|
|
110
|
+
|
|
111
|
+
extern pure def infixNeq[R](x: R, y: R): Boolean =
|
|
112
|
+
"(not (equal_impl ${x} ${y}))"
|
|
113
|
+
|
|
114
|
+
extern pure def infixLt(x: Int, y: Int): Boolean =
|
|
115
|
+
"(< ${x} ${y})"
|
|
116
|
+
|
|
117
|
+
extern pure def infixLte(x: Int, y: Int): Boolean =
|
|
118
|
+
"(<= ${x} ${y})"
|
|
119
|
+
|
|
120
|
+
extern pure def infixGt(x: Int, y: Int): Boolean =
|
|
121
|
+
"(> ${x} ${y})"
|
|
122
|
+
|
|
123
|
+
extern pure def infixGte(x: Int, y: Int): Boolean =
|
|
124
|
+
"(>= ${x} ${y})"
|
|
125
|
+
|
|
126
|
+
extern pure def infixLt(x: Double, y: Double): Boolean =
|
|
127
|
+
"(< ${x} ${y})"
|
|
128
|
+
|
|
129
|
+
extern pure def infixLte(x: Double, y: Double): Boolean =
|
|
130
|
+
"(<= ${x} ${y})"
|
|
131
|
+
|
|
132
|
+
extern pure def infixGt(x: Double, y: Double): Boolean =
|
|
133
|
+
"(> ${x} ${y})"
|
|
134
|
+
|
|
135
|
+
extern pure def infixGte(x: Double, y: Double): Boolean =
|
|
136
|
+
"(>= ${x} ${y})"
|
|
137
|
+
|
|
138
|
+
// Boolean ops
|
|
139
|
+
// ===========
|
|
140
|
+
// for now those are considered eager
|
|
141
|
+
extern pure def not(b: Boolean): Boolean =
|
|
142
|
+
"(not ${b})"
|
|
143
|
+
|
|
144
|
+
extern pure def infixOr(x: Boolean, y: Boolean): Boolean =
|
|
145
|
+
"(or ${x} ${y})"
|
|
146
|
+
|
|
147
|
+
extern pure def infixAnd(x: Boolean, y: Boolean): Boolean =
|
|
148
|
+
"(and ${x} ${y})"
|
|
149
|
+
|
|
150
|
+
// Should only be used internally since values in Effekt should not be undefined
|
|
151
|
+
extern pure def isUndefined[A](value: A): Boolean =
|
|
152
|
+
"(eq? ${value} #f)"
|
|
153
|
+
|
|
154
|
+
// Pairs
|
|
155
|
+
// =====
|
|
156
|
+
record Tuple2[A, B](first: A, second: B)
|
|
157
|
+
record Tuple3[A, B, C](first: A, second: B, third: C)
|
|
158
|
+
record Tuple4[A, B, C, D](first: A, second: B, third: C, fourth: D)
|
|
159
|
+
record Tuple5[A, B, C, D, E](first: A, second: B, third: C, fourth: D, fifth: E)
|
|
160
|
+
record Tuple6[A, B, C, D, E, F](first: A, second: B, third: C, fourth: D, fifth: E, sixth: F)
|
|
161
|
+
|
|
162
|
+
// Exceptions
|
|
163
|
+
// ==========
|
|
164
|
+
// a fatal runtime error that cannot be caught
|
|
165
|
+
extern io def panic[R](msg: String): R =
|
|
166
|
+
"(raise ${msg})"
|
|
167
|
+
|
|
168
|
+
interface Exception[E] {
|
|
169
|
+
def raise(exception: E, msg: String): Nothing
|
|
170
|
+
}
|
|
171
|
+
record RuntimeError()
|
|
172
|
+
|
|
173
|
+
def raise[A](msg: String): A / Exception[RuntimeError] = do raise(RuntimeError(), msg) match {}
|
|
174
|
+
def raise[A, E](exception: E, msg: String): A / Exception[E] = do raise(exception, msg) match {}
|
|
175
|
+
|
|
176
|
+
// converts exceptions of (static) type E to an uncatchable panic that aborts the program
|
|
177
|
+
def panicOn[E] { prog: => Unit / Exception[E] }: Unit =
|
|
178
|
+
try { prog() } with Exception[E] { def raise(exception: E, msg: String) = panic(msg) }
|
|
179
|
+
|
|
180
|
+
// reports exceptions of (static) type E to the console
|
|
181
|
+
def report[E] { prog: => Unit / Exception[E] }: Unit =
|
|
182
|
+
try { prog() } with Exception[E] { def raise(exception: E, msg: String) = println(msg) }
|
|
183
|
+
|
|
184
|
+
// ignores exceptions of (static) type E
|
|
185
|
+
// TODO this should be called "ignore" but that name currently clashes with internal pattern matching names on $effekt
|
|
186
|
+
def ignoring[E] { prog: => Unit / Exception[E] }: Unit =
|
|
187
|
+
try { prog() } with Exception[E] { def raise(exception: E, msg: String) = () }
|
|
188
|
+
|
|
189
|
+
// Control Flow
|
|
190
|
+
// ============
|
|
191
|
+
interface Control {
|
|
192
|
+
def break(): Unit
|
|
193
|
+
def continue(): Unit
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
def loop { f: () => Unit / Control }: Unit = try {
|
|
197
|
+
def go(): Unit = { f(); go() }
|
|
198
|
+
go()
|
|
199
|
+
} with Control {
|
|
200
|
+
def break() = ()
|
|
201
|
+
def continue() = loop { f }
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Calls provided action repeatedly. `start` is inclusive, `end` is not.
|
|
206
|
+
*/
|
|
207
|
+
def each(start: Int, end: Int) { action: (Int) => Unit / Control } = {
|
|
208
|
+
var i = start;
|
|
209
|
+
loop {
|
|
210
|
+
if (i < end) { val el = i; i = i + 1; action(el) }
|
|
211
|
+
else { do break() }
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
def repeat(n: Int) { action: () => Unit / Control } = each(0, n) { n => action() }
|
|
216
|
+
|
|
217
|
+
// Benchmarking
|
|
218
|
+
// ============
|
|
219
|
+
// should only be used with pure blocks
|
|
220
|
+
extern control def measure(warmup: Int, iterations: Int) { block: => Unit }: Unit =
|
|
221
|
+
"(display (measure ${box block} ${warmup} ${iterations}))"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
; ;; EXAMPLE
|
|
3
|
+
; ; (handle ([Fail_22 (Fail_109 () resume_120 (Nil_74))])
|
|
4
|
+
; ; (let ((tmp86_121 ((Fail_109 Fail_22))))
|
|
5
|
+
; ; (Cons_73 tmp86_121 (Nil_74))))
|
|
6
|
+
; (define-syntax handle
|
|
7
|
+
; (syntax-rules ()
|
|
8
|
+
; [(_ ((cap1 (op1 (arg1 ...) k exp ...) ...) ...) body ...)
|
|
9
|
+
; (let ([P (newPrompt)])
|
|
10
|
+
; (pushPrompt P
|
|
11
|
+
; (let ([cap1 (cap1 (define-effect-op P (arg1 ...) k exp ...) ...)] ...)
|
|
12
|
+
; body ...)))]))
|
|
13
|
+
|
|
14
|
+
(define-syntax handle
|
|
15
|
+
(syntax-rules ()
|
|
16
|
+
[(_ ((cap1 (op1 (arg1 ...) k exp ...) ...) ...) body)
|
|
17
|
+
(let ([P (newPrompt)])
|
|
18
|
+
(pushPrompt P
|
|
19
|
+
(body (cap1 (define-effect-op P (arg1 ...) k exp ...) ...) ...)))]))
|
|
20
|
+
|
|
21
|
+
(define-syntax define-effect-op
|
|
22
|
+
(syntax-rules ()
|
|
23
|
+
[(_ P (arg1 ...) k exp ...)
|
|
24
|
+
(lambda (arg1 ...)
|
|
25
|
+
(shift0-at P k exp ...))]))
|
|
26
|
+
|
|
27
|
+
; state(init) { cell => ... }
|
|
28
|
+
(define (state init body)
|
|
29
|
+
(with-region (lambda (arena) (body (fresh arena init)))))
|
|
30
|
+
|
|
31
|
+
(define call/cc/base call/cc)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
;;; seq.ss
|
|
2
|
+
;;; Copyright (c) 2005, R. Kent Dybvig, Simon L. Peyton Jones, and Amr Sabry
|
|
3
|
+
|
|
4
|
+
;;; sequence (Seq) datatype
|
|
5
|
+
|
|
6
|
+
(define-datatype Seq
|
|
7
|
+
(EmptyS)
|
|
8
|
+
(PushP p Seq)
|
|
9
|
+
; Box -> BackupState -> Seq -> Seq
|
|
10
|
+
(PushState b s Seq)
|
|
11
|
+
(PushSeg k Seq))
|
|
12
|
+
|
|
13
|
+
(define (splitSeq p seq)
|
|
14
|
+
(Seq-case seq
|
|
15
|
+
[(EmptyS) (error 'splitSeq "prompt ~s not found on stack" p)]
|
|
16
|
+
[(PushP p* sk)
|
|
17
|
+
(if (not (eq? p p*))
|
|
18
|
+
(let-values ([(subk sk*) (splitSeq p sk)])
|
|
19
|
+
(values (PushP p* subk) sk*))
|
|
20
|
+
(values (EmptyS) sk))]
|
|
21
|
+
[(PushState b _ sk)
|
|
22
|
+
(let-values ([(subk sk*) (splitSeq p sk)])
|
|
23
|
+
(values (PushState b (unbox b) subk) sk*))]
|
|
24
|
+
[(PushSeg k sk)
|
|
25
|
+
(let-values ([(subk sk*) (splitSeq p sk)])
|
|
26
|
+
(values (PushSeg k subk) sk*))]))
|
|
27
|
+
|
|
28
|
+
(define (appendSeq seq_1 seq_2)
|
|
29
|
+
(Seq-case seq_1
|
|
30
|
+
[(EmptyS) seq_2]
|
|
31
|
+
[(PushP p subk) (PushP p (appendSeq subk seq_2))]
|
|
32
|
+
[(PushState b s subk)
|
|
33
|
+
(set-box! b s)
|
|
34
|
+
(PushState b #f (appendSeq subk seq_2))]
|
|
35
|
+
[(PushSeg k subk) (PushSeg k (appendSeq subk seq_2))]))
|
|
36
|
+
|
|
37
|
+
(define-syntax shift0-at
|
|
38
|
+
(syntax-rules ()
|
|
39
|
+
[(_ P id exp ...)
|
|
40
|
+
(withSubCont
|
|
41
|
+
P
|
|
42
|
+
(lambda (s)
|
|
43
|
+
(let ([id (lambda (v) (pushPrompt P (pushSubCont s v)))])
|
|
44
|
+
exp ...)))]))
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
; [ [f1, f2, f3, f4| fields | prompt], [f1, f2, f3, f4| fields | prompt]... ]
|
|
2
|
+
(define-record Stack (
|
|
3
|
+
[immutable frames]
|
|
4
|
+
[immutable arena]
|
|
5
|
+
[immutable prompt]))
|
|
6
|
+
|
|
7
|
+
(define-record Substack (
|
|
8
|
+
[immutable frames]
|
|
9
|
+
[immutable arena]
|
|
10
|
+
[immutable field-backup]
|
|
11
|
+
[immutable prompt]))
|
|
12
|
+
|
|
13
|
+
; MetaCont = (non-empty-list-of Stack)
|
|
14
|
+
; SubCont = (non-empty-list-of Stack)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
; An Arena is a pointer to a list of cells
|
|
18
|
+
(define (make-arena) (box '()))
|
|
19
|
+
|
|
20
|
+
(define (fresh arena init)
|
|
21
|
+
(let* ([cell (box init)]
|
|
22
|
+
[cells (unbox arena)])
|
|
23
|
+
(set-box! arena (cons cell cells))
|
|
24
|
+
cell))
|
|
25
|
+
|
|
26
|
+
; Backup = List<(Cell, Value)>
|
|
27
|
+
|
|
28
|
+
; Arena -> Backup
|
|
29
|
+
(define (backup arena)
|
|
30
|
+
(let ([fields (unbox arena)])
|
|
31
|
+
(map (lambda (cell) (cons cell (unbox cell))) fields)))
|
|
32
|
+
|
|
33
|
+
; Backup -> ()
|
|
34
|
+
(define (restore data)
|
|
35
|
+
(for-each (lambda (cell-data)
|
|
36
|
+
(set-box! (car cell-data) (cdr cell-data)))
|
|
37
|
+
data))
|
|
38
|
+
|
|
39
|
+
; Prompt MetaCont -> SubCont, MetaCont
|
|
40
|
+
(define (splitSeq p seq)
|
|
41
|
+
(define (split sub s)
|
|
42
|
+
(if (null? s)
|
|
43
|
+
(error 'splitSeq "prompt ~s not found on stack" p)
|
|
44
|
+
(let* ([stack (car s)]
|
|
45
|
+
[frames (Stack-frames stack)]
|
|
46
|
+
[arena (Stack-arena stack)]
|
|
47
|
+
[prompt (Stack-prompt stack)]
|
|
48
|
+
[rest (cdr s)])
|
|
49
|
+
(define sub* (cons (make-Substack frames arena (backup arena) prompt) sub))
|
|
50
|
+
(if (not (eq? prompt p))
|
|
51
|
+
(split sub* rest)
|
|
52
|
+
(values sub* rest)))))
|
|
53
|
+
(split (list) seq))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
(define (appendSeq subcont meta)
|
|
57
|
+
(if (null? subcont)
|
|
58
|
+
meta
|
|
59
|
+
(let* ([stack (car subcont)]
|
|
60
|
+
[frames (Substack-frames stack)]
|
|
61
|
+
[arena (Substack-arena stack)]
|
|
62
|
+
[fields (Substack-field-backup stack)]
|
|
63
|
+
[prompt (Substack-prompt stack)]
|
|
64
|
+
[_ (restore fields)]
|
|
65
|
+
[rest (cdr subcont)])
|
|
66
|
+
(appendSeq rest (cons (make-Stack frames arena prompt) meta)))))
|
|
67
|
+
|
|
68
|
+
; (define ex (list (make-Stack '(1 2 3) (list (box 1)) 4) (make-Stack '(1 2 3) (list (box 2)) 3) (make-Stack '(1 2 3) (list (box 3)) 2) (make-Stack '(4 5 6) (list (box 4)) 1)))
|
|
69
|
+
; (let-values ([(cont meta) (splitSeq 2 ex)]) (appendSeq cont meta))
|