From b8514ccf048cfadaf808817fe6061d59830db54e Mon Sep 17 00:00:00 2001
From: Lovro Lugovic <lovro.lugovic@memgraph.io>
Date: Fri, 10 May 2019 14:49:42 +0200
Subject: [PATCH] LCP: Update documentation

Summary: Depends on D2090

Reviewers: mtomic, teon.banek

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D2091
---
 docs/dev/lcp.md     |   2 +-
 src/lisp/types.lisp | 181 ++++++++++++++++++++++++++++++--------------
 2 files changed, 127 insertions(+), 56 deletions(-)

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<Base>`, 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>
+    (<value>*)
+    <enum-option>*)
+
+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 <name> (<super-class>*)
+    (<cpp-slot-definition>*)
+    <class-option>*)
 
-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 TValue>
-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<Derived> 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 <name>
+    (:request (<slot>*) <struct-option>*)
+    (:response (<slot>*) <struct-option>*))
+
 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.