special.scm 6.6 KB

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