schemify.scm 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. ;;; Ported from Scheme 48 1.9. See file COPYING for notices and license.
  2. ;;;
  3. ;;; Port Author: Andrew Whatson
  4. ;;;
  5. ;;; Original Authors: Richard Kelsey, Jonathan Rees, Martin Gasbichler, Mike Sperber
  6. ;;;
  7. ;;; scheme48-1.9.2/scheme/bcomp/schemify.scm
  8. ;;;
  9. ;;; schemify
  10. ;;;
  11. ;;; This is only used for producing error and warning messages.
  12. ;;;
  13. ;;; Flush nodes and generated names in favor of something a little more
  14. ;;; readable. Eventually, (schemify node env) ought to produce an
  15. ;;; s-expression that has the same semantics as node, when node is fully
  16. ;;; expanded.
  17. (define-module (prescheme bcomp schemify)
  18. #:use-module (prescheme scheme48)
  19. #:use-module (prescheme bcomp cenv)
  20. #:use-module (prescheme bcomp binding)
  21. #:use-module (prescheme bcomp mtype)
  22. #:use-module (prescheme bcomp name)
  23. #:use-module (prescheme bcomp node)
  24. #:use-module (prescheme bcomp package)
  25. #:use-module (prescheme bcomp transform)
  26. #:export (schemify))
  27. (define (schemify node . maybe-env)
  28. (if (node? node)
  29. (schemify-node node
  30. (if (null? maybe-env)
  31. #f
  32. (car maybe-env)))
  33. (schemify-sexp node)))
  34. (define schemifiers
  35. (make-operator-table (lambda (node env)
  36. (let ((form (node-form node)))
  37. (if (list? form)
  38. (let ((op (car form)))
  39. (cons (cond ((operator? op)
  40. (operator-name op))
  41. ((node? op)
  42. (schemify-node op env))
  43. (else
  44. (schemify-sexp op)))
  45. (schemify-nodes (cdr form) env)))
  46. form)))))
  47. ;; We cache the no-env version because that's the one used to generate the
  48. ;; sources in the debugging info (which takes up a lot of space).
  49. (define (schemify-node node env)
  50. (or (and (not env)
  51. (node-ref node 'schemify))
  52. (let ((form ((operator-table-ref schemifiers (node-operator-id node))
  53. node
  54. env)))
  55. (if (not env)
  56. (node-set! node 'schemify form))
  57. form)))
  58. (define (schemify-nodes nodes env)
  59. (map (lambda (node)
  60. (schemify-node node env))
  61. nodes))
  62. (define (define-schemifier name type proc)
  63. (operator-define! schemifiers name type proc))
  64. (define-schemifier 'name 'leaf
  65. (lambda (node env)
  66. (if env
  67. (name->qualified (node-form node)
  68. env)
  69. (let ((form (node-form node)))
  70. (if (or #f (node? form))
  71. (schemify-node form env)
  72. (desyntaxify form))))))
  73. ;; Convert an alias (generated name) to S-expression form ("qualified name").
  74. (define (name->qualified name env)
  75. (cond ((not (generated? name))
  76. name)
  77. ((let ((d0 (lookup env name))
  78. (d1 (lookup env (generated-name name))))
  79. (and d0 d1 (same-denotation? d0 d1)))
  80. (generated-name name)) ;;+++
  81. (else
  82. (make-qualified (qualify-parent (generated-parent-name name)
  83. env)
  84. (generated-name name)
  85. (generated-uid name)))))
  86. ;; As an optimization, we elide intermediate steps in the lookup path
  87. ;; when possible. E.g.
  88. ;; #(>> #(>> #(>> define-record-type define-accessors)
  89. ;; define-accessor)
  90. ;; record-ref)
  91. ;; is replaced with
  92. ;; #(>> define-record-type record-ref)
  93. (define (qualify-parent name env)
  94. (let recur ((name name) (env env))
  95. (if (generated? name)
  96. (let ((parent (generated-parent-name name)))
  97. (if (and (environment-stable? env)
  98. (let ((b1 (generic-lookup env name))
  99. (b2 (generic-lookup env parent)))
  100. (and b1
  101. b2
  102. (or (same-denotation? b1 b2)
  103. (and (binding? b1)
  104. (binding? b2)
  105. (let ((s1 (binding-static b1))
  106. (s2 (binding-static b2)))
  107. (and (transform? s1)
  108. (transform? s2)
  109. (eq? (transform-env s1)
  110. (transform-env s2)))))))))
  111. (recur parent env) ;;+++
  112. (make-qualified (recur parent (generated-env name))
  113. (generated-name name)
  114. (generated-uid name))))
  115. name)))
  116. (define-schemifier 'quote syntax-type
  117. (lambda (node env)
  118. (let ((form (node-form node)))
  119. `(quote ,(cadr form)))))
  120. (define-schemifier 'call 'internal
  121. (lambda (node env)
  122. (map (lambda (node)
  123. (schemify-node node env))
  124. (node-form node))))
  125. ;; We ignore the list of free variables in flat lambdas.
  126. (define (schemify-lambda node env)
  127. (let ((form (node-form node)))
  128. `(lambda ,(schemify-formals (cadr form) env)
  129. ,(schemify-node (last form) env))))
  130. (define-schemifier 'lambda syntax-type schemify-lambda)
  131. (define-schemifier 'flat-lambda syntax-type schemify-lambda)
  132. (define (schemify-formals formals env)
  133. (cond ((node? formals)
  134. (schemify-node formals env))
  135. ((pair? formals)
  136. (cons (schemify-node (car formals) env)
  137. (schemify-formals (cdr formals) env)))
  138. (else
  139. (schemify-sexp formals)))) ;; anything besides '() ?
  140. ;; let-syntax, letrec-syntax...
  141. (define-schemifier 'letrec syntax-type
  142. (lambda (node env)
  143. (let ((form (node-form node)))
  144. (schemify-letrec 'letrec (cadr form) (caddr form) env))))
  145. (define-schemifier 'letrec* syntax-type
  146. (lambda (node env)
  147. (let ((form (node-form node)))
  148. (schemify-letrec 'letrec* (cadr form) (caddr form) env))))
  149. (define-schemifier 'pure-letrec syntax-type
  150. (lambda (node env)
  151. (let ((form (node-form node)))
  152. (schemify-letrec 'letrec (cadr form) (cadddr form) env))))
  153. (define (schemify-letrec op specs body env)
  154. `(,op ,(map (lambda (spec)
  155. (schemify-nodes spec env))
  156. specs)
  157. ,(schemify-node body env)))
  158. (define-schemifier 'loophole syntax-type
  159. (lambda (node env)
  160. (let ((form (node-form node)))
  161. (list 'loophole
  162. (type->sexp (cadr form) #t)
  163. (schemify-node (caddr form) env)))))
  164. (define-schemifier 'lap syntax-type
  165. (lambda (node env)
  166. (let ((form (node-form node)))
  167. `(lap
  168. ,(cadr form)
  169. ,(schemify-nodes (caddr form) env)
  170. . ,(cdddr form)))))
  171. ;;----------------
  172. (define (schemify-sexp thing)
  173. (cond ((name? thing)
  174. (desyntaxify thing))
  175. ((pair? thing)
  176. (let ((x (schemify-sexp (car thing)))
  177. (y (schemify-sexp (cdr thing))))
  178. (if (and (eq? x (car thing))
  179. (eq? y (cdr thing)))
  180. thing ;;+++
  181. (cons x y))))
  182. ((vector? thing)
  183. (let ((new (make-vector (vector-length thing) #f)))
  184. (let loop ((i 0) (same? #t))
  185. (if (>= i (vector-length thing))
  186. (if same? thing new) ;+++
  187. (let ((x (schemify-sexp (vector-ref thing i))))
  188. (vector-set! new i x)
  189. (loop (+ i 1)
  190. (and same? (eq? x (vector-ref thing i)))))))))
  191. (else thing)))