spec.scm 4.8 KB

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