type.py
Go to the documentation of this file.
1 """
2 GTSAM Copyright 2010-2020, Georgia Tech Research Corporation,
3 Atlanta, Georgia 30332-0415
4 All Rights Reserved
5 
6 See LICENSE for the license information
7 
8 Define the parser rules and classes for various C++ types.
9 
10 Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert
11 """
12 
13 # pylint: disable=unnecessary-lambda, expression-not-assigned
14 
15 from typing import List, Sequence, Union
16 
17 from pyparsing import ParseResults # type: ignore
18 from pyparsing import Forward, Optional, Or, delimitedList
19 
20 from .tokens import (BASIC_TYPES, CONST, IDENT, LOPBRACK, RAW_POINTER, REF,
21  ROPBRACK, SHARED_POINTER)
22 
23 
24 class Typename:
25  """
26  Class which holds a type's name, full namespace, and template arguments.
27 
28  E.g.
29  ```
30  gtsam::PinholeCamera<gtsam::Cal3S2>
31  ```
32 
33  will give the name as `PinholeCamera`, namespace as `gtsam`,
34  and template instantiations as `[gtsam::Cal3S2]`.
35 
36  Args:
37  namespaces_and_name: A list representing the namespaces of the type
38  with the type being the last element.
39  instantiations: Template parameters to the type.
40  """
41 
42  namespaces_name_rule = delimitedList(IDENT, "::")
43  instantiation_name_rule = delimitedList(IDENT, "::")
44  rule = (
45  namespaces_name_rule("namespaces_and_name") #
46  ).setParseAction(lambda t: Typename(t))
47 
48  def __init__(self,
49  t: ParseResults,
50  instantiations: Sequence[ParseResults] = ()):
51  self.name = t[-1] # the name is the last element in this list
52  self.namespaces = t[:-1]
53 
54  # If the first namespace is empty string, just get rid of it.
55  if self.namespaces and self.namespaces[0] == '':
56  self.namespaces.pop(0)
57 
58  if instantiations:
59  if isinstance(instantiations, Sequence):
60  self.instantiations = instantiations # type: ignore
61  else:
62  self.instantiations = instantiations.asList()
63  else:
64  self.instantiations = []
65 
66  if self.name in ["Matrix", "Vector"] and not self.namespaces:
67  self.namespaces = ["gtsam"]
68 
69  @staticmethod
70  def from_parse_result(parse_result: Union[str, list]):
71  """Unpack the parsed result to get the Typename instance."""
72  return parse_result[0]
73 
74  def __repr__(self) -> str:
75  return self.to_cpp()
76 
77  def instantiated_name(self) -> str:
78  """Get the instantiated name of the type."""
79  res = self.name
80  for instantiation in self.instantiations:
81  res += instantiation.instantiated_name()
82  return res
83 
84  def qualified_name(self):
85  """Return the fully qualified name, e.g. `gtsam::internal::PoseKey`."""
86  return "::".join(self.namespaces + [self.name])
87 
88  def to_cpp(self) -> str:
89  """Generate the C++ code for wrapping."""
90  if self.instantiations:
91  cpp_name = self.name + "<{}>".format(", ".join(
92  [inst.to_cpp() for inst in self.instantiations]))
93  else:
94  cpp_name = self.name
95  return '{}{}{}'.format(
96  "::".join(self.namespaces),
97  "::" if self.namespaces else "",
98  cpp_name,
99  )
100 
101  def __eq__(self, other) -> bool:
102  if isinstance(other, Typename):
103  return str(self) == str(other)
104  else:
105  return False
106 
107  def __ne__(self, other) -> bool:
108  res = self.__eq__(other)
109  return not res
110 
111 
112 class BasicType:
113  """
114  Basic types are the fundamental built-in types in C++ such as double, int, char, etc.
115 
116  When using templates, the basic type will take on the same form as the template.
117 
118  E.g.
119  ```
120  template<T = {double}>
121  void func(const T& x);
122  ```
123 
124  will give
125 
126  ```
127  m_.def("funcDouble",[](const double& x){
128  ::func<double>(x);
129  }, py::arg("x"));
130  ```
131  """
132 
133  rule = (Or(BASIC_TYPES)("typename")).setParseAction(lambda t: BasicType(t))
134 
135  def __init__(self, t: ParseResults):
136  self.typename = Typename(t)
137 
138 
140  """
141  Custom defined types with the namespace.
142  Essentially any C++ data type that is not a BasicType.
143 
144  E.g.
145  ```
146  gtsam::Matrix wTc;
147  ```
148 
149  Here `gtsam::Matrix` is a custom type.
150  """
151 
152  rule = (Typename.rule("typename")).setParseAction(lambda t: CustomType(t))
153 
154  def __init__(self, t: ParseResults):
155  self.typename = Typename(t)
156 
157 
158 class Type:
159  """
160  Parsed datatype, can be either a fundamental/basic type or a custom datatype.
161  E.g. void, double, size_t, Matrix.
162  Think of this as a high-level type which encodes the typename and other
163  characteristics of the type.
164 
165  The type can optionally be a raw pointer, shared pointer or reference.
166  Can also be optionally qualified with a `const`, e.g. `const int`.
167  """
168  rule = (
169  Optional(CONST("is_const")) #
170  + (BasicType.rule("basic") | CustomType.rule("qualified")) # BR
171  + Optional(
172  SHARED_POINTER("is_shared_ptr") | RAW_POINTER("is_ptr")
173  | REF("is_ref")) #
174  ).setParseAction(lambda t: Type.from_parse_result(t))
175 
176  def __init__(self, typename: Typename, is_const: str, is_shared_ptr: str,
177  is_ptr: str, is_ref: str, is_basic: bool):
178  self.typename = typename
179  self.is_const = is_const
180  self.is_shared_ptr = is_shared_ptr
181  self.is_ptr = is_ptr
182  self.is_ref = is_ref
183  self.is_basic = is_basic
184 
185  @staticmethod
186  def from_parse_result(t: ParseResults):
187  """Return the resulting Type from parsing the source."""
188  # If the type is a basic/fundamental c++ type (e.g int, bool)
189  if t.basic:
190  return Type(
191  typename=t.basic.typename,
192  is_const=t.is_const,
193  is_shared_ptr=t.is_shared_ptr,
194  is_ptr=t.is_ptr,
195  is_ref=t.is_ref,
196  is_basic=True,
197  )
198  elif t.qualified:
199  return Type(
200  typename=t.qualified.typename,
201  is_const=t.is_const,
202  is_shared_ptr=t.is_shared_ptr,
203  is_ptr=t.is_ptr,
204  is_ref=t.is_ref,
205  is_basic=False,
206  )
207  else:
208  raise ValueError("Parse result is not a Type")
209 
210  def __repr__(self) -> str:
211  is_ptr_or_ref = "{0}{1}{2}".format(self.is_shared_ptr, self.is_ptr,
212  self.is_ref)
213  return "{is_const}{self.typename}{is_ptr_or_ref}".format(
214  self=self,
215  is_const="const " if self.is_const else "",
216  is_ptr_or_ref=" " + is_ptr_or_ref if is_ptr_or_ref else "")
217 
218  def to_cpp(self) -> str:
219  """
220  Generate the C++ code for wrapping.
221 
222  Treat all pointers as "const shared_ptr<T>&"
223  Treat Matrix and Vector as "const Matrix&" and "const Vector&" resp.
224  """
225 
226  if self.is_shared_ptr:
227  typename = "std::shared_ptr<{typename}>".format(
228  typename=self.typename.to_cpp())
229  elif self.is_ptr:
230  typename = "{typename}*".format(typename=self.typename.to_cpp())
231  elif self.is_ref or self.typename.name in ["Matrix", "Vector"]:
232  typename = typename = "{typename}&".format(
233  typename=self.typename.to_cpp())
234  else:
235  typename = self.typename.to_cpp()
236 
237  return ("{const}{typename}".format(
238  const="const " if
239  (self.is_const
240  or self.typename.name in ["Matrix", "Vector"]) else "",
241  typename=typename))
242 
243  def get_typename(self):
244  """Convenience method to get the typename of this type."""
245  return self.typename.name
246 
247 
249  """
250  Parser rule for data types which are templated.
251  This is done so that the template parameters can be pointers/references.
252 
253  E.g. std::vector<double>, BearingRange<Pose3, Point3>
254  """
255 
256  rule = Forward()
257  rule << (
258  Optional(CONST("is_const")) #
259  + Typename.rule("typename") #
260  + (
261  LOPBRACK #
262  + delimitedList(Type.rule ^ rule, ",")("template_params") #
263  + ROPBRACK) #
264  + Optional(
265  SHARED_POINTER("is_shared_ptr") | RAW_POINTER("is_ptr")
266  | REF("is_ref")) #
267  ).setParseAction(lambda t: TemplatedType.from_parse_result(t))
268 
269  def __init__(self, typename: Typename, template_params: List[Type],
270  is_const: str, is_shared_ptr: str, is_ptr: str, is_ref: str):
271  instantiations = [param.typename for param in template_params]
272  # Recreate the typename but with the template params as instantiations.
273  self.typename = Typename(typename.namespaces + [typename.name],
274  instantiations)
275 
276  self.template_params = template_params
277 
278  self.is_const = is_const
279  self.is_shared_ptr = is_shared_ptr
280  self.is_ptr = is_ptr
281  self.is_ref = is_ref
282 
283  @staticmethod
284  def from_parse_result(t: ParseResults):
285  """Get the TemplatedType from the parser results."""
286  return TemplatedType(t.typename, t.template_params, t.is_const,
287  t.is_shared_ptr, t.is_ptr, t.is_ref)
288 
289  def __repr__(self):
290  return "TemplatedType({typename.namespaces}::{typename.name})".format(
291  typename=self.typename)
292 
293  def to_cpp(self):
294  """
295  Generate the C++ code for wrapping.
296  """
297  # Use Type.to_cpp to do the heavy lifting for the template parameters.
298  template_args = ", ".join([t.to_cpp() for t in self.template_params])
299 
300  typename = "{typename}<{template_args}>".format(
301  typename=self.typename.qualified_name(),
302  template_args=template_args)
303 
304  if self.is_shared_ptr:
305  typename = f"std::shared_ptr<{typename}>"
306  elif self.is_ptr:
307  typename = "{typename}*".format(typename=typename)
308  elif self.is_ref or self.typename.name in ["Matrix", "Vector"]:
309  typename = typename = "{typename}&".format(typename=typename)
310  else:
311  pass
312 
313  return ("{const}{typename}".format(
314  const="const " if
315  (self.is_const
316  or self.typename.name in ["Matrix", "Vector"]) else "",
317  typename=typename))
bool isinstance(handle obj)
Definition: pytypes.h:700
Definition: pytypes.h:1403
std::string format(const std::string &str, const std::vector< std::string > &find, const std::vector< std::string > &replace)


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:40:38