comp.scm 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Martin Gasbichler, Mike Sperber
  3. ; This is the main entry point to the compiler. It returns a template
  4. ; that will execute the forms (each of which is a node).
  5. ;
  6. ; This is written in a somewhat odd fashion to make sure that the forms are
  7. ; not retained once they have been compiled.
  8. (define (compile-forms forms name package-key)
  9. (with-package-key package-key
  10. (lambda ()
  11. (if (null? forms)
  12. (segment->template (sequentially
  13. (lambda-protocol 0 #t #f #f)
  14. (deliver-value (instruction (enum op unspecific))
  15. (return-cont #f)))
  16. (make-frame #f name 0 #f #f #f))
  17. (compile-forms-loop (reverse forms)
  18. name
  19. #f))))) ;next template
  20. (define (compile-forms-loop forms name next)
  21. (if (null? forms)
  22. next
  23. (compile-forms-loop (cdr forms)
  24. name
  25. (compile-form (car forms) name next))))
  26. ; Compile a single top-level form, returning a template. NEXT is either #F or
  27. ; a template; if it is a template we jump to it after FORM.
  28. ; Stack has zero args, no env, template.
  29. (define (compile-form form name next)
  30. (let ((frame (make-frame #f name 0 #t #f #f)))
  31. (segment->template
  32. (sequentially
  33. (lambda-protocol 0 #t #f #f) ; template, no env, no closure
  34. (let ((node (flatten-form (force-node form))))
  35. (cond ((define-node? node)
  36. (sequentially
  37. (compile-definition node frame an-ignore-values-cont)
  38. (if next
  39. (call-template-inst next #f 0 1 frame)
  40. (instruction (enum op values) 0 0))))
  41. (next
  42. (sequentially
  43. (compile-expression node 1 frame an-ignore-values-cont)
  44. (call-template-inst next #f 0 1 frame)))
  45. (else
  46. (compile-expression node 1 frame (return-cont #f))))))
  47. frame)))
  48. (define (call-template-inst template label nargs depth frame)
  49. (let ((offset (template-offset frame depth))
  50. (index (literal->index frame template)))
  51. (using-optional-label (enum op call-template)
  52. label
  53. (high-byte offset)
  54. (low-byte offset)
  55. (high-byte index)
  56. (low-byte index)
  57. nargs)))
  58. (define (template-call template depth frame cont)
  59. (receive (before depth label after)
  60. (push-continuation depth frame cont #f)
  61. (sequentially before
  62. (call-template-inst template label 0 depth frame)
  63. after)))
  64. ; Definitions must be treated differently from assignments: we must
  65. ; use STORED-OBJECT-SET! instead of SET-GLOBAL! because the SET-GLOBAL!
  66. ; instruction traps if an attempt is made to store into an undefined
  67. ; location.
  68. ;
  69. ; Called with a stack depth of one (the template).
  70. (define (compile-definition node frame cont)
  71. (let* ((form (node-form node))
  72. (name (cadr form)))
  73. (sequentially (stack-indirect-instruction
  74. (template-offset frame 1)
  75. (binding->index frame
  76. (node-ref name 'binding)
  77. (node-form name)
  78. #f))
  79. (begin (depth-check! frame 2)
  80. (instruction (enum op push)))
  81. (compile-expression (caddr form)
  82. 2 ; stack depth
  83. frame
  84. (named-cont (node-form name)))
  85. (deliver-value
  86. (instruction (enum op stored-object-set!)
  87. (enum stob location)
  88. location-contents-offset
  89. 0) ; do not log in current proposal
  90. cont))))
  91. (define location-contents-offset
  92. (cond ((assq 'location stob-data)
  93. => (lambda (stuff)
  94. (let loop ((slots (cdddr stuff)) (i 0))
  95. (if (eq? (caar slots) 'contents)
  96. i
  97. (loop (cdr slots) (+ i 1))))))
  98. (else
  99. (assertion-violation 'location-contents-offset
  100. "can't find location data in STOB-DATA"))))
  101. ;----------------
  102. ; Make a startup procedure from a list of initialization templates. This
  103. ; is only used by the static linker. RESUMER should be a template that
  104. ; returns a procedure that takes 8 arguments (the number the VM passes to
  105. ; the startup procedure).
  106. ; The length of the argument list needs to be in sync with
  107. ; MAKE-USUAL-RESUMER in rts/init.scm, and S48-CALL-STARTUP-PROCEDURE
  108. ; in vm/interp/resume.scm.
  109. (define (make-startup-procedure inits resumer)
  110. (let* ((nargs 8)
  111. (frame (make-frame #f ; no parent
  112. #f ; no name
  113. nargs ; args on stack
  114. #t ; keep template
  115. #f ; drop environment
  116. #f))) ; drop closure
  117. (append-templates inits
  118. nargs
  119. frame
  120. (sequentially
  121. (template-call resumer
  122. (+ nargs 1) ; args + template
  123. frame
  124. (fall-through-cont #f #f))
  125. (instruction (enum op pop-n) 0 1) ; remove template
  126. (instruction (enum op tail-call) nargs 0 0)))))
  127. ; Return a template that accepts NARGS arguments, invokes TEMPLATES in turn,
  128. ; and then calls template FINAL on the arguments.
  129. (define (append-templates templates nargs frame final)
  130. (segment->template
  131. (sequentially
  132. (lambda-protocol nargs #t #f #f) ; push template
  133. (reduce (lambda (template seg)
  134. (sequentially
  135. (template-call template
  136. (+ nargs 1) ; arguments + template
  137. frame
  138. an-ignore-values-cont)
  139. seg))
  140. final
  141. templates))
  142. frame))
  143. (define an-ignore-values-cont (ignore-values-cont #f #f))