syntax-rules-compiler.scm 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Mike Sperber
  3. ; Returns the a list of compiled rules and a list of the names that are
  4. ; free in the templates. 'ellipsis?' is a predicate that matches ellipses.
  5. ; Both values are #F if an error is found.
  6. (define (compile-rules form ellipsis?)
  7. (let ((subkeywords (cadr form)))
  8. (let loop ((rules (cddr form)) (compiled '()) (inserted '()))
  9. (if (null? rules)
  10. (values (reverse compiled) inserted)
  11. (receive (c inserted)
  12. (compile-rule (car rules) subkeywords ellipsis? inserted)
  13. (if c
  14. (loop (cdr rules) (cons c compiled) inserted)
  15. (values #f #f)))))))
  16. (define (compile-rule rule subkeywords ellipsis? inserted)
  17. (let ((pattern (cdar rule))
  18. (template (cadr rule)))
  19. (receive (pattern vars)
  20. (compile-pattern pattern subkeywords ellipsis?)
  21. (if pattern
  22. (receive (template inserted referenced)
  23. (compile-template template vars ellipsis? inserted)
  24. (if inserted ; template may legitimately be #f
  25. (values (cons pattern template) inserted)
  26. (values #f #f)))
  27. (values #f #f)))))
  28. (define (compile-pattern pattern subkeywords ellipsis?)
  29. (let label ((pattern pattern) (vars '()) (rank 0))
  30. (cond ((name? pattern)
  31. (if (memq pattern subkeywords)
  32. (values pattern vars)
  33. (let ((var (make-pattern-variable pattern rank)))
  34. (values var (cons var vars)))))
  35. ((vector? pattern)
  36. (receive (patterns vars)
  37. (label (vector->list pattern) vars rank)
  38. (values (make-vector-marker patterns)
  39. vars)))
  40. ((not (pair? pattern))
  41. (values pattern vars))
  42. ((not (and (pair? (cdr pattern))
  43. (ellipsis? (cadr pattern))))
  44. (receive (head vars)
  45. (label (car pattern) vars rank)
  46. (receive (tail vars)
  47. (label (cdr pattern) vars rank)
  48. (values (cons head tail) vars))))
  49. ((null? (cddr pattern))
  50. (receive (compiled ellipsis-vars)
  51. (label (car pattern)
  52. '()
  53. (+ rank 1))
  54. (values (make-ellipsis-form compiled ellipsis-vars)
  55. (union ellipsis-vars vars))))
  56. (else
  57. (values #f '())))))
  58. (define (compile-template template vars ellipsis? inserted)
  59. (call-with-current-continuation
  60. (lambda (quit)
  61. (let label ((template template)
  62. (rank 0)
  63. (inserted inserted) ; free identifiers
  64. (referenced '())) ; pattern variables referenced
  65. (cond ((name? template)
  66. (let ((x (lookup-pattern-variable template vars)))
  67. (cond ((not x)
  68. (values template
  69. (if (memq x inserted)
  70. inserted
  71. (cons template inserted))
  72. referenced))
  73. ((<= (pattern-variable-rank x)
  74. rank)
  75. (values x inserted (cons x referenced)))
  76. (else
  77. (quit #f #f #f)))))
  78. ((vector? template)
  79. (receive (templates inserted referenced)
  80. (label (vector->list template) rank inserted referenced)
  81. (values (make-vector-marker templates)
  82. inserted
  83. referenced)))
  84. ((not (pair? template))
  85. (values template inserted referenced))
  86. (else
  87. (let ((count (count-ellipsis (cdr template) ellipsis?)))
  88. (receive (head inserted head-referenced)
  89. (label (car template)
  90. (+ rank count)
  91. inserted
  92. '())
  93. (receive (tail inserted referenced)
  94. (label (list-tail (cdr template) count)
  95. rank
  96. inserted
  97. (union head-referenced referenced))
  98. (values (cons (make-ellipsis-template head
  99. count
  100. head-referenced
  101. rank
  102. quit)
  103. tail)
  104. inserted
  105. referenced))))))))))
  106. ; Utilities
  107. (define (union x y)
  108. (cond ((null? x)
  109. y)
  110. ((member (car x) y)
  111. (union (cdr x) y))
  112. (else
  113. (union (cdr x) (cons (car x) y)))))
  114. (define (filter p l)
  115. (let label ((l l))
  116. (cond ((null? l)
  117. '())
  118. ((p (car l))
  119. (cons (car l) (label (cdr l))))
  120. (else
  121. (label (cdr l))))))
  122. (define (lookup-pattern-variable v vars)
  123. (cond ((null? vars)
  124. #f)
  125. ((eq? v (pattern-variable-name (car vars)))
  126. (car vars))
  127. (else
  128. (lookup-pattern-variable v (cdr vars)))))
  129. (define (count-ellipsis template ellipsis?)
  130. (let loop ((template template) (count 0))
  131. (if (and (pair? template)
  132. (ellipsis? (car template)))
  133. (loop (cdr template) (+ count 1))
  134. count)))
  135. (define (make-ellipsis-template template count referenced rank quit)
  136. (if (= count 0)
  137. template
  138. (let ((ellipsis-vars (filter (lambda (var)
  139. (< rank
  140. (pattern-variable-rank var)))
  141. referenced)))
  142. (if (null? ellipsis-vars)
  143. (quit #f #f #f)
  144. (do ((template template (make-ellipsis-form template ellipsis-vars))
  145. (count count (- count 1)))
  146. ((= count 0)
  147. template))))))