Massive reorganization in progress.
[sod] / pre-reorg / module.lisp
similarity index 60%
rename from module.lisp
rename to pre-reorg/module.lisp
index 6f8aeec..604703f 100644 (file)
 (cl:in-package #:sod)
 
 ;;;--------------------------------------------------------------------------
-;;; Module basics.
-
-(defclass module ()
-  ((name :initarg :name :type pathname :reader module-name)
-   (pset :initarg :pset :initform (make-pset) :type pset :reader module-pset)
-   (items :initarg :items :initform nil :type list :accessor module-items)
-   (dependencies :initarg :dependencies :initform nil
-                :type list :accessor module-dependencies)
-   (state :initarg :state :initform nil :accessor module-state))
-  (:documentation
-   "A module is a container for the definitions made in a source file.
-
-   Modules are the fundamental units of translation.  The main job of a
-   module is to remember which definitions it contains, so that they can be
-   translated and written to output files.  The module contains the following
-   handy bits of information:
-
-     * A (path) name, which is the filename we used to find it.  The default
-       output filenames are derived from this.  (We use the file's truename
-       as the hash key to prevent multiple inclusion, and that's a different
-       thing.)
-
-     * A property list containing other useful things.
-
-     * A list of the classes defined in the source file.
-
-     * Lists of C fragments to be included in the output header and C source
-       files.
-
-     * A list of other modules that this one depends on.
-
-   Modules are usually constructed by the PARSE-MODULE function, which is in
-   turn usually invoked by IMPORT-MODULE, though there's nothing to stop
-   fancy extensions building modules programmatically."))
-
-(defparameter *module* nil
-  "The current module under construction.
-
-   This is always an instance of MODULE.  Once we've finished constructing
-   it, we'll call CHANGE-CLASS to turn it into an instance of whatever type
-   is requested in the module's :LISP-CLASS property.")
-
-(defgeneric module-import (object)
-  (:documentation
-   "Import definitions into the current environment.
-
-   Instructs the OBJECT to import its definitions into the current
-   environment.  Modules pass the request on to their constituents.  There's
-   a default method which does nothing at all.
-
-   It's not usual to modify the current module.  Inserting things into the
-   *TYPE-MAP* is a good plan.")
-  (:method (object) nil))
-
-(defgeneric add-to-module (module item)
-  (:documentation
-   "Add ITEM to the MODULE's list of accumulated items.
-
-   The module items participate in the MODULE-IMPORT and ADD-OUTPUT-HOOKS
-   protocols."))
-
-(defgeneric finalize-module (module)
-  (:documentation
-   "Finalizes a module, setting everything which needs setting.
-
-   This isn't necessary if you made the module by hand.  If you've
-   constructed it incrementally, then it might be a good plan.  In
-   particular, it will change the class (using CHANGE-CLASS) of the module
-   according to the class choice set in the module's :LISP-CLASS property.
-   This has the side effects of calling SHARED-INITIALIZE, setting the
-   module's state to T, and checking for unrecognized properties.  (Therefore
-   subclasses should add a method to SHARED-INITIALIZE should take care of
-   looking at interesting properties, just to make sure they're ticked
-   off.)"))
-
-(defmethod module-import ((module module))
-  (dolist (item (module-items module))
-    (module-import item)))
-
-(defmethod add-to-module ((module module) item)
-  (setf (module-items module)
-       (nconc (module-items module) (list item)))
-  (module-import item))
-
-(defmethod shared-initialize :after ((module module) slot-names &key pset)
-  "Tick off known properties on the property set."
-  (declare (ignore slot-names))
-  (when pset
-    (dolist (prop '(:guard))
-      (get-property pset prop nil))))
-
-(defmethod finalize-module ((module module))
-  (let* ((pset (module-pset module))
-        (class (get-property pset :lisp-class :symbol 'module)))
-
-    ;; Always call CHANGE-CLASS, even if it's the same one; this will
-    ;; exercise the property-set fiddling in SHARED-INITIALIZE and we can
-    ;; catch unknown-property errors.
-    (change-class module class :state t :pset pset)
-    (check-unused-properties pset)
-    module))
-
-;;;--------------------------------------------------------------------------
 ;;; Module importing.
 
-(defun build-module
-    (name body-func &key (truename (probe-file name)) location)
-  (let ((*module* (make-instance 'module
-                                :name (pathname name)
-                                :state (file-location location)))
-       (*type-map* (make-hash-table :test #'equal)))
-    (module-import *builtin-module*)
-    (when truename
-      (setf (gethash truename *module-map*) *module*))
-    (unwind-protect
-        (progn
-          (funcall body-func)
-          (finalize-module *module*))
-      (when (and truename (not (eq (module-state *module*) t)))
-       (remhash truename *module-map*)))))
-
-(defmacro define-module
-    ((name &key (truename nil truenamep) (location nil locationp))
-     &body body)
-  `(build-module ,name
-                (lambda () ,@body)
-                ,@(and truenamep `(:truename ,truename))
-                ,@(and locationp `(:location ,location))))
-
 (defun read-module (pathname &key (truename (truename pathname)) location)
   "Reads a module.
 
        :report "Ignore the error and continue parsing."
        nil))))
 
-;;;--------------------------------------------------------------------------
-;;; Type definitions.
-
-(defclass type-item ()
-  ((name :initarg :name :type string :reader type-name))
-  (:documentation
-   "A note that a module exports a type.
-
-   We can only export simple types, so we only need to remember the name.
-   The magic simple-type cache will ensure that we get the same type object
-   when we do the import."))
-
-(defmethod module-import ((item type-item))
-  (let* ((name (type-name item))
-        (def (gethash name *type-map*))
-        (type (make-simple-type name)))
-    (cond ((not def)
-          (setf (gethash name *type-map*) type))
-         ((not (eq def type))
-          (error "Conflicting types `~A'" name)))))
-
-(defmethod module-import ((class sod-class))
-  (record-sod-class class))
-
 (defmethod parse-module-declaration ((tag (eql :typename)) lexer pset)
   "module-decl ::= `typename' id-list `;'"
   (loop (let ((name (require-token lexer :id)))
 ;;;--------------------------------------------------------------------------
 ;;; Fragments.
 
-(defclass code-fragment-item ()
-  ((fragment :initarg :fragment :type c-fragment :reader code-fragment)
-   (reason :initarg :reason :type keyword :reader code-fragment-reason)
-   (name :initarg :name :type t :reader code-fragment-name)
-   (constraints :initarg :constraints :type list
-               :reader code-fragment-constraints))
-  (:documentation
-   "A plain fragment of C to be dropped in at top-level."))
-
-(defmacro define-fragment ((reason name) &body things)
-  (categorize (thing things)
-      ((constraints (listp thing))
-       (frags (typep thing '(or string c-fragment))))
-    (when (null frags)
-      (error "Missing code fragment"))
-    (when (cdr frags)
-      (error "Multiple code fragments"))
-    `(add-to-module
-      *module*
-      (make-instance 'code-fragment-item
-                    :fragment ',(car frags)
-                    :name ,name
-                    :reason ,reason
-                    :constraints (list ,@(mapcar (lambda (constraint)
-                                                   (cons 'list constraint))
-                                                 constraints))))))
-
 (defmethod parse-module-declaration ((tag (eql :code)) lexer pset)
   "module-decl ::= `code' id `:' id [constraint-list] `{' c-fragment `}'
    constraint ::= id*"
     (finalize-sod-class class)
     (add-to-module *module* class)))
 
-;;;--------------------------------------------------------------------------
-;;; Modules.
-
-#+(or)
-(defun parse-module (lexer)
-  "Parse a module from the given LEXER.
-
-   The newly constructed module is returned.  This is the top-level parsing
-   function."
-
-  (let ((hfrags nil)
-       (cfrags nil)
-       (classes nil)
-       (plist nil)
-       (deps nil))
-
-    (labels ((fragment (func)
-              (next-token lexer)
-              (when (require-token lexer #\{ :consumep nil)
-                (let ((frag (scan-c-fragment lexer '(#\}))))
-                  (next-token lexer)
-                  (require-token lexer #\})
-                  (funcall func frag)))))
-
-      (tagbody
-
-       top
-        ;; module : empty | module-def module
-        ;;
-        ;; Just read module-defs until we reach the end of the file.
-        (case (token-type lexer)
-
-          (:eof
-           (go done))
-          (#\;
-           (next-token lexer)
-           (go top))
-
-          ;; module-def : `lisp' sexp
-          ;;
-          ;; Process an in-line Lisp form immediately.
-          (:lisp
-           
-           (next-token lexer)
-           (go top))
-
-          ;; module-def : `typename' ids `;'
-          ;; ids : id | ids `,' id
-          ;;
-          ;; Add ids as registered type names.  We don't need to know what
-          ;; they mean at this level.
-          (:typename
-           (next-token lexer)
-           (loop
-             (let ((id (require-token lexer :id)))
-               (cond ((null id)
-                      (return))
-                     ((gethash id *type-map*)
-                      (cerror* "Type ~A is already defined" id))
-                     (t
-                      (setf (gethash id *type-map*)
-                            (make-instance 'simple-c-type :name id))))
-               (unless (eql (token-type lexer) #\,)
-                 (return))
-               (next-token lexer)))
-           (go semicolon))
-
-          ;; module-def : `source' `{' c-stuff `}'
-          ;; module-def : `header' `{' c-stuff `}'
-          (:source
-           (fragment (lambda (frag) (push frag cfrags)))
-           (go top))
-          (:header
-           (fragment (lambda (frag) (push frag hfrags)))
-           (go top))
-
-          ;; Anything else is an error.
-          (t
-           (cerror* "Unexpected token ~A ignored" (format-token lexer))
-           (next-token lexer)
-           (go top)))
-
-       semicolon
-        ;; Scan a terminating semicolon.
-        (require-token lexer #\;)
-        (go top)
-
-       done)
-
-      ;; Assemble the module and we're done.
-      (make-instance 'module
-                    :name (stream-pathname (lexer-stream lexer))
-                    :plist plist
-                    :classes classes
-                    :header-fragments hfrags
-                    :source-fragments cfrags
-                    :dependencies deps))))
-
 ;;;----- That's all, folks --------------------------------------------------