pp-cps.scm 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  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, Mike Sperber
  6. ;;;
  7. ;;; scheme48-1.9.2/ps-compiler/node/pp-cps.scm
  8. ;;;
  9. ;;; Pretty-printing the node tree
  10. ;;;
  11. ;;; Sample output:
  12. ;;;
  13. ;;; 34 (F_12 (C_11 UNIT_0)
  14. ;;; (SET-CONTENTS 1 C_11 UNIT_0 UNIT '0 ^F_14))
  15. ;;;
  16. ;;; 35 (F_14 (C_13 N_1)
  17. ;;; 36 (LET* (((LOOP_73) (CONS CELL '0))
  18. ;;; 37 (() (SET-CONTENTS LOOP_73 CELL '0 ^F_34))
  19. ;;; 38 ((V_77) (CONTENTS LOOP_73 CELL '0)))
  20. ;;; (V_77 1 C_13 N_1 '1)))
  21. ;;;
  22. ;;; 39 (F_34 (C_33 I_9 R_7)
  23. ;;; 40 (LET* (((V_61) (CONTENTS UNIT_0 UNIT '3))
  24. ;;; 41 ((V_63) (V_61 I_9 '0)))
  25. ;;; (TRUE? 2 ^C_58 ^C_41 V_63)))
  26. ;;;
  27. ;;; 42 (C_58 ()
  28. ;;; (C_33 0 R_7))
  29. ;;;
  30. ;;; 43 (C_41 ()
  31. ;;; 44 (LET* (((V_46) (CONTENTS UNIT_0 UNIT '2))
  32. ;;; 45 ((V_56) (V_46 I_9 R_7))
  33. ;;; 46 ((V_44) (CONTENTS UNIT_0 UNIT '1))
  34. ;;; 47 ((V_54) (V_44 I_9 '1))
  35. ;;; 48 ((V_52) (CONTENTS LOOP_73 CELL '0)))
  36. ;;; (V_52 1 C_33 V_54 V_56)))
  37. ;;;
  38. ;;; What it means:
  39. ;;;
  40. ;;; Variables `<name>_<id>' V_61
  41. ;;; Primops `<primop name>' CONTENTS
  42. ;;; Lambdas `^<self variable>' ^F_34
  43. ;;; Literals `'<value>' '0
  44. ;;;
  45. ;;; 35 (F_14 (C_13 N_1)
  46. ;;; This is the header for a lambda node. `35' is the object hash of the node.
  47. ;;; `F_14' is the LAMBDA-NAME and LAMBDA-ID, `(C_13 N_1)' is the variable list. The
  48. ;;; start of this line (not counting the object hash) is indented one column
  49. ;;; more than the start of the lexically superior lambda.
  50. ;;;
  51. ;;; 36 (LET* (((LOOP_73) (CONS CELL '0))
  52. ;;; 37 (() (SET-CONTENTS LOOP_73 CELL '0 ^F_34))
  53. ;;; 38 ((V_77) (CONTENTS LOOP_73 CELL '0)))
  54. ;;; (V_77 1 C_13 N_1 '1)))
  55. ;;; This is the body of the lambda. It is a block consisting of three simple
  56. ;;; calls and then a tail recursive call. The simple calls are in the form
  57. ;;; of a LET* that allows multiple value returns. The actual body of the
  58. ;;; lambda is the call `(CONS CELL '0)'. The continuation to this call is
  59. ;;; a lambda node `(LAMBDA (LOOP_73) (SET-CONTENTS ...))'. `36' is the
  60. ;;; object hash of this continuation lambda.
  61. ;;; After the block any lambdas in the block are printed. This lambda is
  62. ;;; followed by `F_34'.
  63. ;;;
  64. ;;; (PP-CPS node . port)
  65. ;;;---------------------------------------------------------------------------
  66. ;;; Print CPS node tree in linear form. Port defaults to the current output port.
  67. ;;; This just dispatches on the type of NODE.
  68. (define-module (ps-compiler node pp-cps)
  69. #:use-module (ice-9 format)
  70. #:use-module (prescheme scheme48)
  71. #:use-module (ps-compiler node node)
  72. #:use-module (ps-compiler node node-util)
  73. #:use-module (ps-compiler node primop)
  74. #:use-module (ps-compiler util util)
  75. #:export (pp-cps))
  76. (define (pp-cps node . port)
  77. (let* ((port (if (null? port) (current-output-port) (car port)))
  78. (port (if (current-column port)
  79. port
  80. (make-tracking-output-port port))))
  81. (set! *rereadable?* #f)
  82. (cond ((lambda-node? node)
  83. (pp-cps-lambda node 4 port))
  84. ((call-node? node)
  85. (write-non-simple-call node port))
  86. (else
  87. (write-node-value node port)))
  88. (newline port)
  89. (force-output port)))
  90. (define (rereadable-pp-cps node port)
  91. (set! *rereadable?* #t)
  92. (pp-cps-lambda node 4 port)
  93. (values))
  94. (define (indent port count)
  95. (let ((count (cond ((<= (current-column port) count)
  96. (- count (current-column port)))
  97. (else
  98. (newline port)
  99. count))))
  100. (do ((count count (- count 1)))
  101. ((>= 0 count))
  102. (writec port #\space))))
  103. (define *rereadable?* #f)
  104. (define *next-pp-id* 0)
  105. (define (reset-pp-cps)
  106. (set! *next-pp-id* 0))
  107. (define (next-pp-id)
  108. (let ((id *next-pp-id*))
  109. (set! *next-pp-id* (+ *next-pp-id* 1))
  110. id))
  111. ;; Print a lambda node by printing its identifiers, then its call, and finally
  112. ;; any other lambdas that it includes.
  113. (define (pp-cps-lambda node indent-to port)
  114. (format port "~&~%")
  115. (cond ((not *rereadable?*)
  116. (node-hash node)
  117. (format port "~D" (lambda-id node))))
  118. (indent port indent-to)
  119. (write-lambda-header node port)
  120. (let ((internal (pp-cps-body (lambda-body node) indent-to port)))
  121. (writec port #\))
  122. (for-each (lambda (n)
  123. (pp-cps-lambda n (+ indent-to 1) port))
  124. internal)))
  125. (define (write-lambda-header node port)
  126. (writec port '#\()
  127. (writec port (case (lambda-type node)
  128. ((proc known-proc) #\P)
  129. ((cont) #\C)
  130. ((jump) #\J)
  131. ((escape) #\E)))
  132. (writec port #\space)
  133. (print-lambda-name node port)
  134. (writec port #\space)
  135. (write-lambda-vars node port))
  136. (define (write-lambda-vars node port)
  137. (let ((vars (lambda-variables node)))
  138. (cond ((not (null? vars))
  139. (writec port '#\()
  140. (print-variable-name (car vars) port)
  141. (do ((v (cdr vars) (cdr v)))
  142. ((null? v))
  143. (writec port '#\space)
  144. (print-variable-name (car v) port))
  145. (writec port '#\)))
  146. (else
  147. (format port "()")))))
  148. ;; Print the body of a lambda node. A simple call is one that has exactly
  149. ;; one exit. They and calls to lambda nodes are printed as a LET*.
  150. (define (pp-cps-body call indent-to port)
  151. (newline port)
  152. (cond ((or (simple-call? call)
  153. (let-call? call))
  154. (write-let* call indent-to port))
  155. (else
  156. (indent port (+ '2 indent-to))
  157. (write-non-simple-call call port))))
  158. ;; Write out a series of calls as a LET*. The LET* ends when a call is reached
  159. ;; that is neither a simple call or a call to a lambda.
  160. (define (write-let* call indent-to port)
  161. (cond ((not *rereadable?*)
  162. (node-hash (call-arg call 0))
  163. (format port "~D" (lambda-id (call-arg call '0)))))
  164. (indent port (+ '2 indent-to))
  165. (writec port '#\()
  166. (format port "LET* ")
  167. (writec port '#\()
  168. (let loop ((call (next-call call))
  169. (ns (write-simple-call call indent-to port)))
  170. (cond ((or (simple-call? call)
  171. (let-call? call))
  172. (newline port)
  173. (cond ((not *rereadable?*)
  174. (format port "~D" (lambda-id (call-arg call '0)))
  175. (node-hash (call-arg call 0))))
  176. (indent port (+ '9 indent-to))
  177. (loop (next-call call)
  178. (append (write-simple-call call indent-to port) ns)))
  179. (else
  180. (writec port '#\))
  181. (newline port)
  182. (indent port (+ '4 indent-to))
  183. (let ((ns (append (write-non-simple-call call port) ns)))
  184. (writec port '#\))
  185. ns)))))
  186. (define (simple-call? call)
  187. (= '1 (call-exits call)))
  188. (define (let-call? call)
  189. (calls-this-primop? call 'let))
  190. ;; Get the call that follows CALL in a LET*.
  191. (define (next-call call)
  192. (lambda-body (call-arg call '0)))
  193. ;; Write out one line of a LET*.
  194. (define (write-simple-call call indent-to port)
  195. (if (let-call? call)
  196. (write-let-call call indent-to port)
  197. (really-write-simple-call call indent-to port)))
  198. ;; Write the variables bound by the continuation and then the primop and
  199. ;; non-continuation arguments of the call.
  200. (define (really-write-simple-call call indent-to port)
  201. (writec port '#\()
  202. (write-lambda-vars (call-arg call '0) port)
  203. (indent port (+ indent-to '21))
  204. (writec port '#\()
  205. (format port "~S" (primop-id (call-primop call)))
  206. (write-call-args call '1 port)
  207. (writec port '#\))
  208. (find-lambda-nodes call 1))
  209. ;; Write the variables of the lambda and then the values of the arguments.
  210. (define (write-let-call call indent-to port)
  211. (writec port '#\()
  212. (write-lambda-vars (call-arg call '0) port)
  213. (cond ((= '1 (vector-length (call-args call)))
  214. (writec port '#\))
  215. '())
  216. (else
  217. (writec port #\*)
  218. (indent port (+ indent-to '21))
  219. (write-node-value (call-arg call '1) port)
  220. (write-call-args call '2 port)
  221. (find-lambda-nodes call 1))))
  222. (define (find-lambda-nodes call start)
  223. (reverse (let label ((call call) (start start) (ls '()))
  224. (do ((i start (+ i 1))
  225. (ls ls (let ((arg (call-arg call i)))
  226. (cond ((call-node? arg)
  227. (label arg 0 ls))
  228. ((lambda-node? arg)
  229. (cons arg ls))
  230. (else ls)))))
  231. ((>= i (call-arg-count call))
  232. ls)))))
  233. ;; Write out a call that ends a LET* block.
  234. (define (write-non-simple-call call port)
  235. (writec port '#\()
  236. (format port "~A ~D" (primop-id (call-primop call)) (call-exits call))
  237. (write-call-args call '0 port)
  238. (find-lambda-nodes call 0))
  239. ;; Write out the arguments of CALL starting with START.
  240. (define (write-call-args call start port)
  241. (let* ((vec (call-args call))
  242. (len (vector-length vec)))
  243. (do ((i start (+ i '1)))
  244. ((>= i len))
  245. (writec port '#\space)
  246. (write-node-value (vector-ref vec i) port))
  247. (writec port '#\))))
  248. ;; Print out a literal value.
  249. (define (cps-print-literal value port)
  250. (format port "'~S" value))
  251. ;; Dispatch on the type of NODE to get the appropriate printing method.
  252. (define (write-node-value node port)
  253. (cond ((not (node? node))
  254. (format port "{not a node}"))
  255. ((lambda-node? node)
  256. (writec port '#\^)
  257. (print-lambda-name node port))
  258. ((call-node? node)
  259. (format port "(~S" (primop-id (call-primop node)))
  260. (write-call-args node '0 port))
  261. ((literal-node? node)
  262. (cps-print-literal (literal-value node) port))
  263. ((reference-node? node)
  264. (print-variable-name (reference-variable node) port))
  265. (else
  266. (bug "WRITE-NODE-VALUE got funny node ~S" node))))
  267. ;; Printing variables and lambda nodes
  268. ;; #T if variables are supposed to print as the name of the register containing
  269. ;; them instead of their name.
  270. (define *pp-register-names?* '#f)
  271. ;; A whole bunch of different entry points for printing variables in slightly
  272. ;; different ways.
  273. (define (print-variable-name var port)
  274. (cond ((not var)
  275. (format port "#f"))
  276. ;; ((and *pp-register-names?*
  277. ;; (reg? (variable-register var)))
  278. ;; (format port "~S" (reg-name (variable-register var))))
  279. (else
  280. (let ((id (cond ((not *rereadable?*)
  281. (variable-id var))
  282. ((variable-flag var)
  283. => identity)
  284. (else
  285. (let ((id (next-pp-id)))
  286. (set-variable-flag! var id)
  287. id)))))
  288. (format port "~S_~S" (variable-name var) id)))))
  289. ;; Same as the above without the check for a register.
  290. (define (print-variable-plain-name var port)
  291. (cond ((not var)
  292. (format port "#f"))
  293. (else
  294. (format port "~S_~D" (variable-name var) (variable-id var)))))
  295. ;; Return the name as a string.
  296. (define (variable-print-name var)
  297. (print-variable-name var '#f))
  298. ;; Return the name as a symbol.
  299. (define (variable-unique-name var)
  300. (string->symbol (variable-print-name var)))
  301. ;; Printing lambda-nodes as variables
  302. (define (print-lambda-name lnode port)
  303. (let ((id (cond ((not *rereadable?*)
  304. (lambda-id lnode))
  305. ((node-flag lnode)
  306. => identity)
  307. (else
  308. (let ((id (next-pp-id)))
  309. (set-node-flag! lnode id)
  310. id)))))
  311. (format port "~S_~D" (lambda-name lnode) id)))
  312. (define (lambda-print-name lnode)
  313. (print-lambda-name lnode '#f))
  314. (define (lambda-unique-name lnode)
  315. (string->symbol (lambda-print-name lnode)))