@@ -102,7 +102,13 @@ USE-FUNCTION-ENTRIES specifies whether to emit FUNCTION-ENTRY for functions, emi
102
102
(if (typep to ' tyvar)
103
103
` (cl :simple-array cl :* (cl :*))
104
104
` (cl :simple-array , (lisp-type to env) (cl :*))))
105
-
105
+
106
+ ; ; When FROM is a transparent type, and we got a specialized type,
107
+ ; ; we propagate parameterization to the inner type.
108
+ ((and (not (typep to ' tyvar))
109
+ (try-recurse-transparent-type from to env)))
110
+
111
+
106
112
; ; Otherwise we fall back.
107
113
(t
108
114
(lisp-type (tapp-from ty) env)))))
@@ -124,3 +130,51 @@ USE-FUNCTION-ENTRIES specifies whether to emit FUNCTION-ENTRY for functions, emi
124
130
(:method ((ty qualified-ty) env)
125
131
(lisp-type (qualified-ty-type ty) env)))
126
132
133
+
134
+ (defun try-recurse-transparent-type (from parameter env)
135
+ " Called when taking a lisp-type of a parameterized type, where a
136
+ concrete type is given to the parameter. For example, a type `(Foo
137
+ :t)` is defined, and we try to take a lisp-type of `(Foo UFix)`. The
138
+ `FROM` argument gets the type `Foo` and the `parameter` argument gets
139
+ the type `UFix`.
140
+
141
+ There is a special opportunity of optimization when `Foo` is defined
142
+ as a transparent type, e.g. `(repr :transparent) (define-type (Foo
143
+ :t) (Content (Lisparray :t)))`. In that case, `(Foo UFix)` can have a
144
+ Lisp type `(cl:simple-array cl:fixnum)`, which allows Lisp compiler to
145
+ optimize further. We check the conditions and returns a specialized
146
+ Lisp type if possible.
147
+
148
+ If we can't get a specialized Lisp type, this returns nil, and let the
149
+ fallback branch take care of it.
150
+ "
151
+ (labels ((transparent-type? (from)
152
+ (alexandria :when-let (entry (lookup-type env from :no-error t ))
153
+ (eq (type-entry-explicit-repr entry) ' :transparent)))
154
+ (reveal-underlying-type (from)
155
+ " If `from` type satisfies the optimizable condition, returns two
156
+ values: the 'inner' type (wrappee type) and the 'outer' type (wrapper
157
+ type)."
158
+ (let ((v (lookup-value-type env from :no-error t )))
159
+ (when (typep v ' ty-scheme)
160
+ (let ((qt (qualified-ty-type (ty-scheme-type v))))
161
+ ; ; In transparent types, we have this in QT.
162
+ ; ; (Arrow <innter-type>) -> <outer-type>
163
+ (when (function-type-p qt)
164
+ (values (function-type-from qt)
165
+ (function-type-to qt))))))))
166
+ (and (transparent-type? from)
167
+ (multiple-value-bind (inner outer) (reveal-underlying-type from)
168
+ (cond ((and (typep inner ' tycon)
169
+ (typep outer ' tycon))
170
+ (lisp-type inner env))
171
+ ((and (typep inner ' tapp)
172
+ (typep outer ' tapp)
173
+ (typep (tapp-to inner) ' tgen)
174
+ (eq (tapp-to inner) (tapp-to outer)))
175
+ ; ; Substitute inner type's type variable with the
176
+ ; ; concrete type
177
+ (lisp-type (make-tapp :from (tapp-from inner)
178
+ :to parameter)
179
+ env))
180
+ (t nil ))))))
0 commit comments