22
22
# :optimize-bindings)
23
23
(:local-nicknames
24
24
(# :util # :coalton-impl/util)
25
+ (# :parser # :coalton-impl/parser)
25
26
(# :settings # :coalton-impl/settings)
26
27
(# :global-lexical # :coalton-impl/global-lexical)
27
28
(# :rt # :coalton-impl/runtime)
@@ -41,41 +42,104 @@ A function bound here will be called with a keyword category, and one or more ad
41
42
42
43
Toplevel definitions, after type checking and before compilation." )
43
44
45
+ ; ; The following functions control the output order of compiled
46
+ ; ; definitions and interleaved lisp expressions.
47
+ ; ;
48
+ ; ; Toplevel define and instance forms are compiled to 1 or more named,
49
+ ; ; lisp-source-valued output definitions: when these definitions are
50
+ ; ; generated, they are associated with the starting source offset of their
51
+ ; ; toplevel form:
52
+ ; ;
53
+ ; ; toplevel definition:
54
+ ; ; #<def .... (300 . 345)>
55
+ ; ;
56
+ ; ; bindings (lisp definitions):
57
+ ; ; (300 b1 .. bn)
58
+ ; ;
59
+ ; ; Then when compile-definitions emits the full set of output
60
+ ; ; definitions, any lisp source forms that occurred earlier in the
61
+ ; ; file are emitted first.
62
+
63
+ (defun bindings-offset (bindings offsets)
64
+ " Given a list of binding names, and a name -> offset map, return the earliest binding start offset."
65
+ (apply #' min
66
+ (mapcar (lambda (binding)
67
+ (or (gethash (car binding) offsets) 0 ))
68
+ bindings)))
69
+
70
+ (defun merge-forms (forms-a forms-b &optional merged)
71
+ " Stably merge two lists of forms.
72
+
73
+ 1. The inputs and output are lists of 2-lists, structured as (OFFSET FORM).
74
+ 2. The order of both lists is preserved.
75
+ 3. Lists are merged by recursively selecting the head of the list with the lowest offset."
76
+ (cond ((endp forms-a)
77
+ (return-from merge-forms
78
+ (append (nreverse merged) forms-b)))
79
+ ((endp forms-b)
80
+ (return-from merge-forms
81
+ (append (nreverse merged) forms-a)))
82
+ ((< (caar forms-a)
83
+ (caar forms-b))
84
+ (push (pop forms-a) merged))
85
+ (t
86
+ (push (pop forms-b) merged)))
87
+ (merge-forms forms-a forms-b merged))
88
+
89
+ (defun compile-definitions (sccs definitions lisp-forms offsets env)
90
+ " Compile SCCs and generate a final output definition list, merging any present lisp sources."
91
+ (let ((bindings (loop :for scc :in sccs
92
+ :for bindings := (remove-if-not (lambda (binding)
93
+ (find (car binding) scc))
94
+ definitions)
95
+ :collect (cons (bindings-offset bindings offsets)
96
+ (compile-scc bindings env))))
97
+ (lisp-forms (mapcar (lambda (lisp-form)
98
+ (cons (car (parser :toplevel-lisp-form-source lisp-form))
99
+ (parser :toplevel-lisp-form-body lisp-form)))
100
+ lisp-forms)))
101
+ (mapcan #' cdr (merge-forms bindings lisp-forms))))
102
+
103
+ (defun definition-bindings (definitions env offsets)
104
+ (loop :for define :in definitions
105
+ :for offset := (car (tc :toplevel-define-source define))
106
+ :for name := (tc :node-variable-name (tc :toplevel-define-name define))
107
+ :for compiled-node := (translate-toplevel define env)
108
+
109
+ :when *codegen-hook*
110
+ :do (funcall *codegen-hook* :ast
111
+ name
112
+ (tc :lookup-value-type env name)
113
+ (tc :binding-value define))
114
+
115
+ :collect (cons name compiled-node)))
116
+
117
+ (defun instance-bindings (instances env offsets)
118
+ (loop :for instance :in instances
119
+ :for offset := (car (tc :toplevel-define-instance-source instance))
120
+ :for instance-bindings := (translate-instance instance env)
121
+
122
+ :do (dolist (binding instance-bindings)
123
+ (setf (gethash (car binding) offsets) offset))
124
+ :append instance-bindings))
125
+
44
126
(defun compile-translation-unit (translation-unit monomorphize-table env)
45
127
(declare (type tc :translation-unit translation-unit)
46
128
(type hash-table monomorphize-table)
47
129
(type tc :environment env))
48
130
49
- (let* ((definitions
131
+ (let* ((offsets (make-hash-table ))
132
+ (definitions
50
133
(append
51
- (loop :for define :in (tc :translation-unit-definitions translation-unit)
52
- :for name := (tc :node-variable-name (tc :toplevel-define-name define))
53
-
54
- :for compiled-node := (translate-toplevel define env)
55
-
56
- :do (when *codegen-hook*
57
- (funcall *codegen-hook*
58
- ' :AST
59
- name
60
- (tc :lookup-value-type env name)
61
- (tc :binding-value define)))
62
- :collect (cons name compiled-node))
63
-
64
- ; ; HACK: this load bearing reverse should be replaced with an actual solution
65
- (loop :for instance :in (reverse (tc :translation-unit-instances translation-unit))
66
- :append (translate-instance instance env))))
67
-
68
- (definition-names
69
- (mapcar #' car definitions)))
134
+ (definition-bindings (tc :translation-unit-definitions translation-unit) env offsets)
135
+ (instance-bindings (tc :translation-unit-instances translation-unit) env offsets)))
136
+ (definition-names (mapcar #' car definitions)))
70
137
71
138
(multiple-value-bind (definitions env)
72
- (optimize-bindings
73
- definitions
74
- monomorphize-table
75
- *package*
76
- env)
139
+ (optimize-bindings definitions monomorphize-table *package* env)
77
140
78
- (let ((sccs (node-binding-sccs definitions)))
141
+ (let ((sccs (node-binding-sccs definitions))
142
+ (lisp-forms (tc :translation-unit-lisp-forms translation-unit)))
79
143
80
144
(values
81
145
` (progn
@@ -102,13 +166,7 @@ A function bound here will be called with a keyword category, and one or more ad
102
166
(list
103
167
` (declaim (sb-ext :start-block ,@ definition-names))))
104
168
105
- ,@ (loop :for scc :in sccs
106
- :for bindings
107
- := (remove-if-not
108
- (lambda (binding)
109
- (find (car binding) scc))
110
- definitions)
111
- :append (compile-scc bindings env))
169
+ ,@ (compile-definitions sccs definitions lisp-forms offsets env)
112
170
113
171
#+ sbcl
114
172
,@ (when (eq sb-ext :*block-compile-default* :specified )
0 commit comments