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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; HOL 88 Version 2.0 ;;;
;;; ;;;
;;; FILE NAME: f-typeol.l ;;;
;;; ;;;
;;; DESCRIPTION: Checks types in quotations, and puts them into ;;;
;;; canonical form ;;;
;;; ;;;
;;; USES FILES: f-franz (or f-cl.l), f-constants.l, f-macro.l, ;;;
;;; f-ol-rec.l ;;;
;;; ;;;
;;; University of Cambridge ;;;
;;; Hardware Verification Group ;;;
;;; Computer Laboratory ;;;
;;; New Museums Site ;;;
;;; Pembroke Street ;;;
;;; Cambridge CB2 3QG ;;;
;;; England ;;;
;;; ;;;
;;; COPYRIGHT: University of Edinburgh ;;;
;;; COPYRIGHT: University of Cambridge ;;;
;;; COPYRIGHT: INRIA ;;;
;;; ;;;
;;; REVISION HISTORY: Original code: typeol (lisp 1.6) part of Edinburgh ;;;
;;; LCF by M. Gordon, R. Milner and C. Wadsworth (1978) ;;;
;;; Transported by G. Huet in Maclisp on Multics, Fall ;;;
;;; 1981 ;;;
;;; ;;;
;;; V2.2 : quotch and tyquotch rewritten using tag ;;;
;;; ;;;
;;; V4 : quotations redone, eliminating fexprs ;;;
;;; ;;;
;;; April 1987: all instances of "trunc" replaced by ;;;
;;; "hol-trunc" to prevent problems with redefining ;;;
;;; the system "trunc" -- J. Joyce ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(eval-when (compile)
#+franz (include "lisp/f-franz")
(include "lisp/f-constants")
(include "lisp/f-macro")
(include "lisp/f-ol-rec")
(special %term %sticky-types %linkcount %stickylist |%show_types-flag|
%canonlist |%type_error-flag| %tyvars |%sticky-flag|))
#+franz
(declare
(localf unifyb hol-trunc occb set-sticky use-sticky canon-quot-fm
canon-ty omutant1))
(setq %linkcount 0)
;;; generate a type link, an internal type variable for matching
;;; explicit type variables such as * are not matched
(defun genlink () (cons '%LINK (incf %linkcount))) ;genlink
;;; Unify two OL types for checking types in quotations
(defun unify (ty1 ty2) (unifyb (hol-trunc ty1) (hol-trunc ty2))) ;unify
;;; Unify "base types" -- no intervening %LINK nodes
(defun unifyb (bty1 bty2)
(and bty1
bty2
(cond
((eq bty1 bty2))
((is-linktype bty1) (if (occb bty1 bty2) nil (rplacd bty1 bty2)))
((is-linktype bty2) (if (occb bty2 bty1) nil (rplacd bty2 bty1)))
((is-vartype bty1) nil) ; since vartypes are eq
((is-vartype bty2) nil)
((and (eq (get-type-op bty1) (get-type-op bty2))
(forall 'unify (get-type-args bty1) (get-type-args bty2))))))
) ;unifyb
;;; skip past antiquotes and resolved links in a type
(defun hol-trunc (ty)
(cond ((and (is-linktype ty) (not (atom (cdr ty)))) (hol-trunc (cdr ty)))
((is-antiquot ty) (hol-trunc (cdr ty)))
(ty))) ;hol-trunc
;;; For unification : see if type variable v occurs in ty
(defun occ (v ty) (occb v (hol-trunc ty))) ;occ
(defun occb (v bty)
(or (eq v bty)
(case (type-class bty)
((%LINK %VARTYPE %ANTIQUOT) nil)
(t (exists #'(lambda (ty) (occ v ty)) (get-type-args bty)))))) ; occb
;;; set sticky types -- called after successful evaluation of a quotation
;;; Sets sticky types of all variables to their most recent type
;;; MJCG 13/11/88 for HOL88
;;; Record sticktypes in %sticky-types
(defun set-sticky (styl)
(mapc
#'(lambda (vty)
(let ((sty (q-mk_antiquot (cdr vty))))
(putprop (car vty) sty 'stickytype)
#+franz (putprop %sticky-types sty (car vty))
#-franz (setf (getf %sticky-types (car vty)) sty)))
styl)) ; set-sticky
;;; Apply sticky types to those variables whose type is still undefined
;;; In previous LCF, the sticky type was always used, requiring a hack
;;; in MK=TYPED to override it.
(defun use-sticky ()
(mapc #'(lambda (vty)
(let ((v (car vty)) (ty (hol-trunc (cdr vty))))
(if (eq (car ty) '%LINK)
(rplacd ty (get v 'stickytype)))))
%vtyl)) ; use-sticky
;;; Map canon-ty over all types of a formula (or term).
;;; Nodes from antiquotations are already in proper form.
;;; Retain sticky types of variables (but don't set yet)
(defun canon-quot-fm (fm)
(case (form-class fm)
(%ANTIQUOT (cdr fm))
(pred (make-pred-form (get-pred-sym fm) (canon-quot-tm (get-pred-arg fm))))
((conj disj imp) ; iff deleted [TFM 90.01.20]
(make-conn-form (get-conn fm)
(canon-quot-fm (get-left-form fm))
(canon-quot-fm (get-right-form fm))))
((forall exists)
(make-quant-form (get-quant fm)
(canon-quot-tm (get-quant-var fm))
(canon-quot-fm (get-quant-body fm))))
(t (canon-quot-tm fm))
)) ;canon-quot-fm
;;; MJCG 2/12/88 for HOL88
;;; Make %term a special variable useable for error messages.
;;; for terms only.
(defun canon-quot-tm (%term)
(case (term-class %term)
(%ANTIQUOT (cdr %term))
(comb
(make-comb (canon-quot-tm (get-rator %term))
(canon-quot-tm (get-rand %term))
(canon-ty (get-type %term))))
(abs
(make-abs (canon-quot-tm (get-abs-var %term))
(canon-quot-tm (get-abs-body %term))
(canon-ty (get-type %term))))
(var (let ((tok (get-var-name %term)) (ty (canon-ty(get-type %term))))
(push (cons tok ty) %stickylist) (mk_realvar tok ty)))
(const (ml-mk_const (get-const-name %term) (canon-ty(get-type %term))))
(t (lcferror 'canon-quot-tm))
)) ;canon-quot-tm
;;; MJCG 1/12/88 for HOL88
;;; Function for printing types indeterminate error messages
(defun print-indeterminate-error (tm)
(prog (save-flag)
(setq save-flag |%show_types-flag|)
(setq |%show_types-flag| t)
(ptoken "Indeterminate types:")
(pbreak 2 4)
(ml-print_term(prep-term-for-print tm))
(pnewline)
(pnewline)
(setq |%show_types-flag| save-flag)))
;;; Strip all links from a type, complain if any are still undefined.
;;; To prevent expanding the DAG of links into a tree (which is exponential),
;;; retain before/after pairs of types in %canonlist
;;; Types beginning with %ANTIQUOT are already in canonical form.
;;; MJCG 1/12/88 for HOL88
;;; Printer of error message added
;;; (defun canon-ty (ty)
;;; (cond ((assq1 ty %canonlist))
;;; ((case (type-class ty)
;;; (%ANTIQUOT (cdr ty))
;;; (%LINK (if (atom (cdr ty))
;;; (prog2 (if |%type_error-flag|
;;; (print-indeterminate-error %term))
;;; (throw-from evaluation "types indeterminate"))
;;; (canon-ty (cdr ty))))
;;; (%VARTYPE ty)
;;; (t (let ((cty (make-type (get-type-op ty)
;;; (mapcar #'canon-ty (get-type-args ty)))))
;;; (if (get-type-args ty) (push (cons ty cty) %canonlist))
;;; cty)))))
;;; ) ; canon-ty
;;; Optimized version from David Shepherd
;;; (optimization only works for Common Lisp)
;;; [DES] 9may91
;;; for lists push sticks 1 element on %canonlist for *each* list
;;; element even though all are identical which causes problems with
;;; list search funs like assq1 later!
;;; pushnew with equality test fast-list-equal only puts distinct
;;; elements on the list !
;;;
;;; (defun canon-ty (ty)
;;; (cond ((assq1 ty %canonlist))
;;; ((case (type-class ty)
;;; (%ANTIQUOT (cdr ty))
;;; (%LINK (if (atom (cdr ty))
;;; (prog2 (if |%type_error-flag|
;;; (print-indeterminate-error %term))
;;; (throw-from evaluation "types indeterminate"))
;;; (canon-ty (cdr ty))))
;;; (%VARTYPE ty)
;;; (t (let ((cty (make-type (get-type-op ty)
;;; (mapcar #'canon-ty (get-type-args ty)))))
;;; (if (get-type-args ty)
;;; #+franz (push (cons ty cty) %canonlist)
;;; #-franz (pushnew (cons ty cty) %canonlist :test 'fast-list-equal)
;;; )
;;; cty)))))
;;; ) ; canon-ty
;;; Another optimized version from David Shepherd
;;;
;;; the problem is that %canonlist introduces more complexity than it
;;; reduces. without it canon-izing a given type takes o(n) where n is the
;;; number of nodes in the type. if we save this in %canonlist then we also
;;; potentially have we have o(n) comparisons on each element of %canonlust
;;; to see if its there already and if it isn't something similar to put it
;;; into the list.
;;;
;;; i.e. the benefit (in number of calls) of not recursing down a type and
;;; getting the result out of %canonlist is similar to the number of extra
;;; calls used in checking the type against the keys in %canonlist in
;;; assq1. Since canon-ty does very little on each node then this call
;;; count is equivalent to speed.
;;;
;;; hence replace canon-ty with following code.
;;;
;;; on the term i was infuriated with it has reduced its retrieval from
;;; 120s to 3s and the maximum call count to 280,000 :-)
;;; the original version (before my mod of 9may91) took 350s and had a
;;; maximum call count of 120 million calls to EQL !
;;; naturally this fix will apply to all versions of lisp.
;;;
;;; [Installed by TFM, Feb 8 1992 for version 2.01]
(defun canon-ty (ty)
(case (type-class ty)
(%ANTIQUOT (cdr ty))
(%LINK (if (atom (cdr ty))
(prog2 (if |%type_error-flag|
(print-indeterminate-error %term))
(throw-from evaluation "types indeterminate"))
(canon-ty (cdr ty))))
(%VARTYPE ty)
(t (make-type (get-type-op ty)
(mapcar #'canon-ty (get-type-args ty))))
)
) ; canon-ty
;;; Convert all type variables to type links
(defun omutant (ty) (let ((%tyvars nil)) (omutant1 ty))) ;omutant
(defun omutant1 (ty)
(if (is-vartype ty)
(or (assq1 ty %tyvars)
(let ((newty (genlink))) (push (cons ty newty) %tyvars) newty))
(make-type (get-type-op ty)
(mapcar #'omutant1 (get-type-args ty)))
)) ;omutant1
;;; Functions called in ML object code
;;; Report errors found during evaluation of a quotation
;;; x is either a failure token or a list containing the quotation
(defun qtrap (x)
(if (atom x)
(throw-from evaluation (catenate x " in quotation")) (car x))
) ;qtrap
;;; clean up a quotation
;;; if quotation is OK then sets sticky types and returns a singleton list.
;;; MJCG 13/11/88 for HOL88
;;; stop sticktypes from being set if |%sticky-flag| is nil
;;; %sticky-types is a disembodied property list holding the sticky types
;;; of variables
(setq |%sticky-flag| nil)
(setq %sticky-types #+franz '(sticky-types) #-franz nil)
(defun quotation (qob)
(use-sticky)
(let ((%stickylist nil) (%canonlist nil))
(prog1 (list (canon-quot-fm qob))
(if |%sticky-flag| (set-sticky %stickylist))
))
) ; quotation
;;; MJCG 13/11/88 for HOL88
;;; ML functions for setting and removing sticky types
(defun ml-set_sticky_type (var ty)
(let ((sty (q-mk_antiquot ty)))
(putprop var sty 'stickytype)
#+franz (putprop %sticky-types sty var)
#-franz (setf (getf %sticky-types var) sty)
nil))
(dml |set_sticky_type|
2
ml-set_sticky_type
((|string| |#| |type|) |->| |void|))
(defun ml-remove_sticky_type (var)
(let ((ty (get var 'stickytype)))
(if ty
(prog1 (cdr ty) (remprop var 'stickytype)
#+franz (remprop %sticky-types var)
#-franz (remf %sticky-types var))
(failwith '|remove_sticky_type|))))
(dml |remove_sticky_type|
1
ml-remove_sticky_type
(|string| |->| |type|))
;;; Get list of sticky-types
(defun ml-sticky_list ()
(prog (temp res)
(setq temp
#+franz (cdr %sticky-types) #-franz %sticky-types)
(setq res nil)
loop (if (null temp) (return res))
(setq res (cons (cons (car temp) (cdadr temp)) res))
(setq temp (cddr temp))
(go loop)))
(dml |sticky_list|
0
ml-sticky_list
(|void| -> ((|string| |#| |type|) |list|)))
;;; Switch old stickytypes on
;;;(defun ml-sticky_types (x)
;;; (prog1 |%sticky-flag| (setq |%sticky-flag| x)))
;;;(dml |sticky_types|
;;; 1
;;; ml-sticky_types
;;; (|bool| -> |bool|))
;;; Convert a preterm to a term
(defun eval-preterm (pt)
(case (car pt)
(|preterm_var| (q-mk_var (cdr pt)))
(|preterm_const| (q-mk_const (cdr pt)))
(|preterm_comb|
(q-mk_comb
(eval-preterm(cadr pt))
(eval-preterm(cddr pt))))
(|preterm_abs|
(q-mk_abs
(eval-preterm(cadr pt))
(eval-preterm(cddr pt))))
(|preterm_typed|
(q-mk_typed
(eval-preterm(cadr pt))
(cddr pt)))
(|preterm_antiquot|
(q-mk_antiquot
(cdr pt)))
(t (failwith '|preterm_to_term|))))
(defun ml-preterm_to_term (pt)
(let ((%vtyl nil)(%sharetypes nil))
(car (quotation (eval-preterm pt)))))
(dml |preterm_to_term| 1 ml-preterm_to_term (|preterm| |->| |term|))
|