This repository has been archived by the owner on Aug 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
19.01-macros_for_cps
110 lines (93 loc) · 3.58 KB
/
19.01-macros_for_cps
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
MACROS PARA CPS
=================
Vamos criar um processador de macros para o estilo de processamento de
continuação. Com ele, transformaremos um tipo de expressão em outra.
Fazeremos uma conversão de sintaxe. Escreveremos com nosso estilo, e a
traduziremos com os comandos tradicionais do Racket para o estilo de
continuação.
| Sintaxe CPS | Racket |
|===============|==============|
| with | let |
| rec | letrec |
| lam | lambda |
| cnd | if |
| set | set! |
| seq | begin |
(define-syntax (cps e)
(syntax-case e (with rec lam cnd seq set quote display read-number)
[(_ atomic)
#'(lambda (k) (k atomic))]
; Rec é como o let recursivo (letrec), que muda o storage
; conforme novas associações são feitas
[(_ (rec (v f) b))
#'(cps (with (v (lam (arg) (error 'dummy "nothind")))
(seq
(set v f)
b)))
]
; lambda
[(_ (lam (a) b))
(identifier? #'a)
; Toda sintaxe convertida deve ser um lambda que recebe como
; parâmetro uma continuação. Essa continuação, definida no
; tempo de definição da função, chama-se k. O corpo da função,
; seja qual for, deve ser argumento para esta continuação.
#'(lambda (k)
; Todo argumento devolvido por uma função também deve
; estar no CPS. Precisamos converter o λ de verdade para
; esse estilo. Para fazer isso:
; 1) Expandimos a lista de argumento para receber como
; argumento final uma continuação: dyn-k
; 2) O corpo também precisa ser passado para o estilo de
; continuação. Isso pode ser feito aplicando a
; continuação dyn-k para ele.
;
(k (lambda (a dyn-k) ((cps b) dyn-k) ))
]
; Ex:
; (λ (a) b)
; (λ (k)
; (k (λ (a dyn-k) (eps b dyn-k)))
; )
;
; Ex:
; (cps (+ (rn "um") (rn "dois")) )
; (
; (λ (k)
; (+ k (rn "dois"))
; )
; (rn "um")
; )
[(_ (f a))
#'(lambda (k)
((cps f) (lambda (fv)
((cps a) (lambda (av) (fv av k)))
)))
[(_ (f a b))
; Pegamos uma aplicação de função, com dois argumentos.
; Ela tem uma continuação
#'(lambda (k)
; Interpretamos 'a' e passamos como continuação para
; ele o segundo argumento
((cps a) (lambda (av)
; Interpretamos 'b' e passamos como continuação para
; ele a funçaõ aplicada a ambos os argumentos
((cps b) (lambda (bv)
(k (f av bv) )))))
)
]
))
; Continuação "identidade", para não fazermos nada na última continuação
(define identity '(lambda (c) c))
; Açúcar sintático para rodar expressões feitas na linguagem
; de escrita de continuações. Ele pega uma continuação e passa
; como continuação final para ela a identidade, que fará a última
; ação parar a recursão.
(define (run [k : s-exp]) (k identity) )
Exemplo de expansão
---------------------
(cps (display (+ (rn "f") (rn "s"))) )
(λ (k) ( (cps (+ (...) (λ (ov (k (display ov))))))
(λ(k) ( (λ (k2) ((cps (rn ...)
(λ (av) (cps ((rn "s"))
(λ (bv) (k2 (f av bv))))))))))