2018-10-31 20:54:36 +08:00
|
|
|
;;;; This file contains definitions of types used to store meta information on
|
|
|
|
;;;; C++ types. Along with data defintions, you will find various functions
|
|
|
|
;;;; and methods for operating on that data.
|
|
|
|
|
|
|
|
(in-package #:lcp)
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(named-readtables:in-readtable lcp:lcp-syntax)
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; Supported and unsupported C++ types
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(deftype general-cpp-type ()
|
|
|
|
'(or cpp-type unsupported-cpp-type))
|
|
|
|
|
|
|
|
(defgeneric cpp-type-decl (cpp-type &key namespacep globalp enclosing-classes-p
|
|
|
|
type-params-p)
|
|
|
|
(:documentation "Return the C++ type declaration corresponding to the given
|
|
|
|
object."))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; Supported C++ types
|
|
|
|
|
|
|
|
(defvar +cpp-primitive-type-names+
|
|
|
|
'("bool" "char" "int" "int16_t" "int32_t" "int64_t" "uint" "uint16_t"
|
|
|
|
"uint32_t" "uint64_t" "float" "double"))
|
2018-10-31 20:54:36 +08:00
|
|
|
|
|
|
|
(defclass cpp-type ()
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
((documentation
|
|
|
|
:type (or null string)
|
|
|
|
:initarg :documentation
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-type-documentation
|
|
|
|
:documentation "Documentation string for this C++ type.")
|
|
|
|
(namespace
|
|
|
|
:type list
|
|
|
|
:initarg :namespace
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-type-namespace
|
|
|
|
:documentation "A list of strings naming the individual namespace parts of
|
|
|
|
the namespace of this type. Enclosing classes aren't included, even though they
|
|
|
|
form valid C++ namespaces.")
|
|
|
|
(enclosing-classes
|
|
|
|
:type list
|
|
|
|
:initarg :enclosing-classes
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-type-enclosing-classes
|
|
|
|
:accessor %cpp-type-enclosing-classes
|
|
|
|
:documentation "A list of strings naming the enclosing classes of this
|
|
|
|
type.")
|
|
|
|
(name
|
|
|
|
:type string
|
|
|
|
:initarg :name
|
|
|
|
:reader cpp-type-name
|
|
|
|
:documentation "The name of this type.")
|
|
|
|
(type-params
|
|
|
|
:type list
|
|
|
|
:initarg :type-params
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-type-type-params
|
|
|
|
:documentation "A list of strings naming the template parameters that are
|
|
|
|
needed to instantiate a concrete type. For example, in `template <TValue> class
|
|
|
|
vector`, `TValue' is the type parameter.")
|
|
|
|
(type-args
|
|
|
|
:type list
|
|
|
|
:initarg :type-args
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-type-type-args
|
|
|
|
:accessor %cpp-type-type-args
|
|
|
|
:documentation "A list of `CPP-TYPE' instances that represent the template
|
|
|
|
type arguments used within the instantiation of the template. For example in
|
|
|
|
`std::vector<int>`, `int' is a template type argument."))
|
2018-10-31 20:54:36 +08:00
|
|
|
(:documentation "Base class for meta information on C++ types."))
|
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(defun make-cpp-type (name &key namespace enclosing-classes type-params
|
|
|
|
type-args)
|
|
|
|
"Create an instance of CPP-TYPE. The keyword arguments correspond to the slots
|
|
|
|
of the class CPP-TYPE and expect values according to their type and
|
|
|
|
documentation, except as noted below.
|
|
|
|
|
|
|
|
If the first element of NAMESPACE is an empty string, it is removed. NAMESPACE
|
|
|
|
parts must not contain characters from +WHITESPACE-CHARS+.
|
|
|
|
|
|
|
|
TYPE-ARGS can be a list of CPP-TYPE designators, each of which will be coerced
|
|
|
|
into a CPP-TYPE instance as if by ENSURE-CPP-TYPE.
|
|
|
|
|
|
|
|
TYPE-PARAMS and TYPE-ARGS cannot be provided simultaneously."
|
|
|
|
(check-type name string)
|
|
|
|
(check-type namespace list)
|
|
|
|
(check-type enclosing-classes list)
|
|
|
|
(check-type type-params list)
|
|
|
|
(check-type type-args list)
|
|
|
|
(dolist (list (list namespace enclosing-classes type-params))
|
|
|
|
(dolist (elem list)
|
|
|
|
(check-type elem string)))
|
|
|
|
(let ((namespace (if (and namespace (string= (car namespace) ""))
|
|
|
|
(cdr namespace)
|
|
|
|
namespace)))
|
|
|
|
(dolist (part namespace)
|
|
|
|
(when (or (string= part "")
|
|
|
|
(find-if
|
|
|
|
(lambda (c) (member c +whitespace-chars+ :test #'char=))
|
|
|
|
part))
|
|
|
|
(error "~@<Invalid namespace part ~S in ~S~@:>" part namespace)))
|
|
|
|
(when (and type-params type-args)
|
|
|
|
(error "~@<A CPP-TYPE can't have both of TYPE-PARAMS and TYPE-ARGS~@:>"))
|
|
|
|
(make-instance 'cpp-type
|
|
|
|
:name name
|
|
|
|
:namespace namespace
|
|
|
|
:enclosing-classes enclosing-classes
|
|
|
|
:type-params type-params
|
|
|
|
:type-args (mapcar #'ensure-cpp-type type-args))))
|
|
|
|
|
|
|
|
(defmethod print-object ((cpp-type cpp-type) stream)
|
|
|
|
(print-unreadable-object (cpp-type stream :type t)
|
|
|
|
(format stream "~A" (cpp-type-decl cpp-type))))
|
|
|
|
|
|
|
|
(defun cpp-type= (a b)
|
|
|
|
(check-type a cpp-type)
|
|
|
|
(check-type b cpp-type)
|
|
|
|
"Test whether two instances of CPP-TYPE, A and B, represent the same C++ type.
|
|
|
|
|
|
|
|
For the test to return true, the following must hold:
|
|
|
|
|
|
|
|
- The CPP-TYPE-NAME of A and B must be STRING=.
|
|
|
|
|
|
|
|
- The CPP-TYPE-NAMESPACE of A and B must be EQUAL.
|
|
|
|
|
|
|
|
- The CPP-TYPE-ENCLOSING-CLASSES of A and B must be EQUAL.
|
|
|
|
|
|
|
|
- The CPP-TYPE-TYPE-PARAMS of A and B must be pairwise STRING=.
|
|
|
|
|
|
|
|
- The CPP-TYPE-TYPE-ARGS of A and B must be pairwise CPP-TYPE=."
|
|
|
|
(and (string= (cpp-type-name a) (cpp-type-name b))
|
|
|
|
(equal (cpp-type-namespace a) (cpp-type-namespace b))
|
|
|
|
(equal (cpp-type-enclosing-classes a) (cpp-type-enclosing-classes b))
|
|
|
|
(not (mismatch (cpp-type-type-params a) (cpp-type-type-params b)
|
|
|
|
:test #'string=))
|
|
|
|
(not (mismatch (cpp-type-type-args a) (cpp-type-type-args b)
|
|
|
|
:test #'cpp-type=))))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; Unsupported C++ types
|
|
|
|
|
|
|
|
(defclass unsupported-cpp-type ()
|
|
|
|
((typestring
|
|
|
|
:type string
|
|
|
|
:initarg :typestring
|
|
|
|
:initform nil
|
|
|
|
:reader unsupported-cpp-type-typestring
|
|
|
|
:documentation "The typestring for this type that LCP couldn't
|
|
|
|
parse (doesn't support)."))
|
|
|
|
(:documentation "A class that represents unsupported C++ types."))
|
|
|
|
|
|
|
|
(defun make-unsupported-cpp-type (typestring)
|
|
|
|
(make-instance 'unsupported-cpp-type :typestring typestring))
|
|
|
|
|
|
|
|
(defmethod print-object ((cpp-type unsupported-cpp-type) stream)
|
|
|
|
(print-unreadable-object (cpp-type stream :type t)
|
|
|
|
(princ (unsupported-cpp-type-typestring cpp-type) stream)))
|
|
|
|
|
|
|
|
(macrolet ((define-unsupported-cpp-type-methods ()
|
|
|
|
(let ((names '(documentation namespace enclosing-classes
|
|
|
|
type-params type-args name)))
|
|
|
|
`(progn
|
|
|
|
,@(loop :for name :in names
|
|
|
|
:for fname := (alexandria:symbolicate 'cpp-type- name)
|
|
|
|
:collect
|
|
|
|
`(defmethod ,fname ((cpp-type unsupported-cpp-type))
|
|
|
|
(error ,(format
|
|
|
|
nil "~S doesn't support the method ~S"
|
|
|
|
'unsupported-cpp-type fname))))))))
|
|
|
|
(define-unsupported-cpp-type-methods))
|
|
|
|
|
|
|
|
(defmethod cpp-type-decl ((cpp-type unsupported-cpp-type)
|
|
|
|
&key &allow-other-keys)
|
|
|
|
"Return the captured typestring for the instance of UNSUPPORTED-CPP-TYPE."
|
|
|
|
(unsupported-cpp-type-typestring cpp-type))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; Known C++ enums
|
2018-10-31 20:54:36 +08:00
|
|
|
|
|
|
|
(defclass cpp-enum (cpp-type)
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
((values
|
|
|
|
:type list
|
|
|
|
:initarg :values
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-enum-values)
|
2018-12-04 21:41:37 +08:00
|
|
|
;; If true, generate serialization code for this enum.
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(serializep
|
|
|
|
:type boolean
|
|
|
|
:initarg :serializep
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-enum-serializep))
|
2018-10-31 20:54:36 +08:00
|
|
|
(:documentation "Meta information on a C++ enum."))
|
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; Known C++ classes
|
|
|
|
|
2018-10-31 20:54:36 +08:00
|
|
|
(defstruct cpp-member
|
|
|
|
"Meta information on a C++ class (or struct) member variable."
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;; The class that contains this member.
|
|
|
|
(name nil :type string :read-only t)
|
|
|
|
(type nil :type (or string general-cpp-type))
|
2018-10-31 20:54:36 +08:00
|
|
|
(initval nil :type (or null string integer float) :read-only t)
|
|
|
|
(scope :private :type (member :public :protected :private) :read-only t)
|
|
|
|
;; TODO: Support giving a name for reader function.
|
|
|
|
(reader nil :type boolean :read-only t)
|
|
|
|
(documentation nil :type (or null string) :read-only t)
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;; If T, skips this member in serialization code generation. The member may
|
2018-11-14 20:06:26 +08:00
|
|
|
;; still be deserialized with custom load hook.
|
|
|
|
(dont-save nil :type boolean :read-only t)
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;; May be a function which takes 1 argument, member-name. It needs to return
|
|
|
|
;; C++ code.
|
2018-11-14 20:06:26 +08:00
|
|
|
(slk-save nil :type (or null function) :read-only t)
|
2019-01-17 23:44:55 +08:00
|
|
|
(slk-load nil :type (or null function) :read-only t)
|
|
|
|
(clone t :type (or boolean (eql :copy) function) :read-only t))
|
2018-10-31 20:54:36 +08:00
|
|
|
|
2018-12-04 19:54:35 +08:00
|
|
|
(defstruct slk-opts
|
|
|
|
"SLK serialization options for C++ class."
|
|
|
|
;; BASE is T if the class should be treated as a base class for SLK, even
|
|
|
|
;; though it may have parents.
|
|
|
|
(base nil :type boolean :read-only t)
|
|
|
|
;; Extra arguments to the generated save function. List of (name cpp-type).
|
|
|
|
(save-args nil :read-only t)
|
|
|
|
(load-args nil :read-only t)
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;; In case of multiple inheritance, pretend we only inherit the 1st base
|
|
|
|
;; class.
|
2018-12-04 19:54:35 +08:00
|
|
|
(ignore-other-base-classes nil :type boolean :read-only t))
|
|
|
|
|
2019-01-17 23:44:55 +08:00
|
|
|
(defstruct clone-opts
|
|
|
|
"Cloning options for C++ class."
|
|
|
|
;; Extra arguments to the generated clone function. List of (name cpp-type).
|
|
|
|
(args nil :read-only t)
|
|
|
|
(return-type nil :type (or null function) :read-only t)
|
|
|
|
(base nil :read-only t)
|
|
|
|
(ignore-other-base-classes nil :read-only t)
|
|
|
|
(init-object nil :read-only t))
|
|
|
|
|
2019-01-25 17:15:15 +08:00
|
|
|
(defstruct type-info-opts
|
|
|
|
"Options for generating TypeInfo of C++ class."
|
|
|
|
(base nil :read-only t)
|
|
|
|
(ignore-other-base-classes nil :read-only t))
|
|
|
|
|
2018-10-31 20:54:36 +08:00
|
|
|
(defclass cpp-class (cpp-type)
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
((structp
|
|
|
|
:type boolean
|
|
|
|
:initarg :structp
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-class-structp)
|
|
|
|
(super-classes
|
|
|
|
:initarg :super-classes
|
|
|
|
:initform nil
|
|
|
|
:accessor %cpp-class-super-classes)
|
|
|
|
(members
|
|
|
|
:initarg :members
|
|
|
|
:initform nil
|
|
|
|
:accessor %cpp-class-members)
|
2018-10-31 20:54:36 +08:00
|
|
|
;; Custom C++ code in 3 scopes. May be a list of C++ meta information or a
|
|
|
|
;; single element.
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(public
|
|
|
|
:initarg :public
|
|
|
|
:initform nil
|
|
|
|
:accessor cpp-class-public)
|
|
|
|
(protected
|
|
|
|
:initarg :protected
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-class-protected)
|
|
|
|
(private
|
|
|
|
:initarg :private
|
|
|
|
:initform nil
|
|
|
|
:accessor cpp-class-private)
|
|
|
|
(slk-opts
|
|
|
|
:type (or null slk-opts)
|
|
|
|
:initarg :slk-opts
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-class-slk-opts)
|
|
|
|
(clone-opts
|
|
|
|
:type (or null clone-opts)
|
|
|
|
:initarg :clone-opts
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-class-clone-opts)
|
|
|
|
(type-info-opts
|
|
|
|
:type type-info-opts
|
|
|
|
:initarg :type-info-opts
|
|
|
|
:initform (make-type-info-opts)
|
|
|
|
:reader cpp-class-type-info-opts)
|
|
|
|
(inner-types
|
|
|
|
:initarg :inner-types
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-class-inner-types)
|
|
|
|
(abstractp
|
|
|
|
:initarg :abstractp
|
|
|
|
:initform nil
|
|
|
|
:reader cpp-class-abstractp))
|
2018-10-31 20:54:36 +08:00
|
|
|
(:documentation "Meta information on a C++ class (or struct)."))
|
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(defmethod cpp-type-decl ((cpp-type cpp-type) &rest kwargs
|
|
|
|
&key (namespacep t) (globalp nil)
|
|
|
|
(enclosing-classes-p t) (type-params-p t))
|
|
|
|
"Return the C++ type declaration corresponding to the given CPP-TYPE.
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
If NAMESPACEP is true, the namespace (excluding enclosing classes) is included
|
|
|
|
in the declaration. If GLOBALP is true, the namespace (if included) is fully
|
|
|
|
qualified.
|
2018-11-14 20:06:26 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
If ENCLOSING-CLASSES-P is true, the namespace formed by the enclosing classes is
|
|
|
|
included in the declaration.
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
If TYPE-PARAMS-P is true, type parameters are included when CPP-TYPE has type
|
|
|
|
parameters.
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
If CPP-TYPE has type arguments, type arguments are included in the declaration
|
|
|
|
and formatted by recursively calling CPP-TYPE-DECL with the same keyword
|
|
|
|
arguments."
|
|
|
|
(flet ((rec (cpp-type)
|
|
|
|
(apply #'cpp-type-decl cpp-type kwargs)))
|
|
|
|
(with-output-to-string (s)
|
|
|
|
(cond
|
|
|
|
;; Handle pointers and references specially.
|
|
|
|
((or (cpp-type-raw-pointer-p cpp-type)
|
|
|
|
(cpp-type-reference-p cpp-type))
|
|
|
|
(write-string (rec (car (cpp-type-type-args cpp-type))) s)
|
|
|
|
(format s " ~A" (cpp-type-name cpp-type)))
|
|
|
|
(t
|
|
|
|
(when namespacep
|
|
|
|
(when globalp
|
|
|
|
(write-string "::" s))
|
|
|
|
(write-string (cpp-type-namespace-string cpp-type) s))
|
|
|
|
(when enclosing-classes-p
|
|
|
|
(write-string (cpp-type-enclosing-classes-string cpp-type) s))
|
|
|
|
(write-string (cpp-type-name cpp-type) s)
|
|
|
|
(cond
|
|
|
|
((cpp-type-type-args cpp-type)
|
|
|
|
(format s "<~{~A~^, ~}>"
|
|
|
|
(mapcar #'rec (cpp-type-type-args cpp-type))))
|
|
|
|
((and type-params-p (cpp-type-type-params cpp-type))
|
|
|
|
(format s "<~{~A~^, ~}>" (cpp-type-type-params cpp-type)))))))))
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; C++ type parsing
|
2019-01-17 23:44:55 +08:00
|
|
|
|
2018-10-31 20:54:36 +08:00
|
|
|
(defun parse-cpp-type-declaration (type-decl)
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
"Try to construct a CPP-TYPE instance from the string TYPE-DECL representing a
|
|
|
|
C++ type declaration.
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
The function assumes that TYPE-DECL is a well-formed C++ type declaration. No
|
|
|
|
attempt is made to handle erroneous declarations.
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
Note that the function doesn't aim to support the whole of C++'s type
|
|
|
|
declaration syntax. Certain declarations just aren't supported.
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
If the declaration is successfuly parsed, the resulting CPP-TYPE instance is
|
|
|
|
returned. Otherwise, if the string is empty or if unsupported constructs were
|
|
|
|
used, NIL is returned."
|
2018-10-31 20:54:36 +08:00
|
|
|
(check-type type-decl string)
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;; A C++ type declaration for our purposes is of the form:
|
|
|
|
;;
|
|
|
|
;; namespace::namespace::type<type-arg, type-arg> <* or &>
|
|
|
|
;; |^^^^^^^^^^^^^^^^^^^^| |^^^^^^^^^^^^^^^^^^| |^^^^^|
|
|
|
|
;; optional optional optional
|
|
|
|
;;
|
|
|
|
;; The type arguments are recursively parsed.
|
|
|
|
|
|
|
|
(when (string= "" type-decl)
|
|
|
|
(return-from parse-cpp-type-declaration nil))
|
|
|
|
;; Unsupported: `typename' and array syntax
|
|
|
|
(when (or (search "typename" type-decl)
|
|
|
|
(cl-ppcre:scan "[[\\]]" type-decl))
|
|
|
|
(return-from parse-cpp-type-declaration nil))
|
2018-10-31 20:54:36 +08:00
|
|
|
(setf type-decl (string-trim +whitespace-chars+ type-decl))
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;; Check if the type is a primitive type
|
|
|
|
(let ((type-keyword (member type-decl +cpp-primitive-type-names+
|
|
|
|
:test #'string=)))
|
2018-10-31 20:54:36 +08:00
|
|
|
(when type-keyword
|
|
|
|
(return-from parse-cpp-type-declaration
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(make-cpp-type (car type-keyword)))))
|
|
|
|
;; Check if the type is a pointer
|
|
|
|
(let ((ptr-pos (position-if (lambda (c) (or (char= c #\*) (char= c #\&)))
|
|
|
|
type-decl :from-end t)))
|
2018-10-31 20:54:36 +08:00
|
|
|
(when (and ptr-pos (not (cl-ppcre:scan "[()<>]" type-decl :start ptr-pos)))
|
|
|
|
(return-from parse-cpp-type-declaration
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(let ((type-arg (parse-cpp-type-declaration
|
|
|
|
(subseq type-decl 0 ptr-pos))))
|
|
|
|
(when type-arg
|
|
|
|
(make-cpp-type (subseq type-decl ptr-pos)
|
|
|
|
:type-args (list type-arg)))))))
|
2018-10-31 20:54:36 +08:00
|
|
|
;; Other cases
|
|
|
|
(destructuring-bind (full-name &optional template)
|
|
|
|
(cl-ppcre:split "<" type-decl :limit 2)
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;; Unsupported: Function or array syntax
|
|
|
|
(let ((pos (if template
|
|
|
|
(position-of-closing-delimiter type-decl #\< #\>)
|
|
|
|
0)))
|
|
|
|
(when (or (cl-ppcre:scan "[()]" full-name)
|
|
|
|
(cl-ppcre:scan "[()]" type-decl :start (1+ pos)))
|
|
|
|
(return-from parse-cpp-type-declaration nil)))
|
|
|
|
(let* ((parts (cl-ppcre:split "::" full-name))
|
|
|
|
(name (car (last parts)))
|
|
|
|
(namespace (butlast parts))
|
|
|
|
(type-args nil))
|
2018-10-31 20:54:36 +08:00
|
|
|
(when template
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;; A class template instantiation ends with the '>' character
|
2018-10-31 20:54:36 +08:00
|
|
|
(let ((arg-start 0))
|
|
|
|
(cl-ppcre:do-scans (match-start match-end reg-starts reg-ends
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
"[a-zA-Z0-9_:<>() *&]+[,>]" template)
|
2018-10-31 20:54:36 +08:00
|
|
|
(flet ((matchedp (open-char close-char)
|
|
|
|
"Return T if the TEMPLATE[ARG-START:MATCH-END] contains
|
|
|
|
matched OPEN-CHAR and CLOSE-CHAR."
|
|
|
|
(= (count open-char template :start arg-start :end match-end)
|
|
|
|
(count close-char template :start arg-start :end match-end))))
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(when (or (= match-end (length template)) ;; We are at the end
|
2018-10-31 20:54:36 +08:00
|
|
|
(and (matchedp #\< #\>) (matchedp #\( #\))))
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(let ((type-arg (parse-cpp-type-declaration
|
|
|
|
;; Take the arg and omit the final [,>]
|
|
|
|
(subseq template arg-start (1- match-end)))))
|
|
|
|
(if type-arg
|
|
|
|
(push type-arg type-args)
|
|
|
|
(return-from parse-cpp-type-declaration nil)))
|
|
|
|
(setf arg-start match-end))))))
|
|
|
|
;; Treat the first capitalized namespace and all the ones after that as
|
|
|
|
;; enclosing classes, whether or not they're known to LCP.
|
|
|
|
(let ((pos (or (position-if
|
|
|
|
(lambda (part)
|
|
|
|
(and (string/= "" part) (upper-case-p (aref part 0))))
|
|
|
|
namespace)
|
|
|
|
(length namespace))))
|
2018-10-31 20:54:36 +08:00
|
|
|
(make-cpp-type name
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
:namespace (subseq namespace 0 pos)
|
|
|
|
:enclosing-classes (subseq namespace pos)
|
2018-10-31 20:54:36 +08:00
|
|
|
:type-args (reverse type-args))))))
|
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; Typestrings
|
|
|
|
|
|
|
|
(defun ensure-typestring (thing)
|
|
|
|
"Return the typestring corresponding to the typestring designator THING.
|
|
|
|
|
|
|
|
- If THING is a symbol whose name is STRING-EQUAL to an element in
|
|
|
|
+CPP-PRIMITIVE-TYPE-NAMES+, return it.
|
|
|
|
|
|
|
|
- If THING is any other symbol, return the result of (cpp-name-for-class thing).
|
|
|
|
|
|
|
|
- If THING is a string, return it."
|
|
|
|
(check-type thing (or symbol string))
|
|
|
|
(ctypecase thing
|
|
|
|
(symbol (if (member thing +cpp-primitive-type-names+ :test #'string-equal)
|
|
|
|
(string-downcase thing)
|
|
|
|
(cpp-name-for-class thing)))
|
|
|
|
(string thing)))
|
|
|
|
|
|
|
|
(defun typestring-supported-p (typestring)
|
|
|
|
"Test whether the typestring TYPESTRING would resolve to a supported
|
|
|
|
CPP-TYPE."
|
|
|
|
(and (parse-cpp-type-declaration typestring) t))
|
|
|
|
|
|
|
|
(defun typestring-class-template-instantiation-p (typestring)
|
|
|
|
"Return whether the typestring TYPESTRING would resolve to a CPP-TYPE which is
|
|
|
|
a class template instantiation."
|
|
|
|
(and (cl-ppcre:scan "<|>" typestring) t))
|
|
|
|
|
|
|
|
(defun typestring-fully-qualified-p (typestring)
|
|
|
|
"Test whether the supported typestring TYPESTRING is fully qualified. If the
|
|
|
|
typestring is unsupported, return NIL."
|
|
|
|
(and (>= (length typestring) 2)
|
|
|
|
(string= "::" typestring :end2 2)))
|
|
|
|
|
|
|
|
(defun typestring-qualified-p (typestring)
|
|
|
|
"Test whether the supported typestring TYPESTRING is qualified. If the
|
|
|
|
typestring is unsupported, return NIL.
|
|
|
|
|
|
|
|
Note that the test only checks the topmost type and doesn't recurse into its
|
|
|
|
type arguments."
|
|
|
|
(or
|
|
|
|
;; NOTE: Checking whether the typestring is fully qualified is not just an
|
|
|
|
;; optimization. Since PARSE-CPP-TYPE-DECLARATION drops any qualifiers for
|
|
|
|
;; the global namespace, without this check we wouldn't be able to tell e.g.
|
|
|
|
;; whether the typestring "::MyClass" is fully qualified or not.
|
|
|
|
(typestring-fully-qualified-p typestring)
|
|
|
|
(let ((cpp-type (parse-cpp-type-declaration typestring)))
|
|
|
|
(and cpp-type (cpp-type-extended-namespace cpp-type) t))))
|
|
|
|
|
|
|
|
(define-condition typestring-warning (simple-warning)
|
|
|
|
())
|
|
|
|
|
|
|
|
(defun typestring-warn (control &rest args)
|
|
|
|
(warn 'typestring-warning :format-control control :format-arguments args))
|
|
|
|
|
|
|
|
(defun process-typestring (typestring)
|
|
|
|
"Process the typestring TYPESTRING.
|
|
|
|
|
|
|
|
To process the typestring means to:
|
|
|
|
|
|
|
|
- Leave it as is if it's fully qualified, unqualified or unsupported.
|
|
|
|
|
|
|
|
- Fully qualify it if it's partially qualified."
|
|
|
|
(check-type typestring string)
|
|
|
|
(cond
|
|
|
|
((or (not (typestring-supported-p typestring))
|
|
|
|
(typestring-fully-qualified-p typestring))
|
|
|
|
typestring)
|
|
|
|
((typestring-qualified-p typestring)
|
2019-05-08 23:17:38 +08:00
|
|
|
(let ((cpp-type (parse-cpp-type-declaration typestring)))
|
|
|
|
(unless (string= (first (cpp-type-namespace cpp-type)) "std")
|
|
|
|
(typestring-warn
|
|
|
|
"Treating qualified type \"~A\" as the fully qualified type \"::~A\"."
|
|
|
|
typestring typestring)))
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(format nil "::~A" typestring))
|
|
|
|
;; Unqualified.
|
|
|
|
(t
|
|
|
|
typestring)))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; Class and Enum Registry
|
|
|
|
|
|
|
|
(defvar *cpp-classes* nil
|
|
|
|
"List of defined classes from LCP file.")
|
|
|
|
|
|
|
|
(defvar *cpp-enums* nil
|
|
|
|
"List of defined enums from LCP file.")
|
|
|
|
|
|
|
|
(defun split-namespace-string (namespace)
|
|
|
|
(let ((parts (cl-ppcre:split "::" namespace)))
|
|
|
|
(if (string= (car parts) "")
|
|
|
|
(cdr parts)
|
|
|
|
parts)))
|
|
|
|
|
|
|
|
(defun find-cpp-class (name &optional namespace)
|
|
|
|
"Find an instance of CPP-CLASS in the class registry by searching for a
|
|
|
|
specific type.
|
|
|
|
|
|
|
|
NAME must be either a string, a symbol or a CPP-TYPE instance:
|
|
|
|
|
|
|
|
- If NAME is a string or a symbol, it is treated as a designator for a class
|
|
|
|
namestring.
|
|
|
|
|
|
|
|
- If NAME is a CPP-TYPE instance, it is treated as the string produced
|
|
|
|
by (cpp-type-decl name).
|
|
|
|
|
|
|
|
If the resulting string is qualified, it is split into parts by \"::\", trimming
|
|
|
|
any empty strings on both sides. Every part but the last one is used to form a
|
|
|
|
list of strings that is the namespace, while the last string is used as the
|
|
|
|
name. NAMESPACE is ignored in this case.
|
|
|
|
|
|
|
|
If the resulting string is not qualified, it is taken to be the name, while the
|
|
|
|
namespace is formed according to the value of NAMESPACE.
|
|
|
|
|
|
|
|
NAMESPACE can be either a string or a list of strings:
|
|
|
|
|
|
|
|
- If NAMESPACE is a string, it is treated as the list that's the result of
|
|
|
|
splitting the string by \"::\", trimming any empty strings on both sides. If
|
|
|
|
the string is empty, it designates the empty list.
|
|
|
|
|
|
|
|
- If NAMESPACE is a list, it must be a list of strings, each naming a single
|
|
|
|
namespace.
|
|
|
|
|
|
|
|
Finally, the name and the namespace are compared as follows:
|
|
|
|
|
|
|
|
- The names are compared using STRING=.
|
|
|
|
|
|
|
|
- The namespaces are compared pairwise using STRING=. The empty list designates
|
|
|
|
the global namespace.
|
|
|
|
|
|
|
|
Return a CPP-CLASS instance if one is found, otherwise return NIL."
|
|
|
|
(check-type name (or symbol string cpp-type))
|
|
|
|
(check-type namespace (or nil string list))
|
|
|
|
(multiple-value-bind (name namespace)
|
|
|
|
(let ((name (ctypecase name
|
|
|
|
((or symbol string) (ensure-namestring-for-class name))
|
|
|
|
(cpp-type (cpp-type-decl name)))))
|
|
|
|
(if (typestring-qualified-p name)
|
|
|
|
(let ((parts (split-namespace-string name)))
|
|
|
|
(values (car (last parts)) (butlast parts)))
|
|
|
|
(values name (ctypecase namespace
|
|
|
|
(list namespace)
|
|
|
|
(string (split-namespace-string namespace))))))
|
|
|
|
(find-if
|
|
|
|
(lambda (cpp-type)
|
|
|
|
(and (string= name (cpp-type-name cpp-type))
|
|
|
|
(equal namespace (cpp-type-extended-namespace cpp-type))))
|
|
|
|
*cpp-classes*)))
|
|
|
|
|
|
|
|
(defun find-cpp-class-ascending (name namespace)
|
|
|
|
"Find an instance of CPP-CLASS in the class registry by searching upwards from
|
|
|
|
the given namespace.
|
|
|
|
|
|
|
|
The arguments NAME and NAMESPACE work just the same as in FIND-CPP-CLASS, except
|
|
|
|
that:
|
|
|
|
|
|
|
|
- NAME cannot be a qualified name.
|
|
|
|
|
|
|
|
- If NAME is a CPP-TYPE instance, then it is treated as the
|
|
|
|
string (cpp-type-name name)."
|
|
|
|
(check-type name (or symbol string cpp-type))
|
|
|
|
(check-type namespace (or nil string list))
|
|
|
|
(let ((name (ctypecase name
|
|
|
|
((or symbol string) (ensure-namestring-for-class name))
|
|
|
|
(cpp-type (cpp-type-name name))))
|
|
|
|
(namespace (ctypecase namespace
|
|
|
|
(list namespace)
|
|
|
|
(string (split-namespace-string namespace)))))
|
|
|
|
(when (typestring-qualified-p name)
|
|
|
|
(error "Using the qualified name ~S with ~S" name
|
|
|
|
'find-cpp-class-ascending))
|
|
|
|
(let ((cpp-classes
|
|
|
|
(remove-if-not
|
|
|
|
(lambda (cpp-type)
|
|
|
|
(and (string= name (cpp-type-name cpp-type))
|
|
|
|
(prefix-of-p (cpp-type-extended-namespace cpp-type)
|
|
|
|
namespace :test #'string=)))
|
|
|
|
*cpp-classes*)))
|
|
|
|
(and cpp-classes
|
|
|
|
(minimize
|
|
|
|
cpp-classes
|
|
|
|
:test #'>
|
|
|
|
:key (lambda (cpp-type)
|
|
|
|
(length (cpp-type-extended-namespace cpp-type))))))))
|
|
|
|
|
|
|
|
(defun find-cpp-class-descending (name &optional namespace)
|
|
|
|
"Find an instance of CPP-CLASS in the class registry by searching downwards
|
|
|
|
from the given namespace.
|
|
|
|
|
|
|
|
The arguments NAME and NAMESPACE work just the same as in FIND-CPP-CLASS, except
|
|
|
|
that:
|
|
|
|
|
|
|
|
- NAME cannot be a qualified name.
|
|
|
|
|
|
|
|
- If NAME is a CPP-TYPE instance, then it is treated as the
|
|
|
|
string (cpp-type-name name)."
|
|
|
|
(check-type name (or symbol string cpp-type))
|
|
|
|
(check-type namespace (or nil string list))
|
|
|
|
(let ((name (ctypecase name
|
|
|
|
((or symbol string) (ensure-namestring-for-class name))
|
|
|
|
(cpp-type (cpp-type-name name))))
|
|
|
|
(namespace (ctypecase namespace
|
|
|
|
(list namespace)
|
|
|
|
(string (split-namespace-string namespace)))))
|
|
|
|
(when (typestring-qualified-p name)
|
|
|
|
(error "Using the qualified name ~S with ~S" name
|
|
|
|
'find-cpp-class-descending))
|
|
|
|
(let ((cpp-classes
|
|
|
|
(remove-if-not
|
|
|
|
(lambda (cpp-type)
|
|
|
|
(and (string= name (cpp-type-name cpp-type))
|
|
|
|
(prefix-of-p namespace
|
|
|
|
(cpp-type-extended-namespace cpp-type)
|
|
|
|
:test #'string=)))
|
|
|
|
*cpp-classes*)))
|
|
|
|
(and cpp-classes
|
|
|
|
(minimize
|
|
|
|
cpp-classes
|
|
|
|
:key (lambda (cpp-type)
|
|
|
|
(length (cpp-type-extended-namespace cpp-type))))))))
|
|
|
|
|
|
|
|
(defun find-cpp-enum (name &optional namespace)
|
|
|
|
"Find an instance of CPP-ENUM in the enum registry.
|
|
|
|
|
|
|
|
NAME must be either a string, a symbol or a CPP-TYPE instance:
|
|
|
|
|
|
|
|
- If NAME is a string or a symbol, it is treated as a designator for a class
|
|
|
|
namestring.
|
|
|
|
|
|
|
|
- If NAME is a CPP-TYPE instance, it is treated as the string produced
|
|
|
|
by (cpp-type-decl name).
|
|
|
|
|
|
|
|
If the resulting string is qualified, it is split into parts by \"::\", trimming
|
|
|
|
any empty strings on both sides. Every part but the last one is used to form a
|
|
|
|
list of strings that is the namespace, while the last string is used as the
|
|
|
|
name. NAMESPACE is ignored in this case.
|
|
|
|
|
|
|
|
If the resulting string is not qualified, it is taken to be the name, while the
|
|
|
|
namespace is formed according to the value of NAMESPACE.
|
|
|
|
|
|
|
|
NAMESPACE can be either a string or a list of strings:
|
|
|
|
|
|
|
|
- If NAMESPACE is a string, it is treated as the list that's the result of
|
|
|
|
splitting the string by \"::\", trimming any empty strings on both sides. If
|
|
|
|
the string is empty, it designates the empty list.
|
|
|
|
|
|
|
|
- If NAMESPACE is a list, it must be a list of strings, each naming a single
|
|
|
|
namespace.
|
|
|
|
|
|
|
|
Finally, the name and the namespace are compared as follows:
|
|
|
|
|
|
|
|
- The names are compared using STRING=.
|
|
|
|
|
|
|
|
- The namespaces are compared pairwise using STRING=. The empty list designates
|
|
|
|
the global namespace.
|
|
|
|
|
|
|
|
Return a CPP-CLASS instance if one is found, otherwise return NIL."
|
|
|
|
(check-type name (or symbol string cpp-type))
|
|
|
|
(check-type namespace (or nil string list))
|
|
|
|
(multiple-value-bind (name namespace)
|
|
|
|
(let ((name (ctypecase name
|
|
|
|
((or symbol string) (ensure-namestring-for-class name))
|
|
|
|
(cpp-type (cpp-type-decl name)))))
|
|
|
|
(if (typestring-qualified-p name)
|
|
|
|
(let ((parts (split-namespace-string name)))
|
|
|
|
(values (car (last parts)) (butlast parts)))
|
|
|
|
(values name (ctypecase namespace
|
|
|
|
(list namespace)
|
|
|
|
(string (split-namespace-string namespace))))))
|
|
|
|
(find-if
|
|
|
|
(lambda (cpp-type)
|
|
|
|
(and (string= name (cpp-type-name cpp-type))
|
|
|
|
(equal namespace (cpp-type-extended-namespace cpp-type))))
|
|
|
|
*cpp-enums* :from-end t)))
|
|
|
|
|
|
|
|
(defun find-cpp-enum-ascending (name namespace)
|
|
|
|
"Find an instance of CPP-ENUM in the enum registry by searching upwards from
|
|
|
|
the given namespace.
|
|
|
|
|
|
|
|
The arguments NAME and NAMESPACE work just the same as in FIND-CPP-ENUM, except
|
|
|
|
that:
|
|
|
|
|
|
|
|
- NAME cannot be a qualified name.
|
|
|
|
|
|
|
|
- If NAME is a CPP-TYPE instance, then it is treated as the
|
|
|
|
string (cpp-type-name name)."
|
|
|
|
(check-type name (or symbol string cpp-type))
|
|
|
|
(check-type namespace (or nil string list))
|
|
|
|
(let ((name (ctypecase name
|
|
|
|
((or symbol string) (ensure-namestring-for-class name))
|
|
|
|
(cpp-type (cpp-type-name name))))
|
|
|
|
(namespace (ctypecase namespace
|
|
|
|
(list namespace)
|
|
|
|
(string (split-namespace-string namespace)))))
|
|
|
|
(when (typestring-qualified-p name)
|
|
|
|
(error "Using the qualified name ~S with ~S" name
|
|
|
|
'find-cpp-enum-ascending))
|
|
|
|
(let ((cpp-enums
|
|
|
|
(remove-if-not
|
|
|
|
(lambda (cpp-type)
|
|
|
|
(and (string= name (cpp-type-name cpp-type))
|
|
|
|
(prefix-of-p (cpp-type-extended-namespace cpp-type)
|
|
|
|
namespace :test #'string=)))
|
|
|
|
*cpp-enums*)))
|
|
|
|
(and cpp-enums
|
|
|
|
(minimize
|
|
|
|
cpp-enums
|
|
|
|
:test #'>
|
|
|
|
:key (lambda (cpp-type)
|
|
|
|
(length (cpp-type-extended-namespace cpp-type))))))))
|
|
|
|
|
|
|
|
(defun find-cpp-enum-descending (name &optional namespace)
|
|
|
|
"Find an instance of CPP-ENUM in the enum registry by searching downwards
|
|
|
|
from the given namespace.
|
|
|
|
|
|
|
|
The arguments NAME and NAMESPACE work just the same as in FIND-CPP-ENUM, except
|
|
|
|
that:
|
|
|
|
|
|
|
|
- NAME cannot be a qualified name.
|
|
|
|
|
|
|
|
- If NAME is a CPP-TYPE instance, then it is treated as the
|
|
|
|
string (cpp-type-name name)."
|
|
|
|
(check-type name (or symbol string cpp-type))
|
|
|
|
(check-type namespace (or nil string list))
|
|
|
|
(let ((name (ctypecase name
|
|
|
|
(string name)
|
|
|
|
(symbol (cpp-name-for-class name))))
|
|
|
|
(namespace (ctypecase namespace
|
|
|
|
(list namespace)
|
|
|
|
(string (split-namespace-string namespace)))))
|
|
|
|
(when (typestring-qualified-p name)
|
|
|
|
(error "Using the qualified name ~S with an iterative traversal" name))
|
|
|
|
(let ((cpp-enums
|
|
|
|
(remove-if-not
|
|
|
|
(lambda (cpp-type)
|
|
|
|
(and (string= name (cpp-type-name cpp-type))
|
|
|
|
(prefix-of-p namespace
|
|
|
|
(cpp-type-extended-namespace cpp-type)
|
|
|
|
:test #'string=)))
|
|
|
|
*cpp-enums*)))
|
|
|
|
(and cpp-enums
|
|
|
|
(minimize
|
|
|
|
cpp-enums
|
|
|
|
:key (lambda (cpp-type)
|
|
|
|
(length (cpp-type-extended-namespace cpp-type))))))))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; Type queries
|
|
|
|
|
|
|
|
(defun cpp-enum-p (object)
|
|
|
|
"Test whether OBJECT is an instance of CPP-ENUM."
|
|
|
|
(typep object 'cpp-enum))
|
|
|
|
|
|
|
|
(defun cpp-class-p (object)
|
|
|
|
"Test whether OBJECT is an instance of CPP-CLASS."
|
|
|
|
(typep object 'cpp-class))
|
|
|
|
|
|
|
|
(defun cpp-type-supported-p (general-cpp-type)
|
|
|
|
"Test whether the given GENERAL-CPP-TYPE instance is a supported type (i.e.
|
|
|
|
not an instance of UNSUPPORTED-CPP-TYPE)."
|
|
|
|
(check-type general-cpp-type general-cpp-type)
|
|
|
|
(not (typep general-cpp-type 'unsupported-cpp-type)))
|
|
|
|
|
|
|
|
(defun cpp-type-known-p (general-cpp-type)
|
|
|
|
"Test whether the given GENERAL-CPP-TYPE instance is a known type."
|
|
|
|
(check-type general-cpp-type general-cpp-type)
|
|
|
|
(or (cpp-class-p general-cpp-type) (cpp-enum-p general-cpp-type)))
|
|
|
|
|
|
|
|
(defun cpp-type-primitive-p (cpp-type)
|
|
|
|
"Test whether CPP-TYPE represents a primitive C++ type."
|
|
|
|
(check-type cpp-type cpp-type)
|
|
|
|
(and (null (cpp-type-namespace cpp-type))
|
|
|
|
(null (cpp-type-enclosing-classes cpp-type))
|
|
|
|
(null (cpp-type-type-params cpp-type))
|
|
|
|
(null (cpp-type-type-args cpp-type))
|
|
|
|
(member (cpp-type-name cpp-type) +cpp-primitive-type-names+
|
|
|
|
:test #'string=)
|
|
|
|
t))
|
|
|
|
|
|
|
|
(defun cpp-type-raw-pointer-p (cpp-type)
|
|
|
|
"Test whether CPP-TYPE represents a raw pointer type."
|
|
|
|
(check-type cpp-type cpp-type)
|
|
|
|
(string= (cpp-type-name cpp-type) "*"))
|
|
|
|
|
|
|
|
(defun cpp-type-reference-p (cpp-type)
|
|
|
|
"Test whether CPP-TYPE represents a reference type."
|
|
|
|
(check-type cpp-type cpp-type)
|
2019-05-24 20:16:42 +08:00
|
|
|
(string= (cpp-type-name cpp-type) "&"))
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
|
|
|
|
(defun cpp-type-smart-pointer-p (cpp-type)
|
|
|
|
"Test whether CPP-TYPE represents a smart pointer type."
|
|
|
|
(check-type cpp-type cpp-type)
|
|
|
|
(and (cpp-type-class-template-instantiation-p cpp-type)
|
|
|
|
(member (cpp-type-name cpp-type) '("shared_ptr" "unique_ptr")
|
|
|
|
:test #'string=)
|
|
|
|
t))
|
|
|
|
|
|
|
|
(defun cpp-type-pointer-p (cpp-type)
|
|
|
|
"Test whether CPP-TYPE represents either a raw or a smart pointer type."
|
|
|
|
(check-type cpp-type cpp-type)
|
|
|
|
(or (cpp-type-raw-pointer-p cpp-type)
|
|
|
|
(cpp-type-smart-pointer-p cpp-type)))
|
|
|
|
|
|
|
|
(defun cpp-type-simple-class-p (cpp-type)
|
|
|
|
"Test whether CPP-TYPE represents a simple class (class which is not a class
|
|
|
|
template instantiation)."
|
|
|
|
(check-type cpp-type cpp-type)
|
|
|
|
(and (not (cpp-type-primitive-p cpp-type))
|
|
|
|
(not (cpp-type-type-params cpp-type))
|
|
|
|
(not (cpp-type-type-args cpp-type))))
|
|
|
|
|
|
|
|
(defun cpp-type-class-template-p (cpp-type)
|
|
|
|
"Test whether CPP-TYPE represents a class template."
|
|
|
|
(check-type cpp-type cpp-type)
|
|
|
|
(and (not (cpp-type-raw-pointer-p cpp-type))
|
|
|
|
(not (cpp-type-reference-p cpp-type))
|
|
|
|
(cpp-type-type-params cpp-type)
|
|
|
|
t))
|
|
|
|
|
|
|
|
(defun cpp-type-class-template-instantiation-p (cpp-type)
|
|
|
|
"Test whether CPP-TYPE represents a class template instantiation."
|
|
|
|
(check-type cpp-type cpp-type)
|
|
|
|
(and (not (member (cpp-type-name cpp-type) '("*" "&") :test #'string=))
|
|
|
|
(cpp-type-type-args cpp-type)
|
|
|
|
t))
|
|
|
|
|
|
|
|
(defun cpp-type-class-p (cpp-type)
|
|
|
|
"Test whether CPP-TYPE represents either a simple class or a class template
|
|
|
|
instantiation."
|
|
|
|
(check-type cpp-type cpp-type)
|
|
|
|
(or (cpp-type-simple-class-p cpp-type)
|
|
|
|
(cpp-type-class-template-instantiation-p cpp-type)))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; Resolution
|
|
|
|
|
|
|
|
(defun resolve-typestring-for-super-class (typestring cpp-class)
|
|
|
|
"Resolve the typestring TYPESTRING for a superclass. CPP-CLASS is the
|
|
|
|
CPP-CLASS instance that subclasss the class named by the typestring and is used
|
|
|
|
to perform proper relative lookup, if any."
|
|
|
|
(flet ((rec (cpp-type)
|
|
|
|
;; NOTE: This will surely produce the original typestring because
|
|
|
|
;; we only ever resolve typestrings that are either fully qualified
|
|
|
|
;; or not qualified at all, both of which are preserved by the
|
|
|
|
;; declaration parsing process.
|
|
|
|
(resolve-typestring-for-super-class
|
|
|
|
(cpp-type-decl
|
|
|
|
cpp-type :globalp (cpp-type-extended-namespace cpp-type))
|
|
|
|
cpp-class)))
|
|
|
|
(let* ((cpp-type (parse-cpp-type-declaration typestring))
|
|
|
|
(resolved (cond
|
|
|
|
((not cpp-type)
|
|
|
|
(make-unsupported-cpp-type typestring))
|
|
|
|
((typestring-fully-qualified-p typestring)
|
|
|
|
(or (find-cpp-class typestring)
|
|
|
|
cpp-type))
|
|
|
|
(t
|
|
|
|
(or (find-cpp-class-ascending
|
|
|
|
typestring (cpp-type-extended-namespace cpp-class))
|
|
|
|
cpp-type)))))
|
|
|
|
(prog1 resolved
|
|
|
|
;; Recursively resolve any type arguments, but only for supported types.
|
|
|
|
(when cpp-type
|
|
|
|
(setf (%cpp-type-type-args resolved)
|
|
|
|
(mapcar #'rec (cpp-type-type-args resolved))))))))
|
|
|
|
|
|
|
|
(defun resolve-typestring-for-member (typestring cpp-class)
|
|
|
|
"Resolve the typestring TYPESTRING for the type of a member. CPP-CLASS is a
|
|
|
|
CPP-CLASS instance that contains the CPP-MEMBER and is used in order to perform
|
|
|
|
proper relative lookup, if any."
|
|
|
|
(flet ((rec (cpp-type)
|
|
|
|
(resolve-typestring-for-member
|
|
|
|
;; NOTE: This will surely produce the original typestring because
|
|
|
|
;; we only ever resolve typestrings that are either fully
|
|
|
|
;; qualified or not qualified at all, both of which are preserved
|
|
|
|
;; by the declaration parsing process.
|
|
|
|
(cpp-type-decl
|
|
|
|
cpp-type :globalp (cpp-type-extended-namespace cpp-type))
|
|
|
|
cpp-class)))
|
|
|
|
(let* ((cpp-type (parse-cpp-type-declaration typestring))
|
|
|
|
(resolved (cond
|
|
|
|
((not cpp-type)
|
|
|
|
(make-unsupported-cpp-type typestring))
|
|
|
|
((typestring-fully-qualified-p typestring)
|
|
|
|
(or (find-cpp-class typestring)
|
|
|
|
(find-cpp-enum typestring)
|
|
|
|
cpp-type))
|
|
|
|
((cpp-type-primitive-p cpp-type)
|
|
|
|
cpp-type)
|
|
|
|
(t
|
|
|
|
;; The types of members may be defined within the class
|
|
|
|
;; itself.
|
|
|
|
(let ((namespace
|
|
|
|
(append (cpp-type-extended-namespace cpp-class)
|
|
|
|
(list (cpp-type-name cpp-class)))))
|
|
|
|
(or (find-cpp-class-ascending typestring namespace)
|
|
|
|
(find-cpp-enum-ascending typestring namespace)
|
|
|
|
cpp-type))))))
|
|
|
|
(prog1 resolved
|
|
|
|
;; Recursively resolve any type arguments, but only for supported types.
|
|
|
|
(when cpp-type
|
|
|
|
(setf (%cpp-type-type-args resolved)
|
|
|
|
(mapcar #'rec (cpp-type-type-args resolved))))))))
|
|
|
|
|
|
|
|
(defmethod cpp-class-super-classes ((cpp-class cpp-class))
|
|
|
|
"Return a list of GENERAL-CPP-TYPE instances which are the superclasses of the
|
|
|
|
C++ class CPP-CLASS."
|
|
|
|
(mapcar
|
|
|
|
(lambda (typestring)
|
|
|
|
(resolve-typestring-for-super-class typestring cpp-class))
|
|
|
|
(%cpp-class-super-classes cpp-class)))
|
|
|
|
|
|
|
|
(defmethod cpp-class-members (cpp-class)
|
|
|
|
(mapcar
|
|
|
|
(lambda (member)
|
|
|
|
(let ((member (copy-cpp-member member)))
|
|
|
|
(prog1 member
|
|
|
|
(setf (cpp-member-type member)
|
|
|
|
(resolve-typestring-for-member
|
|
|
|
(cpp-member-type member) cpp-class)))))
|
|
|
|
(%cpp-class-members cpp-class)))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; Type utilities
|
|
|
|
|
|
|
|
(defun ensure-cpp-type (thing)
|
|
|
|
"Return a CPP-TYPE instance corresponding to the CPP-TYPE designator
|
|
|
|
THING.
|
|
|
|
|
|
|
|
- If THING is of type CPP-TYPE, return it.
|
|
|
|
|
|
|
|
- If THING is a typestring designator it is coerced into a typestring as if by
|
|
|
|
ENSURE-TYPESTRING. The typestring is then parsed using
|
|
|
|
PARSE-CPP-TYPE-DECLARATION. If it is successfully parsed, return the resulting
|
|
|
|
CPP-TYPE instance. Otherwise, return an instance of UNSUPPORTED-CPP-TYPE."
|
|
|
|
(ctypecase thing
|
|
|
|
(cpp-type
|
|
|
|
thing)
|
|
|
|
((or symbol string)
|
|
|
|
(let ((thing (ensure-typestring thing)))
|
|
|
|
(or (parse-cpp-type-declaration thing)
|
|
|
|
(make-unsupported-cpp-type thing))))))
|
|
|
|
|
|
|
|
(defun cpp-class-direct-subclasses (cpp-class)
|
|
|
|
"Return a list of CPP-CLASS instances which are the direct subclasses of the
|
|
|
|
C++ class CPP-CLASS."
|
|
|
|
(check-type cpp-class cpp-class)
|
|
|
|
;; Reverse to get them in definition order.
|
|
|
|
(reverse
|
|
|
|
(remove-if-not
|
|
|
|
(lambda (subclass)
|
|
|
|
(member cpp-class
|
|
|
|
(remove-if-not #'cpp-type-supported-p
|
|
|
|
(cpp-class-super-classes subclass))
|
|
|
|
:test #'cpp-type=))
|
|
|
|
*cpp-classes*)))
|
|
|
|
|
|
|
|
(defun cpp-type-extended-namespace (cpp-type)
|
|
|
|
(check-type cpp-type cpp-type)
|
|
|
|
(append (cpp-type-namespace cpp-type) (cpp-type-enclosing-classes cpp-type)))
|
|
|
|
|
2018-10-31 20:54:36 +08:00
|
|
|
(defun cpp-type-namespace-string (cpp-type)
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
"Return the namespace part of CPP-TYPE as a string ending with \"::\". When
|
2018-10-31 20:54:36 +08:00
|
|
|
CPP-TYPE has no namespace, return an empty string."
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(check-type cpp-type cpp-type)
|
2018-10-31 20:54:36 +08:00
|
|
|
(format nil "~{~A::~}" (cpp-type-namespace cpp-type)))
|
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(defun cpp-type-enclosing-classes-string (cpp-type)
|
|
|
|
"Return as a string the concatenation of the names of the enclosing classes of
|
|
|
|
the type CPP-TYPE. The names are delimited with \"::\" and a trailing delimiter
|
|
|
|
is included."
|
|
|
|
(check-type cpp-type cpp-type)
|
|
|
|
(format nil "~{~A::~}" (cpp-type-enclosing-classes cpp-type)))
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(defun cpp-class-members-for-save (cpp-class)
|
|
|
|
(check-type cpp-class cpp-class)
|
|
|
|
(remove-if #'cpp-member-dont-save (cpp-class-members cpp-class)))
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;;
|
|
|
|
;;; Macros
|
|
|
|
;;;
|
|
|
|
;;; These provide a small DSL for defining enums and classes. The defined enums
|
|
|
|
;;; and classes are automatically added to the global enum and class registries.
|
|
|
|
;;;
|
|
|
|
;;; *CPP-INNER-TYPES* and *CPP-ENCLOSING-CLASSES* are used to communicate (at
|
|
|
|
;;; run-time, not macroexpansion-time) information between nested usages of the
|
|
|
|
;;; macros. The expansions are such that any nested expansions will be evaluated
|
|
|
|
;;; within a dynamic environment set up by the parent macro.
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(defvar *cpp-inner-types* :toplevel
|
|
|
|
"A list of CPP-TYPE instances defined within the current class being
|
|
|
|
defined.")
|
2018-10-31 20:54:36 +08:00
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(defvar *cpp-enclosing-classes* nil
|
|
|
|
"A list of strings naming the enclosing classes of the current class being
|
|
|
|
defined. The names are ordered from outermost to innermost enclosing class.")
|
2018-10-31 20:54:36 +08:00
|
|
|
|
2019-05-24 20:16:42 +08:00
|
|
|
(defun cons-or-replace (element list &key (test #'eql) (key #'identity))
|
|
|
|
"Cons the ELEMENT to the LIST and remove existing elements.
|
|
|
|
|
|
|
|
All elements that compare equal (under TEST) with ELEMENT are removed. KEY will
|
|
|
|
be applied to each element of LIST before calling TEST."
|
|
|
|
(cons element (remove-if (lambda (other) (funcall test element other))
|
|
|
|
list :key key)))
|
|
|
|
|
2019-05-24 20:08:49 +08:00
|
|
|
(defun register-enum (cpp-enum)
|
2019-05-24 20:16:42 +08:00
|
|
|
"Register the given CPP-ENUM instance with the enum registry."
|
2019-05-24 20:08:49 +08:00
|
|
|
(check-type cpp-enum cpp-enum)
|
|
|
|
(prog1 cpp-enum
|
2019-05-24 20:16:42 +08:00
|
|
|
;; Add or redefine the enum.
|
|
|
|
(setf *cpp-enums*
|
|
|
|
(cons cpp-enum
|
|
|
|
(delete-if
|
|
|
|
(lambda (other)
|
|
|
|
(string= (cpp-type-decl cpp-enum) (cpp-type-decl other)))
|
|
|
|
*cpp-enums*)))
|
|
|
|
;; Add to the parent's inner types.
|
2019-05-24 20:08:49 +08:00
|
|
|
(unless (eq *cpp-inner-types* :toplevel)
|
|
|
|
(push cpp-enum *cpp-inner-types*))))
|
|
|
|
|
|
|
|
(defun register-class (cpp-class)
|
|
|
|
"Register the given CPP-CLASS instance with the class registry."
|
|
|
|
(check-type cpp-class cpp-class)
|
|
|
|
(prog1 cpp-class
|
|
|
|
;; Add or redefine the class.
|
2019-05-24 20:16:42 +08:00
|
|
|
(setf *cpp-classes*
|
|
|
|
(cons cpp-class
|
|
|
|
(delete-if
|
|
|
|
(lambda (other)
|
|
|
|
(string= (cpp-type-decl cpp-class) (cpp-type-decl other)))
|
|
|
|
*cpp-classes*)))
|
2019-05-24 20:08:49 +08:00
|
|
|
;; Add to the parent's inner types.
|
|
|
|
(unless (eq *cpp-inner-types* :toplevel)
|
|
|
|
(push cpp-class *cpp-inner-types*))))
|
|
|
|
|
2018-10-31 20:54:36 +08:00
|
|
|
(defmacro define-enum (name values &rest options)
|
2019-05-10 20:49:42 +08:00
|
|
|
"Define a C++ enum.
|
2018-10-31 20:54:36 +08:00
|
|
|
|
2019-05-10 20:49:42 +08:00
|
|
|
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."
|
2019-05-24 20:08:49 +08:00
|
|
|
`(register-enum
|
|
|
|
(make-instance
|
|
|
|
'cpp-enum
|
|
|
|
:documentation ',(assoc-second :documentation options)
|
|
|
|
:name ',(ensure-namestring-for-class name)
|
|
|
|
:values ',(mapcar #'ensure-namestring-for-enumerator values)
|
|
|
|
:namespace (reverse *cpp-namespaces*)
|
|
|
|
:enclosing-classes (reverse *cpp-enclosing-classes*)
|
|
|
|
:serializep ',(if (assoc :serialize options) t))))
|
|
|
|
|
|
|
|
(defun generate-make-cpp-member (slot-definition &key structp)
|
|
|
|
(destructuring-bind (name type &rest kwargs &key reader scope
|
|
|
|
&allow-other-keys)
|
|
|
|
slot-definition
|
|
|
|
(let ((scope (or scope (if structp :public :private))))
|
|
|
|
(when (and structp reader (eq :private scope))
|
|
|
|
(error "~A is a private member with a getter, but a struct is being defined" name))
|
|
|
|
(when (and structp reader (eq :public scope))
|
|
|
|
(error "~A is a public member, but a getter was defined" name))
|
|
|
|
`(make-cpp-member
|
|
|
|
:name ,(ensure-namestring-for-member name :structp structp)
|
|
|
|
:type (process-typestring ,(ensure-typestring type))
|
|
|
|
:scope ',scope
|
|
|
|
,@kwargs))))
|
|
|
|
|
|
|
|
(defun generate-define-class (name super-classes slots options)
|
|
|
|
"Generate the expansion for DEFINE-CLASS."
|
|
|
|
(let* ((name (alexandria:ensure-list name))
|
|
|
|
(class-name (ensure-namestring-for-class (car name)))
|
|
|
|
(type-params (mapcar #'ensure-namestring-for-type-param (cdr name)))
|
|
|
|
(structp (assoc-second :structp options))
|
|
|
|
(abstractp (assoc-second :abstractp options))
|
|
|
|
(members (mapcar (lambda (s) (generate-make-cpp-member s :structp structp)) slots))
|
|
|
|
(super-classes (mapcar #'ensure-typestring super-classes))
|
|
|
|
(serialize (assoc-body :serialize options))
|
|
|
|
(slk (assoc :slk serialize))
|
|
|
|
(clone (assoc :clone options))
|
|
|
|
(type-info (assoc-body :type-info options))
|
|
|
|
(documentation (assoc-second :documentation options))
|
2019-05-24 20:10:06 +08:00
|
|
|
(public (concat (assoc-body-all :public options)))
|
|
|
|
(protected (concat (assoc-body-all :protected options)))
|
|
|
|
(private (concat (assoc-body-all :private options))))
|
2019-05-24 20:08:49 +08:00
|
|
|
;; Call REGISTER-CLASS within the original context.
|
|
|
|
`(register-class
|
|
|
|
;; Save our original context.
|
|
|
|
,(alexandria:once-only ((cpp-enclosing-classes '*cpp-enclosing-classes*))
|
|
|
|
;; Evaluate the subforms of DEFINE-CLASS within a nested context, so
|
|
|
|
;; that recursive invocations of the same macro are handled properly.
|
|
|
|
`(let ((*cpp-inner-types* '())
|
|
|
|
(*cpp-enclosing-classes* (cons ,class-name *cpp-enclosing-classes*)))
|
|
|
|
;; Explicitly sequence the evaluation of user-provided subforms to aid clarity.
|
|
|
|
,(alexandria:once-only
|
|
|
|
((public `(list ,@public))
|
|
|
|
(protected `(list ,@protected))
|
|
|
|
(private `(list ,@private))
|
|
|
|
(slk (and slk `(make-slk-opts ,@(cdr slk))))
|
|
|
|
(clone (and clone `(make-clone-opts ,@(cdr clone))))
|
|
|
|
(type-info `(make-type-info-opts ,@type-info)))
|
|
|
|
`(make-instance
|
|
|
|
'cpp-class
|
|
|
|
:documentation ',documentation
|
|
|
|
:namespace (reverse *cpp-namespaces*)
|
|
|
|
:enclosing-classes (reverse ,cpp-enclosing-classes)
|
|
|
|
:name ,class-name
|
|
|
|
:type-params ',type-params
|
|
|
|
:structp ',structp
|
|
|
|
:super-classes (mapcar #'process-typestring ',super-classes)
|
|
|
|
:members (list ,@members)
|
|
|
|
:public ,public
|
|
|
|
:protected ,protected
|
|
|
|
:private ,private
|
|
|
|
:slk-opts ,slk
|
|
|
|
:clone-opts ,clone
|
|
|
|
:type-info-opts ,type-info
|
|
|
|
:inner-types *cpp-inner-types*
|
|
|
|
:abstractp ',abstractp)))))))
|
2018-10-31 20:54:36 +08:00
|
|
|
|
|
|
|
(defmacro define-class (name super-classes slots &rest options)
|
2019-05-10 20:49:42 +08:00
|
|
|
"Define a simple C++ class or a C++ class template.
|
|
|
|
|
|
|
|
The syntax is:
|
|
|
|
|
|
|
|
(define-class <name> (<super-class>*)
|
|
|
|
(<cpp-slot-definition>*)
|
|
|
|
<class-option>*)
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
Each SUPER-CLASS is a typestring representing a superclass of the class being
|
|
|
|
defined.
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
SLOT-OPTIONS is a plist whose values are not evaluated by default. The possible
|
|
|
|
keys are:
|
|
|
|
|
|
|
|
- :INITVAL -- Evaluated. A number or a string representing a C++ expression that
|
|
|
|
will be used to initialize the member using the member initializer list.
|
|
|
|
|
|
|
|
- :READER -- If T, generates a public getter for the member.
|
|
|
|
|
|
|
|
- :SCOPE -- The class scope of the member. One of :PUBLIC, :PROTECTED
|
|
|
|
or :PRIVATE (default).
|
|
|
|
|
|
|
|
- :DOCUMENTATION -- String specifying the Doxygen documentation for the member.
|
|
|
|
|
|
|
|
The SLK serialization backend also introduces the following member options:
|
|
|
|
|
|
|
|
- :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.
|
|
|
|
|
|
|
|
- :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.
|
|
|
|
|
2019-05-24 20:10:06 +08:00
|
|
|
CLASS-OPTION is a pair (KEY VALUE*). VALUE is by default not evaluated. Options
|
|
|
|
by default have overriding behavior, meaning that if a key appears multiple
|
|
|
|
times, the value associated with the leftmost one is taken. Options might
|
|
|
|
instead have aggregating behavior, meaning that the value is formed by
|
|
|
|
collecting the values associated with all of the appearances of the key. The
|
2019-05-10 20:49:42 +08:00
|
|
|
possible values of KEY are:
|
|
|
|
|
|
|
|
- :DOCUMENTATION -- String specifying the Doxygen documentation for the class.
|
|
|
|
|
2019-05-24 20:10:06 +08:00
|
|
|
- :PUBLIC, :PROTECTED, :PRIVATE -- Evaluated. Aggregated. 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.
|
2019-05-10 20:49:42 +08:00
|
|
|
|
|
|
|
- :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."
|
2019-05-24 20:08:49 +08:00
|
|
|
(generate-define-class name super-classes slots options))
|
2018-10-31 20:54:36 +08:00
|
|
|
|
|
|
|
(defmacro define-struct (name super-classes slots &rest options)
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
"The same as DEFINE-CLASS, except that a struct is defined instead (by passing
|
|
|
|
T to the :STRUCTP option)."
|
2018-10-31 20:54:36 +08:00
|
|
|
`(define-class ,name ,super-classes ,slots (:structp t) ,@options))
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
|
|
|
|
(defun rpc-constructors (class-name members)
|
|
|
|
"Generate C++ code for an RPC's constructors.
|
|
|
|
|
|
|
|
CLASS-NAME is the name of the class whose constructors to generate. MEMBERS
|
|
|
|
should be a list of members as in DEFINE-RPC. Detailed documentation regarding
|
|
|
|
the constructors and various options can be found within DEFINE-RPC."
|
|
|
|
(let* ((members (remove-if (lambda (member)
|
|
|
|
(let ((initarg (member :initarg member)))
|
|
|
|
(and initarg (null (second initarg)))))
|
|
|
|
members))
|
|
|
|
(args
|
|
|
|
(mapcar
|
|
|
|
(lambda (member)
|
|
|
|
(list (ensure-typestring (second member))
|
|
|
|
(ensure-namestring-for-member (first member) :structp t)))
|
|
|
|
members))
|
|
|
|
(init-list
|
|
|
|
(mapcar
|
|
|
|
(lambda (member)
|
|
|
|
(let ((var (ensure-namestring-for-variable (first member)))
|
|
|
|
(movep (eq :move (second (member :initarg member)))))
|
|
|
|
(list var (if movep
|
|
|
|
(format nil "std::move(~A)" var)
|
|
|
|
var))))
|
|
|
|
members))
|
|
|
|
(full-constructor
|
|
|
|
(with-output-to-string (s)
|
|
|
|
(when members
|
|
|
|
(format s "~A ~A(~:{~A ~A~:^, ~}) : ~:{~A(~A)~:^, ~} {}"
|
|
|
|
(if (= (length members) 1) "explicit" "")
|
|
|
|
class-name args init-list)))))
|
|
|
|
#>cpp
|
|
|
|
${class-name}() {}
|
|
|
|
${full-constructor}
|
|
|
|
cpp<#))
|
|
|
|
|
|
|
|
(defun rpc-save-load (name)
|
|
|
|
"Generate SLK's `Save` and `Load` functions for a request or response RPC
|
|
|
|
structure named by the string NAME."
|
|
|
|
;; TODO: Replace FIND-CPP-CLASS-DESCENDING.
|
|
|
|
`(let ((class (find-cpp-class-descending ,name)))
|
|
|
|
(unless (lcp.slk::save-extra-args class)
|
|
|
|
(push ,(progn
|
|
|
|
#>cpp
|
|
|
|
static void Save(const ${name} &self, slk::Builder *builder);
|
|
|
|
cpp<#)
|
|
|
|
(cpp-class-public class))
|
|
|
|
(in-impl
|
|
|
|
,(progn
|
|
|
|
#>cpp
|
|
|
|
void ${name}::Save(const ${name} &self, slk::Builder *builder) {
|
|
|
|
slk::Save(self, builder);
|
|
|
|
}
|
|
|
|
cpp<#)))
|
|
|
|
(unless (lcp.slk::load-extra-args class)
|
|
|
|
(push ,(progn #>cpp
|
|
|
|
static void Load(${name} *self, slk::Reader *reader);
|
|
|
|
cpp<#)
|
|
|
|
(cpp-class-public class))
|
|
|
|
(in-impl
|
|
|
|
,(progn
|
|
|
|
#>cpp
|
|
|
|
void ${name}::Load(${name} *self, slk::Reader *reader) {
|
|
|
|
slk::Load(self, reader);
|
|
|
|
}
|
|
|
|
cpp<#)))))
|
|
|
|
|
|
|
|
(defmacro define-rpc (name &body options)
|
|
|
|
"Define an RPC. Two structures are defined, representing the request and
|
|
|
|
the response for the given RPC.
|
|
|
|
|
2019-05-10 20:49:42 +08:00
|
|
|
The syntax is:
|
|
|
|
|
|
|
|
(define-rpc <name>
|
|
|
|
(:request (<slot>*) <struct-option>*)
|
|
|
|
(:response (<slot>*) <struct-option>*))
|
|
|
|
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
NAME should designate a namestring for a class, which is used to produce the
|
2019-05-10 20:49:42 +08:00
|
|
|
names of the two structures.
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
|
|
|
|
The names of the structures are formed by concatenating the namestring NAME with
|
|
|
|
\"Req\" and \"Res\".
|
|
|
|
|
2019-05-24 20:10:06 +08:00
|
|
|
The two options :REQUEST and :RESPONSE are mandatory. Their bodies should follow
|
|
|
|
the same syntax and conventions of DEFINE-STRUCT's (i.e. DEFINE-CLASS's) class
|
|
|
|
and member options.
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
|
2019-05-24 20:10:06 +08:00
|
|
|
DEFINE-RPC introduces the following additional class options:
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
|
2019-05-24 20:10:06 +08:00
|
|
|
- :CTOR -- If NIL, inhibits the generation of constructors.
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
|
2019-05-24 20:10:06 +08:00
|
|
|
For both structures two constructors are generated:
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
|
2019-05-24 20:10:06 +08:00
|
|
|
- A default constructor that does no explicit initialization of members.
|
|
|
|
|
|
|
|
- A custom constructor that accepts values and initializes members according
|
|
|
|
to their :INITARG option, in order of appearance.
|
|
|
|
|
|
|
|
If the constructor ends up accepting just one member, it is marked
|
|
|
|
`explicit`.
|
|
|
|
|
|
|
|
If the constructor ends up accepting no members, it is not generated.
|
|
|
|
|
|
|
|
DEFINE-RPC introduces the following additional member options:
|
|
|
|
|
|
|
|
- :INITARG -- Controls the way in which the corresponding member participates in
|
|
|
|
the custom constructor.
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
|
|
|
|
If the :INITARG option is omitted or NIL, the constructor doesn't accept a
|
|
|
|
value for the member and the member is not explicitly initialized.
|
|
|
|
|
|
|
|
If the :INITARG option is true, the constructor accepts a value for the member
|
|
|
|
and the member is copy-initialized.
|
|
|
|
|
|
|
|
If the :INITARG option is :MOVE, the constructor accepts a value for the
|
2019-05-24 20:10:06 +08:00
|
|
|
member and the member is move-initialized using `std::move`."
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(flet ((remove-rpc-options (body)
|
|
|
|
`(,(mapcar
|
|
|
|
(lambda (member)
|
|
|
|
`(,(first member)
|
|
|
|
,(second member)
|
|
|
|
,@(alexandria:remove-from-plist (cddr member) :initarg)))
|
|
|
|
(car body))
|
2019-05-24 20:10:06 +08:00
|
|
|
,@(remove :ctor (cdr body) :key #'car))))
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(let* ((name (ensure-namestring-for-class name))
|
|
|
|
(rpc-name (format nil "~ARpc" name))
|
|
|
|
(req-name (format nil "~AReq" name))
|
|
|
|
(res-name (format nil "~ARes" name))
|
|
|
|
(rpc-decl
|
|
|
|
#>cpp
|
|
|
|
using ${rpc-name} = communication::rpc::RequestResponse<${req-name}, ${res-name}>;
|
|
|
|
cpp<#)
|
|
|
|
(request-body (cdr (assoc :request options)))
|
2019-05-24 20:10:06 +08:00
|
|
|
(response-body (cdr (assoc :response options)))
|
|
|
|
(req-ctor (assoc :ctor (cdr request-body)))
|
|
|
|
(res-ctor (assoc :ctor (cdr response-body))))
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
`(cpp-list
|
|
|
|
(define-struct ,req-name ()
|
|
|
|
,@(remove-rpc-options request-body)
|
2019-05-24 20:10:06 +08:00
|
|
|
,@(when (or (not req-ctor) (not (cdr req-ctor)))
|
|
|
|
`((:public
|
|
|
|
,(rpc-constructors req-name (first request-body)))))
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(:serialize (:slk)))
|
|
|
|
,(rpc-save-load req-name)
|
|
|
|
(define-struct ,res-name ()
|
|
|
|
,@(remove-rpc-options response-body)
|
2019-05-24 20:10:06 +08:00
|
|
|
,@(when (or (not res-ctor) (not (cdr res-ctor)))
|
|
|
|
`((:public
|
|
|
|
,(rpc-constructors res-name (first response-body)))))
|
LCP: Refactor the type representation
Summary:
# Summary
## Concepts and terminology
A **namestring for <object>** is a Lisp string that names the C++ language element
`<object>` (such as a namespace, a variable, a class, etc.). Therefore we have a
"namestring for a namespace", a "namestring for a variable", etc.
A **designator for a namestring for <object>** is a Lisp object that denotes a
"namestring for <object>". These are symbols and strings themselves.
A **typestring** is a Lisp string that represents a C++ type, i.e. its
declaration.
A **typestring designator** is a Lisp object that denotes a typestring.
A typestring (and the corresponding C++ type) is said to be **supported** if it
can be parsed using `parse-cpp-type-declaration`. This concept is important and
should form the base of our design because we can't really hope to ever support
all of C++'s type declarations.
A typestring (and the corresponding C++ type) that is not supported is
**unsupported**.
A **processed typestring** is a typestring that is either fully qualified or
unqualified.
A C++ type is said to be **known** if LCP knows extra information about the type,
rather than just what kind of type it is, in which namespace it lives, etc. For
now, the only known types are those that are defined within LCP itself using
`define-class` & co.
A C++ type is **unknown** if it is not known.
**Typestring resolution** is the process of resolving a (processed) typestring
into an instance of `cpp-type` or `unsupported-cpp-type`.
**Resolving accessors** are accessors which perform typestring resolution.
## Changes
Explicitly introduce the concept of supported and known types. `cpp-type` models
supported types while `unsupported-cpp-type` models unsupported types.
Subclasses of `cpp-type` model known types. `general-cpp-type` is either a
`cpp-type` or an `unsupported-cpp-type`.
Add various type queries.
Fix `define-rpc`'s `:initarg` (remove it from the `cpp-member` struct).
Introduce namestrings and their designators in `names.lisp`.
Introduce typestrings and their designators.
Introduce **processed typestrings**. Our DSL's macros (`define-class` & co.)
convert all of the given typestrings into processed typestrings because we don't
attempt to support partially qualified names and relative name lookup yet. A
warning is signalled when a partially qualified name is treated as a fully
qualified name.
The slots of `cpp-type`, `cpp-class`, `cpp-member` and `cpp-capnp-opts` now
store processed typestrings which are lazily resolved into their corresponding
C++ types.
The only thing that instances of `unsupported-cpp-type` are good for is getting
the typestring that was used to construct them. Most of LCP's functions only
work with known C++ types, i.e. `cpp-type` instances. The only function so far
that works for both of them is `cpp-type-decl`.
Since "unsupportedness" is now explicitly part of LCP, client code is expected
to manually check whether a returned type is unsupported or not (or face
receiving an error otherwise), unless a function is documented to return only
`cpp-type` instances.
A similar thing goes for "knowness". Client code is expected to manually check
whether a returned type is known or not, unless a function is documented to
return only (instances of `cpp-type` subclasses) known types.
## TODO
Resolution still has to be done for the following slots of the
following structures:
- `slk-opts`
- `save-args`
- `load-args`
- `clone-opts`
- `args`
- `return-type`
Reviewers: teon.banek, mtomic
Reviewed By: teon.banek
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D1962
2019-05-10 19:55:21 +08:00
|
|
|
(:serialize (:slk)))
|
|
|
|
,(rpc-save-load res-name)
|
|
|
|
,rpc-decl))))
|