spec.scm 3.4 KB

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