desugar.scm 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. (define include-stack (empty-stack))
  2. (define (head? atom exp shadow)
  3. (and (pair? exp)
  4. (not (member atom shadow))
  5. (eq? (car exp) atom)))
  6. (define macro-definitions
  7. (box '()))
  8. (define (load-macro mac)
  9. (if (head? 'defmacro mac '())
  10. (push-box! macro-definitions (cons (cadr mac) (eval (caddr mac))))
  11. (eval mac)))
  12. (define (macro? exp)
  13. (and (pair? exp)
  14. (cond ((assoc (car exp) (unbox macro-definitions)) => cdr)
  15. (else #f))))
  16. (define (desugar exp shadow)
  17. (cond ((or (number? exp) (string? exp) (char? exp) (boolean? exp))
  18. `(datum ,exp))
  19. ((symbol? exp) exp)
  20. ((macro? exp)
  21. => (lambda (expander)
  22. (desugar (expander exp) shadow)))
  23. ;; named let -> letrec
  24. ((and (head? 'let exp shadow)
  25. (>= (length exp) 4)
  26. (symbol? (cadr exp)))
  27. (let ((name (cadr exp))
  28. (table (caddr exp))
  29. (body* (cdddr exp)))
  30. (let ((vars (map car table))
  31. (vals (map cadr table)))
  32. `(letrec ((,name ,(desugar `(lambda ,vars . ,body*) (cons name shadow))))
  33. (app ,name . ,(mapply desugar vals shadow))))))
  34. ((head? 'if exp shadow)
  35. (unless (= 4 (length exp))
  36. (error 'desugar "malformed if expression" exp))
  37. `(if ,(desugar (cadr exp) shadow)
  38. ,(desugar (caddr exp) shadow)
  39. ,(desugar (cadddr exp) shadow)))
  40. ;; TEMPORORAY
  41. ((head? 'let* exp shadow)
  42. (desugar `(let . ,(cdr exp)) shadow))
  43. ((head? 'lambda exp shadow)
  44. (desugar-lambda (cadr exp) (cddr exp) shadow))
  45. ((head? 'begin exp shadow)
  46. (desugar-begin (mapply desugar (cdr exp) shadow)))
  47. ((head? 'quote exp shadow)
  48. (desugar-quote (cadr exp)))
  49. ((or (head? 'let exp shadow)
  50. (head? 'letrec exp shadow))
  51. (desugar-let (car exp) (cadr exp) (cddr exp) shadow))
  52. ((pair? exp)
  53. `(app . ,(mapply desugar exp shadow)))
  54. (else (error 'desugar "unknown object" exp))))
  55. (define (desugar-begin stmts)
  56. (cond ((null? stmts) (error 'desugar-begin "null" 0))
  57. ((null? (cdr stmts)) (car stmts))
  58. (else `(begin . ,stmts))))
  59. (define (desugar-lambda vars body* shadow)
  60. `(lambda ,vars ,(desugar-begin (mapply desugar body* (append vars shadow)))))
  61. (define (desugar-quote q)
  62. (cond ((pair? q)
  63. `(app cons ,(desugar-quote (car q))
  64. ,(desugar-quote (cdr q))))
  65. (else
  66. `(datum ,q))))
  67. (define (desugar-let-binding binding shadow)
  68. (let ((var (car binding))
  69. (exp (cadr binding)))
  70. `(,var ,(desugar exp shadow))))
  71. (define (desugar-let l bindings body* shadow)
  72. (let ((vars (map car bindings)))
  73. `(,l ,(mapply desugar-let-binding bindings shadow)
  74. ,(desugar-begin (mapply desugar body* (append vars shadow))))))
  75. ;;
  76. (define (desugar-def def filename stk)
  77. (unless (and (pair? def) (eq? 'define (car def)))
  78. (begin (print def)
  79. (error 'desugar-def "not a definition" def)))
  80. (let loop ((def-head (cadr def))
  81. (def-body (cddr def)))
  82. (cond ((symbol? def-head)
  83. (when (member def-head '(if lambda begin))
  84. (begin (print def)
  85. (error 'desugar-def "ridiculous" 0)))
  86. (let ((def-body (desugar (desugar-begin def-body) '())))
  87. (stack-push! stk (list def-head filename (estimate-arity def-body)))
  88. `(define ,filename ,def-head ,def-body)))
  89. ((pair? def-head)
  90. ;;
  91. ;; (define (foo x y z) ...)
  92. ;; ~> (define foo (lambda (x y z) ...)
  93. ;;
  94. (loop (car def-head) (list `(lambda ,(cdr def-head) . ,def-body))))
  95. (else (print def) (error 'desugar-def "bad definition head" def)))))
  96. (define (desugar-top top filename stk)
  97. ;; at the top level we will see either
  98. ;; (include <filename>)
  99. ;; (define <name> <body> ...)
  100. ;; or a raw lisp expression to execute
  101. (cond ((head? 'include top '())
  102. (if (member (cadr top) (stack-get include-stack))
  103. '()
  104. (let ((filename (cadr top)))
  105. (stack-push! include-stack filename)
  106. (concatenate (mapply desugar-top (read-file filename) filename stk)))))
  107. ((head? 'define top '())
  108. (list (desugar-def top filename stk)))
  109. (else (list `(raw ,filename ,(desugar top '()))))))
  110. ;;
  111. (define (estimate-arity d)
  112. ;; TODO: support understanding the arity of things like (define stream-car car) ?
  113. (if (and (pair? d)
  114. (eq? (car d) 'lambda))
  115. (length (cadr d))
  116. #f))