spec.scm 3.4 KB

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