File: frame.scm

package info (click to toggle)
scheme48 1.9.2-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 18,232 kB
  • sloc: lisp: 88,907; ansic: 87,519; sh: 3,224; makefile: 771
file content (147 lines) | stat: -rw-r--r-- 4,730 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
; Part of Scheme 48 1.9.  See file COPYING for notices and license.

; Authors: Richard Kelsey, Jonathan Rees, Martin Gasbichler, Mike Sperber

; A frame contains information about a procedure's current stack frame.  It
; also has a list of the literals that will go in the procedure's template
; and the debugging data for the template.
;
; template-index - the location of this procedure's template in the frame
;                  (#f if the template is not needed)
; env-index      - the location of this procedure's environment in the frame
;                  (#f if the procedure does not use its environment)
; closure-index  - the location of this procedure's closure in the frame
;                  (#f if the closure is not needed)
; size		 - largest size reached by the frame, in descriptors
; literals	 - list of literals and bindings referenced
; count		 - length of LITERALS
; debug-data	 - debug information (see ddata.scm)

(define-record-type frame :frame
  (really-make-frame literals count debug-data template-index env-index closure-index size)
  frame?
  (template-index frame-template-index)
  (env-index      frame-env-index)
  (closure-index  frame-closure-index)
  (size           frame-size     set-frame-size!)
  (literals       frame-literals set-frame-literals!)
  (count	  frame-count    set-frame-count!)
  (debug-data     frame-debug-data))

; SIZE is the number of values on the stack when the procedure is
; entered (typically the number of arguments).  ENV? is true if the
; environment was pushed on after the arguments, TEMPLATE? is true if
; the template was pushed as well.  CLOSURE? is true if the closure
; was pushed as well.

(define (make-frame parent name size template? env? closure?)
  (let* ((ddata (new-debug-data (adjust-procedure-name name)
				(if parent
				    (frame-debug-data parent)
				    #f))))
    
    (define (allocate-index really?)
      (and really?
	   (let ((index size))
	     (set! size (+ 1 size))
	     index)))

    (let* ((closure-index (allocate-index closure?))
	   (env-index (allocate-index env?))
	   (template-index (allocate-index template?)))

      (really-make-frame '()
			 0
			 ddata
			 template-index env-index closure-index
			 size))))

(define (adjust-procedure-name name)
  (cond ((string? name)			; only files have strings for names
	 (if (keep-file-names?)
	     name
	     #f))
	((and (keep-procedure-names?)
	      (name? name))
	 (name->symbol name))
	(else
	 #f)))

; Convert an index, which is relative to the base of the frame, to an offset
; from the current stack pointer.

(define (index->offset index depth)
  (- depth (+ index 1)))

; Offsets for the template and environment.

(define (template-offset frame depth)
  (if (frame-template-index frame)
      (index->offset (frame-template-index frame)
                     depth)
      #f))

(define (environment-offset frame depth)
  (index->offset (frame-env-index frame)
		 depth))

; Note that FRAME reaches a size of DEPTH.

(define (depth-check! frame depth)
  (if (< (frame-size frame)
	 depth)
      (set-frame-size! frame depth)))

; These two procedures look up bindings and literals in the list of values
; to go in the template.  They're added if not already present.  The returned
; index is that of template, not the frame's list.

(define (binding->index frame binding name assigned?)
  (let loop ((i 0) (l (frame-literals frame)))
    (cond ((null? l)
	   (really-literal->index frame 
				  (make-thingie binding name assigned?)
				  #f))
	  ((and (thingie? (car l))
		(eq? binding (thingie-binding (car l)))
		(eq? name (thingie-name (car l))))
	   (if assigned?
	       (set-thingie-assigned?! (car l) #t))
	   (really-literal->index frame #f i))
	  (else
	   (loop (+ i 1) (cdr l))))))

(define (literal->index frame thing)
  (really-literal->index frame thing
			 (position thing (frame-literals frame))))

(define (really-literal->index frame thing probe)
  (let ((count (frame-count frame)))
    (if probe
	;; +++  Eliminate duplicate entries.
	;; Not necessary, just a modest space saver [how much?].
	;; Measurably slows down compilation.
	;; when 1 thing, lits = (x), count = 1, probe = 0, want 2
	(+ (- count probe)
	   (- template-overhead 1))
	(begin
	  (if (>= count two-byte-limit)
	      (assertion-violation 'literal->index
				   "compiler bug: too many literals"
				   thing))
	  (set-frame-literals! frame
			       (cons thing
				     (frame-literals frame)))
	  (set-frame-count! frame (+ count 1))
	  ;; when 1st thing, count = 0, want 2
	  (+ count template-overhead)))))

(define (position elt list)
  (let loop ((i 0) (l list))
    (cond ((null? l)
	   #f)
	  ((equal? elt (car l))
	   i)
	  (else
	   (loop (+ i 1) (cdr l))))))