;;;----- Licensing notice ---------------------------------------------------
;;;
-;;; This file is part of the Sensble Object Design, an object system for C.
+;;; This file is part of the Sensible Object Design, an object system for C.
;;;
;;; SOD is free software; you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
`((setf (documentation ',name 'variable) ,documentation)))
(add-module-binding ',name (lambda () ,value-form))))
-(export 'call-with-module-environment)
-(defun call-with-module-environment (thunk)
- "Invoke THUNK with a new collection of bindings for the module variables."
- (progv
- (mapcar #'car *module-bindings-alist*)
- (mapcar (compose #'cdr #'funcall) *module-bindings-alist*)
- (funcall thunk)))
+(export 'with-module-environment)
+(defmacro with-module-environment ((&optional (module '*module*)) &body body)
+ "Evaluate the BODY with MODULE's variable bindings in scope."
+ `(call-with-module-environment (lambda () ,@body) ,module))
;;;--------------------------------------------------------------------------
;;; The reset switch.
When `clear-the-decks' is called, the BODY will be evaluated as a progn.
The relative order of `clear-the-decks' operations is unspecified."
- `(add-clear-the-decks-function ',name (lambda () ,@body)))
+ (multiple-value-bind (docs decls body) (parse-body body)
+ `(add-clear-the-decks-function ',name (lambda ()
+ ,@docs ,@decls
+ (block ,name ,@body)))))
(export 'clear-the-decks)
(defun clear-the-decks ()
During module 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'
+ an instance of whatever type is requested in the module's `:module-class'
property.")
(export 'module-import)
It's not usual to modify the current module. Inserting things into the
`*module-type-map*' is a good plan.")
- (:method (object) nil))
+ (:method (object)
+ (declare (ignore object))
+ nil))
(export 'add-to-module)
(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'
+ The module items participate in the `module-import' and `hook-output'
protocols."))
(export 'finalize-module)
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' taking care of looking at interesting properties, just
- to make sure they're ticked off.)"))
+ according to the class choice set in the module's `:module-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' taking care of looking at interesting properties, just to make
+ sure they're ticked off.)"))
;;;--------------------------------------------------------------------------
;;; Module objects.
-(export '(module module-name module-pset module-items module-dependencies))
+(export '(module module-name module-pset module-errors
+ module-items module-dependencies))
(defclass module ()
((name :initarg :name :type pathname :reader module-name)
- (pset :initarg :pset :initform (make-pset) :type pset :reader module-pset)
+ (%pset :initarg :pset :initform (make-pset)
+ :type pset :reader module-pset)
+ (errors :initarg :errors :initform 0 :type fixnum :reader module-errors)
(items :initarg :items :initform nil :type list :accessor module-items)
(dependencies :initarg :dependencies :initform nil
:type list :accessor module-dependencies)
+ (variables :initarg :variables :type list :accessor module-variables
+ :initform (mapcar (compose #'cdr #'funcall)
+ *module-bindings-alist*))
(state :initarg :state :initform nil :accessor module-state))
(:documentation
"A module is a container for the definitions made in a source file.
* A list of other modules that this one depends on.
+ * A list of module-variable values, in the order in which they're named
+ in `*module-bindings-alist*'.
+
Modules are usually constructed by the `read-module' function, though
there's nothing to stop fancy extensions building modules
programmatically."))
,@(and truenamep `(:truename ,truename))
,@(and locationp `(:location ,location))))
+(export 'with-temporary-module)
+(defmacro with-temporary-module ((&key) &body body)
+ "Evaluate BODY within the context of a temporary module."
+ `(call-with-temporary-module (lambda () ,@body)))
+
+;;;--------------------------------------------------------------------------
+;;; Code fragments.
+
+(export '(c-fragment c-fragment-text))
+(defclass c-fragment ()
+ ((location :initarg :location :type file-location :reader file-location)
+ (text :initarg :text :type string :reader c-fragment-text))
+ (:documentation
+ "Represents a fragment of C code to be written to an output file.
+
+ A C fragment is aware of its original location, and will bear proper
+ `#line' markers when written out."))
+
;;;----- That's all, folks --------------------------------------------------