diff --git a/Code/documentation.lisp b/Code/documentation.lisp index 3cf90a0..f5554e4 100644 --- a/Code/documentation.lisp +++ b/Code/documentation.lisp @@ -10,9 +10,11 @@ The status is either NIL, meaning not fbound, or :FUNCTION, :MACRO, or :SPECIAL- (function sys:operator-cell "Retrieve the cell for OPERATOR-NAME's fbinding in ENVIRONMENT. The nature of the cell is implementation-defined, except that it must work with OPERATOR-CELL-VALUE, OPERATOR-CELL-BOUNDP, and OPERATOR-CELL-MAKUNBOUND. -Calls to this function always retrieve the same cell given the same arguments, regardless of the operator being fbound or not.") +If no cell yet exists in this environment, NIL is returned. + +See ENSURE-OPERATOR-CELL") (function sys:ensure-operator-cell - "Ensure that OPERATOR-NAME has a cell in ENVIRONMENT, and return that cell.") + "Ensure that OPERATOR-NAME has a cell in ENVIRONMENT, and return that cell. Calls to this function always retrieve the same cell given the same arguments, regardless of the operator being fbound or not.") (function sys:compiler-macro-function "Return the compiler macro function for OPERATOR-NAME in ENVIRONMENT. This is NIL if no function has been set, or else the object set by (SETF COMPILER-MACRO-FUNCTION).") @@ -24,6 +26,20 @@ This is NIL if no expander has been set, or else the object set by (SETF SETF-EX The nature of a setf expander is otherwise implementation-defined. One choice would be to have it as a function of two arguments, a place and an environment, analogous to a macro expander, that returns the setf expansion.") (function (setf sys:setf-expander) "Set the setf expander for OPERATOR-NAME in ENVIRONMENT.") + (function sys:operator-inline + "Return the inline proclamation for the given operator. This is either CL:INLINE, CL:NOTINLINE, or NIL, meaning no proclamation either way.") + (function (setf sys:operator-inline) + "Set the inline proclamation for the given operator.") + (function sys:operator-inline-known-p + "Return true iff the inline proclamation for this operator has been set. This function exists so that the proclamation can be set to NIL in a child environment without the inheritance-aware high level API functions deciding to consult a parent instead.") + (function sys:operator-inline-data + "Return the inline data for the given operator. The nature of this data is defined by the client.") + (function (setf sys:operator-inline-data) + "Set the inline data for the given operator.") + (function sys:operator-ftype + "Return the proclaimed ftype for the given operator. Clostrum does not impose any kind of representation of types on clients, so using OPERATOR-FTYPE before an ftype is proclaimed (by (SETF OPERATOR-FTYPE)) may result in an error. Implementations are recommended to install a default type themselves to avoid this.") + (function (setf sys:operator-ftype) + "Proclaim an ftype for the given operator. Clostrum does not impose any kind of representation of types on clients.") (function sys:operator-cell-value "Get the value stored in CELL. The CELL is an object returned by OPERATOR-CELL. If OPERATOR-CELL-BOUNDP is not true, a function signals UNDEFINED-FUNCTION when called with any arguments is returned.") (function (setf sys:operator-cell-value) @@ -51,6 +67,16 @@ Calls to this function always retrieve the same cell given the same arguments, r This is NIL if no expander has been set, or else the object set by (SETF VARIABLE-MACRO-EXPANDER).") (function (setf sys:variable-macro-expander) "Set the symbol macro expander for VARIABLE-NAME in ENVIRONMENT.") + (function sys:variable-type + "Return the proclaimed type for the given variable. Clostrum does not impose any kind of representation of types on clients, so using VARIABLE-FTYPE before a type is proclaimed (by (SETF VARIABLE-TYPE)) may result in an error. Implementations are recommended to install a default type themselves to avoid this.") + (function (setf sys:variable-type) + "Proclaim a type for the given variable. Clostrum does not impose any kind of representation of types on clients.") + (function sys:symbol-plist + "Return the plist for a symbol.") + (function (setf sys:symbol-plist) + "Set the plist for a symbol.") + (function sys:symbol-plist-known-p + "Return true iff the symbol's plist in this environment has been set. This is used by the high-level API to disambiguate the situation in which a symbol plist has been set to NIL in one environment but set to something non-NIL in a parent.") (function sys:variable-cell-value "Get the value stored in CELL. The CELL is an object returned by VARIABLE-CELL. If VARIABLE-CELL-BOUNDP is not true of the cell, the effects are undefined.") (function sys:variable-cell-boundp @@ -87,6 +113,12 @@ The return values of this function are undefined.")) "Find the package bound to NAME in ENVIRONMENT, or NIL if none has been defined.") (function (setf sys:find-package) "Set the package bound to NAME in ENVIRONMENT.") + (function sys:package-names + "Return a fresh list of all names of PACKAGE in ENVIRONMENT.") + (function sys:package-name + "Return the name of PACKAGE in ENVIRONMENT, or NIL if it has none.") + (function (setf sys:package-name) + "Set the name of PACKAGE in ENVIRONMENT. Note that this function does not necessarily establish the name for FIND-PACKAGE.") (function sys:map-all-packages "Call FUNCTION on all PACKAGES in ENVIRONMENT, in some undefined order. This can be used for example to implement LIST-ALL-PACKAGES.") (function sys:proclamation @@ -120,6 +152,8 @@ If the operator names a macro, the object passed to (SETF MACRO-FUNCTION) will b "As CL:SPECIAL-OPERATOR-P. Return true iff OPERATOR-NAME names a special operator in ENVIRONMENT.") (function env:make-special-operator "Make OPERATOR-NAME a special operator in ENVIRONMENT. Future calls to FDEFINITION will return the object given as NEW.") + (function env:note-function + "Make OPERATOR-NAME a function in ENVIRONMENT, without providing a definition. The name will not be fbound, but this information can be retrieved by OPERATOR-STATUS. This function is provided to implement the (optional) compile time side effect of DEFUN.") (function sys:setf-expander "Return the setf expander for OPERATOR-NAME in ENVIRONMENT. This is NIL if no expander has been set, or else the object set by (SETF SETF-EXPANDER). @@ -136,6 +170,10 @@ The nature of a setf expander is otherwise implementation-defined. One choice wo "As CL:BOUNDP. Return true iff VARIABLE-NAME has a global value in ENVIRONMENT.") (function env:makunbound "As CL:MAKUNBOUND. Make VARIABLE-NAME have no global value in ENVIRONMENT. Returns VARIABLE-NAME.") + (function env:symbol-plist + "As CL:SYMBOL-PLIST.") + (function (setf env:symbol-plist) + "As (SETF CL:SYMBOL-PLIST).") (function env:make-variable "Functional version of CL:DEFVAR. Proclaim VARIABLE-NAME special, and if it has no global value and VALUE is provided, set its global value to VALUE.") (function env:make-parameter diff --git a/README.md b/README.md index 31bdfca..e6c123f 100644 --- a/README.md +++ b/README.md @@ -25,24 +25,46 @@ client-specific environment classes. # API -The Clostrum API is divided into two parts, a "high level" package `clostrum`, and a "low level" package `clostrum-sys`. `clostrum-sys` has generic functions that access environments directly and simply, without error checking, while `clostrum`'s generic functions mimic standard Common Lisp operators' more complex behavior. `clostrum` has default methods implemented in terms of `clostrum-sys`, so environment implementation need only specialize the `clostrum-sys` functions in order to make `clostrum`'s high level facilities available. +The Clostrum API is divided into two parts, a "high level" package `clostrum`, and a "low level" package `clostrum-sys`. `clostrum-sys` has generic functions that access environments directly and simply, without error checking, while `clostrum`'s generic functions mimic standard Common Lisp operators' more complex behavior and account for inheritance. `clostrum` has default methods implemented in terms of `clostrum-sys`, so environment implementation need only specialize the `clostrum-sys` functions in order to make `clostrum`'s high level facilities available. Users (rather than implementors) of the Clostrum protocol should only need to use the `clostrum` package. ## High level interface -The `clostrum` package makes available environment manipulation functions and accessors similar to those in the standard: `fdefinition`, `fboundp`, `fmakunbound`, `macro-function`, `special-operator-p` for functions; `symbol-value`, `boundp`, `makunbound` for variables; `find-class` for classes; `find-package` for packages; and `macroexpand-1`, `macroexpand`, and `constantp`. +For operating on run-time environments, the `clostrum` package makes available environment manipulation functions and accessors similar to those in the standard: `fdefinition`, `fboundp`, `fmakunbound`, `macro-function`, `special-operator-p` for functions; `symbol-value`, `boundp`, `makunbound`, `symbol-plist` for variables; `find-class` for classes; `find-package` for packages; and `macroexpand-1`, `macroexpand`, and `constantp`. -There are additional functions and accessors corresponding to some other Lisp operators. `setf-expander` can be used for `define-setf-expander`; `make-variable`, `make-parameter`, `make-constant`, and `make-symbol-macro` for `defvar`, `defparameter`, `defconstant`, and `deine-symbol-macro` respectively; `proclamation` can be ued for the `declaration` proclamation or CLtL2's `define-declaration`; and `make-type` and `type-expander` for `deftype`, along with `type-expand-1` and `type-expand` to work with type specifiers. +There are additional functions and accessors corresponding to some other Lisp operators. `setf-expander` can be used for `define-setf-expander`; `make-variable`, `make-parameter`, `make-constant`, and `make-symbol-macro` for `defvar`, `defparameter`, `defconstant`, and `define-symbol-macro` respectively; and `make-type` and `type-expander` for `deftype`, along with `type-expand-1` and `type-expand` to work with type specifiers. + +For proclamations, `proclamation` can be used for `declaration` or CLtL2's `define-declaration`. `variable-type` covers `type`, and `special` proclamations can be done with `make-variable`. `operator-ftype` handles `ftype` and `operator-inline` `inline`. User-defined inlining data, such as a definition, can be associated with an operator through `operator-inline-data`. + +`note-function` will declare an operator to be a function without needing a definition for said function. This is useful for the compile-time effect of `defun`. + +The package environment can be accessed via `find-package`. New nicknames for a package can be installed via `(setf find-package)`, and the list of all names for a package in an environment retrieved via `package-names`. All packages in an environment can be iterated over with `map-all-packages`. Additionally, the canonical name of a package is considered part of the environment as well, and can be accessed via `package-name`. ### Compilation environments -The compilation environment interface is comparatively simple: `function-description`, `variable-description`, and `type-description` access named data in an environment. The nature of these compilation descriptions is left undefined by Clostrum, but using [Trucler](https://github.com/s-expressionists/Trucler) would be appropriate. +Compilation environments support a subset of the runtime environment operations. They lack package mappings, and functions only needed at runtime like `(setf symbol-value)` are not implemented. `macro-function` and `make-constant` still work. + +## Cells + +Each variable, operator, and type has a _cell_ retrievable by name, and variables and operators have a _status_. The cell is an object of implementation-defined nature, accessed by `-value`, `-boundp`, and `-makunbound` functions, that holds the value of a binding. Cells are an essential part of Clostrum's design and explained more in the paper. The status indicates what kind of binding a variable or operator has, e.g. as a variable or a constant, or a function or a macro. Some statuses can be read but not directly written (in the high-level API). + +In the high level API, cells are retrieved by `ensure-variable-cell`, etc. This will return a cell if it exists or make a new one to return if not. Undefining a variable etc. does _not_ remove the cell, so they can be used for continued access regardless of boundedness. -## Low level interface +## Low-level API -In the low level interface, each variable, operator, and type has a _cell_ retrievable by name, and variables and operators have a _status_. The cell is an object of implementation-defined nature accessed by `-value`, `-boundp`, and `-makunbound` function that holds the value of a binding. Cells are an essential part of Clostrum's design and explained more in the paper. The status indicates what kind of binding a variable or operator has, e.g. as a variable or a constant, or a function or a macro. +The `clostrum-sys` package contains the functions that must be implemented by environment objects for the high level functions to work. These consist of direct access to cells and statuses, along with additional functions for the non-cell properties such as a compiler macro functions. Additionally, a `parent` function should be supported for inheritance, but the rest of the functions do not need to consult parent environments as this is handled by the high-level API. -There are some additional interfaces for values outside the cells, such as setf and type expanders. +# Inheritance semantics + +The Common Lisp standard mentions environments inheriting from each other in the context of compilation (CLHS 3.2.1) but does not describe the semantics in detail. Clostrum supports inherited environments, and the parent of an environment can be read by `parent`; if an environment has no parent, `parent` returns `nil`. + +The basic rule of inherited bindings Clostrum has adopted is as follows: The _values_ in bindings are inherited from parent environments, but the bindings _themselves_ are not. Mutating a binding or making it unbound has no effect on a parent environment; in fact, no operation on a child environment will mutate anything in the parent environment. + +Since the standard only contemplates environment inheritance in the context of compilation, these inheritance semantics are designed to allow `compile-file` operations to mutate an evaluation environment without mutating anything in the parent. For example, a function definition or redefinition within `(eval-when (:compile-toplevel) ...)` can affect an evaluation environment, but after `compile-file` returns, this evaluation environment is discarded, and the startup environment has no trace. # Basic The `clostrum-basic` system is the reference implementation of Clostrum. It implements the low level interface, so the high level interface can be used with the basic environments. The classes `run-time-environment` and `compilation-environment` represent run-time and compilation environments respectively. + +# Trucler + +The `clostrum-trucler` system implements the [Trucler](https://github.com/s-expressionists/Trucler/) protocol for Clostrum environments. The system package has no exports, instead just specializing the Trucler protocol methods.