function.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 Parser classes and rules for parsing C++ functions.
9 
10 Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert
11 """
12 
13 from typing import Iterable, List, Union
14 
15 from pyparsing import Optional, ParseResults, delimitedList
16 
17 from .template import Template
18 from .tokens import (COMMA, DEFAULT_ARG, EQUAL, IDENT, LOPBRACK, LPAREN, PAIR,
19  ROPBRACK, RPAREN, SEMI_COLON)
20 from .type import TemplatedType, Type
21 
22 
23 class Argument:
24  """
25  The type and name of a function/method argument.
26 
27  E.g.
28  ```
29  void sayHello(/*`s` is the method argument with type `const string&`*/ const string& s);
30  ```
31  """
32  rule = ((Type.rule ^ TemplatedType.rule)("ctype") + IDENT("name") + \
33  Optional(EQUAL + (DEFAULT_ARG ^ Type.rule ^ TemplatedType.rule) + \
34  Optional(LPAREN + RPAREN) # Needed to parse the parens for default constructors
35  )("default")
36  ).setParseAction(lambda t: Argument(t.ctype, t.name, t.default))
37 
38  def __init__(self,
39  ctype: Union[Type, TemplatedType],
40  name: str,
41  default: ParseResults = None):
42  if isinstance(ctype, Iterable):
43  self.ctype = ctype[0]
44  else:
45  self.ctype = ctype
46  self.name = name
47  # If the length is 1, it's a regular type,
48  if len(default) == 1:
49  default = default[0]
50  # This means a tuple has been passed so we convert accordingly
51  elif len(default) > 1:
52  default = tuple(default.asList())
53  else:
54  # set to None explicitly so we can support empty strings
55  default = None
56  self.default = default
57 
58  self.parent: Union[ArgumentList, None] = None
59 
60  def __repr__(self) -> str:
61  return self.to_cpp()
62 
63  def to_cpp(self) -> str:
64  """Return full C++ representation of argument."""
65  return '{} {}'.format(repr(self.ctype), self.name)
66 
67 
69  """
70  List of Argument objects for all arguments in a function.
71  """
72  rule = Optional(delimitedList(Argument.rule)("args_list")).setParseAction(
73  lambda t: ArgumentList.from_parse_result(t.args_list))
74 
75  def __init__(self, args_list: List[Argument]):
76  self.args_list = args_list
77  for arg in args_list:
78  arg.parent = self
79  # The parent object which contains the argument list
80  # E.g. Method, StaticMethod, Template, Constructor, GlobalFunction
81  self.parent = None
82 
83  @staticmethod
84  def from_parse_result(parse_result: ParseResults):
85  """Return the result of parsing."""
86  if parse_result:
87  return ArgumentList(parse_result.asList())
88  else:
89  return ArgumentList([])
90 
91  def __repr__(self) -> str:
92  return self.args_list.__repr__()
93 
94  def __len__(self) -> int:
95  return len(self.args_list)
96 
97  def args_names(self) -> List[str]:
98  """Return a list of the names of all the arguments."""
99  return [arg.name for arg in self.args_list]
100 
101  def to_cpp(self, use_boost: bool) -> List[str]:
102  """Generate the C++ code for wrapping."""
103  return [arg.ctype.to_cpp(use_boost) for arg in self.args_list]
104 
105 
107  """
108  Rule to parse the return type.
109 
110  The return type can either be a single type or a pair such as <type1, type2>.
111  """
112  _pair = (
113  PAIR.suppress() #
114  + LOPBRACK #
115  + Type.rule("type1") #
116  + COMMA #
117  + Type.rule("type2") #
118  + ROPBRACK #
119  )
120  rule = (_pair ^
121  (Type.rule ^ TemplatedType.rule)("type1")).setParseAction( # BR
122  lambda t: ReturnType(t.type1, t.type2))
123 
124  def __init__(self, type1: Union[Type, TemplatedType], type2: Type):
125  # If a TemplatedType, the return is a ParseResults, so we extract out the type.
126  self.type1 = type1[0] if isinstance(type1, ParseResults) else type1
127  self.type2 = type2
128  # The parent object which contains the return type
129  # E.g. Method, StaticMethod, Template, Constructor, GlobalFunction
130  self.parent = None
131 
132  def is_void(self) -> bool:
133  """
134  Check if the return type is void.
135  """
136  return self.type1.typename.name == "void" and not self.type2
137 
138  def __repr__(self) -> str:
139  return "{}{}".format(
140  self.type1, (', ' + self.type2.__repr__()) if self.type2 else '')
141 
142  def to_cpp(self, use_boost: bool) -> str:
143  """
144  Generate the C++ code for wrapping.
145 
146  If there are two return types, we return a pair<>,
147  otherwise we return the regular return type.
148  """
149  if self.type2:
150  return "std::pair<{type1},{type2}>".format(
151  type1=self.type1.to_cpp(use_boost),
152  type2=self.type2.to_cpp(use_boost))
153  else:
154  return self.type1.to_cpp(use_boost)
155 
156 
158  """
159  Rule to parse functions defined in the global scope.
160  """
161  rule = (
162  Optional(Template.rule("template")) + ReturnType.rule("return_type") #
163  + IDENT("name") #
164  + LPAREN #
165  + ArgumentList.rule("args_list") #
166  + RPAREN #
167  + SEMI_COLON #
168  ).setParseAction(lambda t: GlobalFunction(t.name, t.return_type, t.
169  args_list, t.template))
170 
171  def __init__(self,
172  name: str,
173  return_type: ReturnType,
174  args_list: ArgumentList,
175  template: Template,
176  parent: str = ''):
177  self.name = name
178  self.return_type = return_type
179  self.args = args_list
180  self.template = template
181 
182  self.parent = parent
183  self.return_type.parent = self
184  self.args.parent = self
185 
186  def __repr__(self) -> str:
187  return "GlobalFunction: {}{}({})".format(self.return_type, self.name,
188  self.args)
189 
190  def to_cpp(self) -> str:
191  """Generate the C++ code for wrapping."""
192  return self.name
bool isinstance(handle obj)
Definition: pytypes.h:384
str repr(handle h)
Definition: pytypes.h:1536
size_t len(handle h)
Definition: pytypes.h:1514


gtsam
Author(s):
autogenerated on Sat May 8 2021 02:42:05