@effekt-lang/effekt 0.2.1 → 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/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.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_primitives.ss +105 -0
- package/libraries/chez/common/immutable/cslist.effekt +37 -0
- package/libraries/chez/common/mutable/dict.effekt +28 -0
- package/libraries/chez/common/text/pregexp.scm +772 -0
- package/libraries/chez/common/text/regex.effekt +31 -0
- package/libraries/chez/lift/effekt.ss +118 -0
- package/libraries/chez/monadic/effekt.ss +84 -0
- package/libraries/chez/monadic/seq0.ss +76 -0
- 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/common/dequeue.effekt +92 -0
- 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/common/list.effekt +687 -0
- 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/common/seq.effekt +914 -0
- package/libraries/common/string.effekt +395 -0
- package/libraries/common/test.effekt +98 -0
- package/libraries/js/effekt_builtins.js +57 -0
- package/libraries/js/effekt_runtime.js +385 -0
- package/libraries/js/io.js +143 -0
- package/libraries/js/mutable/map.effekt +31 -0
- package/libraries/js/text/regex.effekt +33 -0
- package/libraries/js/unsafe/cont.effekt +11 -0
- package/libraries/js/web/dom.effekt +45 -0
- package/libraries/llvm/array.c +53 -0
- package/libraries/llvm/buffer.c +286 -0
- package/libraries/llvm/forward-declare-c.ll +43 -0
- package/libraries/llvm/hole.c +11 -0
- package/libraries/llvm/io.c +566 -0
- package/libraries/llvm/io.ll +19 -0
- package/libraries/llvm/main.c +41 -0
- package/libraries/llvm/ref.c +45 -0
- package/libraries/llvm/rts.ll +761 -0
- package/libraries/llvm/sanity.c +16 -0
- package/libraries/llvm/types.c +43 -0
- package/libraries/ml/effekt.sml +65 -0
- package/libraries/ml/internal/mllist.effekt +9 -0
- package/libraries/ml/internal/mloption.effekt +18 -0
- package/libraries/ml/random.effekt +85 -0
- package/libraries/ml/text/regex.effekt +102 -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 +1239 -0
- package/licenses/the apache software license, version 2.0 - license-2.0.txt +202 -0
- package/licenses/the bsd license - bsd-license.html +1237 -0
- package/licenses/the mit license - mit.html +1239 -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,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))
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
;;; tail.ss
|
|
2
|
+
;;; Copyright (c) 2005, R. Kent Dybvig, Simon L. Peyton Jones, and Amr Sabry
|
|
3
|
+
|
|
4
|
+
;;; Tail-recursive implementation of the operators
|
|
5
|
+
|
|
6
|
+
;(case-sensitive #t)
|
|
7
|
+
|
|
8
|
+
(define-syntax pushPrompt
|
|
9
|
+
(syntax-rules ()
|
|
10
|
+
[(_ p e1 e2 ...)
|
|
11
|
+
($pushPrompt p (lambda () e1 e2 ...))]))
|
|
12
|
+
|
|
13
|
+
(define-syntax pushSubCont
|
|
14
|
+
(syntax-rules ()
|
|
15
|
+
[(_ subk e1 e2 ...)
|
|
16
|
+
($pushSubCont subk (lambda () e1 e2 ...))]))
|
|
17
|
+
|
|
18
|
+
(define abort)
|
|
19
|
+
(define mk)
|
|
20
|
+
(define base-k)
|
|
21
|
+
|
|
22
|
+
(define (PushSeg/t k seq)
|
|
23
|
+
(if (eqv? k base-k)
|
|
24
|
+
seq
|
|
25
|
+
(PushSeg k seq)))
|
|
26
|
+
|
|
27
|
+
(define ($pushPrompt p th)
|
|
28
|
+
(call/cc (lambda (k)
|
|
29
|
+
(set! mk (PushP p (PushSeg/t k mk)))
|
|
30
|
+
(abort th))))
|
|
31
|
+
|
|
32
|
+
(define (state init th)
|
|
33
|
+
(define b (box init))
|
|
34
|
+
(set! mk (PushState b #f mk))
|
|
35
|
+
(th b))
|
|
36
|
+
|
|
37
|
+
(define (getter ref)
|
|
38
|
+
(lambda () (unbox ref)))
|
|
39
|
+
|
|
40
|
+
(define (setter ref)
|
|
41
|
+
(lambda (v) (set-box! ref v)))
|
|
42
|
+
|
|
43
|
+
(define (withSubCont p f)
|
|
44
|
+
(let-values ([(subk mk*) (splitSeq p mk)])
|
|
45
|
+
(set! mk mk*)
|
|
46
|
+
(call/cc (lambda (k)
|
|
47
|
+
(abort (lambda () (f (PushSeg/t k subk))))))))
|
|
48
|
+
|
|
49
|
+
(define ($pushSubCont subk th)
|
|
50
|
+
(call/cc (lambda (k)
|
|
51
|
+
(set! mk (appendSeq subk (PushSeg/t k mk)))
|
|
52
|
+
(abort th))))
|
|
53
|
+
|
|
54
|
+
(define newPrompt (lambda () (string #\p)))
|
|
55
|
+
|
|
56
|
+
(define (run th)
|
|
57
|
+
(set! mk (EmptyS))
|
|
58
|
+
(underflow
|
|
59
|
+
(call/cc/base
|
|
60
|
+
(lambda (k_1)
|
|
61
|
+
(set! base-k k_1)
|
|
62
|
+
((call/cc (lambda (k_2)
|
|
63
|
+
(set! abort k_2)
|
|
64
|
+
(abort th))))))))
|
|
65
|
+
|
|
66
|
+
(define (underflow v)
|
|
67
|
+
(Seq-case mk
|
|
68
|
+
[(EmptyS) v]
|
|
69
|
+
[(PushP _ mk*) (set! mk mk*) (underflow v)]
|
|
70
|
+
[(PushState b _ mk*) (set! mk mk*) (underflow v)]
|
|
71
|
+
[(PushSeg k mk*) (set! mk mk*) (k v)]))
|
|
72
|
+
|
|
73
|
+
(define (go)
|
|
74
|
+
(new-cafe
|
|
75
|
+
(lambda (x)
|
|
76
|
+
(run (lambda () (eval x))))))
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
;;; tail.ss
|
|
2
|
+
;;; Copyright (c) 2005, R. Kent Dybvig, Simon L. Peyton Jones, and Amr Sabry
|
|
3
|
+
|
|
4
|
+
;;; Tail-recursive implementation of the operators
|
|
5
|
+
|
|
6
|
+
;(case-sensitive #t)
|
|
7
|
+
|
|
8
|
+
(define-syntax pushPrompt
|
|
9
|
+
(syntax-rules ()
|
|
10
|
+
[(_ p e1 e2 ...)
|
|
11
|
+
($pushPrompt p (lambda () e1 e2 ...))]))
|
|
12
|
+
|
|
13
|
+
(define-syntax pushSubCont
|
|
14
|
+
(syntax-rules ()
|
|
15
|
+
[(_ subk e1 e2 ...)
|
|
16
|
+
($pushSubCont subk (lambda () e1 e2 ...))]))
|
|
17
|
+
|
|
18
|
+
(define abort)
|
|
19
|
+
(define mk)
|
|
20
|
+
(define base-k)
|
|
21
|
+
|
|
22
|
+
(define ($pushPrompt p th)
|
|
23
|
+
(call/cc (lambda (k)
|
|
24
|
+
(pushFrame k)
|
|
25
|
+
(set! mk (cons (make-Stack (list) (make-arena) p) mk))
|
|
26
|
+
(abort th))))
|
|
27
|
+
|
|
28
|
+
(define (with-region body)
|
|
29
|
+
(let* ([stack (car mk)]
|
|
30
|
+
[arena (Stack-arena stack)])
|
|
31
|
+
(body arena)))
|
|
32
|
+
|
|
33
|
+
(define (withSubCont p f)
|
|
34
|
+
(call/cc (lambda (k)
|
|
35
|
+
(pushFrame k)
|
|
36
|
+
(let-values ([(subk mk*) (splitSeq p mk)])
|
|
37
|
+
(set! mk mk*)
|
|
38
|
+
(abort (lambda () (f subk)))))))
|
|
39
|
+
|
|
40
|
+
(define (pushFrame f)
|
|
41
|
+
(if (eqv? f base-k) (values)
|
|
42
|
+
(if (null? mk) (error "ERROR! Cannot push on empty meta cont" #f)
|
|
43
|
+
(let* ([stack (car mk)]
|
|
44
|
+
[frames (Stack-frames stack)]
|
|
45
|
+
[arena (Stack-arena stack)]
|
|
46
|
+
[prompt (Stack-prompt stack)]
|
|
47
|
+
[rest (cdr mk)])
|
|
48
|
+
(set! mk (cons (make-Stack (cons f frames) arena prompt) rest))))))
|
|
49
|
+
|
|
50
|
+
(define ($pushSubCont subk th)
|
|
51
|
+
(call/cc (lambda (k)
|
|
52
|
+
(pushFrame k)
|
|
53
|
+
(set! mk (appendSeq subk mk))
|
|
54
|
+
(abort th))))
|
|
55
|
+
|
|
56
|
+
(define newPrompt (lambda () (string #\p)))
|
|
57
|
+
|
|
58
|
+
(define (run th)
|
|
59
|
+
(define global (make-Stack '() (make-arena) (newPrompt)))
|
|
60
|
+
(set! mk (list global))
|
|
61
|
+
(underflow
|
|
62
|
+
(call/cc
|
|
63
|
+
(lambda (k_1)
|
|
64
|
+
(set! base-k k_1)
|
|
65
|
+
((call/cc (lambda (k_2)
|
|
66
|
+
(set! abort k_2)
|
|
67
|
+
(abort th))))))))
|
|
68
|
+
|
|
69
|
+
(define (underflow v)
|
|
70
|
+
(if (null? mk) v
|
|
71
|
+
(let* ([stack (car mk)]
|
|
72
|
+
[frames (Stack-frames stack)]
|
|
73
|
+
[arena (Stack-arena stack)]
|
|
74
|
+
[prompt (Stack-prompt stack)]
|
|
75
|
+
[rest (cdr mk)])
|
|
76
|
+
(if (null? frames) (begin (set! mk rest) (underflow v))
|
|
77
|
+
(begin
|
|
78
|
+
(set! mk (cons (make-Stack (cdr frames) arena prompt) rest))
|
|
79
|
+
((car frames) v))))))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
(define-syntax shift0-at
|
|
83
|
+
(syntax-rules ()
|
|
84
|
+
[(_ P id exp ...)
|
|
85
|
+
(withSubCont
|
|
86
|
+
P
|
|
87
|
+
(lambda (s)
|
|
88
|
+
(let ([id (lambda (v) (pushSubCont s v))])
|
|
89
|
+
exp ...)))]))
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
(define (show_impl obj)
|
|
2
|
+
(cond
|
|
3
|
+
[(number? obj) (show-number obj)]
|
|
4
|
+
[(string? obj) obj]
|
|
5
|
+
[(boolean? obj) (if obj "true" "false")]
|
|
6
|
+
[(char? obj) (show-char obj)]
|
|
7
|
+
; [(record? obj)
|
|
8
|
+
; (let* ([rtd (record-rtd obj)]
|
|
9
|
+
; [name (symbol->string (record-type-name rtd))])
|
|
10
|
+
; ;; how can we show the fields?
|
|
11
|
+
; (string-append name))]
|
|
12
|
+
[(list? obj) (map show_impl obj)]
|
|
13
|
+
[(record? obj) (show-record obj)]
|
|
14
|
+
[else (generic-show obj)]))
|
|
15
|
+
|
|
16
|
+
(define (generic-show obj)
|
|
17
|
+
(define out (open-output-string))
|
|
18
|
+
(write obj out)
|
|
19
|
+
(get-output-string out))
|
|
20
|
+
|
|
21
|
+
; conform with the JS way of printing numbers
|
|
22
|
+
(define (show-number n)
|
|
23
|
+
(if (integer? n) (number->string (exact n)) (number->string n)))
|
|
24
|
+
|
|
25
|
+
(define (show-char c)
|
|
26
|
+
(string c))
|
|
27
|
+
|
|
28
|
+
; here we use eval to find the show function defined with the record...
|
|
29
|
+
; (define (show-record rec)
|
|
30
|
+
; (let* ([rtd (record-rtd rec)]
|
|
31
|
+
; [showName (string-append "show" (generic-show (record-type-name rtd)))]
|
|
32
|
+
; [showFun (eval (string->symbol showName))])
|
|
33
|
+
; (showFun rec)))
|
|
34
|
+
|
|
35
|
+
; we needed to add a unique id to the types in order to prevent duplicate definitions
|
|
36
|
+
; now for printing, we need to strip the unique id (starting with $) again.
|
|
37
|
+
(define (strip-type-name tpe)
|
|
38
|
+
(define out "")
|
|
39
|
+
(define found #f)
|
|
40
|
+
(for-each
|
|
41
|
+
(lambda (el)
|
|
42
|
+
(if (char=? el #\$) (set! found #t) #f)
|
|
43
|
+
(if found #f (set! out (string-append out (string el)))))
|
|
44
|
+
(string->list tpe))
|
|
45
|
+
out)
|
|
46
|
+
|
|
47
|
+
(define (show-record rec)
|
|
48
|
+
(let* ([rtd (record-rtd rec)]
|
|
49
|
+
[unique-tpe (generic-show (record-type-name rtd))]
|
|
50
|
+
[tpe (strip-type-name unique-tpe)]
|
|
51
|
+
[fields (record-type-field-names rtd)]
|
|
52
|
+
[n (vector-length fields)])
|
|
53
|
+
(define out (string-append tpe "("))
|
|
54
|
+
(do ([i 0 (+ i 1)])
|
|
55
|
+
((= i n))
|
|
56
|
+
(set! out (string-append out (show_impl ((record-accessor rtd i) rec))))
|
|
57
|
+
(if (< i (- n 1)) (set! out (string-append out ", "))))
|
|
58
|
+
(set! out (string-append out ")"))
|
|
59
|
+
out))
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
(define (println_impl str)
|
|
64
|
+
(display str)
|
|
65
|
+
(newline))
|
|
66
|
+
|
|
67
|
+
(define (equal_impl obj1 obj2)
|
|
68
|
+
(equal? obj1 obj2))
|
|
69
|
+
|
|
70
|
+
(define-syntax thunk
|
|
71
|
+
(syntax-rules ()
|
|
72
|
+
[(_ e ...) (lambda () e ...)]))
|
|
73
|
+
|
|
74
|
+
;; Benchmarking utils
|
|
75
|
+
|
|
76
|
+
; time in milliseconds
|
|
77
|
+
(define (timed block)
|
|
78
|
+
(let ([before (current-time)])
|
|
79
|
+
(block)
|
|
80
|
+
(let ([after (current-time)])
|
|
81
|
+
(seconds (time-difference after before)))))
|
|
82
|
+
|
|
83
|
+
(define (seconds diff)
|
|
84
|
+
(+ (time-second diff) (/ (time-nanosecond diff) 1000000000.0)))
|
|
85
|
+
|
|
86
|
+
(define (timestamp)
|
|
87
|
+
(let ([t (current-time)])
|
|
88
|
+
(+ (* (time-second t) 1000000000) (time-nanosecond t))))
|
|
89
|
+
|
|
90
|
+
(define (measure block warmup iterations)
|
|
91
|
+
(define (run n)
|
|
92
|
+
(if (<= n 0)
|
|
93
|
+
'()
|
|
94
|
+
(begin
|
|
95
|
+
(collect)
|
|
96
|
+
(cons (timed block) (run (- n 1))))))
|
|
97
|
+
(begin
|
|
98
|
+
(run warmup)
|
|
99
|
+
(run iterations)))
|
|
100
|
+
|
|
101
|
+
(define (hole)
|
|
102
|
+
(raise
|
|
103
|
+
(condition
|
|
104
|
+
(make-error)
|
|
105
|
+
(make-message-condition "not implemented"))))
|