macros.scm 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. ; auxilary functions
  2. (define (foldr f a l)
  3. (if (null? l)
  4. a
  5. (f (car l)
  6. (foldr f a (cdr l)))))
  7. (define (quasiquote^ t)
  8. (if (pair? t)
  9. (if (eq? (car t) 'unquote)
  10. (cadr t)
  11. (cons 'cons
  12. (cons (quasiquote^ (car t))
  13. (cons (quasiquote^ (cdr t))
  14. '()))))
  15. (cons 'quote (cons t '()))))
  16. (defmacro quasiquote
  17. (lambda (t)
  18. (quasiquote^ (cadr t))))
  19. ; macros
  20. (defmacro or
  21. (lambda (t)
  22. (if (null? (cdr t))
  23. #f
  24. (if (null? (cddr t))
  25. (cadr t)
  26. (let ((a (cadr t))
  27. (b (cddr t))
  28. (tmp (gensym "tmp")))
  29. `(let ((,tmp ,a))
  30. (if ,tmp ,tmp (or . ,b))))))))
  31. (defmacro and
  32. (lambda (t)
  33. (if (null? (cdr t))
  34. #t
  35. (if (null? (cddr t))
  36. (cadr t)
  37. (let ((a (cadr t))
  38. (b (cddr t)))
  39. `(if ,a (and . ,b) #f))))))
  40. (include "compiler/mac/macro-shapes.scm")
  41. (defmacro list
  42. (lambda (t) (foldr (lambda (a c) `(cons ,a ,c)) ''() (cdr t))))
  43. (defmacro when
  44. (lambda (exp)
  45. (let ((test (cadr exp))
  46. (body `(begin . ,(cddr exp))))
  47. `(if ,test
  48. ,body
  49. #f))))
  50. (defmacro unless
  51. (lambda (exp)
  52. (let ((test (cadr exp))
  53. (body `(begin . ,(cddr exp))))
  54. `(if ,test
  55. #f
  56. ,body))))
  57. (define (cond-get-next exp)
  58. `(cond . ,(cddr exp)))
  59. (defmacro cond
  60. (lambda (exp)
  61. (if (cond/0? exp)
  62. `(exit) ;; todo void
  63. (if (cond/else? exp)
  64. `(begin . ,(cond/else-get-else exp))
  65. (if (cond/1? exp)
  66. `(or ,(cond/1-get-one exp) ,(cond-get-next exp))
  67. (if (cond/=>? exp)
  68. (let ((test (cond/clause-get-test exp))
  69. (thunk (cond/=>-get-thunk exp))
  70. (tmp (gensym "cond-tmp")))
  71. `(let ((,tmp ,test))
  72. (if ,tmp
  73. (,thunk ,tmp)
  74. ,(cond-get-next exp))))
  75. (if (cond/clause? exp)
  76. (let ((test (cond/clause-get-test exp))
  77. (rest (cond/clause-get-rest exp)))
  78. `(if ,test
  79. (begin . ,rest)
  80. ,(cond-get-next exp)))
  81. (exit) ;; bad syntax
  82. )))))))
  83. (defmacro vector
  84. (lambda (exp)
  85. (let ((l (length (cdr exp)))
  86. (tmp (gensym "tmp")))
  87. (letrec ((loop (lambda (i elts)
  88. (if (null? elts)
  89. tmp
  90. `(begin
  91. (vector-set! ,tmp ,i ,(car elts))
  92. ,(loop (+ i 1) (cdr elts)))))))
  93. `(let ((,tmp (make-vector ,l #f)))
  94. ,(loop 0 (cdr exp)))))))
  95. ;; <case> ::= (case <exp> <clause> (else <exp>))
  96. ;;
  97. ;; <clause> ::= ((<thing>) <exp>)
  98. ;; (case foo ((x) 1) ((y) 2) (else 3))
  99. ;; -->
  100. ;; let tmp foo
  101. ;; (if (eq? tmp 'x) 1)
  102. ;; ...((y) 2) (else 3))
  103. (define (else-clause? head)
  104. (and (pair? head)
  105. (eq? 'else (car head))))
  106. (define (compile-case t clauses)
  107. (if (null? clauses)
  108. '(exit)
  109. (let ((head (car clauses))
  110. (rest (cdr clauses)))
  111. (if (else-clause? head)
  112. (cadr head)
  113. (let ((test (car head))
  114. (body (cdr head)))
  115. `(if (member ,t ',test)
  116. (begin . ,body)
  117. ,(compile-case t rest)))))))
  118. (defmacro case
  119. (lambda (exp)
  120. (let ((discriminant (cadr exp))
  121. (tmp (gensym "tmp")))
  122. `(let ((,tmp ,discriminant))
  123. ,(compile-case tmp (cddr exp))))))
  124. (defmacro mapply
  125. (lambda (exp)
  126. ;;(mapply f xs arg ...)
  127. (let ((f (cadr exp))
  128. (xs (caddr exp))
  129. (args (cdddr exp))
  130. (x (gensym "x")))
  131. `(map (lambda (,x) (,f ,x . ,args)) ,xs))))
  132. ;;; ADDED
  133. (defmacro inc!
  134. (lambda (form)
  135. (let ((x (cadr form)))
  136. `(set-box! ,x (+ (unbox ,x) 1)))))
  137. (defmacro dec!
  138. (lambda (form)
  139. (let ((x (cadr form)))
  140. `(set-box! ,x (- (unbox ,x) 1)))))