Skip to content

Commit

Permalink
Merging 'master' into 'wrap'
Browse files Browse the repository at this point in the history
  • Loading branch information
varunagrawal committed Jun 16, 2021
2 parents ce1c73e + 56bede0 commit 87a04f9
Show file tree
Hide file tree
Showing 39 changed files with 820 additions and 376 deletions.
2 changes: 1 addition & 1 deletion wrap/.github/workflows/linux-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
python-version: [3.5, 3.6, 3.7, 3.8, 3.9]

steps:
- name: Checkout
Expand Down
2 changes: 1 addition & 1 deletion wrap/.github/workflows/macos-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
python-version: [3.5, 3.6, 3.7, 3.8, 3.9]

steps:
- name: Checkout
Expand Down
3 changes: 2 additions & 1 deletion wrap/DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the
```

- Using classes defined in other modules
- If you are using a class `OtherClass` not wrapped in an interface file, add `class OtherClass;` as a forward declaration to avoid a dependency error. `OtherClass` should be in the same project.
- If you are using a class `OtherClass` not wrapped in an interface file, add `class OtherClass;` as a forward declaration to avoid a dependency error.
- `OtherClass` may not be in the same project. If this is the case, include the header for the appropriate project `#include <other_project/OtherClass.h>`.

- Virtual inheritance
- Specify fully-qualified base classes, i.e. `virtual class Derived : ns::Base {` where `ns` is the namespace.
Expand Down
2 changes: 1 addition & 1 deletion wrap/gtwrap/interface_parser/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def __init__(self,

# Check to ensure arg and return type are the same.
if len(args) == 1 and self.operator not in ("()", "[]"):
assert args.args_list[0].ctype.typename.name == return_type.type1.typename.name, \
assert args.list()[0].ctype.typename.name == return_type.type1.typename.name, \
"Mixed type overloading not supported. Both arg and return type must be the same."

def __repr__(self) -> str:
Expand Down
13 changes: 9 additions & 4 deletions wrap/gtwrap/interface_parser/declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from .tokens import (CLASS, COLON, INCLUDE, LOPBRACK, ROPBRACK, SEMI_COLON,
VIRTUAL)
from .type import Typename
from .utils import collect_namespaces


class Include:
Expand Down Expand Up @@ -42,11 +43,12 @@ class ForwardDeclaration:
t.name, t.parent_type, t.is_virtual))

def __init__(self,
name: Typename,
typename: Typename,
parent_type: str,
is_virtual: str,
parent: str = ''):
self.name = name
self.name = typename.name
self.typename = typename
if parent_type:
self.parent_type = parent_type
else:
Expand All @@ -55,6 +57,9 @@ def __init__(self,
self.is_virtual = is_virtual
self.parent = parent

def namespaces(self) -> list:
"""Get the namespaces which this class is nested under as a list."""
return collect_namespaces(self)

def __repr__(self) -> str:
return "ForwardDeclaration: {} {}({})".format(self.is_virtual,
self.name, self.parent)
return "ForwardDeclaration: {} {}".format(self.is_virtual, self.name)
30 changes: 13 additions & 17 deletions wrap/gtwrap/interface_parser/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ class Argument:
void sayHello(/*`s` is the method argument with type `const string&`*/ const string& s);
```
"""
rule = ((Type.rule ^ TemplatedType.rule)("ctype") + IDENT("name") + \
Optional(EQUAL + (DEFAULT_ARG ^ Type.rule ^ TemplatedType.rule) + \
Optional(LPAREN + RPAREN) # Needed to parse the parens for default constructors
)("default")
).setParseAction(lambda t: Argument(t.ctype, t.name, t.default))
rule = ((Type.rule ^ TemplatedType.rule)("ctype") #
+ IDENT("name") #
+ Optional(EQUAL + DEFAULT_ARG)("default")
).setParseAction(lambda t: Argument(
t.ctype, #
t.name, #
t.default[0] if isinstance(t.default, ParseResults) else None))

def __init__(self,
ctype: Union[Type, TemplatedType],
Expand All @@ -44,18 +46,8 @@ def __init__(self,
else:
self.ctype = ctype
self.name = name
# If the length is 1, it's a regular type,
if len(default) == 1:
default = default[0]
# This means a tuple has been passed so we convert accordingly
elif len(default) > 1:
default = tuple(default.asList())
else:
# set to None explicitly so we can support empty strings
default = None
self.default = default

self.parent: Union[ArgumentList, None] = None
self.parent = None # type: Union[ArgumentList, None]

def __repr__(self) -> str:
return self.to_cpp()
Expand Down Expand Up @@ -94,10 +86,14 @@ def __repr__(self) -> str:
def __len__(self) -> int:
return len(self.args_list)

def args_names(self) -> List[str]:
def names(self) -> List[str]:
"""Return a list of the names of all the arguments."""
return [arg.name for arg in self.args_list]

def list(self) -> List[Argument]:
"""Return a list of the names of all the arguments."""
return self.args_list

def to_cpp(self, use_boost: bool) -> List[str]:
"""Generate the C++ code for wrapping."""
return [arg.ctype.to_cpp(use_boost) for arg in self.args_list]
Expand Down
2 changes: 1 addition & 1 deletion wrap/gtwrap/interface_parser/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def find_class_or_function(
res = []
for namespace in found_namespaces:
classes_and_funcs = (c for c in namespace.content
if isinstance(c, (Class, GlobalFunction)))
if isinstance(c, (Class, GlobalFunction, ForwardDeclaration)))
res += [c for c in classes_and_funcs if c.name == typename.name]
if not res:
raise ValueError("Cannot find class {} in module!".format(
Expand Down
28 changes: 16 additions & 12 deletions wrap/gtwrap/interface_parser/tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert
"""

from pyparsing import (Keyword, Literal, Or, QuotedString, Suppress, Word,
alphanums, alphas, delimitedList, nums,
pyparsing_common)
from pyparsing import (Keyword, Literal, OneOrMore, Or, QuotedString, Suppress,
Word, alphanums, alphas, nestedExpr, nums,
originalTextFor, printables)

# rule for identifiers (e.g. variable names)
IDENT = Word(alphas + '_', alphanums + '_') ^ Word(nums)
Expand All @@ -22,16 +22,20 @@
LPAREN, RPAREN, LBRACE, RBRACE, COLON, SEMI_COLON = map(Suppress, "(){}:;")
LOPBRACK, ROPBRACK, COMMA, EQUAL = map(Suppress, "<>,=")

# Encapsulating type for numbers, and single and double quoted strings.
# The pyparsing_common utilities ensure correct coversion to the corresponding type.
# E.g. pyparsing_common.number will convert 3.1415 to a float type.
NUMBER_OR_STRING = (pyparsing_common.number ^ QuotedString('"') ^ QuotedString("'"))

# A python tuple, e.g. (1, 9, "random", 3.1415)
TUPLE = (LPAREN + delimitedList(NUMBER_OR_STRING) + RPAREN)

# Default argument passed to functions/methods.
DEFAULT_ARG = (NUMBER_OR_STRING ^ pyparsing_common.identifier ^ TUPLE)
# Allow anything up to ',' or ';' except when they
# appear inside matched expressions such as
# (a, b) {c, b} "hello, world", templates, initializer lists, etc.
DEFAULT_ARG = originalTextFor(
OneOrMore(
QuotedString('"') ^ # parse double quoted strings
QuotedString("'") ^ # parse single quoted strings
Word(printables, excludeChars="(){}[]<>,;") ^ # parse arbitrary words
nestedExpr(opener='(', closer=')') ^ # parse expression in parentheses
nestedExpr(opener='[', closer=']') ^ # parse expression in brackets
nestedExpr(opener='{', closer='}') ^ # parse expression in braces
nestedExpr(opener='<', closer='>') # parse template expressions
))

CONST, VIRTUAL, CLASS, STATIC, PAIR, TEMPLATE, TYPEDEF, INCLUDE = map(
Keyword,
Expand Down
16 changes: 7 additions & 9 deletions wrap/gtwrap/interface_parser/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from pyparsing import Optional, ParseResults

from .tokens import DEFAULT_ARG, EQUAL, IDENT, SEMI_COLON, STATIC
from .tokens import DEFAULT_ARG, EQUAL, IDENT, SEMI_COLON
from .type import TemplatedType, Type


Expand All @@ -32,10 +32,12 @@ class Hello {
"""
rule = ((Type.rule ^ TemplatedType.rule)("ctype") #
+ IDENT("name") #
#TODO(Varun) Add support for non-basic types
+ Optional(EQUAL + (DEFAULT_ARG))("default") #
+ Optional(EQUAL + DEFAULT_ARG)("default") #
+ SEMI_COLON #
).setParseAction(lambda t: Variable(t.ctype, t.name, t.default))
).setParseAction(lambda t: Variable(
t.ctype, #
t.name, #
t.default[0] if isinstance(t.default, ParseResults) else None))

def __init__(self,
ctype: Type,
Expand All @@ -44,11 +46,7 @@ def __init__(self,
parent=''):
self.ctype = ctype[0] # ParseResult is a list
self.name = name
if default:
self.default = default[0]
else:
self.default = None

self.default = default
self.parent = parent

def __repr__(self) -> str:
Expand Down
Loading

0 comments on commit 87a04f9

Please sign in to comment.