diff --git a/docs/dev/lcp.md b/docs/dev/lcp.md
index 0b2978bdd..79f2a680b 100644
--- a/docs/dev/lcp.md
+++ b/docs/dev/lcp.md
@@ -1164,7 +1164,7 @@ We have already seen two options that `:clone` accepts: `:return-type` and
`:return-type` expects a function that takes a single argument which is the C++
type name of the class and produces C++ code, which is a valid C++ type
-delcaration. Here we used it to specify that `Clone` function should return a
+declaration. Here we used it to specify that `Clone` function should return a
`std::unique_ptr` to the newly created `Node` to override the default behavior.
When `:return-type` option is not provided and class `T` is a member of an
inheritance hierarchy, `Clone` will return `std::unique_ptr`, where
diff --git a/src/lisp/types.lisp b/src/lisp/types.lisp
index e8d96587e..a99f83eaf 100644
--- a/src/lisp/types.lisp
+++ b/src/lisp/types.lisp
@@ -1039,12 +1039,22 @@ defined.")
defined. The names are ordered from outermost to innermost enclosing class.")
(defmacro define-enum (name values &rest options)
- "Define a C++ enum. Documentation is optional. The only options are
-:documentation and :serialize. Syntax is:
+ "Define a C++ enum.
-;; (define-enum name
-;; (value1 value2 ...)
-;; (:enum-option option-value)*)"
+The syntax is:
+
+ (define-enum
+ (*)
+ *)
+
+NAME should be a designator for a class namestring. VALUE should be a designator
+for an enumerator namestring.
+
+Each ENUM-OPTION is of the type (KEY VALUE). The possible values of KEY are:
+
+- :DOCUMENTATION -- String specifying the Doxygen documentation for the enum.
+
+- :SERIALIZE -- If T, generate serialization code for this enum."
(check-type name (or symbol string))
(let ((documentation (second (assoc :documentation options)))
(enum (gensym (format nil "ENUM-~A" name))))
@@ -1062,65 +1072,120 @@ defined. The names are ordered from outermost to innermost enclosing class.")
(push ,enum *cpp-inner-types*))))))
(defmacro define-class (name super-classes slots &rest options)
- "Define a C++ class. Syntax is:
+ "Define a simple C++ class or a C++ class template.
-;; (define-class name (list-of-super-classes)
-;; ((c++-slot-definition)*)
-;; (:class-option option-value)*)
+The syntax is:
-Class name may be a list where the first element is the class name, while
-others are template parameters.
+ (define-class (*)
+ (*)
+ *)
-For example:
+NAME is either an atom ATOM or a list of the form (ATOM TYPE-PARAM+). If NAME is
+an atom, the invocation defines a simple C++ class. Otherwise, a class template
+is defined. In both cases ATOM must be a designator for a class namestring.
+TYPE-PARAM must be designator for a type parameter namestring.
-;; (define-class (optional t-value)
-;; ...)
+Each SUPER-CLASS is a typestring representing a superclass of the class being
+defined.
-defines a templated C++ class:
+Each CPP-SLOT-DEFINITION is of the form (NAME CPP-TYPE . SLOT-OPTIONS). NAME
+must be a designator for a member namestring. CPP-TYPE must be a typestring
+designator.
-template
-class Optional { ... };
+SLOT-OPTIONS is a plist whose values are not evaluated by default. The possible
+keys are:
-Each C++ member/slot definition is of the form:
-;; (name cpp-type slot-options)
+- :INITVAL -- Evaluated. A number or a string representing a C++ expression that
+ will be used to initialize the member using the member initializer list.
-slot-options are keyword arguments. Currently supported options are:
- * :initval -- initializer value for the member, a C++ string or a number.
- * :reader -- if t, generates a public getter for the member.
- * :scope -- class scope of the member, either :public, :protected or :private (default).
- * :documentation -- Doxygen documentation of the member.
+- :READER -- If T, generates a public getter for the member.
-Currently supported class-options are:
- * :documentation -- Doxygen documentation of the class.
- * :public -- additional C++ code in public scope.
- * :protected -- additional C++ code in protected scope.
- * :private -- additional C++ code in private scope.
- * :serialize -- only (:slk) is supported for now. You may specify additional
- options additional options after :slk to fill the `SLK-OPTS' slots.
- * :abstractp -- if t, marks that this class cannot be instantiated
- (currently only useful in serialization code)
+- :SCOPE -- The class scope of the member. One of :PUBLIC, :PROTECTED
+ or :PRIVATE (default).
-Larger example:
+- :DOCUMENTATION -- String specifying the Doxygen documentation for the member.
-;; (lcp:define-class derived (base)
-;; ((val :int :reader t :initval 42))
-;; (:public #>cpp void set_val(int new_val) { val_ = new_val; } cpp<#)
-;; (:serialize (:slk)))
+The SLK serialization backend also introduces the following member options:
-Generates C++:
+- :SLK-SAVE -- Evaluated. A function that accepts a single argument, a
+ namestring corresponding to the member. The function should return a RAW-CPP
+ object representing the C++ code that saves the member.
-;; class Derived : public Base {
-;; public:
-;; void set_val(int new_val) { val_ = new_val; }
-;; auto val() { return val_; } // autogenerated from :reader t
-;;
-;; void Save(capnp::Base::Builder *builder) const;
-;; static std::unique_ptr Construct(const capnp::Base::Reader &reader);
-;; void Load(const capnp::Base::Reader &reader);
-;;
-;; private:
-;; int val_ = 42; // :initval is assigned
-;; };"
+- :SLK-LOAD -- Evaluated. A function that accepts a single argument, a
+ namestring corresponding to the member. The function should return a RAW-CPP
+ object representing the C++ code that loads the member.
+
+CLASS-OPTION is a pair (KEY VALUE*). VALUE is by default not evaluated. The
+possible values of KEY are:
+
+- :DOCUMENTATION -- String specifying the Doxygen documentation for the class.
+
+- :PUBLIC, :PROTECTED, :PRIVATE -- Evaluated. Lisp forms that evaluate to
+ RAW-CPP objects representing C++ code that is to be included within the
+ public (or protected or private) scope of the class body. Results that are not
+ of type RAW-CPP are ignored.
+
+- :SERIALIZE -- Generate serialization code for the class using the given
+ serialization backend.
+
+ Each VALUE should be of the form (BACKEND . BACKEND-OPTIONS), where BACKEND is
+ a keyword corresponding to the serialization backend. BACKEND-OPTIONS is a
+ plist specifying backend-specific options.
+
+ For now, only the SLK (:slk) backend is supported. Its options are:
+
+ - :SAVE-ARGS -- Evaluated. A list of (NAME TYPE) pairs that designate extra
+ arguments of the generated serialization function. NAME should be a variable
+ namestring designator while TYPE should be a typestring designator.
+
+ - :LOAD-ARGS -- Evaluated. A list of (NAME TYPE) pairs that designate
+ arguments of the generated deserialization function. NAME should be a
+ variable namestring designator while TYPE should be a typestring designator.
+
+ - :BASE -- If T, treat the class as the root of a class hierarchy for the
+ purpose of serialization.
+
+ - :IGNORE-OTHER-BASE-CLASSES -- If T, treat the class as if it inherits just
+ the first of its superclasses, ignoring the others.
+
+- :CLONE -- Generate cloning code for the class.
+
+ All VALUEs should form a plist of clone options. The following options are
+ supported:
+
+ - :RETURN-TYPE -- Evaluated. A function that accepts a single argument, a
+ typestring corresponding to the class being defined. The function should
+ return a typestring that represents the return type of the cloning function.
+
+ - :ARGS -- Evaluated. A list of (NAME TYPE) pairs that designate arguments of
+ the generated cloning function. NAME should be a variable namestring
+ designator while TYPE should be a typestring designator.
+
+ - :INIT-OBJECT -- Evaluated. A function that accepts two arguments, NAME and
+ TYPE. NAME is a variable namestring while TYPE is a typestring corresponding
+ to the class being defined. The function should return, as a string, C++
+ code that declares and initializes the C++ variable NAME, of type TYPE.
+
+ - :IGNORE-OTHER-BASE-CLASSES -- If T, treat the class as if it inherits just
+ the first of its superclasses, ignoring the others.
+
+- :TYPE-INFO -- Specify additional type information options. Type information
+ code for the class is generated unconditionally, whether or not this option is
+ present.
+
+ All VALUEs should form a plist of type information options. The following
+ options are supported:
+
+ - :BASE -- If T, treat the class as the root of a class hierarchy for the
+ purpose of serialization.
+
+ - :IGNORE-OTHER-BASE-CLASSES -- If T, treat the class as if it inherits just
+ the first of its superclasses, ignoring the others.
+
+- :ABSTRACTP -- If T, marks that this class cannot be instantiated (currently
+ only useful in serialization code).
+
+- :STRUCTP -- If T, define a struct instead of a class."
(let ((structp (second (assoc :structp options))))
(flet ((parse-slot (slot-name type &rest kwargs
&key reader scope &allow-other-keys)
@@ -1260,16 +1325,22 @@ structure named by the string NAME."
"Define an RPC. Two structures are defined, representing the request and
the response for the given RPC.
+The syntax is:
+
+ (define-rpc
+ (:request (*) *)
+ (:response (*) *))
+
NAME should designate a namestring for a class, which is used to produce the
-names of the two structures. OPTIONS should be an alist of options.
+names of the two structures.
The names of the structures are formed by concatenating the namestring NAME with
\"Req\" and \"Res\".
The two options :REQUEST and :RESPONSE are mandatory. Their bodies should be
-similar to the body of DEFINE-STRUCT, i.e. (SLOTS STRUCT-OPTION*). Their bodies
-will be passed to DEFINE-STRUCT, but with any DEFINE-RPC-specific member and
-structure options removed.
+similar to the body of DEFINE-STRUCT, i.e. ((SLOT*) STRUCT-OPTION*). Their
+bodies will be passed to DEFINE-STRUCT, but with any DEFINE-RPC-specific member
+and structure options removed.
DEFINE-RPC introduces an extra member option :INITARG that is described below.