Closer-mop — Portable MOP Access for Common Lisp
Table of Contents
- Definition
- Functions Used in Tolk
class-slots— all effective slots of a classclass-direct-slots— slots defined directly on a classslot-definition-name— name of a slot definitionslot-definition-readers— reader methods for a slotclass-finalized-pandfinalize-inheritanceclass-precedence-list— the class hierarchy in dispatch order
- Why This Requires
eval-whenin Tolk - Loading
- Related
Definition
closer-mop is a portability library for the Common Lisp Meta-Object
Protocol (MOP). The MOP is a standard extension to CLOS that allows programs
to introspect and modify the class system itself: querying slot definitions,
class hierarchies, generic function dispatch, and so on. Different CL
implementations expose the MOP with slightly different APIs; closer-mop
smooths these differences.
Online documentation: github.com/pcostanza/closer-mop MOP reference: clos-mop.hexstruct.com
Functions Used in Tolk
closer-mop is used exclusively in tolk/utils to support defmethod-bind.
The relevant functions are:
class-slots — all effective slots of a class
(closer-mop:class-slots (find-class 'num))
;; => (#<EFFECTIVE-SLOT-DEFINITION N>)
Returns the list of effective slot definitions for a class, including inherited slots. Each slot definition object carries the slot name, type, initargs, and any readers/writers.
class-slots requires the class to be finalised (see class-finalized-p
and finalize-inheritance below).
class-direct-slots — slots defined directly on a class
Returns only the slots defined in the class's own defclass form, not
inherited ones.
slot-definition-name — name of a slot definition
(closer-mop:slot-definition-name slot-def) ; => :N (or N, implementation-dependent)
slot-definition-readers — reader methods for a slot
(closer-mop:slot-definition-readers slot-def) ; => (N-READER) or NIL
defmethod-bind uses this to decide whether to use (:accessors ...) or
(:slots ...) in the generated bind call: if a reader exists, the accessor
is more efficient (avoids slot-value lookup); if not, :slots is used.
class-finalized-p and finalize-inheritance
(unless (closer-mop:class-finalized-p class)
(closer-mop:finalize-inheritance class))
A class is finalised when its effective slot list has been computed (taking
inheritance into account). SBCL finalises classes automatically on first
instantiation, but at macro-expansion time (inside defmethod-bind's
eval-when) the class may not yet have been instantiated. finalize-inheritance
forces this computation so that slot introspection works.
class-precedence-list — the class hierarchy in dispatch order
(closer-mop:class-precedence-list (find-class 'plus))
;; => (#<STANDARD-CLASS PLUS> #<STANDARD-CLASS ARITH-BINARY-OP>
;; #<STANDARD-CLASS AST-NODE> #<STANDARD-CLASS STANDARD-OBJECT> ...)
Used in tolk/utils class-readers to walk the inheritance chain and
collect all reader methods, including those inherited from superclasses.
Why This Requires eval-when in Tolk
defmethod-bind is a macro that introspects class slot definitions at
macro-expansion time to decide how to generate the bind body. For this
to work, the class must be defined and finalised before the macro expands.
In tolk, AST classes are therefore wrapped in:
(eval-when (:compile-toplevel :load-toplevel :execute)
(defclass ast-node () ())
(defclass num (ast-node) ((n :type number :initarg :n)))
(defclass arith-binary-op (ast-node) ...)
(defclass plus (arith-binary-op) ...)
(defclass mult (arith-binary-op) ...))
eval-when (:compile-toplevel ...) ensures the class definitions are
evaluated when the compiler processes the file, not just when the file is
loaded at runtime. Without this, defmethod-bind would try to introspect
classes that do not yet exist in the compile-time environment, causing a
"class not found" error.
See Defmethod-bind for the full macro and its use of closer-mop.
Loading
(ql:quickload :closer-mop)
Related
- Defmethod-bind — the macro that uses closer-mop for slot introspection
- Metabang-bind — the binding macro that defmethod-bind generates calls to
- Tolk — uses closer-mop via defmethod-bind
- Wikipedia: CLOS