aboutsummaryrefslogtreecommitdiff
path: root/src/interp/daase.lisp.pamphlet
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp/daase.lisp.pamphlet')
-rw-r--r--src/interp/daase.lisp.pamphlet2043
1 files changed, 2043 insertions, 0 deletions
diff --git a/src/interp/daase.lisp.pamphlet b/src/interp/daase.lisp.pamphlet
new file mode 100644
index 00000000..e5de9ba5
--- /dev/null
+++ b/src/interp/daase.lisp.pamphlet
@@ -0,0 +1,2043 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/interp daase.lisp}
+\author{Timothy Daly}
+\maketitle
+\begin{abstract}
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+\section{Database structure}
+In order to understand this program you need to understand some details
+of the structure of the databases it reads. Axiom has 5 databases,
+the interp.daase, operation.daase, category.daase, compress.daase, and
+browse.daase. The compress.daase is special and does not follow the
+normal database format.
+
+\subsection{KAF File Format}
+This documentation refers to KAF files which are random access files.
+NRLIB files are KAF files (look for NRLIB/index.KAF)
+The format of a random access file is
+\begin{verbatim}
+byte-offset-of-key-table
+first-entry
+second-entry
+...
+last-entry
+((key1 . first-entry-byte-address)
+ (key2 . second-entry-byte-address)
+ ...
+ (keyN . last-entry-byte-address))
+\end{verbatim}
+The key table is a standard lisp alist.
+
+To open a database you fetch the first number, seek to that location,
+and (read) which returns the key-data alist. To look up data you
+index into the key-data alist, find the ith-entry-byte-address,
+seek to that address, and (read).
+
+For instance, see src/share/algebra/USERS.DAASE/index.KAF
+
+One existing optimization is that if the data is a simple thing like a
+symbol then the nth-entry-byte-address is replaced by immediate data.
+
+Another existing one is a compression algorithm applied to the
+data so that the very long names don't take up so much space.
+We could probably remove the compression algorithm as 64k is no
+longer considered 'huge'. The database-abbreviation routine
+handles this on read and write-compress handles this on write.
+The squeeze routine is used to compress the keys, the unsqueeze
+routine uncompresses them. Making these two routines disappear
+should remove all of the compression.
+
+Indeed, a faster optimization is to simply read the whole database
+into the image before it is saved. The system would be easier to
+understand and the interpreter would be faster.
+
+The system uses another optimization: database contains a stamp
+(consisting of offset to the main list and build time). Before
+saving the image selected data is fetched to memory. When the
+saved image starts it checks if the stamp of saved data matches
+in-core data -- in case of agreement in-core data is used.
+Parts of the datatabase which was not pre-loaded is still
+(lazily) fetched from the filesystem.
+
+\subsection{Database Files}
+
+Database files are very similar to KAF files except that there
+is an optimization (currently broken) which makes the first
+item a pair of two numbers. The first number in the pair is
+the offset of the key-value table, the second is a time stamp.
+If the time stamp in the database matches the time stamp in
+the image the database is not needed (since the internal hash
+tables already contain all of the information). When the database
+is built the time stamp is saved in both the gcl image and the
+database.
+
+\section{License}
+<<license>>=
+;; Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+;; All rights reserved.
+;;
+;; Redistribution and use in source and binary forms, with or without
+;; modification, are permitted provided that the following conditions are
+;; met:
+;;
+;; - Redistributions of source code must retain the above copyright
+;; notice, this list of conditions and the following disclaimer.
+;;
+;; - Redistributions in binary form must reproduce the above copyright
+;; notice, this list of conditions and the following disclaimer in
+;; the documentation and/or other materials provided with the
+;; distribution.
+;;
+;; - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+;; names of its contributors may be used to endorse or promote products
+;; derived from this software without specific prior written permission.
+;;
+;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+;; IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+;; TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+;; PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+;; OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+;; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+;; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+@
+<<*>>=
+<<license>>
+
+;;TTT 7/2/97
+; Regarding the 'ancestors field for a category: At database build
+; time there exists a *ancestors-hash* hash table that gets filled
+; with CATEGORY (not domain) ancestor information. This later provides
+; the information that goes into interp.daase This *ancestors-hash*
+; does not exist at normal runtime (it can be made by a call to
+; genCategoryTable). Note that the ancestor information in
+; *ancestors-hash* (and hence interp.daase) involves #1, #2, etc
+; instead of R, Coef, etc. The latter thingies appear in all
+; .NRLIB/index.KAF files. So we need to be careful when we )lib
+; categories and update the ancestor info.
+
+
+; This file contains the code to build, open and access the .DAASE
+; files this file contains the code to )library NRLIBS and asy files
+
+; There is a major issue about the data that resides in these
+; databases. the fundamental problem is that the system requires more
+; information to build the databases than it needs to run the
+; interpreter. in particular, MODEMAP.DAASE is constructed using
+; properties like "modemaps" but the interpreter will never ask for
+; this information.
+
+; So, the design is as follows:
+; first, the MODEMAP.DAASE needs to be built. this is done by doing
+; a )library on ALL of the NRLIB files that are going into the system.
+; this will bring in "modemap" information and add it to the
+; *modemaps-hash* hashtable.
+; next, database build proceeds, accessing the "modemap" property
+; from the hashtables. once this completes this information is never
+; used again.
+; next, the interp.daase database is built. this contains only the
+; information necessary to run the interpreter. note that during the
+; running of the interpreter users can extend the system by do a
+; )library on a new NRLIB file. this will cause fields such as "modemap"
+; to be read and hashed.
+
+; In the old system each constructor (e.g. LIST) had one library directory
+; (e.g. LIST.NRLIB). this directory contained a random access file called
+; the index.KAF file. the interpreter needed this KAF file at runtime for
+; two entries, the operationAlist and the ConstructorModemap.
+; during the redesign for the new compiler we decided to merge all of
+; these .NRLIB/index.KAF files into one database, INTERP.DAASE.
+; requests to get information from this database are intended to be
+; cached so that multiple references do not cause additional disk i/o.
+; this database is left open at all times as it is used frequently by
+; the interpreter. one minor complication is that newly compiled files
+; need to override information that exists in this database.
+; The design calls for constructing a random read (KAF format) file
+; that is accessed by functions that cache their results. when the
+; database is opened the list of constructor-index pairs is hashed
+; by constructor name. a request for information about a constructor
+; causes the information to replace the index in the hash table. since
+; the index is a number and the data is a non-numeric sexpr there is
+; no source of confusion about when the data needs to be read.
+;
+; The format of this new database is as follows:
+;
+;first entry:
+; an integer giving the byte offset to the constructor alist
+; at the bottom of the file
+;second and subsequent entries (one per constructor)
+; (operationAlist)
+; (constructorModemap)
+; ....
+;last entry: (pointed at by the first entry)
+; an alist of (constructor . index) e.g.
+; ( (PI offset-of-operationAlist offset-of-constructorModemap)
+; (NNI offset-of-operationAlist offset-of-constructorModemap)
+; ....)
+; This list is read at open time and hashed by the car of each item.
+
+; the system has been changed to use the property list of the
+; symbols rather than hash tables. since we already hashed once
+; to get the symbol we need only an offset to get the property
+; list. this also has the advantage that eq hash tables no longer
+; need to be moved during garbage collection.
+; there are 3 potential speedups that could be done. the best
+; would be to use the value cell of the symbol rather than the
+; property list but i'm unable to determine all uses of the
+; value cell at the present time.
+; a second speedup is to guarantee that the property list is
+; a single item, namely the database structure. this removes
+; an assoc but leaves one open to breaking the system if someone
+; adds something to the property list. this was not done because
+; of the danger mentioned.
+; a third speedup is to make the getdatabase call go away, either
+; by making it a macro or eliding it entirely. this was not done
+; because we want to keep the flexibility of changing the database
+; forms.
+
+; the new design does not use hash tables. the database structure
+; contains an entry for each item that used to be in a hash table.
+; initially the structure contains file-position pointers and
+; these are replaced by real data when they are first looked up.
+; the database structure is kept on the property list of the
+; constructor, thus, (get '|DenavitHartenbergMatrix| 'database)
+; will return the database structure object.
+
+; each operation has a property on its symbol name called 'operation
+; which is a list of all of the signatures of operations with that name.
+
+; -- tim daly
+
+(in-package "BOOT")
+
+(defstruct database
+ abbreviation ; interp.
+ ancestors ; interp.
+ constructor ; interp.
+ constructorcategory ; interp.
+ constructorkind ; interp.
+ constructormodemap ; interp.
+ cosig ; interp.
+ defaultdomain ; interp.
+ modemaps ; interp.
+ niladic ; interp.
+ object ; interp.
+ operationalist ; interp.
+ documentation ; browse.
+ constructorform ; browse.
+ attributes ; browse.
+ predicates ; browse.
+ sourcefile ; browse.
+ parents ; browse.
+ users ; browse.
+ dependents ; browse.
+ spare ; superstition
+ ) ; database structure
+
+; there are only a small number of domains that have default domains.
+; rather than keep this slot in every domain we maintain a list here.
+
+(defvar *defaultdomain-list* '(
+ (|MultisetAggregate| |Multiset|)
+ (|FunctionSpace| |Expression|)
+ (|AlgebraicallyClosedFunctionSpace| |Expression|)
+ (|ThreeSpaceCategory| |ThreeSpace|)
+ (|DequeueAggregate| |Dequeue|)
+ (|ComplexCategory| |Complex|)
+ (|LazyStreamAggregate| |Stream|)
+ (|AssociationListAggregate| |AssociationList|)
+ (|QuaternionCategory| |Quaternion|)
+ (|PriorityQueueAggregate| |Heap|)
+ (|PointCategory| |Point|)
+ (|PlottableSpaceCurveCategory| |Plot3D|)
+ (|PermutationCategory| |Permutation|)
+ (|StringCategory| |String|)
+ (|FileNameCategory| |FileName|)
+ (|OctonionCategory| |Octonion|)))
+
+; this hash table is used to answer the question "does domain x
+; have category y?". this is answered by constructing a pair of
+; (x . y) and doing an equal hash into this table.
+
+(defvar *operation-hash* nil "given an operation name, what are its modemaps?")
+(defvar *hasCategory-hash* nil "answers x has y category questions")
+
+(defvar *miss* nil "print out cache misses on getdatabase calls")
+
+ ; note that constructorcategory information need only be kept for
+ ; items of type category. this will be fixed in the next iteration
+ ; when the need for the various caches are reviewed
+
+ ; note that the *modemaps-hash* information does not need to be kept
+ ; for system files. these are precomputed and kept in modemap.daase
+ ; however, for user-defined files these are needed.
+ ; currently these are added to the database for 2 reasons:
+ ; there is a still-unresolved issue of user database extensions
+ ; this information is used during database build time
+
+
+
+; this are the streams for the databases. they are always open.
+; there is an optimization for speeding up system startup. if the
+; database is opened and the ..-stream-stamp* variable matches the
+; position information in the database then the database is NOT
+; read in and is assumed to match the in-core version
+
+(defvar *compressvector* nil "a vector of things to compress in the databases")
+(defvar *compressVectorLength* 0 "length of the compress vector")
+(defvar *compress-stream* nil "an stream containing the compress vector")
+(defvar *compress-stream-stamp* 0 "*compress-stream* (position . time)")
+
+(defvar *interp-stream* nil "an open stream to the interpreter database")
+(defvar *interp-stream-stamp* 0 "*interp-stream* (position . time)")
+
+; this is indexed by operation, not constructor
+(defvar *operation-stream* nil "the stream to operation.daase")
+(defvar *operation-stream-stamp* 0 "*operation-stream* (position . time)")
+
+(defvar *browse-stream* nil "an open stream to the browser database")
+(defvar *browse-stream-stamp* 0 "*browse-stream* (position . time)")
+
+; this is indexed by (domain . category)
+(defvar *category-stream* nil "an open stream to the category table")
+(defvar *category-stream-stamp* 0 "*category-stream* (position . time)")
+
+(defvar *allconstructors* nil "a list of all the constructors in the system")
+(defvar *allOperations* nil "a list of all the operations in the system")
+
+(defvar *asharpflags* "-O -laxiom -Fasy -Flsp" "library compiler flags")
+
+(defun asharp (file &optional (flags *asharpflags*))
+ "call the asharp compiler"
+ (system::system
+ (concatenate 'string (|getEnv| "AXIOM") "/compiler/bin/axiomxl "
+ flags " " file)))
+
+(defun resethashtables ()
+ "set all -hash* to clean values. used to clean up core before saving system"
+ (setq *hascategory-hash* (make-hash-table :test #'equal))
+ (setq *operation-hash* (make-hash-table))
+ (setq *allconstructors* nil)
+ (setq *compressvector* nil)
+ (setq *compress-stream-stamp* '(0 . 0))
+ (compressopen)
+ (setq *interp-stream-stamp* '(0 . 0))
+ (interpopen)
+ (setq *operation-stream-stamp* '(0 . 0))
+ (operationopen)
+ (setq *browse-stream-stamp* '(0 . 0))
+ (browseopen)
+ (setq *category-stream-stamp* '(0 . 0))
+ (categoryopen) ;note: this depends on constructorform in browse.daase
+#-:CCL (initial-getdatabase)
+ (close *interp-stream*)
+ (close *operation-stream*)
+ (close *category-stream*)
+ (close *browse-stream*)
+#+:AKCL (gbc t)
+)
+
+(defun initial-getdatabase ()
+ "fetch data we want in the saved system"
+ (let (hascategory constructormodemapAndoperationalist operation constr)
+ (format t "Initial getdatabase~%")
+ (setq hascategory '(
+ (|Equation| . |Ring|)
+ (|Expression| . |CoercibleTo|) (|Expression| . |CommutativeRing|)
+ (|Expression| . |IntegralDomain|) (|Expression| . |Ring|)
+ (|Float| . |RetractableTo|)
+ (|Fraction| . |Algebra|) (|Fraction| . |CoercibleTo|)
+ (|Fraction| . |OrderedSet|) (|Fraction| . |RetractableTo|)
+ (|Integer| . |Algebra|) (|Integer| . |CoercibleTo|)
+ (|Integer| . |ConvertibleTo|) (|Integer| . |LinearlyExplicitRingOver|)
+ (|Integer| . |RetractableTo|)
+ (|List| . |CoercibleTo|) (|List| . |FiniteLinearAggregate|)
+ (|List| . |OrderedSet|)
+ (|Polynomial| . |CoercibleTo|) (|Polynomial| . |CommutativeRing|)
+ (|Polynomial| . |ConvertibleTo|) (|Polynomial| . |OrderedSet|)
+ (|Polynomial| . |RetractableTo|)
+ (|Symbol| . |CoercibleTo|) (|Symbol| . |ConvertibleTo|)
+ (|Variable| . |CoercibleTo|)))
+ (dolist (pair hascategory) (getdatabase pair 'hascategory))
+ (setq constructormodemapAndoperationalist '(
+ |BasicOperator| |Boolean|
+ |CardinalNumber| |Color| |Complex|
+ |Database|
+ |Equation| |EquationFunctions2| |Expression|
+ |Float| |Fraction| |FractionFunctions2|
+ |Integer| |IntegralDomain|
+ |Kernel|
+ |List|
+ |Matrix| |MappingPackage1|
+ |Operator| |OutputForm|
+ |NonNegativeInteger|
+ |ParametricPlaneCurve| |ParametricSpaceCurve| |Point| |Polynomial|
+ |PolynomialFunctions2| |PositiveInteger|
+ |Ring|
+ |SetCategory| |SegmentBinding| |SegmentBindingFunctions2| |DoubleFloat|
+ |SparseMultivariatePolynomial| |SparseUnivariatePolynomial| |Segment|
+ |String| |Symbol|
+ |UniversalSegment|
+ |Variable| |Vector|))
+ (dolist (con constructormodemapAndoperationalist)
+ (getdatabase con 'constructormodemap)
+ (getdatabase con 'operationalist))
+ (setq operation '(
+ |+| |-| |*| |/| |**| |coerce| |convert| |elt| |equation|
+ |float| |sin| |cos| |map| |SEGMENT|))
+ (dolist (op operation) (getdatabase op 'operation))
+ (setq constr '( ;these are sorted least-to-most freq. delete early ones first
+ |Factored| |SparseUnivariatePolynomialFunctions2| |TableAggregate&|
+ |RetractableTo&| |RecursiveAggregate&| |UserDefinedPartialOrdering|
+ |None| |UnivariatePolynomialCategoryFunctions2| |IntegerPrimesPackage|
+ |SetCategory&| |IndexedExponents| |QuotientFieldCategory&| |Polynomial|
+ |EltableAggregate&| |PartialDifferentialRing&| |Set|
+ |UnivariatePolynomialCategory&| |FlexibleArray|
+ |SparseMultivariatePolynomial| |PolynomialCategory&|
+ |DifferentialExtension&| |IndexedFlexibleArray| |AbelianMonoidRing&|
+ |FiniteAbelianMonoidRing&| |DivisionRing&| |FullyLinearlyExplicitRingOver&|
+ |IndexedVector| |IndexedOneDimensionalArray| |LocalAlgebra| |Localize|
+ |Boolean| |Field&| |Vector| |IndexedDirectProductObject| |Aggregate&|
+ |PolynomialRing| |FreeModule| |IndexedDirectProductAbelianGroup|
+ |IndexedDirectProductAbelianMonoid| |SingletonAsOrderedSet|
+ |SparseUnivariatePolynomial| |Fraction| |Collection&| |HomogeneousAggregate&|
+ |RepeatedSquaring| |IntegerNumberSystem&| |AbelianSemiGroup&|
+ |AssociationList| |OrderedRing&| |SemiGroup&| |Symbol|
+ |UniqueFactorizationDomain&| |EuclideanDomain&| |IndexedAggregate&|
+ |GcdDomain&| |IntegralDomain&| |DifferentialRing&| |Monoid&| |Reference|
+ |UnaryRecursiveAggregate&| |OrderedSet&| |AbelianGroup&| |Algebra&|
+ |Module&| |Ring&| |StringAggregate&| |AbelianMonoid&|
+ |ExtensibleLinearAggregate&| |PositiveInteger| |StreamAggregate&|
+ |IndexedString| |IndexedList| |ListAggregate&| |LinearAggregate&|
+ |Character| |String| |NonNegativeInteger| |SingleInteger|
+ |OneDimensionalArrayAggregate&| |FiniteLinearAggregate&| |PrimitiveArray|
+ |Integer| |List| |OutputForm|))
+ (dolist (con constr)
+ (let ((c (concatenate 'string
+ (|getEnv| "AXIOM") "/algebra/"
+ (string (getdatabase con 'abbreviation)) ".o")))
+ (format t " preloading ~a.." c)
+ (if (probe-file c)
+ (progn
+ (put con 'loaded c)
+ (load c)
+ (format t "loaded.~%"))
+ (format t "skipped.~%"))))
+ (format t "~%")))
+
+; format of an entry in interp.daase:
+; (constructor-name
+; operationalist
+; constructormodemap
+; modemaps -- this should not be needed. eliminate it.
+; object -- the name of the object file to load for this con.
+; constructorcategory -- note that this info is the cadar of the
+; constructormodemap for domains and packages so it is stored
+; as NIL for them. it is valid for categories.
+; niladic -- t or nil directly
+; unused
+; cosig -- kept directly
+; constructorkind -- kept directly
+; defaultdomain -- a short list, for %i
+; ancestors -- used to compute new category updates
+; )
+(defun interpOpen ()
+ "open the interpreter database and hash the keys"
+ (declare (special $spadroot))
+ (let (constructors pos stamp dbstruct)
+ (setq *interp-stream* (open (DaaseName "interp.daase" nil)))
+ (setq stamp (read *interp-stream*))
+ (unless (equal stamp *interp-stream-stamp*)
+ (format t " Re-reading interp.daase")
+ (setq *interp-stream-stamp* stamp)
+ (setq pos (car stamp))
+ (file-position *interp-stream* pos)
+ (setq constructors (read *interp-stream*))
+ (dolist (item constructors)
+ (setq item (unsqueeze item))
+ (setq *allconstructors* (adjoin (first item) *allconstructors*))
+ (setq dbstruct (make-database))
+ (setf (get (car item) 'database) dbstruct)
+ (setf (database-operationalist dbstruct) (second item))
+ (setf (database-constructormodemap dbstruct) (third item))
+ (setf (database-modemaps dbstruct) (fourth item))
+ (setf (database-object dbstruct) (fifth item))
+ (setf (database-constructorcategory dbstruct) (sixth item))
+ (setf (database-niladic dbstruct) (seventh item))
+ (setf (database-abbreviation dbstruct) (eighth item))
+ (setf (get (eighth item) 'abbreviationfor) (first item)) ;invert
+ (setf (database-cosig dbstruct) (ninth item))
+ (setf (database-constructorkind dbstruct) (tenth item))
+ (setf (database-ancestors dbstruct) (nth 11 item))))
+ (format t "~&")))
+
+; this is an initialization function for the constructor database
+; it sets up 2 hash tables, opens the database and hashes the index values
+
+; there is a slight asymmetry in this code. sourcefile information for
+; system files is only the filename and extension. for user files it
+; contains the full pathname. when the database is first opened the
+; sourcefile slot contains system names. the lookup function
+; has to prefix the $spadroot information if the directory-namestring is
+; null (we don't know the real root at database build time).
+; a object-hash table is set up to look up nrlib and ao information.
+; this slot is empty until a user does a )library call. we remember
+; the location of the nrlib or ao file for the users local library
+; at that time. a NIL result from this probe means that the
+; library is in the system-specified place. when we get into multiple
+; library locations this will also contain system files.
+
+
+; format of an entry in browse.daase:
+; ( constructorname
+; sourcefile
+; constructorform
+; documentation
+; attributes
+; predicates
+; )
+
+(defun browseOpen ()
+ "open the constructor database and hash the keys"
+ (declare (special $spadroot))
+ (let (constructors pos stamp dbstruct)
+ (setq *browse-stream* (open (DaaseName "browse.daase" nil)))
+ (setq stamp (read *browse-stream*))
+ (unless (equal stamp *browse-stream-stamp*)
+ (format t " Re-reading browse.daase")
+ (setq *browse-stream-stamp* stamp)
+ (setq pos (car stamp))
+ (file-position *browse-stream* pos)
+ (setq constructors (read *browse-stream*))
+ (dolist (item constructors)
+ (setq item (unsqueeze item))
+ (unless (setq dbstruct (get (car item) 'database))
+ (format t "browseOpen:~%")
+ (format t "the browse database contains a contructor ~a~%" item)
+ (format t "that is not in the interp.daase file. we cannot~%")
+ (format t "get the database structure for this constructor and~%")
+ (warn "will create a new one~%")
+ (setf (get (car item) 'database) (setq dbstruct (make-database)))
+ (setq *allconstructors* (adjoin item *allconstructors*)))
+ (setf (database-sourcefile dbstruct) (second item))
+ (setf (database-constructorform dbstruct) (third item))
+ (setf (database-documentation dbstruct) (fourth item))
+ (setf (database-attributes dbstruct) (fifth item))
+ (setf (database-predicates dbstruct) (sixth item))
+ (setf (database-parents dbstruct) (seventh item))))
+ (format t "~&")))
+
+(defun categoryOpen ()
+ "open category.daase and hash the keys"
+ (declare (special $spadroot))
+ (let (pos keys stamp)
+ (setq *category-stream* (open (DaaseName "category.daase" nil)))
+ (setq stamp (read *category-stream*))
+ (unless (equal stamp *category-stream-stamp*)
+ (format t " Re-reading category.daase")
+ (setq *category-stream-stamp* stamp)
+ (setq pos (car stamp))
+ (file-position *category-stream* pos)
+ (setq keys (read *category-stream*))
+ (setq *hasCategory-hash* (make-hash-table :test #'equal))
+ (dolist (item keys)
+ (setq item (unsqueeze item))
+ (setf (gethash (first item) *hasCategory-hash*) (second item))))
+ (format t "~&")))
+
+(defun operationOpen ()
+ "read operation database and hash the keys"
+ (declare (special $spadroot))
+ (let (operations pos stamp)
+ (setq *operation-stream* (open (DaaseName "operation.daase" nil)))
+ (setq stamp (read *operation-stream*))
+ (unless (equal stamp *operation-stream-stamp*)
+ (format t " Re-reading operation.daase")
+ (setq *operation-stream-stamp* stamp)
+ (setq pos (car stamp))
+ (file-position *operation-stream* pos)
+ (setq operations (read *operation-stream*))
+ (dolist (item operations)
+ (setq item (unsqueeze item))
+ (setf (gethash (car item) *operation-hash*) (cdr item))))
+ (format t "~&")))
+
+(defun addoperations (constructor oldmaps)
+ "add ops from a )library domain to *operation-hash*"
+ (declare (special *operation-hash*))
+ (dolist (map oldmaps) ; out with the old
+ (let (oldop op)
+ (setq op (car map))
+ (setq oldop (getdatabase op 'operation))
+ (setq oldop (lisp::delete (cdr map) oldop :test #'equal))
+ (setf (gethash op *operation-hash*) oldop)))
+ (dolist (map (getdatabase constructor 'modemaps)) ; in with the new
+ (let (op newmap)
+ (setq op (car map))
+ (setq newmap (getdatabase op 'operation))
+ (setf (gethash op *operation-hash*) (cons (cdr map) newmap)))))
+
+(defun showdatabase (constructor)
+ (format t "~&~a: ~a~%" 'constructorkind
+ (getdatabase constructor 'constructorkind))
+ (format t "~a: ~a~%" 'cosig
+ (getdatabase constructor 'cosig))
+ (format t "~a: ~a~%" 'operation
+ (getdatabase constructor 'operation))
+ (format t "~a: ~%" 'constructormodemap)
+ (pprint (getdatabase constructor 'constructormodemap))
+ (format t "~&~a: ~%" 'constructorcategory)
+ (pprint (getdatabase constructor 'constructorcategory))
+ (format t "~&~a: ~%" 'operationalist)
+ (pprint (getdatabase constructor 'operationalist))
+ (format t "~&~a: ~%" 'modemaps)
+ (pprint (getdatabase constructor 'modemaps))
+ (format t "~a: ~a~%" 'hascategory
+ (getdatabase constructor 'hascategory))
+ (format t "~a: ~a~%" 'object
+ (getdatabase constructor 'object))
+ (format t "~a: ~a~%" 'niladic
+ (getdatabase constructor 'niladic))
+ (format t "~a: ~a~%" 'abbreviation
+ (getdatabase constructor 'abbreviation))
+ (format t "~a: ~a~%" 'constructor?
+ (getdatabase constructor 'constructor?))
+ (format t "~a: ~a~%" 'constructor
+ (getdatabase constructor 'constructor))
+ (format t "~a: ~a~%" 'defaultdomain
+ (getdatabase constructor 'defaultdomain))
+ (format t "~a: ~a~%" 'ancestors
+ (getdatabase constructor 'ancestors))
+ (format t "~a: ~a~%" 'sourcefile
+ (getdatabase constructor 'sourcefile))
+ (format t "~a: ~a~%" 'constructorform
+ (getdatabase constructor 'constructorform))
+ (format t "~a: ~a~%" 'constructorargs
+ (getdatabase constructor 'constructorargs))
+ (format t "~a: ~a~%" 'attributes
+ (getdatabase constructor 'attributes))
+ (format t "~a: ~%" 'predicates)
+ (pprint (getdatabase constructor 'predicates))
+ (format t "~a: ~a~%" 'documentation
+ (getdatabase constructor 'documentation))
+ (format t "~a: ~a~%" 'parents
+ (getdatabase constructor 'parents)))
+
+(defun setdatabase (constructor key value)
+ (let (struct)
+ (when (symbolp constructor)
+ (unless (setq struct (get constructor 'database))
+ (setq struct (make-database))
+ (setf (get constructor 'database) struct))
+ (case key
+ (abbreviation
+ (setf (database-abbreviation struct) value)
+ (when (symbolp value)
+ (setf (get value 'abbreviationfor) constructor)))
+ (constructorkind
+ (setf (database-constructorkind struct) value))))))
+
+(defun deldatabase (constructor key)
+ (when (symbolp constructor)
+ (case key
+ (abbreviation
+ (setf (get constructor 'abbreviationfor) nil)))))
+
+(defun getdatabase (constructor key)
+ (declare (special $spadroot) (special *miss*))
+ (when (eq *miss* t) (format t "getdatabase call: ~20a ~a~%" constructor key))
+ (let (data table stream ignore struct)
+ (declare (ignore ignore))
+ (when (or (symbolp constructor)
+ (and (eq key 'hascategory) (pairp constructor)))
+ (case key
+; note that abbreviation, constructorkind and cosig are heavy hitters
+; thus they occur first in the list of things to check
+ (abbreviation
+ (setq stream *interp-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-abbreviation struct))))
+ (constructorkind
+ (setq stream *interp-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-constructorkind struct))))
+ (cosig
+ (setq stream *interp-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-cosig struct))))
+ (operation
+ (setq stream *operation-stream*)
+ (setq data (gethash constructor *operation-hash*)))
+ (constructormodemap
+ (setq stream *interp-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-constructormodemap struct))))
+ (constructorcategory
+ (setq stream *interp-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-constructorcategory struct))
+ (when (null data) ;domain or package then subfield of constructormodemap
+ (setq data (cadar (getdatabase constructor 'constructormodemap))))))
+ (operationalist
+ (setq stream *interp-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-operationalist struct))))
+ (modemaps
+ (setq stream *interp-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-modemaps struct))))
+ (hascategory
+ (setq table *hasCategory-hash*)
+ (setq stream *category-stream*)
+ (setq data (gethash constructor table)))
+ (object
+ (setq stream *interp-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-object struct))))
+ (asharp?
+ (setq stream *interp-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-object struct))))
+ (niladic
+ (setq stream *interp-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-niladic struct))))
+ (constructor?
+ (when (setq struct (get constructor 'database))
+ (setq data (when (database-operationalist struct) t))))
+ (superdomain ; only 2 superdomains in the world
+ (case constructor
+ (|NonNegativeInteger|
+ (setq data '((|Integer|) (IF (< |#1| 0) |false| |true|))))
+ (|PositiveInteger|
+ (setq data '((|NonNegativeInteger|) (< 0 |#1|))))))
+ (constructor
+ (when (setq data (get constructor 'abbreviationfor))))
+ (defaultdomain
+ (setq data (cadr (assoc constructor *defaultdomain-list*))))
+ (ancestors
+ (setq stream *interp-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-ancestors struct))))
+ (sourcefile
+ (setq stream *browse-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-sourcefile struct))))
+ (constructorform
+ (setq stream *browse-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-constructorform struct))))
+ (constructorargs
+ (setq data (cdr (getdatabase constructor 'constructorform))))
+ (attributes
+ (setq stream *browse-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-attributes struct))))
+ (predicates
+ (setq stream *browse-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-predicates struct))))
+ (documentation
+ (setq stream *browse-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-documentation struct))))
+ (parents
+ (setq stream *browse-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-parents struct))))
+ (users
+ (setq stream *browse-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-users struct))))
+ (dependents
+ (setq stream *browse-stream*)
+ (when (setq struct (get constructor 'database))
+ (setq data (database-dependents struct))))
+ (otherwise (warn "~%(GETDATABASE ~a ~a) failed~%" constructor key)))
+ (when (numberp data) ;fetch the real data
+ (when *miss* (format t "getdatabase miss: ~20a ~a~%" key constructor))
+ (file-position stream data)
+ (setq data (unsqueeze (read stream)))
+ (case key ; cache the result of the database read
+ (operation (setf (gethash constructor *operation-hash*) data))
+ (hascategory (setf (gethash constructor *hascategory-hash*) data))
+ (constructorkind (setf (database-constructorkind struct) data))
+ (cosig (setf (database-cosig struct) data))
+ (constructormodemap (setf (database-constructormodemap struct) data))
+ (constructorcategory (setf (database-constructorcategory struct) data))
+ (operationalist (setf (database-operationalist struct) data))
+ (modemaps (setf (database-modemaps struct) data))
+ (object (setf (database-object struct) data))
+ (niladic (setf (database-niladic struct) data))
+ (abbreviation (setf (database-abbreviation struct) data))
+ (constructor (setf (database-constructor struct) data))
+ (ancestors (setf (database-ancestors struct) data))
+ (constructorform (setf (database-constructorform struct) data))
+ (attributes (setf (database-attributes struct) data))
+ (predicates (setf (database-predicates struct) data))
+ (documentation (setf (database-documentation struct) data))
+ (parents (setf (database-parents struct) data))
+ (users (setf (database-users struct) data))
+ (dependents (setf (database-dependents struct) data))
+ (sourcefile (setf (database-sourcefile struct) data))))
+ (case key ; fixup the special cases
+ (sourcefile
+ (when (and data (string= (directory-namestring data) "")
+ (string= (pathname-type data) "spad"))
+ (setq data
+ (concatenate 'string $spadroot "/../../src/algebra/" data))))
+ (asharp? ; is this asharp code?
+ (if (consp data)
+ (setq data (cdr data))
+ (setq data nil)))
+ (object ; fix up system object pathname
+ (if (consp data)
+ (setq data
+ (if (string= (directory-namestring (car data)) "")
+ (concatenate 'string $spadroot "/algebra/" (car data) ".o")
+ (car data)))
+ (when (and data (string= (directory-namestring data) ""))
+ (setq data (concatenate 'string $spadroot "/algebra/" data ".o")))))))
+ data))
+
+; )library top level command -- soon to be obsolete
+
+(defun |with| (args)
+ (|library| args))
+
+; )library top level command
+
+(defun |library| (args)
+ (declare (special |$options|))
+ (declare (special |$newConlist|))
+ (setq original-directory (get-current-directory))
+ (setq |$newConlist| nil)
+ (localdatabase args |$options|)
+#+:CCL
+ (dolist (a args) (check-module-exists a))
+ (|extendLocalLibdb| |$newConlist|)
+ (system::chdir original-directory)
+ (tersyscommand))
+
+;; check-module-exists looks to see if a module exists in one of the current
+;; libraries and, if not, compiles it. If the output-library exists but has not
+;; been opened then it opens it first.
+#+:CCL
+(defun check-module-exists (module)
+ (prog (|$options| mdate)
+ (if (and (not output-library) (filep (or |$outputLibraryName| "user.lib")))
+ (seq (setq |$outputLibraryName|
+ (if |$outputLibraryName| (truename |$outputLibraryName|)
+ (make-pathname :directory (get-current-directory)
+ :name "user.lib")))
+ (|openOutputLibrary| |$outputLibraryName|)))
+ (setq mdate (modulep module))
+ (setq |$options| '((|nolibrary| nil) (|quiet| nil)))
+ (|sayMSG| (format nil " Checking for module ~s." (namestring module)))
+ (let* ((fn (concatenate 'string (namestring module) ".lsp"))
+ (fdate (filedate fn)) )
+ (if (and fdate (or (null mdate) (datelessp mdate fdate)))
+ (|compileAsharpLispCmd| (list fn))
+ (let* ((fn (concatenate 'string (namestring module) ".NRLIB"))
+ (fdate (filedate fn)) )
+ (if (and fdate (or (null mdate) (datelessp mdate fdate)))
+ (|compileSpadLispCmd| (list fn))))))))
+
+; localdatabase tries to find files in the order of:
+; NRLIB/index.KAF
+; .asy
+; .ao, then asharp to .asy
+
+(defun localdatabase (filelist options &optional (make-database? nil))
+ "read a local filename and update the hash tables"
+ (labels (
+ (processOptions (options)
+ (let (only dir noexpose)
+ (when (setq only (assoc '|only| options))
+ (setq options (lisp::delete only options :test #'equal))
+ (setq only (cdr only)))
+ (when (setq dir (assoc '|dir| options))
+ (setq options (lisp::delete dir options :test #'equal))
+ (setq dir (second dir))
+ (when (null dir)
+ (|sayKeyedMsg| 'S2IU0002 nil) ))
+ (when (setq noexpose (assoc '|noexpose| options))
+ (setq options (lisp::delete noexpose options :test #'equal))
+ (setq noexpose 't) )
+ (when options
+ (format t " Ignoring unknown )library option: ~a~%" options))
+ (values only dir noexpose)))
+ (processDir (dirarg thisdir)
+ (let (allfiles skipasos)
+ (system:chdir (string dirarg))
+ (setq allfiles (directory "*"))
+ (system:chdir thisdir)
+ (values
+ (mapcan #'(lambda (f)
+ (when (string-equal (pathname-type f) "NRLIB")
+ (list (concatenate 'string (namestring f) "/"
+ vmlisp::*index-filename*)))) allfiles)
+ (mapcan #'(lambda (f)
+ (when (string= (pathname-type f) "asy")
+ (push (pathname-name f) skipasos)
+ (list (namestring f)))) allfiles)
+ (mapcan #'(lambda (f)
+ (when (and (string= (pathname-type f) "ao")
+ (not (member (pathname-name f) skipasos :test #'string=)))
+ (list (namestring f))))
+ allfiles)
+ ;; At the moment we will only look for user.lib: others are taken care
+ ;; of by localasy and localnrlib.
+#+:CCL
+ (mapcan #'(lambda (f)
+ (when (and (string= (pathname-type f) "lib") (string= (pathname-name f) "user"))
+ (list (namestring f))))
+ allfiles)
+#-:CCL nil
+ ))))
+ (let (thisdir nrlibs asos asys libs object only dir key
+ (|$forceDatabaseUpdate| t) noexpose)
+ (declare (special |$forceDatabaseUpdate|))
+ (setq thisdir (namestring (truename ".")))
+ (setq noexpose nil)
+ (multiple-value-setq (only dir noexpose) (processOptions options))
+ ;don't force exposure during database build
+ (if make-database? (setq noexpose t))
+ (when dir (multiple-value-setq (nrlibs asys asos libs) (processDir dir thisdir)))
+ (dolist (file filelist)
+ (let ((filename (pathname-name file))
+ (namedir (directory-namestring file)))
+ (unless namedir (setq thisdir (concatenate 'string thisdir "/")))
+ (cond
+ ((setq file (probe-file
+ (concatenate 'string namedir filename ".NRLIB/"
+ vmlisp::*index-filename*)))
+ (push (namestring file) nrlibs))
+ ((setq file (probe-file
+ (concatenate 'string namedir filename ".asy")))
+ (push (namestring file) asys))
+ ((setq file (probe-file
+ (concatenate 'string namedir filename ".ao")))
+ (push (namestring file) asos))
+ ('else (format t " )library cannot find the file ~a.~%" filename)))))
+#+:CCL
+ (dolist (file libs) (|addInputLibrary| (truename file)))
+ (dolist (file (nreverse nrlibs))
+ (setq key (pathname-name (first (last (pathname-directory file)))))
+ (setq object (concatenate 'string (directory-namestring file) "code"))
+ (localnrlib key file object make-database? noexpose))
+ (dolist (file (nreverse asys))
+ (setq object
+ (concatenate 'string (directory-namestring file) (pathname-name file)))
+ (localasy (|astran| file) object only make-database? noexpose))
+ (dolist (file (nreverse asos))
+ (setq object
+ (concatenate 'string (directory-namestring file) (pathname-name file)))
+ (asharp file)
+ (setq file (|astran| (concatenate 'string (pathname-name file) ".asy")))
+ (localasy file object only make-database? noexpose))
+ (HCLEAR |$ConstructorCache|))))
+
+(defun localasy (asy object only make-database? noexpose)
+ "given an alist from the asyfile and the objectfile update the database"
+ (labels (
+ (fetchdata (alist index)
+ (cdr (assoc index alist :test #'string=))))
+ (let (cname kind key alist (systemdir? nil) oldmaps asharp-name dbstruct abbrev)
+#+:CCL
+ ;; Open the library
+ (let (lib)
+ (if (filep (setq lib (make-pathname :name object :type "lib")) )
+ (setq input-libraries (cons (open-library (truename lib)) input-libraries))))
+ (set-file-getter object) ; sets the autoload property for G-object
+ (dolist (domain asy)
+ (setq key (first domain))
+ (setq alist (rest domain))
+ (setq asharp-name
+ (foam::axiomxl-global-name (pathname-name object) key
+ (lassoc '|typeCode| alist)))
+ (if (< (length alist) 4) ;we have a naked function object
+ (let ((opname key)
+ (modemap (car (LASSOC '|modemaps| alist))) )
+ (setq oldmaps (getdatabase opname 'operation))
+ (setf (gethash opname *operation-hash*)
+ (adjoin (subst asharp-name opname (cdr modemap))
+ oldmaps :test #'equal))
+ (asharpMkAutoloadFunction object asharp-name))
+ (when (if (null only) (not (eq key '%%)) (member key only))
+ (setq *allOperations* nil) ; force this to recompute
+ (setq oldmaps (getdatabase key 'modemaps))
+ (setq dbstruct (make-database))
+ (setf (get key 'database) dbstruct)
+ (setq *allconstructors* (adjoin key *allconstructors*))
+ (setf (database-constructorform dbstruct)
+ (fetchdata alist "constructorForm"))
+ (setf (database-constructorkind dbstruct)
+ (fetchdata alist "constructorKind"))
+ (setf (database-constructormodemap dbstruct)
+ (fetchdata alist "constructorModemap"))
+ (unless (setf (database-abbreviation dbstruct)
+ (fetchdata alist "abbreviation"))
+ (setf (database-abbreviation dbstruct) key)) ; default
+ (setq abbrev (database-abbreviation dbstruct))
+ (setf (get abbrev 'abbreviationfor) key)
+ (setf (database-constructorcategory dbstruct)
+ (fetchdata alist "constructorCategory"))
+ (setf (database-attributes dbstruct)
+ (fetchdata alist "attributes"))
+ (setf (database-sourcefile dbstruct)
+ (fetchdata alist "sourceFile"))
+ (setf (database-operationalist dbstruct)
+ (fetchdata alist "operationAlist"))
+ (setf (database-modemaps dbstruct)
+ (fetchdata alist "modemaps"))
+ (setf (database-documentation dbstruct)
+ (fetchdata alist "documentation"))
+ (setf (database-predicates dbstruct)
+ (fetchdata alist "predicates"))
+ (setf (database-niladic dbstruct)
+ (fetchdata alist "NILADIC"))
+ (addoperations key oldmaps)
+ (setq cname (|opOf| (database-constructorform dbstruct)))
+ (setq kind (database-constructorkind dbstruct))
+ (if (null noexpose) (|setExposeAddConstr| (cons cname nil)))
+ (unless make-database?
+ (|updateDatabase| key cname systemdir?) ;makes many hashtables???
+ (|installConstructor| cname kind)
+ ;; following can break category database build
+ (if (eq kind '|category|)
+ (setf (database-ancestors dbstruct)
+ (fetchdata alist "ancestors")))
+ (if (eq kind '|domain|)
+ (dolist (pair (cdr (assoc "ancestors" alist :test #'string=)))
+ (setf (gethash (cons cname (caar pair)) *hascategory-hash*)
+ (cdr pair))))
+ (if |$InteractiveMode| (setq |$CategoryFrame| |$EmptyEnvironment|)))
+ (setf (database-cosig dbstruct)
+ (cons nil (mapcar #'|categoryForm?|
+ (cddar (database-constructormodemap dbstruct)))))
+ (setf (database-object dbstruct) (cons object asharp-name))
+ (if (eq kind '|category|)
+ (asharpMkAutoLoadCategory object cname asharp-name
+ (database-cosig dbstruct))
+ (asharpMkAutoLoadFunctor object cname asharp-name
+ (database-cosig dbstruct)))
+ (|sayKeyedMsg| 'S2IU0001 (list cname object))))))))
+
+(defun localnrlib (key nrlib object make-database? noexpose)
+ "given a string pathname of an index.KAF and the object update the database"
+ (labels (
+ (fetchdata (alist in index)
+ (let (pos)
+ (setq pos (third (assoc index alist :test #'string=)))
+ (when pos
+ (file-position in pos)
+ (read in)))))
+ (let (alist kind (systemdir? nil) pos constructorform oldmaps abbrev dbstruct)
+ (with-open-file (in nrlib)
+ (file-position in (read in))
+ (setq alist (read in))
+ (setq pos (third (assoc "constructorForm" alist :test #'string=)))
+ (file-position in pos)
+ (setq constructorform (read in))
+ (setq key (car constructorform))
+ (setq oldmaps (getdatabase key 'modemaps))
+ (setq dbstruct (make-database))
+ (setq *allconstructors* (adjoin key *allconstructors*))
+ (setf (get key 'database) dbstruct) ; store the struct, side-effect it...
+ (setf (database-constructorform dbstruct) constructorform)
+ (setq *allOperations* nil) ; force this to recompute
+ (setf (database-object dbstruct) object)
+ (setq abbrev
+ (intern (pathname-name (first (last (pathname-directory object))))))
+ (setf (database-abbreviation dbstruct) abbrev)
+ (setf (get abbrev 'abbreviationfor) key)
+ (setf (database-operationalist dbstruct) nil)
+ (setf (database-operationalist dbstruct)
+ (fetchdata alist in "operationAlist"))
+ (setf (database-constructormodemap dbstruct)
+ (fetchdata alist in "constructorModemap"))
+ (setf (database-modemaps dbstruct) (fetchdata alist in "modemaps"))
+ (setf (database-sourcefile dbstruct) (fetchdata alist in "sourceFile"))
+ (when make-database?
+ (setf (database-sourcefile dbstruct)
+ (file-namestring (database-sourcefile dbstruct))))
+ (setf (database-constructorkind dbstruct)
+ (setq kind (fetchdata alist in "constructorKind")))
+ (setf (database-constructorcategory dbstruct)
+ (fetchdata alist in "constructorCategory"))
+ (setf (database-documentation dbstruct)
+ (fetchdata alist in "documentation"))
+ (setf (database-attributes dbstruct)
+ (fetchdata alist in "attributes"))
+ (setf (database-predicates dbstruct)
+ (fetchdata alist in "predicates"))
+ (setf (database-niladic dbstruct)
+ (when (fetchdata alist in "NILADIC") t))
+ (addoperations key oldmaps)
+ (unless make-database?
+ (if (eq kind '|category|)
+ (setf (database-ancestors dbstruct)
+ (SUBLISLIS |$FormalMapVariableList| (cdr constructorform) (fetchdata alist in "ancestors"))))
+ (|updateDatabase| key key systemdir?) ;makes many hashtables???
+ (|installConstructor| key kind) ;used to be key cname ...
+ (|updateCategoryTable| key kind)
+ (if |$InteractiveMode| (setq |$CategoryFrame| |$EmptyEnvironment|)))
+ (setf (database-cosig dbstruct)
+ (cons nil (mapcar #'|categoryForm?|
+ (cddar (database-constructormodemap dbstruct)))))
+ (remprop key 'loaded)
+ (if (null noexpose) (|setExposeAddConstr| (cons key nil)))
+ #-:CCL
+ (setf (symbol-function key) ; sets the autoload property for cname
+ #'(lambda (&rest args)
+ (unless (get key 'loaded)
+ (|startTimingProcess| '|load|)
+ (|loadLibNoUpdate| key key object)) ; used to be cname key
+ (apply key args)))
+ #+:CCL
+ (let (lib)
+ (if (filep (setq lib (make-pathname :name object :type "lib")) )
+ (setq input-libraries (cons (open-library (truename lib)) input-libraries)))
+ (|unloadOneConstructor| (get abbrev 'abbreviationfor) abbrev) )
+ (|sayKeyedMsg| 'S2IU0001 (list key object))))))
+
+
+; making new databases consists of:
+; 1) reset all of the system hash tables
+; *) set up Union, Record and Mapping
+; 2) map )library across all of the system files (fills the databases)
+; 3) loading some normally autoloaded files
+; 4) making some database entries that are computed (like ancestors)
+; 5) writing out the databases
+; 6) write out 'warm' data to be loaded into the image at build time
+; note that this process should be done in a clean image
+; followed by a rebuild of the system image to include
+; the new index pointers (e.g. *interp-stream-stamp*)
+; the system will work without a rebuild but it needs to
+; re-read the databases on startup. rebuilding the system
+; will cache the information into the image and the databases
+; are opened but not read, saving considerable startup time.
+; also note that the order the databases are written out is
+; critical. interp.daase depends on prior computations and has
+; to be written out last.
+
+(defun make-databases (ext dirlist)
+ (labels (
+ ;; these are types which have no library object associated with them.
+ ;; we store some constructed data to make them perform like library
+ ;; objects, the *operationalist-hash* key entry is used by allConstructors
+ (withSpecialConstructors ()
+ ; note: if item is not in *operationalist-hash* it will not be written
+ ; Category
+ (setf (get '|Category| 'database)
+ (make-database :operationalist nil :niladic t))
+ (push '|Category| *allconstructors*)
+ ; UNION
+ (setf (get '|Union| 'database)
+ (make-database :operationalist nil :constructorkind '|domain|))
+ (push '|Union| *allconstructors*)
+ ; RECORD
+ (setf (get '|Record| 'database)
+ (make-database :operationalist nil :constructorkind '|domain|))
+ (push '|Record| *allconstructors*)
+ ; MAPPING
+ (setf (get '|Mapping| 'database)
+ (make-database :operationalist nil :constructorkind '|domain|))
+ (push '|Mapping| *allconstructors*)
+ ; ENUMERATION
+ (setf (get '|Enumeration| 'database)
+ (make-database :operationalist nil :constructorkind '|domain|))
+ (push '|Enumeration| *allconstructors*)
+ )
+ (final-name (root)
+ (format nil "~a.daase~a" root ext))
+ )
+ (let (d)
+ (declare (special |$constructorList|))
+ (do-symbols (symbol)
+ (when (get symbol 'database)
+ (setf (get symbol 'database) nil)))
+ (setq *hascategory-hash* (make-hash-table :test #'equal))
+ (setq *operation-hash* (make-hash-table))
+ (setq *allconstructors* nil)
+ (setq *compressvector* nil)
+ (withSpecialConstructors)
+ (localdatabase nil
+ (list (list '|dir| (namestring (truename "./")) ))
+ 'make-database)
+ (dolist (dir dirlist)
+ (localdatabase nil
+ (list (list '|dir|
+ (namestring (probe-file
+ (format nil "./~a"
+ dir)))))
+ 'make-database))
+;browse.daase
+#+:AKCL (load (concatenate 'string (|getEnv| "AXIOM") "/autoload/topics")) ;; hack
+ (|oldCompilerAutoloadOnceTrigger|)
+ (|browserAutoloadOnceTrigger|)
+#+:AKCL (|mkTopicHashTable|)
+ (setq |$constructorList| nil) ;; affects buildLibdb
+ (|buildLibdb|)
+ (|dbSplitLibdb|)
+; (|dbAugmentConstructorDataTable|)
+ (|mkUsersHashTable|)
+ (|saveUsersHashTable|)
+ (|mkDependentsHashTable|)
+ (|saveDependentsHashTable|)
+; (|buildGloss|)
+ (write-compress)
+ (write-browsedb)
+ (write-operationdb)
+ ; note: genCategoryTable creates a new *hascategory-hash* table
+ ; this smashes the existing table and regenerates it.
+ ; write-categorydb does getdatabase calls to write the new information
+ (write-categorydb)
+ (dolist (con (|allConstructors|))
+ (let (dbstruct)
+ (when (setq dbstruct (get con 'database))
+ (setf (database-cosig dbstruct)
+ (cons nil (mapcar #'|categoryForm?|
+ (cddar (database-constructormodemap dbstruct)))))
+ (when (and (|categoryForm?| con)
+ (= (length (setq d (|domainsOf| (list con) NIL NIL))) 1))
+ (setq d (caar d))
+ (when (= (length d) (length (|getConstructorForm| con)))
+ (format t " ~a has a default domain of ~a~%" con (car d))
+ (setf (database-defaultdomain dbstruct) (car d)))))))
+ ; note: genCategoryTable creates *ancestors-hash*. write-interpdb
+ ; does gethash calls into it rather than doing a getdatabase call.
+ (write-interpdb)
+#+:AKCL (write-warmdata)
+ (create-initializers)
+ (when (probe-file (final-name "compress"))
+ (delete-file (final-name "compress")))
+ (rename-file "compress.build" (final-name "compress"))
+ (when (probe-file (final-name "interp"))
+ (delete-file (final-name "interp")))
+ (rename-file "interp.build" (final-name "interp"))
+ (when (probe-file (final-name "operation"))
+ (delete-file (final-name "operation")))
+ (rename-file "operation.build" (final-name "operation"))
+ (when (probe-file (final-name "browse"))
+ (delete-file (final-name "browse")))
+ (rename-file "browse.build"
+ (final-name "browse"))
+ (when (probe-file (final-name "category"))
+ (delete-file (final-name "category")))
+ (rename-file "category.build"
+ (final-name "category")))))
+
+(defun DaaseName (name erase?)
+ (let (daase filename)
+ (declare (special $spadroot))
+ (if (setq daase (|getEnv| "DAASE"))
+ (progn
+ (setq filename (concatenate 'string daase "/algebra/" name))
+ (format t " Using local database ~a.." filename))
+ (setq filename (concatenate 'string $spadroot "/algebra/" name)))
+ (when erase? (system::system (concatenate 'string "rm -f " filename)))
+ filename))
+
+;; rewrite this so it works in mnt
+;;(defun DaaseName (name erase?)
+;; (let (daase filename)
+;; (declare (special $spadroot))
+;; (if (setq daase (|getEnv| "DAASE"))
+;; (progn
+;; (setq filename (concatenate 'string daase "/algebra/" name))
+;; (format t " Using local database ~a.." filename))
+;; (setq filename (concatenate 'string $spadroot "/algebra/" name)))
+;; (when erase? (system::system (concatenate 'string "rm -f " filename)))
+;; filename))
+
+@
+\subsection{compress.daase}
+The compress database is special. It contains a list of symbols.
+The character string name of a symbol in the other databases is
+represented by a negative number. To get the real symbol back you
+take the absolute value of the number and use it as a byte index
+into the compress database. In this way long symbol names become
+short negative numbers.
+
+<<*>>=
+
+(defun compressOpen ()
+ (let (lst stamp pos)
+ (declare (special $spadroot))
+ (setq *compress-stream*
+ (open (DaaseName "compress.daase" nil) :direction :input))
+ (setq stamp (read *compress-stream*))
+ (unless (equal stamp *compress-stream-stamp*)
+ (format t " Re-reading compress.daase")
+ (setq *compress-stream-stamp* stamp)
+ (setq pos (car stamp))
+ (file-position *compress-stream* pos)
+ (setq lst (read *compress-stream*))
+ (setq *compressVectorLength* (car lst))
+ (setq *compressvector*
+ (make-array (car lst) :initial-contents (cdr lst))))))
+
+(setq *attributes*
+ '(|nil| |infinite| |arbitraryExponent| |approximate| |complex|
+ |shallowMutable| |canonical| |noetherian| |central|
+ |partiallyOrderedSet| |arbitraryPrecision| |canonicalsClosed|
+ |noZeroDivisors| |rightUnitary| |leftUnitary|
+ |additiveValuation| |unitsKnown| |canonicalUnitNormal|
+ |multiplicativeValuation| |finiteAggregate| |shallowlyMutable|
+ |commutative|))
+
+(defun write-compress ()
+ (let (compresslist masterpos out)
+ (close *compress-stream*)
+ (setq out (open "compress.build" :direction :output))
+ (princ " " out)
+ (finish-output out)
+ (setq masterpos (file-position out))
+ (setq compresslist
+ (append (|allConstructors|) (|allOperations|) *attributes*))
+ (push "algebra" compresslist)
+ (push "failed" compresslist)
+ (push 'signature compresslist)
+ (push '|ofType| compresslist)
+ (push '|Join| compresslist)
+ (push 'and compresslist)
+ (push '|nobranch| compresslist)
+ (push 'category compresslist)
+ (push '|category| compresslist)
+ (push '|domain| compresslist)
+ (push '|package| compresslist)
+ (push 'attribute compresslist)
+ (push '|isDomain| compresslist)
+ (push '|ofCategory| compresslist)
+ (push '|Union| compresslist)
+ (push '|Record| compresslist)
+ (push '|Mapping| compresslist)
+ (push '|Enumeration| compresslist)
+ (setq *compressVectorLength* (length compresslist))
+ (setq *compressvector*
+ (make-array *compressVectorLength* :initial-contents compresslist))
+ (print (cons (length compresslist) compresslist) out)
+ (finish-output out)
+ (file-position out 0)
+ (print (cons masterpos (get-universal-time)) out)
+ (finish-output out)
+ (close out)))
+
+@
+\subsubsection{interp.daase}
+\begin{verbatim}
+ format of an entry in interp.daase:
+ (constructor-name
+ operationalist
+ constructormodemap
+ modemaps -- this should not be needed. eliminate it.
+ object -- the name of the object file to load for this con.
+ constructorcategory -- note that this info is the cadar of the
+ constructormodemap for domains and packages so it is stored
+ as NIL for them. it is valid for categories.
+ niladic -- t or nil directly
+ unused
+ cosig -- kept directly
+ constructorkind -- kept directly
+ defaultdomain -- a short list, for %i
+ ancestors -- used to compute new category updates
+ )
+\end{verbatim}
+
+Here I'll try to outline the interp database write procedure
+
+\begin{verbatim}
+(defun write-interpdb ()
+ "build interp.daase from hash tables"
+ (declare (special $spadroot) (special *ancestors-hash*))
+ (let (opalistpos modemapspos cmodemappos master masterpos obj *print-pretty*
+ concategory categorypos kind niladic cosig abbrev defaultdomain
+ ancestors ancestorspos out)
+ (declare (special *print-pretty*))
+ (print "building interp.daase")
+
+; 1. We open the file we're going to create
+
+ (setq out (open "interp.build" :direction :output))
+
+; 2. We reserve some space at the top of the file for the key-time pair
+; We will overwrite these spaces just before we close the file.
+
+ (princ " " out)
+
+; 3. Make sure we write it out
+ (finish-output out)
+
+; 4. For every constructor in the system we write the parts:
+
+ (dolist (constructor (|allConstructors|))
+ (let (struct)
+
+; 4a. Each constructor has a property list. A property list is a list
+; of (key . value) pairs. The property we want is called 'database
+; so there is a ('database . something) in the property list
+
+ (setq struct (get constructor 'database))
+
+; 5 We write the "operationsalist"
+; 5a. We remember the current file position before we write
+; We need this information so we can seek to this position on read
+
+ (setq opalistpos (file-position out))
+
+; 5b. We get the "operationalist", compress it, and write it out
+
+ (print (squeeze (database-operationalist struct)) out)
+
+; 5c. We make sure it was written
+
+ (finish-output out)
+
+; 6 We write the "constructormodemap"
+; 6a. We remember the current file position before we write
+
+ (setq cmodemappos (file-position out))
+
+; 6b. We get the "constructormodemap", compress it, and write it out
+
+ (print (squeeze (database-constructormodemap struct)) out)
+
+; 6c. We make sure it was written
+
+ (finish-output out)
+
+; 7. We write the "modemaps"
+; 7a. We remember the current file position before we write
+
+ (setq modemapspos (file-position out))
+
+; 7b. We get the "modemaps", compress it, and write it out
+
+ (print (squeeze (database-modemaps struct)) out)
+
+; 7c. We make sure it was written
+
+ (finish-output out)
+
+; 8. We remember source file pathnames in the obj variable
+
+ (if (consp (database-object struct)) ; if asharp code ...
+ (setq obj
+ (cons (pathname-name (car (database-object struct)))
+ (cdr (database-object struct))))
+ (setq obj
+ (pathname-name
+ (first (last (pathname-directory (database-object struct)))))))
+
+; 9. We write the "constructorcategory", if it is a category, else nil
+; 9a. Get the constructorcategory and compress it
+
+ (setq concategory (squeeze (database-constructorcategory struct)))
+
+; 9b. If we have any data we write it out, else we don't write it
+; Note that if there is no data then the byte index for the
+; constructorcatagory will not be a number but will be nil.
+
+ (if concategory ; if category then write data else write nil
+ (progn
+ (setq categorypos (file-position out))
+ (print concategory out)
+ (finish-output out))
+ (setq categorypos nil))
+
+; 10. We get a set of properties which are kept as "immediate" data
+; This means that the key table will hold this data directly
+; rather than as a byte index into the file.
+; 10a. niladic data
+
+ (setq niladic (database-niladic struct))
+
+; 10b. abbreviation data (e.g. POLY for polynomial)
+
+ (setq abbrev (database-abbreviation struct))
+
+; 10c. cosig data
+
+ (setq cosig (database-cosig struct))
+
+; 10d. kind data
+
+ (setq kind (database-constructorkind struct))
+
+; 10e. defaultdomain data
+
+ (setq defaultdomain (database-defaultdomain struct))
+
+; 11. The ancestor data might exist. If it does we fetch it,
+; compress it, and write it out. If it does not we place
+; and immediate value of nil in the key-value table
+
+ (setq ancestors (squeeze (gethash constructor *ancestors-hash*))) ;cattable.boot
+ (if ancestors
+ (progn
+ (setq ancestorspos (file-position out))
+ (print ancestors out)
+ (finish-output out))
+ (setq ancestorspos nil))
+
+; 12. "master" is an alist. Each element of the alist has the name of
+; the constructor and all of the above attributes. When the loop
+; finishes we will have constructed all of the data for the key-value
+; table
+
+ (push (list constructor opalistpos cmodemappos modemapspos
+ obj categorypos niladic abbrev cosig kind defaultdomain
+ ancestorspos) master)))
+
+; 13. The loop is done, we make sure all of the data is written
+
+ (finish-output out)
+
+; 14. We remember where the key-value table will be written in the file
+
+ (setq masterpos (file-position out))
+
+; 15. We compress and print the key-value table
+
+ (print (mapcar #'squeeze master) out)
+
+; 16. We make sure we write the table
+
+ (finish-output out)
+
+; 17. We go to the top of the file
+
+ (file-position out 0)
+
+; 18. We write out the (master-byte-position . universal-time) pair
+; Note that if the universal-time value matches the value of
+; *interp-stream-stamp* then there is no reason to read the
+; interp database because all of the data is already cached in
+; the image. This happens if you build a database and immediatly
+; save the image. The saved image already has the data since we
+; just wrote it out. If the *interp-stream-stamp* and the database
+; time stamp differ we "reread" the database on startup. Actually
+; we just open the database and fetch as needed. You can see fetches
+; by setting the *miss* variable non-nil.
+
+ (print (cons masterpos (get-universal-time)) out)
+
+; 19. We make sure we write it.
+
+ (finish-output out)
+
+; 20 And we are done
+
+ (close out)))
+\end{verbatim}
+
+<<*>>=
+(defun write-interpdb ()
+ "build interp.daase from hash tables"
+ (declare (special $spadroot) (special *ancestors-hash*))
+ (let (opalistpos modemapspos cmodemappos master masterpos obj *print-pretty*
+ concategory categorypos kind niladic cosig abbrev defaultdomain
+ ancestors ancestorspos out)
+ (declare (special *print-pretty*))
+ (print "building interp.daase")
+ (setq out (open "interp.build" :direction :output))
+ (princ " " out)
+ (finish-output out)
+ (dolist (constructor (|allConstructors|))
+ (let (struct)
+ (setq struct (get constructor 'database))
+ (setq opalistpos (file-position out))
+ (print (squeeze (database-operationalist struct)) out)
+ (finish-output out)
+ (setq cmodemappos (file-position out))
+ (print (squeeze (database-constructormodemap struct)) out)
+ (finish-output out)
+ (setq modemapspos (file-position out))
+ (print (squeeze (database-modemaps struct)) out)
+ (finish-output out)
+ (if (consp (database-object struct)) ; if asharp code ...
+ (setq obj
+ (cons (pathname-name (car (database-object struct)))
+ (cdr (database-object struct))))
+ (setq obj
+ (pathname-name
+ (first (last (pathname-directory (database-object struct)))))))
+ (setq concategory (squeeze (database-constructorcategory struct)))
+ (if concategory ; if category then write data else write nil
+ (progn
+ (setq categorypos (file-position out))
+ (print concategory out)
+ (finish-output out))
+ (setq categorypos nil))
+ (setq niladic (database-niladic struct))
+ (setq abbrev (database-abbreviation struct))
+ (setq cosig (database-cosig struct))
+ (setq kind (database-constructorkind struct))
+ (setq defaultdomain (database-defaultdomain struct))
+ (setq ancestors (squeeze (gethash constructor *ancestors-hash*))) ;cattable.boot
+ (if ancestors
+ (progn
+ (setq ancestorspos (file-position out))
+ (print ancestors out)
+ (finish-output out))
+ (setq ancestorspos nil))
+ (push (list constructor opalistpos cmodemappos modemapspos
+ obj categorypos niladic abbrev cosig kind defaultdomain
+ ancestorspos) master)))
+ (finish-output out)
+ (setq masterpos (file-position out))
+ (print (mapcar #'squeeze master) out)
+ (finish-output out)
+ (file-position out 0)
+ (print (cons masterpos (get-universal-time)) out)
+ (finish-output out)
+ (close out)))
+
+@
+\subsubsection{browse.daase}
+\begin{verbatim}
+ format of an entry in browse.daase:
+ ( constructorname
+ sourcefile
+ constructorform
+ documentation
+ attributes
+ predicates
+ )
+\end{verbatim}
+This is essentially the same overall process as write-interpdb.
+
+We reserve some space for the (key-table-byte-position . timestamp)
+
+We loop across the list of constructors dumping the data and
+remembering the byte positions in a key-value pair table.
+
+We dump the final key-value pair table, write the byte position and
+time stamp at the top of the file and close the file.
+
+<<*>>=
+(defun write-browsedb ()
+ "make browse.daase from hash tables"
+ (declare (special $spadroot))
+ (let (master masterpos src formpos docpos attpos predpos *print-pretty* out)
+ (declare (special *print-pretty*))
+ (print "building browse.daase")
+ (setq out (open "browse.build" :direction :output))
+ (princ " " out)
+ (finish-output out)
+ (dolist (constructor (|allConstructors|))
+ (let (struct)
+ (setq struct (get constructor 'database))
+ ; sourcefile is small. store the string directly
+ (setq src (database-sourcefile struct))
+ (setq formpos (file-position out))
+ (print (squeeze (database-constructorform struct)) out)
+ (finish-output out)
+ (setq docpos (file-position out))
+ (print (database-documentation struct) out)
+ (finish-output out)
+ (setq attpos (file-position out))
+ (print (squeeze (database-attributes struct)) out)
+ (finish-output out)
+ (setq predpos (file-position out))
+ (print (squeeze (database-predicates struct)) out)
+ (finish-output out)
+ (push (list constructor src formpos docpos attpos predpos) master)))
+ (finish-output out)
+ (setq masterpos (file-position out))
+ (print (mapcar #'squeeze master) out)
+ (finish-output out)
+ (file-position out 0)
+ (print (cons masterpos (get-universal-time)) out)
+ (finish-output out)
+ (close out)))
+
+@
+\subsubsection{category.daase}
+This is a single table of category hash table information, dumped in the
+database format.
+<<*>>=
+(defun write-categorydb ()
+ "make category.daase from scratch. contains the *hasCategory-hash* table"
+ (let (out master pos *print-pretty*)
+ (declare (special *print-pretty*))
+ (print "building category.daase")
+ (|genCategoryTable|)
+ (setq out (open "category.build" :direction :output))
+ (princ " " out)
+ (finish-output out)
+ (maphash #'(lambda (key value)
+ (if (or (null value) (eq value t))
+ (setq pos value)
+ (progn
+ (setq pos (file-position out))
+ (print (squeeze value) out)
+ (finish-output out)))
+ (push (list key pos) master))
+ *hasCategory-hash*)
+ (setq pos (file-position out))
+ (print (mapcar #'squeeze master) out)
+ (finish-output out)
+ (file-position out 0)
+ (print (cons pos (get-universal-time)) out)
+ (finish-output out)
+ (close out)))
+
+(defun unsqueeze (expr)
+ (cond ((atom expr)
+ (cond ((and (numberp expr) (<= expr 0))
+ (svref *compressVector* (- expr)))
+ (t expr)))
+ (t (rplaca expr (unsqueeze (car expr)))
+ (rplacd expr (unsqueeze (cdr expr)))
+ expr)))
+
+(defun squeeze (expr)
+ (let (leaves pos (bound (length *compressvector*)))
+ (labels (
+ (flat (expr)
+ (when (and (numberp expr) (< expr 0) (>= expr bound))
+ (print expr)
+ (break "squeeze found a negative number"))
+ (if (atom expr)
+ (unless (or (null expr)
+ (and (symbolp expr) (char= (schar (symbol-name expr) 0) #\*)))
+ (setq leaves (adjoin expr leaves)))
+ (progn
+ (flat (car expr))
+ (flat (cdr expr))))))
+ (setq leaves nil)
+ (flat expr)
+ (dolist (leaf leaves)
+ (when (setq pos (position leaf *compressvector*))
+ (nsubst (- pos) leaf expr)))
+ expr)))
+
+@
+\subsubsection{operation.daase}
+This is a single table of operations hash table information, dumped in the
+database format.
+<<*>>=
+(defun write-operationdb ()
+ (let (pos master out)
+ (declare (special leaves))
+ (setq out (open "operation.build" :direction :output))
+ (princ " " out)
+ (finish-output out)
+ (maphash #'(lambda (key value)
+ (setq pos (file-position out))
+ (print (squeeze value) out)
+ (finish-output out)
+ (push (cons key pos) master))
+ *operation-hash*)
+ (finish-output out)
+ (setq pos (file-position out))
+ (print (mapcar #'squeeze master) out)
+ (file-position out 0)
+ (print (cons pos (get-universal-time)) out)
+ (finish-output out)
+ (close out)))
+
+(defun write-warmdata ()
+ "write out information to be loaded into the image at build time"
+ (declare (special |$topicHash|))
+ (with-open-file (out "warm.data" :direction :output)
+ (format out "(in-package \"BOOT\")~%")
+ (format out "(setq |$topicHash| (make-hash-table))~%")
+ (maphash #'(lambda (k v)
+ (format out "(setf (gethash '|~a| |$topicHash|) ~a)~%" k v)) |$topicHash|)))
+
+(defun |allConstructors| ()
+ (declare (special *allconstructors*))
+ *allconstructors*)
+
+(defun |allOperations| ()
+ (declare (special *allOperations*))
+ (unless *allOperations*
+ (maphash #'(lambda (k v) (declare (ignore v)) (push k *allOperations*))
+ *operation-hash*))
+ *allOperations*)
+
+; the variable NOPfuncall is a funcall-able object that is a dummy
+; initializer for libaxiom asharp domains.
+(defvar NOPfuncall (cons 'identity nil))
+
+(defun create-initializers ()
+;; since libaxiom is now built with -name=axiom following unnecessary
+;; (dolist (con (|allConstructors|))
+;; (let ((sourcefile (getdatabase con 'sourcefile)))
+;; (if sourcefile
+;; (set (foam::axiomxl-file-init-name (pathname-name sourcefile))
+;; NOPfuncall))))
+ (set (foam::axiomxl-file-init-name "axiom") NOPfuncall)
+;; (set (foam::axiomxl-file-init-name "axclique") NOPfuncall)
+ (set (foam::axiomxl-file-init-name "filecliq") NOPfuncall)
+ (set (foam::axiomxl-file-init-name "attrib") NOPfuncall)
+;; following needs to happen inside restart since $AXIOM may change
+ (let ((asharprootlib (strconc (|getEnv| "AXIOM") "/aldor/lib/")))
+ (set-file-getter (strconc asharprootlib "runtime"))
+ (set-file-getter (strconc asharprootlib "lang"))
+ (set-file-getter (strconc asharprootlib "attrib"))
+ (set-file-getter (strconc asharprootlib "axlit"))
+ (set-file-getter (strconc asharprootlib "minimach"))
+ (set-file-getter (strconc asharprootlib "axextend"))))
+
+
+
+;---------------------------------------------------------------------
+
+; how the magic works:
+; when a )library is done on a new compiler file we set up multiple
+; functions (refered to as autoloaders). there is an autoloader
+; stored in the symbol-function of the G-filename (e.g. G-basic)
+; (see set-file-getter function)
+; and an autoloader stored in the symbol-function of every domain
+; in the basic.as file ( asharpMkAutoloadFunctor )
+; When a domain is needed the autoloader for the domain is executed.
+; this autoloader invokes file-getter-name to get the name of the
+; file (eg basic) and evaluates the name. the FIRST time this is done
+; for a file the file will be loaded by its autoloader, then it will
+; return the file object. every other time the file is already
+; loaded and the file object is returned directly.
+; Once the file object is gotten getconstructor is called to get the
+; domain. the FIRST time this is done for the domain the autoloader
+; invokes the file object. every other time the domain already
+; exists.
+;(defvar *this-file* "no-file")
+
+(defmacro |CCall| (fun &rest args)
+ (let ((ccc (gensym)) (cfun (gensym)) (cenv (gensym)))
+ `(let ((,ccc ,fun))
+ (let ((,cfun (|ClosFun| ,ccc))
+ (,cenv (|ClosEnv| ,ccc)))
+ (funcall ,cfun ,@args ,cenv )))))
+
+(defmacro |ClosFun| (x) `(car ,x))
+(defmacro |ClosEnv| (x) `(cdr ,x))
+
+(defun file-runner (name)
+ (declare (special foam-user::|G-domainPrepare!|))
+ (|CCall| foam-user::|G-domainPrepare!| (|CCall| name)))
+
+(defun getConstructor (file-fn asharp-name)
+ (|CCall| file-fn)
+; (eval (cdr (assoc file-id (get name 'asharp-name) :test #'equal))))
+ (eval asharp-name))
+
+(defun getop (dom op type)
+ (declare (special foam-user::|G-domainGetExport!|))
+ (|CCall| foam-user::|G-domainGetExport!| dom
+ (|hashString| (symbol-name op)) type))
+
+; the asharp compiler will allow both constant domains and domains
+; which are functions. localasy sets the autoload property so that
+; the symbol-function contains a function that, when invoked with
+; the correct number of args will return a domain.
+
+; this function is called if we are given a new compiler domain
+; which is a function. the symbol-function of the domain is set
+; to call the function with the correct number of arguments.
+
+(defun wrapDomArgs (obj type?)
+ (cond ((not type?) obj)
+ (t (|makeOldAxiomDispatchDomain| obj))))
+
+;; CCL doesn't have closures, so we use an intermediate function in
+;; asharpMkAutoLoadFunctor.
+#+:CCL
+(defun mkFunctorStub (func cosig cname)
+ (setf (symbol-function cname)
+ (if (vectorp (car func))
+ `(lambda () ',func) ;; constant domain
+ `(lambda (&rest args2)
+ (apply ',(|ClosFun| func)
+ (nconc
+ (mapcar #'wrapDomArgs args2 ',(cdr cosig))
+ (list ',(|ClosEnv| func))))))))
+
+#+:CCL
+(defun asharpMkAutoLoadFunctor (file cname asharp-name cosig)
+ (setf (symbol-function cname)
+ `(lambda (&rest args)
+ (mkFunctorStub
+ (getconstructor (eval (file-getter-name ',file)) ',asharp-name)
+ ',cosig ',cname)
+ (apply ',cname args))))
+
+#-:CCL
+(defun asharpMkAutoLoadFunctor (file cname asharp-name cosig)
+ (setf (symbol-function cname)
+ #'(lambda (&rest args)
+ (let ((func (getconstructor (eval (file-getter-name file)) asharp-name)))
+ (setf (symbol-function cname)
+ (if (vectorp (car func))
+ #'(lambda () func) ;; constant domain
+ #'(lambda (&rest args)
+ (apply (|ClosFun| func)
+ (nconc
+ (mapcar #'wrapDomArgs args (cdr cosig))
+ (list (|ClosEnv| func)))))))
+ (apply cname args)))))
+
+;; CCL doesn't have closures, so we use an intermediate function in
+;; asharpMkAutoLoadCategory.
+#+:CCL
+(defun mkCategoryStub (func cosig packname)
+ (setf (symbol-function packname)
+ (if (vectorp (car func))
+ `(lambda (self) ;; constant category
+ (|CCall| (elt ',(car func) 5) ',(cdr func) (wrapDomArgs self t)))
+ `(lambda (self &rest args)
+ (let ((precat
+ (apply (|ClosFun| ',func)
+ (nconc
+ (mapcar #'wrapDomArgs args ',(cdr cosig))
+ (list (|ClosEnv| ',func))))))
+ (|CCall| (elt (car precat) 5) (cdr precat) (wrapDomArgs self t)))))
+))
+
+#+:CCL
+(defun asharpMkAutoLoadCategory (file cname asharp-name cosig)
+ (asharpMkAutoLoadFunctor file cname asharp-name cosig)
+ (let ((packname (INTERN (STRCONC cname "&"))))
+ (setf (symbol-function packname)
+ `(lambda (self &rest args)
+ (mkCategoryStub
+ (getconstructor (eval (file-getter-name ',file)) ',asharp-name)
+ ',cosig ',packname)
+ (apply ',packname self args)))))
+
+#-:CCL
+(defun asharpMkAutoLoadCategory (file cname asharp-name cosig)
+ (asharpMkAutoLoadFunctor file cname asharp-name cosig)
+ (let ((packname (INTERN (STRCONC cname '"&"))))
+ (setf (symbol-function packname)
+ #'(lambda (self &rest args)
+ (let ((func (getconstructor (eval (file-getter-name file)) asharp-name)))
+ (setf (symbol-function packname)
+ (if (vectorp (car func))
+ #'(lambda (self)
+ (|CCall| (elt (car func) 5) (cdr func) (wrapDomArgs self t))) ;; constant category
+ #'(lambda (self &rest args)
+ (let ((precat
+ (apply (|ClosFun| func)
+ (nconc
+ (mapcar #'wrapDomArgs args (cdr cosig))
+ (list (|ClosEnv| func))))))
+ (|CCall| (elt (car precat) 5) (cdr precat) (wrapDomArgs self t))))))
+ (apply packname self args))))))
+
+#+:CCL
+(defun asharpMkAutoLoadFunction (file asharpname)
+ (set asharpname
+ (cons
+ `(lambda (&rest l)
+ (let ((args (butlast l))
+ (func (getconstructor (eval (file-getter-name ',file)) ',asharpname)))
+ (apply (car func) (append args (list (cdr func))))))
+ ())))
+
+#-:CCL
+(defun asharpMkAutoLoadFunction (file asharpname)
+ (set asharpname
+ (cons
+ #'(lambda (&rest l)
+ (let ((args (butlast l))
+ (func (getconstructor (eval (file-getter-name file)) asharpname)))
+ (apply (car func) (append args (list (cdr func))))))
+ ())))
+
+; this function will return the internal name of the file object getter
+
+(defun file-getter-name (filename)
+ (foam::axiomxl-file-init-name (pathname-name filename)))
+
+;;need to initialize |G-filename| to a function which loads file
+;; and then returns the new value of |G-filename|
+
+(defun set-file-getter (filename)
+ (let ((getter-name (file-getter-name filename)))
+ (set getter-name
+ (cons #'init-file-getter (cons getter-name filename)))))
+
+(defun init-file-getter (env)
+ (let ((getter-name (car env))
+ (filename (cdr env)))
+#-:CCL
+ (load filename)
+#+:CCL
+ (load-module filename)
+ (|CCall| (eval getter-name))))
+
+(defun set-lib-file-getter (filename cname)
+ (let ((getter-name (file-getter-name filename)))
+ (set getter-name
+ (cons #'init-lib-file-getter (cons getter-name cname)))))
+
+(defun init-lib-file-getter (env)
+ (let* ((getter-name (car env))
+ (cname (cdr env))
+ (filename (getdatabase cname 'object)))
+#-:CCL
+ (load filename)
+#+:CCL
+ (load-module (pathname-name filename))
+ (|CCall| (eval getter-name))))
+
+;; following 2 functions are called by file-exports and file-imports macros
+(defun foam::process-import-entry (entry)
+ (let* ((asharpname (car entry))
+ (stringname (cadr entry))
+ (hcode (caddr entry))
+ (libname (cadddr entry))
+ (bootname (intern stringname 'boot)))
+ (declare (ignore libname))
+ (if (and (eq hcode 'foam-user::|initializer|) (not (boundp asharpname)))
+ (error (format nil "AxiomXL file ~s is missing!" stringname)))
+ (unless (or (not (numberp hcode)) (zerop hcode) (boundp asharpname))
+ (when (|constructor?| bootname)
+ (set asharpname
+ (if (getdatabase bootname 'niladic)
+ (|makeLazyOldAxiomDispatchDomain| (list bootname))
+ (cons '|runOldAxiomFunctor| bootname))))
+ (when (|attribute?| bootname)
+ (set asharpname (|makeLazyOldAxiomDispatchDomain| bootname))))))
+
+
+
+;(defun foam::process-export-entry (entry)
+; (let* ((asharpname (car entry))
+; (stringname (cadr entry))
+; (hcode (caddr entry))
+; (libname (cadddr entry))
+; (bootname (intern stringname 'boot)))
+; (declare (ignore libname))
+; (when (numberp hcode)
+; (setf (get bootname 'asharp-name)
+; (cons (cons *this-file* asharpname)
+; (get bootname 'asharp-name)))
+; )))
+
+
+
+
+
+
+
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}