mac.scm 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. (module (arguile base mac)
  2. #:export (mac mac? syn-case let-syn w/syn
  3. syn-param w/syn-params gen-tmps))
  4. (use (arguile guile)
  5. (ice-9 receive))
  6. (define-syntax mac
  7. (lambda (x)
  8. (define (ids? exps)
  9. (and-map identifier? exps))
  10. (syntax-case x ()
  11. ((_ name ctx (f1 ...) exp ...)
  12. (and (and-map identifier? `(,#'name ,#'ctx))
  13. (ids? #'(f1 ...)))
  14. #'(%mac name ctx (f1 ...) exp ...))
  15. ((_ name ctx exp ...)
  16. (and-map identifier? `(,#'name ,#'ctx))
  17. #'(mac name ctx () exp ...))
  18. ((_ name (f1 ...) exp ...)
  19. (ids? #'(f1 ...))
  20. #'(mac name ctx (f1 ...) exp ...))
  21. ((_ name exp ...)
  22. (identifier? #'name)
  23. #'(mac name ctx () exp ...)))))
  24. (define-syntax %mac
  25. (lambda (x)
  26. (define (parse-mac exps)
  27. (define (pattern? exp)
  28. (syntax-case exp ()
  29. (((_ . patt) guard ... templ) #t)
  30. (_ #f)))
  31. (let lp ((exps exps) (defs '()) (patts '()))
  32. (if (null? exps) (values (reverse defs) (reverse patts))
  33. (if (pattern? (car exps))
  34. (lp (cdr exps) defs (cons (car exps) patts))
  35. (lp (cdr exps) (cons (car exps) defs) patts)))))
  36. (syntax-case x ()
  37. ((_ name ctx (f1 ...) exp ...)
  38. #`(define-syntax name
  39. (lambda (ctx)
  40. #,@(receive (defs cases) (parse-mac #'(exp ...))
  41. (if (null? cases) defs
  42. #`(#,@defs
  43. (syntax-case ctx (f1 ...) #,@cases))))))))))
  44. (mac mac?
  45. ((_ mac) #'(macro? (module-ref (current-module) 'mac))))
  46. (mac syn-case
  47. ((_ ctx (aux ...) ((kword . patt) templ) ...)
  48. #'(syntax-case ctx (aux ...)
  49. ((kword . patt) templ) ...)))
  50. (mac let-syn
  51. ((_ syn exp body ...)
  52. #'(w/syn (syn exp) body ...)))
  53. (mac w/syn
  54. ((_ (item ...) e1 ...)
  55. (with-syntax ((items (grp #'(item ...) 2)))
  56. #'(with-syntax items e1 ...))))
  57. (mac syn-param
  58. ((_ name fn) #'(define-syntax-parameter name fn)))
  59. ;;; TODO: change to w/ format
  60. (mac w/syn-params
  61. ((_ ((param val) ...) body ...)
  62. #'(syntax-parameterize ((param val) ...) body ...)))
  63. (mac gen-tmps
  64. ((_ syn) #'(generate-temporaries syn)))