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.