/collects/redex/private/term.rkt

http://github.com/agocke/racket · Racket · 225 lines · 205 code · 20 blank · 0 comment · 14 complexity · 5018e77dc151a765449a4f06c0f07a58 MD5 · raw file

  1. #lang scheme/base
  2. (require (for-syntax scheme/base
  3. "term-fn.ss"
  4. syntax/boundmap
  5. racket/syntax)
  6. "error.rkt"
  7. "matcher.ss")
  8. (provide term term-let term-let/error-name term-let-fn term-define-fn hole in-hole)
  9. (define-syntax (hole stx) (raise-syntax-error 'hole "used outside of term"))
  10. (define-syntax (in-hole stx) (raise-syntax-error 'in-hole "used outside of term"))
  11. (define (with-syntax* stx)
  12. (syntax-case stx ()
  13. [(_ () e) (syntax e)]
  14. [(_ (a b ...) e) (syntax (with-syntax (a) (with-syntax* (b ...) e)))]))
  15. (define-syntax-rule (term t)
  16. (#%expression (term/private t)))
  17. (define-syntax (term/private orig-stx)
  18. (define outer-bindings '())
  19. (define applied-metafunctions
  20. (make-free-identifier-mapping))
  21. (define (rewrite stx)
  22. (let-values ([(rewritten _) (rewrite/max-depth stx 0)])
  23. rewritten))
  24. (define (rewrite-application fn args depth)
  25. (let-values ([(rewritten max-depth) (rewrite/max-depth args depth)])
  26. (let ([result-id (car (generate-temporaries '(f-results)))])
  27. (with-syntax ([fn fn])
  28. (let loop ([func (syntax (λ (x) (fn (syntax->datum x))))]
  29. [args-stx rewritten]
  30. [res result-id]
  31. [args-depth (min depth max-depth)])
  32. (with-syntax ([func func]
  33. [args args-stx]
  34. [res res])
  35. (if (zero? args-depth)
  36. (begin
  37. (set! outer-bindings
  38. (cons (syntax [res (func (quasisyntax args))])
  39. outer-bindings))
  40. (values result-id (min depth max-depth)))
  41. (loop (syntax (λ (l) (map func (syntax->list l))))
  42. (syntax/loc args-stx (args (... ...)))
  43. (syntax (res (... ...)))
  44. (sub1 args-depth)))))))))
  45. (define (rewrite/max-depth stx depth)
  46. (syntax-case stx (unquote unquote-splicing in-hole hole)
  47. [(metafunc-name arg ...)
  48. (and (identifier? (syntax metafunc-name))
  49. (term-fn? (syntax-local-value (syntax metafunc-name) (λ () #f))))
  50. (let ([f (term-fn-get-id (syntax-local-value/record (syntax metafunc-name) (λ (x) #t)))])
  51. (free-identifier-mapping-put! applied-metafunctions f #t)
  52. (rewrite-application f (syntax/loc stx (arg ...)) depth))]
  53. [f
  54. (and (identifier? (syntax f))
  55. (term-fn? (syntax-local-value (syntax f) (λ () #f))))
  56. (raise-syntax-error 'term "metafunction must be in an application" orig-stx stx)]
  57. [x
  58. (and (identifier? (syntax x))
  59. (term-id? (syntax-local-value (syntax x) (λ () #f))))
  60. (let ([id (syntax-local-value/record (syntax x) (λ (x) #t))])
  61. (values (datum->syntax (term-id-id id) (syntax-e (term-id-id id)) (syntax x))
  62. (term-id-depth id)))]
  63. [(unquote x)
  64. (values (syntax (unsyntax x)) 0)]
  65. [(unquote . x)
  66. (raise-syntax-error 'term "malformed unquote" orig-stx stx)]
  67. [(unquote-splicing x)
  68. (values (syntax (unsyntax-splicing x)) 0)]
  69. [(unquote-splicing . x)
  70. (raise-syntax-error 'term "malformed unquote splicing" orig-stx stx)]
  71. [(in-hole id body)
  72. (rewrite-application (syntax (λ (x) (apply plug x))) (syntax/loc stx (id body)) depth)]
  73. [(in-hole . x)
  74. (raise-syntax-error 'term "malformed in-hole" orig-stx stx)]
  75. [hole (values (syntax (unsyntax the-hole)) 0)]
  76. [() (values stx 0)]
  77. [(x ... . y)
  78. (not (null? (syntax->list #'(x ...))))
  79. (let-values ([(x-rewrite max-depth)
  80. (let i-loop ([xs (syntax->list (syntax (x ...)))])
  81. (cond
  82. [(null? xs) (rewrite/max-depth #'y depth)]
  83. [else
  84. (let ([new-depth (if (and (not (null? (cdr xs)))
  85. (identifier? (cadr xs))
  86. (free-identifier=? (quote-syntax ...)
  87. (cadr xs)))
  88. (+ depth 1)
  89. depth)])
  90. (let-values ([(fst fst-max-depth)
  91. (rewrite/max-depth (car xs) new-depth)]
  92. [(rst rst-max-depth)
  93. (i-loop (cdr xs))])
  94. (values (cons fst rst)
  95. (max fst-max-depth rst-max-depth))))]))])
  96. (values (datum->syntax stx x-rewrite stx) max-depth))]
  97. [_ (values stx 0)]))
  98. (syntax-case orig-stx ()
  99. [(_ arg)
  100. (with-disappeared-uses
  101. (with-syntax ([rewritten (rewrite (syntax arg))])
  102. #`(begin
  103. #,@(free-identifier-mapping-map
  104. applied-metafunctions
  105. (λ (f _)
  106. (if (eq? (identifier-binding f) 'lexical)
  107. #`(check-defined-lexical #,f '#,f)
  108. #`(check-defined-module (λ () #,f) '#,f))))
  109. #,(let loop ([bs (reverse outer-bindings)])
  110. (cond
  111. [(null? bs) (syntax (syntax->datum (quasisyntax rewritten)))]
  112. [else (with-syntax ([rec (loop (cdr bs))]
  113. [fst (car bs)])
  114. (syntax (with-syntax (fst)
  115. rec)))])))))]))
  116. (define (check-defined-lexical value name)
  117. (when (eq? (letrec ([x x]) x) value)
  118. (report-undefined-metafunction name)))
  119. (define (check-defined-module thunk name)
  120. (with-handlers ([exn:fail:contract:variable?
  121. (λ (_) (report-undefined-metafunction name))])
  122. (thunk)))
  123. (define (report-undefined-metafunction name)
  124. (redex-error #f "metafunction ~s applied before its definition" name))
  125. (define-syntax (term-let-fn stx)
  126. (syntax-case stx ()
  127. [(_ ([f rhs] ...) body1 body2 ...)
  128. (with-syntax ([(g ...) (generate-temporaries (syntax (f ...)))])
  129. (syntax
  130. (let ([g rhs] ...)
  131. (let-syntax ([f (make-term-fn #'g)] ...)
  132. body1
  133. body2 ...))))]))
  134. (define-syntax (term-define-fn stx)
  135. (syntax-case stx ()
  136. [(_ id exp)
  137. (with-syntax ([id2 (datum->syntax #'here (syntax-e #'id))])
  138. (syntax
  139. (begin
  140. (define id2 exp)
  141. (define-syntax id
  142. (make-term-fn ((syntax-local-certifier) #'id2))))))]))
  143. (define-syntax (term-let/error-name stx)
  144. (syntax-case stx ()
  145. [(_ error-name ([x1 rhs1] [x rhs] ...) body1 body2 ...)
  146. (let-values ([(orig-names new-names depths new-x1)
  147. (let loop ([stx #'x1] [depth 0])
  148. (define ((combine orig-names new-names depths new-pat)
  149. orig-names* new-names* depths* new-pat*)
  150. (values (append orig-names orig-names*)
  151. (append new-names new-names*)
  152. (append depths depths*)
  153. (cons new-pat new-pat*)))
  154. (syntax-case stx (...)
  155. [x
  156. (and (identifier? #'x)
  157. (not (free-identifier=? (quote-syntax ...) #'x)))
  158. (let ([new-name (datum->syntax #'here (syntax-e #'x))])
  159. (values (list #'x)
  160. (list new-name)
  161. (list depth)
  162. new-name))]
  163. [(x (... ...) . xs)
  164. (let-values ([(orig-names new-names depths new-pat)
  165. (call-with-values
  166. (λ () (loop #'xs depth))
  167. (call-with-values
  168. (λ () (loop #'x (add1 depth)))
  169. combine))])
  170. (values orig-names new-names depths
  171. (list* (car new-pat) #'(... ...) (cdr new-pat))))]
  172. [(x . xs)
  173. (call-with-values
  174. (λ () (loop #'xs depth))
  175. (call-with-values
  176. (λ () (loop #'x depth))
  177. combine))]
  178. [_
  179. (values '() '() '() stx)]))])
  180. (with-syntax ([(orig-names ...) orig-names]
  181. [(new-names ...) new-names]
  182. [(depths ...) depths]
  183. [new-x1 new-x1]
  184. [no-match (syntax/loc (syntax rhs1)
  185. (error 'error-name "term ~s does not match pattern ~s" rhs1 'x1))])
  186. (syntax
  187. (syntax-case rhs1 ()
  188. [new-x1
  189. (let-syntax ([orig-names (make-term-id #'new-names (syntax-e #'depths))] ...)
  190. (term-let/error-name error-name ((x rhs) ...) body1 body2 ...))]
  191. [_ no-match]))))]
  192. [(_ error-name () body1 body2 ...)
  193. (syntax
  194. (begin body1 body2 ...))]
  195. [(_ x)
  196. (raise-syntax-error 'term-let "expected at least one body" stx)]))
  197. (define-syntax (term-let stx)
  198. (syntax-case stx ()
  199. [(_ () body1)
  200. #'body1]
  201. [(_ ([x rhs] ...) body1 body2 ...)
  202. (syntax
  203. (term-let/error-name term-let ((x rhs) ...) body1 body2 ...))]
  204. [(_ x)
  205. (raise-syntax-error 'term-let "expected at least one body" stx)]))