/usr/share/acl2-6.3/serialize.lisp is in acl2-source 6.3-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | ; ACL2 Version 6.3 -- A Computational Logic for Applicative Common Lisp
; Copyright (C) 2013, Regents of the University of Texas
; This version of ACL2 is a descendent of ACL2 Version 1.9, Copyright
; (C) 1997 Computational Logic, Inc. See the documentation topic NOTE-2-0.
; This program is free software; you can redistribute it and/or modify
; it under the terms of the LICENSE file distributed with ACL2.
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; LICENSE for more details.
; Regarding authorship of ACL2 in general:
; Written by: Matt Kaufmann and J Strother Moore
; email: Kaufmann@cs.utexas.edu and Moore@cs.utexas.edu
; Department of Computer Science
; University of Texas at Austin
; Austin, TX 78701 U.S.A.
; serialize.lisp -- logical definitions for "serialization" routines,
; i.e., saving ACL2 objects in files for later loading
; This file was developed and contributed by Jared Davis on behalf of
; Centaur Technology.
; Note: The serialization routines are restricted to work only in
; ACL2(h). However, they are independent of the remainder of the HONS
; extension and might some day become part of ordinary ACL2.
; Please direct correspondence about this file to Jared Davis
; <jared@centtech.com>.
(in-package "ACL2")
(defdoc serialize
":Doc-Section serialize
routines for saving ACL2 objects to files, and later restoring them~/
This documentation topic relates to an experimental extension of ACL2 that
supports ~ilc[hons], memoization, and fast alists. ~l[hons-and-memoization].
Thanks to Jared Davis for contributing the ``serialization'' routines for
saving ACL2 objects in files for later loading.
We implement some routines for writing arbitrary ACL2 objects to files, and for
loading those files later. We usually call these \".sao\" files, which stands
for (S)erialized (A)CL2 (O)bject.
Our serialization scheme uses a compact, binary format that preserves structure
sharing in the original object. We optimize for read performance.~/~/")
(defmacro serialize-write (filename obj &key verbosep)
":Doc-Section serialize
write an ACL2 object into a file~/
General form:
~bv[]
(serialize-write filename obj
[:verbosep {t, nil}]) ; nil by default
-->
state
~ev[]
In the logic this carries out an oracle read.
Under the hood, we try to save ~c[obj] into the file indicated by ~c[filename],
which must be a string. The object can later be recovered with
~ilc[serialize-read]. We just return ~c[state], and any failures (e.g., file
not openable) will result in a hard Lisp error.
Writing objects to disk is generally slower than reading them back in since
some analysis is required to convert an object into our ~il[serialize]d object
format.
The ~c[verbosep] flag just says whether to print some low-level details related
to timing and memory usage as the file is being read.~/~/"
`(serialize-write-fn ,filename ,obj ,verbosep state))
(defun serialize-write-fn (filename obj verbosep state)
(declare (xargs :guard (and (stringp filename)
(booleanp verbosep)
(state-p state))
:stobjs state)
(ignorable filename obj verbosep))
#-acl2-loop-only
(cond
((live-state-p state)
#-hons
(er hard? 'serialize-write-fn
"Serialization routines are currently only available in the HONS ~
version of ACL2.")
#+hons
(with-open-file
(stream filename
:direction :output
:if-exists :supersede)
(let* ((*ser-verbose* verbosep))
(ser-encode-to-stream obj stream)))
(return-from serialize-write-fn state))
(t
; We fall through to the logic code if we are doing a proof, where
; *hard-error-returns-nilp* is true. Otherwise, we throw here with an error
; message.
(er hard? 'serialize-write-fn "Serialization requires a live state.")))
(mv-let (erp val state)
(read-acl2-oracle state)
(declare (ignore erp val))
state))
(defmacro serialize-read (filename &key
(hons-mode ':smart)
verbosep)
":Doc-Section serialize
read a serialized ACL2 object from a file~/
General form:
~bv[]
(serialize-read filename
[:hons-mode {:always, :never, :smart}] ; :smart by default
[:verbosep {t, nil}]) ; nil by default
-->
(mv obj state)
~ev[]
In the logic this is an oracle read.
Under the hood, we try to read and return a serialized object from a file that
was presumably created by ~ilc[serialize-write]. On success we return the
contents of the file. Any failures (e.g., file not found, bad file contents,
etc.) will result in a hard Lisp error.
The ~c[filename] should be a string that gives the path to the file.
The ~c[hons-mode] controls how whether to use ~ilc[hons] or ~ilc[cons] to
restore the object. The default mode is ~c[:smart], which means that conses
that were ~il[normed] at the time of the file's creation should be restored
with ~c[hons]. But you can override this and insist that ~c[hons] is to
~c[:always] or ~c[:never] be used, instead.
Why would you use ~c[:never]? If your object previously had a lot of honses,
but you no longer have any need for them to be normed, then using ~c[:never]
may sometimes be a lot faster since it can avoid ~c[hons] calls. On the other
hand, if you are going to ~ilc[hons-copy] some part of the file's contents,
then it is likely faster to use ~c[:smart] or ~c[:always] instead of first
creating normal conses and then copying them to build honses.
The ~c[:verbosep] flag just controls whether to print some low-level details
related to timing and memory usage as the file is being read.~/~/"
`(serialize-read-fn ,filename ,hons-mode ,verbosep state))
(defun serialize-read-fn (filename hons-mode verbosep state)
(declare (xargs :guard (and (stringp filename)
(member hons-mode '(:never :always :smart))
(booleanp verbosep)
(state-p state))
:stobjs state)
(ignorable filename hons-mode verbosep))
#-acl2-loop-only
(cond
((live-state-p state)
(return-from
serialize-read-fn
#-hons
(progn (er hard? 'serialize-read-fn
"Serialization routines are currently only available in the ~
HONS version of ACL2.")
(mv nil state))
#+hons
(with-open-file
(stream filename :direction :input)
(let* ((*ser-verbose* verbosep)
(val (ser-decode-from-stream t hons-mode stream)))
(mv val state)))))
(t
; We fall through to the logic code if we are doing a proof, where
; *hard-error-returns-nilp* is true. Otherwise, we throw here with an error
; message.
(er hard? 'serialize-read-fn "Serialization requires a live state.")))
(mv-let (erp val state)
(read-acl2-oracle state)
(declare (ignore erp))
(mv val state)))
(defdoc serialize-alternatives
":Doc-Section serialize
alternatives to the ~il[serialize] routines~/
~il[Hons] users could previously use the routines ~c[compact-print-file] and
~c[compact-read-file]. These are deprecated and are no longer built into ACL2.
However, they are still available by loading the new community book,
~c[serialize/compact-print]. Note that loading this book requires a ttag, and
these routines are still only available in raw lisp.
Another predecessor of the serialization routines were hons archives, which are
still available in the ~c[hons-archive] library. The serialization routines
are generally better and we recommend against using hons archives for new
projects.~/~/")
(defdoc serialize-in-books
":Doc-Section serialize
using serialization efficiently in books~/
Our serialize scheme was developed in order to allow very large ACL2 objects to
be loaded into books. Ordinarily this is carried out using
~ilc[serialize-read] within a ~ilc[make-event], e.g.,
~bv[]
(make-event (mv-let (obj state)
(serialize-read \"my-file\")
(value `(defconst *my-file* ',obj))))
~ev[]
But this scheme is not particularly efficient.
During ~ilc[certify-book], the actual call of ~c[serialize-read] is carried
out, and this is typically pretty fast. But then a number of possibly
inefficient things occur.~bq[]
- The ACL2 function ~c[bad-lisp-object] is run on the resulting object. This
is memoized for efficiency, but may still take considerable time when the file
is very large.
- The checksum of the resulting object is computed. This is also memoized, but
as before may still take some time.
- The object that was just read is then written into book.cert, essentially
with ~ilc[serialize-write]. This can take some time, and results in large
certifiate files.~eq[]
Then, during ~il[include-book], the ~c[make-event] expansion of is loaded.
This is now basically just a ~c[serialize-read].
The moral of the story is that using serialize will only help your
~c[certify-book] time, and it only impacts a portion of the overall time.
To avoid this overhead, we have developed an UNSOUND alternative to
~c[serialize-read], which is available only by loading an additional book. So,
if the above scheme is not performing well for you, you may wish to see
the community book ~c[serialize/unsound-read].~/~/")
(defmacro with-serialize-character (val form)
(declare (xargs :guard (member val '(nil #\Y #\Z))))
":Doc-Section serialize
control output mode for ~c[print-object$]~/
This documentation topic relates to an experimental extension of ACL2 that
supports ~ilc[hons], memoization, and fast alists. ~l[hons-and-memoization].
~l[serialize] for a discussion of ``serialization'' routines, contributed by
Jared Davis for saving ACL2 objects in files for later loading.
The expression ~c[(with-serialize-character char form)] evaluates to the value
of ~c[form], but with the serialize-character of the ~ilc[state] assigned to
~c[char], which should be one of ~c[nil], ~c[#\\Y], or ~c[#\\Z]. We describe
the effect of that assignment below. But note that if you are doing this
because of one or more specific calls of ~c[print-object$], such as
~c[(print-object$ x channel state)], then you may wish instead to evaluate
~c[(print-object$-ser x serialize-character channel state)], in which case you
will not need to use ~c[with-serialize-character]. (Note however that
~c[serialize-character] is treated as ~c[nil] for other than a HONS version.)
~bv[]
General forms:
(with-serialize-character nil form)
(with-serialize-character #\Y form)
(with-serialize-character #\Z form)
~ev[]
where ~c[form] should evaluate to an error triple (~pl[error-triples]).
Note that if you prefer to obtain the same behavior (as described below)
globally, rather than only within the scope of ~c[with-serialize-character],
then use ~c[set-serialize-character] in a corresponding manner:
~bv[]
(set-serialize-character nil state)
(set-serialize-character #\Y state)
(set-serialize-character #\Z state)
~ev[]
In each case above, calls of ~c[print-object$] (~pl[io]) in ~c[form] will
produce an object that can be read by the HONS version of ACL2. In the first
case, that object is printed as one might expect at the terminal, as an
ordinary Lisp s-expression. But in the other cases, the object is printed by
first laying down either ~c[#Y] or ~c[#Z] (as indicated) and then calling
~ilc[serialize-write] (or more precisely, the underlying function called by
~c[serialize-write] that prints to a stream).
Consider what happens when the ACL2 reader encounters an object produced as
described above (in the ~c[#Y] or ~c[#Z] case). When the object was written,
information was recorded on whether that object was a ~il[hons]. In the case
of ~c[#Z], the object will be read as a hons if and only if it was originally
written as a hons. But in the case of ~c[#Y], it will never be read as a hons.
Thus, ~c[#Y] and ~c[#Z] will behave the same if the original written object was
not a hons, creating an object that is not a hons. For an equivalent
explanation and a bit more discussion, ~pl[serialize-read], in particular the
discussion of the hons-mode. The value ~c[:smart] described there corresponds
to ~c[#Z], while ~c[:never] corresponds to ~c[#Y].~/~/"
`(state-global-let*
((serialize-character ,val set-serialize-character))
,form))
|