spec.scm 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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
  6. ;;;
  7. ;;; scheme48-1.9.2/ps-compiler/prescheme/spec.scm
  8. ;;;
  9. ;;; Protocol specifications are lists of representations.
  10. (define-module (ps-compiler prescheme spec)
  11. #:use-module ((ps-compiler param) #:select (set-compiler-parameter!))
  12. #:use-module (ps-compiler node arch)
  13. #:use-module (ps-compiler node let-nodes)
  14. #:use-module (ps-compiler node node)
  15. #:use-module (ps-compiler node node-util)
  16. #:use-module (ps-compiler node primop)
  17. #:use-module (ps-compiler node variable)
  18. #:use-module (ps-compiler prescheme type)
  19. #:use-module (ps-compiler prescheme primop primop)
  20. #:use-module (ps-compiler util util)
  21. #:export (normal-protocol
  22. goto-protocol
  23. goto-protocol?))
  24. (set-compiler-parameter! 'lambda-node-type
  25. (lambda (node)
  26. (let ((vars (lambda-variables node)))
  27. (case (lambda-type node)
  28. ((cont jump)
  29. (make-arrow-type (map variable-type vars)
  30. type/unknown)) ;; what to do?
  31. ((proc known-proc)
  32. (make-arrow-type (map variable-type (cdr vars))
  33. (variable-type (car vars))))
  34. (else
  35. (error "unknown type of lambda node ~S" node))))))
  36. (set-compiler-parameter! 'true-value #t)
  37. (set-compiler-parameter! 'false-value #f)
  38. ;; Tail-calls with goto-protocols cause the lambda node to be annotated
  39. ;; as tail-called.
  40. ;; Calls with a tuple argument need their argument spread out into separate
  41. ;; variables.
  42. (define (determine-lambda-protocol lambda-node call-refs)
  43. (set-lambda-protocol! lambda-node #f)
  44. (for-each (lambda (r)
  45. (let ((call (node-parent r)))
  46. (cond ((goto-protocol? (literal-value (call-arg call 2)))
  47. (if (not (calls-this-primop? call 'unknown-tail-call))
  48. (bug "GOTO marker in non-tail-all ~S" call))
  49. (set-lambda-protocol! lambda-node 'tail-called)))
  50. (unknown-call->known-call call)))
  51. call-refs)
  52. (set-calls-known?! lambda-node))
  53. (set-compiler-parameter! 'determine-lambda-protocol determine-lambda-protocol)
  54. (define (unknown-call->known-call the-call)
  55. (remove-call-arg the-call 2) ;; remove the protocol
  56. (set-call-primop! the-call
  57. (case (primop-id (call-primop the-call))
  58. ((unknown-call)
  59. (get-primop (enum primop-enum call)))
  60. ((unknown-tail-call)
  61. (get-primop (enum primop-enum tail-call)))
  62. (else
  63. (bug "odd primop in call ~S" the-call)))))
  64. ;; CONT is the continuation passed to PROCS.
  65. (define (determine-continuation-protocol cont procs)
  66. (for-each (lambda (proc)
  67. (let ((cont-var (car (lambda-variables proc))))
  68. (walk-refs-safely
  69. (lambda (ref)
  70. (let ((call (node-parent ref)))
  71. (unknown-return->known-return call cont-var cont)))
  72. cont-var)))
  73. procs))
  74. (set-compiler-parameter! 'determine-continuation-protocol
  75. determine-continuation-protocol)
  76. ;; If the return is actually a tail-recursive call we change it to
  77. ;; a non-tail-recursive one (since we have identified the continuation)
  78. ;; and insert the appropriate continuation.
  79. (define (unknown-return->known-return the-call cont-var cont)
  80. (case (primop-id (call-primop the-call))
  81. ((unknown-return)
  82. (set-call-primop! the-call (get-primop (enum primop-enum return))))
  83. ((unknown-tail-call tail-call)
  84. (let* ((vars (map copy-variable (lambda-variables cont)))
  85. (args (map make-reference-node vars)))
  86. (let-nodes ((cont vars (return 0 (* cont-var) . args)))
  87. (replace (call-arg the-call 0) cont)
  88. (set-call-primop! the-call
  89. (if (calls-this-primop? the-call 'tail-call)
  90. (get-primop (enum primop-enum call))
  91. (get-primop (enum primop-enum unknown-call))))
  92. (set-call-exits! the-call 1)
  93. (if (and (calls-this-primop? the-call 'unknown-call)
  94. (goto-protocol? (literal-value (call-arg the-call 2))))
  95. (set-literal-value! (call-arg the-call 2) #f)))))
  96. (else
  97. (bug "odd return primop ~S" (call-primop the-call)))))
  98. (define normal-protocol #f)
  99. (define goto-protocol 'goto)
  100. (define (goto-protocol? x)
  101. (eq? x goto-protocol))
  102. (set-compiler-parameter! 'lookup-primop get-prescheme-primop)
  103. (set-compiler-parameter! 'type/unknown type/unknown)
  104. (set-compiler-parameter! 'type-eq? type-eq?)