File: sort.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 (116 lines) | stat: -rw-r--r-- 3,347 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
; Part of Scheme 48 1.9.  See file COPYING for notices and license.

; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber

; Topological sort on forms.

; Puts top-level forms in the following order:
;
; (DEFINE X <literal>)
; (DEFINE Z (LAMBDA ...))
; ...everything else...
;
; Every (DEFINE W ...) for which W is never SET! is followed by all forms
; (DEFINE V W).
;
; The procedure definitions are topologically sorted; whenever possible no
; use of a variable occurs before its definition.
;
; This uses the FREE-VARIABLES field set by usage.scm.

(define (sort-forms nodes)
  (let ((table (make-name-table))
	(procs '())
	(literals '())
	(aliases '())
	(rest '()))
    (for-each (lambda (node)
		(let ((form (make-form node)))
		  (if (define-node? node)
		      (let ((name (node-form (cadr (node-form node))))
			    (value (caddr (node-form node))))
			(table-set! table name form)
			(cond ((lambda-node? value)
			       (set! procs (cons form procs)))
			      ((name-node? value)
			       (set! aliases (cons form aliases))
			       (set! rest (cons form rest)))
			      ((or (quote-node? value)
				   (literal-node? value))
			       (set! literals (cons form literals)))
			      (else
			       (set! rest (cons form rest)))))
		      (set! rest (cons form rest)))))
	      (reverse nodes))
    (for-each (lambda (form)
		(maybe-make-aliased form table))
	      aliases)
    (insert-aliases
     (append literals
	     (topologically-sort procs table)
	     (filter form-unaliased? rest)))))

(define (stuff-count s)
  (apply + (map (lambda (s) (length (cdr s))) s)))

; For (DEFINE A B) add the form to the list of B's aliases if B is defined
; in the current package and never SET!.

(define (maybe-make-aliased form table)
  (let* ((value (caddr (node-form (form-node form))))
	 (maker (table-ref table (node-form value))))
    (if (and (node-ref value 'binding)
	     maker
	     (= 0 (usage-assignment-count
		    (node-ref (cadr (node-form (form-node maker))) 'usage))))
	(begin
	  (set-form-aliases! maker (cons form (form-aliases maker)))
	  (set-form-unaliased?! form #f)))))

(define (topologically-sort forms table)
  (apply append
	 (strongly-connected-components
	   forms
	   (lambda (form)
	     (filter (lambda (f)
		       (and f
			    (lambda-node? (caddr (node-form (form-node f))))))
		     (map (lambda (name)
			    (table-ref table (node-form name)))
			  (form-free form))))
	   form-temp
	   set-form-temp!)))

(define-record-type form :form
  (really-make-form node free aliases unaliased?)
  form?
  (node form-node)
  (aliases form-aliases set-form-aliases!)
  (unaliased? form-unaliased? set-form-unaliased?!)
  (free form-free set-form-free!)
  (temp form-temp set-form-temp!))

(define-record-discloser :form
  (lambda (form)
    (list 'form
	  (let ((node (form-node form)))
	    (if (define-node? node)
		(node-form (cadr (node-form node)))
		node)))))

(define (make-form node)
  (really-make-form node
		    (map usage-name-node
			 (node-ref node 'free-variables))
		    '()		; aliases
		    #t))	; unaliased?

; (DEFINE A ...) is followed by all forms (DEFINE X A).

(define (insert-aliases forms)
  (let loop ((forms forms) (done '()))
    (if (null? forms)
	(reverse done)
	(let ((form (car forms)))
	  (loop (append (form-aliases form) (cdr forms))
		(cons (form-node form) done))))))