special.scm 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. ; Copyright (c) 1993-2008 by Richard Kelsey. See file COPYING.
  2. ; This file is obsolete and no longer used.
  3. ;----------------------------------------------------------------------------
  4. ; SPECIAL FORMS
  5. ;
  6. ; QUOTE CALL RETURN BLOCK LAMBDA LETREC
  7. ; + LET for reasons of type-checking
  8. ;
  9. ;----------------------------------------------------------------------------
  10. (define-record-type quote-exp :quote-exp
  11. (make-quote-exp value type)
  12. quote-exp?
  13. (value quote-exp-value)
  14. (type quote-exp-type set-quote-exp-type!))
  15. (define-record-type call-exp :call-exp
  16. (make-call-exp! proc exits type args source)
  17. call-exp?
  18. (proc call-exp-proc)
  19. (exits call-exp-exits)
  20. (type call-exp-type set-call-exp-type!)
  21. (args call-exp-args)
  22. (source call-exp-source))
  23. (define-record-type let-exp :let-exp
  24. (make-let-exp vars vals body source)
  25. let-exp?
  26. (vars let-exp-vars)
  27. (vals let-exp-vals)
  28. (body let-exp-body set-let-exp-body!)
  29. (source let-exp-source))
  30. (define-record-type return-exp :return-exp
  31. (make-return-exp protocol type args)
  32. return-exp?
  33. (protocol return-exp-protocol)
  34. (type return-exp-type)
  35. (args return-exp-args))
  36. (define-record-type block-exp :block-exp
  37. (make-block-exp exps)
  38. block-exp?
  39. (exps block-exp-exps))
  40. (define-record-type lambda-exp :lambda-exp
  41. (make-lambda-exp id return-type protocol vars body source)
  42. lambda-exp?
  43. (id lambda-exp-id)
  44. (return-type lambda-exp-return-type set-lambda-exp-return-type!)
  45. (protocol lambda-exp-protocol)
  46. (vars lambda-exp-vars)
  47. (body lambda-exp-body set-lambda-exp-body!)
  48. (source lambda-exp-source))
  49. (define (make-continuation-exp vars body)
  50. (make-lambda-exp #f #f #f vars body #f))
  51. (define-record-type letrec-exp :letrec-exp
  52. (make-letrec-exp vars vals body source)
  53. letrec-exp?
  54. (vars letrec-exp-vars)
  55. (vals letrec-exp-vals)
  56. (body letrec-exp-body set-letrec-exp-body!)
  57. (source letrec-exp-source))
  58. (define-record-type external-value :external-value
  59. (make-external-value type)
  60. external-value?
  61. (type external-value-type set-external-value-type!))
  62. ; Creating nodes and CPS converting calls and blocks.
  63. ;-------------------------------------------------------------------------------
  64. ; (CPS expression) => value + first-call + last-lambda
  65. ; = the value of the expression
  66. ; + the first of any calls that must be executed to get the value
  67. ; + the continuation lambda of the last of the necessary calls
  68. ; The first call and the last lambda will be #F if the value is trivial.
  69. ;
  70. ; (TAIL-CPS expression continuation-variable) => call
  71. ; = the first call to execute to return the value of the expression to
  72. ; the continuation variable
  73. (define (cps exp)
  74. (let ((value (cps-value exp)))
  75. (if value
  76. (values value #f #f)
  77. (generic-cps exp #f))))
  78. (define (tail-cps exp cont-var)
  79. (receive (value type)
  80. (cps-value+type exp)
  81. (if value
  82. (make-value-return cont-var value type)
  83. (generic-cps exp cont-var))))
  84. (define (cps-value exp)
  85. (receive (value type)
  86. (cps-value+type exp)
  87. value))
  88. (define (cps-value+type exp)
  89. (cond ((variable? exp)
  90. (values (make-reference-node exp) (variable-type exp)))
  91. ((quote-exp? exp)
  92. (values (make-literal-node (quote-exp-value exp)
  93. (quote-exp-type exp))
  94. (quote-exp-type exp)))
  95. ((lambda-exp? exp)
  96. (let ((node (lambda-exp->node exp)))
  97. (values node (lambda-node-type node))))
  98. (else
  99. (values #f #f))))
  100. (define (generic-cps exp cont-var)
  101. (cond ((block-exp? exp)
  102. (make-block (block-exp-exps exp) cont-var))
  103. ((return-exp? exp)
  104. (make-return-call exp cont-var))
  105. ((call-exp? exp)
  106. (make-primop-call exp cont-var))
  107. ((let-exp? exp)
  108. (make-lambda-call exp cont-var))
  109. ((letrec-exp? exp)
  110. (letrec-exp->node exp cont-var))
  111. (else
  112. (bug "unknown syntax~% ~S" exp))))
  113. (define (lambda-exp->node exp)
  114. (let* ((cvar (make-variable 'c (lambda-exp-return-type exp)))
  115. (node (make-lambda-node (lambda-exp-id exp)
  116. 'proc
  117. (cons cvar (copy-list (lambda-exp-vars exp))))))
  118. (set-lambda-protocol! node (lambda-exp-protocol exp))
  119. (set-lambda-source! node (lambda-exp-source exp))
  120. (attach-body node (tail-cps (lambda-exp-body exp) cvar))
  121. node))
  122. (define (letrec-exp->node exp cont-var)
  123. (let ((vals (map cps-value (letrec-exp-vals exp)))
  124. (vars (letrec-exp-vars exp))
  125. (cont (make-lambda-node 'c 'cont '())))
  126. (let-nodes ((top (letrec1 1 l1))
  127. (l1 ((x #f) . vars) call2)
  128. (call2 (letrec2 1 cont (* x) . vals)))
  129. (set-call-source! top (letrec-exp-source exp))
  130. (happens-after top cont (letrec-exp-body exp) cont-var))))
  131. ; (CATCH id . body)
  132. ; (THROW primop rep id . args)
  133. (define (make-undefined-value)
  134. (make-quote-exp the-undefined-value #f))
  135. (define (exp->s-exp exp)
  136. (cond ((variable? exp)
  137. (format #f "~S_~S" (variable-name exp) (variable-id exp)))
  138. ((quote-exp? exp)
  139. (list 'quote (quote-exp-value exp)))
  140. ((block-exp? exp)
  141. (cons 'begin (map exp->s-exp (block-exp-exps exp))))
  142. ((return-exp? exp)
  143. (cons 'return (map exp->s-exp (return-exp-args exp))))
  144. ((call-exp? exp)
  145. `(,(primop-id (call-exp-proc exp))
  146. ,(call-exp-exits exp)
  147. . ,(map exp->s-exp (call-exp-args exp))))
  148. ((let-exp? exp)
  149. `(let ,(map list
  150. (map exp->s-exp (let-exp-vars exp))
  151. (map exp->s-exp (let-exp-vals exp)))
  152. ,(exp->s-exp (let-exp-body exp))))
  153. ((lambda-exp? exp)
  154. `(lambda ,(map exp->s-exp (lambda-exp-vars exp))
  155. ,(exp->s-exp (lambda-exp-body exp))))
  156. ((letrec-exp? exp)
  157. `(letrec ,(map list
  158. (map exp->s-exp (letrec-exp-vars exp))
  159. (map exp->s-exp (letrec-exp-vals exp)))
  160. ,(exp->s-exp (letrec-exp-body exp))))
  161. (else
  162. (error '"unknown syntax~% ~S" exp))))
  163. (define (exp-source exp)
  164. (cond ((call-exp? exp)
  165. (call-exp-source exp))
  166. ((let-exp? exp)
  167. (let-exp-source exp))
  168. ((letrec-exp? exp)
  169. (letrec-exp-source exp))
  170. ((lambda-exp? exp)
  171. (lambda-exp-source exp))
  172. (else
  173. #f)))
  174. (define (find-some-source top-exp exp)
  175. (or (exp-source exp)
  176. (call-with-current-continuation
  177. (lambda (exit)
  178. (let recur ((at top-exp))
  179. (let ((hit? (cond ((eq? at exp)
  180. #t)
  181. ((call-exp? at)
  182. (or (recur (call-exp-proc at))
  183. (any recur (call-exp-args at))))
  184. ((let-exp? at)
  185. (or (recur (let-exp-body at))
  186. (any recur (let-exp-vals at))))
  187. ((letrec-exp? at)
  188. (or (recur (letrec-exp-body at))
  189. (any recur (letrec-exp-vals at))))
  190. ((return-exp? at)
  191. (any recur (return-exp-args at)))
  192. ((lambda-exp? at)
  193. (recur (lambda-exp-body at)))
  194. ((block-exp? at)
  195. (any recur (block-exp-exps at)))
  196. (else #f))))
  197. (if (and hit? (exp-source at))
  198. (exit (exp-source at)))
  199. hit?))))))