-
Notifications
You must be signed in to change notification settings - Fork 1
/
xensg.rkt
79 lines (77 loc) · 3.03 KB
/
xensg.rkt
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
#lang racket
(require "x-synt.rkt")
(define (uensg:main src dst prog)
(define (ensugar prog) (map compile-fundef prog))
(define (compile-fundef fundef)
(let ((body (cadddr fundef)) (parlist (cadr fundef)) (fname (car fundef)))
`(define (,fname ,@parlist) ,(compile-exp body))))
(define (compile-exp exp)
(cond ((symbol? exp) exp)
((equal? (car exp) 'quote)
(let ((const (cadr exp))) (if (literal? const) const exp)))
((equal? (car exp) 'car)
(let ((exp1 (cadr exp)))
(*extend-syntax-add-car* (compile-exp exp1))))
((equal? (car exp) 'cdr)
(let ((exp1 (cadr exp)))
(*extend-syntax-add-cdr* (compile-exp exp1))))
((equal? (car exp) 'cons)
(let ((exp2 (caddr exp)) (exp1 (cadr exp)))
(compile-cons (compile-exp exp1) (compile-exp exp2))))
((equal? (car exp) 'if)
(let ((exp3 (cadddr exp)) (exp2 (caddr exp)) (exp1 (cadr exp)))
(compile-if
(compile-exp exp1)
(compile-exp exp2)
(compile-exp exp3))))
((equal? (car exp) 'call)
(let ((exp* (cddr exp)) (fname (cadr exp)))
`(,fname unquote (map compile-exp exp*))))
((equal? (car exp) 'rcall)
(let ((exp* (cddr exp)) (fname (cadr exp)))
`(rcall (,fname unquote (map compile-exp exp*)))))
((equal? (car exp) 'xcall)
(let ((exp* (cddr exp)) (fname (cadr exp)))
`(,fname unquote (map compile-exp exp*))))
(else
(let ((exp* (cdr exp)) (fname (car exp)))
`(,fname unquote (map compile-exp exp*))))))
(define (compile-cons exp1 exp2)
(list 'quasiquote (cons (make-unquote exp1) (make-unquote exp2))))
(define (make-unquote exp)
(cond ((literal? exp) exp)
((and (pair? exp)
(equal? (car exp) 'quote)
(pair? (cdr exp))
(null? (cddr exp)))
(let ((c (cadr exp))) c))
((and (pair? exp)
(equal? (car exp) 'quasiquote)
(pair? (cdr exp))
(null? (cddr exp)))
(let ((c (cadr exp))) c))
(else (list 'unquote exp))))
(define (compile-if exp0 exp1 exp2)
(cond ((and (pair? exp2)
(equal? (car exp2) 'if)
(pair? (cdr exp2))
(pair? (cddr exp2))
(pair? (cdddr exp2))
(null? (cddddr exp2)))
(let ((b (cadddr exp2)) (a (caddr exp2)) (p (cadr exp2)))
`(cond (,exp0 ,exp1) (,p ,a) (else ,b))))
((and (pair? exp2) (equal? (car exp2) 'cond))
(let ((clause* (cdr exp2))) `(cond (,exp0 ,exp1) unquote clause*)))
(else `(if ,exp0 ,exp1 ,exp2))))
(define (literal? x) (or (boolean? x) (number? x) (char? x) (string? x)))
(newline)
(display "-- Ensugaring: ")
(display src)
(display " -> ")
(display dst)
(newline)
(set! prog (ensugar prog))
(display "-- Done --")
(newline)
prog)
(provide (all-defined-out))