Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions transpyle/cpp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
from .unparser import Cpp14Unparser
from .compiler import CppSwigCompiler

# Annotation to mark a class as a struct. (Python -> Cpp)
def struct(f):
return f

class CppBinder(Binder):

Expand Down
135 changes: 107 additions & 28 deletions transpyle/cpp/unparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def for_header_to_tuple(target, target_type, iter_) -> t.Tuple[
init = typed_ast3.Assign(targets=[target], value=begin, type_comment=None)
else:
init = typed_ast3.AnnAssign(target=target, annotation=target_type, value=begin, simple=True)
condition = typed_ast3.Compare(left=target, ops=[typed_ast3.Lt()], comparators=[end])
condition = typed_ast3.Expr(typed_ast3.Compare(left=target, ops=[typed_ast3.Lt()], comparators=[end]))
increment = typed_ast3.AugAssign(target=target, op=typed_ast3.Add(), value=step)
return init, condition, increment

Expand All @@ -85,6 +85,7 @@ def leave(self):
super().leave()
self.fill('}')

# Misusing ast.Index to signify reference types. Should probably fork typed-ast or something. The ast generalizer does something string based.
def dispatch_type(self, type_hint):
_LOG.debug('dispatching type hint %s', type_hint)
if isinstance(type_hint, typed_ast3.Subscript):
Expand All @@ -97,6 +98,18 @@ def dispatch_type(self, type_hint):
sli = type_hint.slice
self.write('>')
return
elif isinstance(type_hint.value, typed_ast3.Name):
unparsed = horast.unparse(type_hint.value).strip()
self.write(unparsed)
self.write('<')
if isinstance(type_hint.slice, typed_ast3.Subscript):
self.dispatch_type(type_hint.slice)
else:
self.write(horast.unparse(type_hint.slice).strip())
self.write(' >')
if isinstance(type_hint.slice, typed_ast3.Index):
self.write('&')
return
self._unsupported_syntax(type_hint)
if isinstance(type_hint, typed_ast3.Attribute):
if isinstance(type_hint.value, typed_ast3.Name):
Expand All @@ -108,12 +121,19 @@ def dispatch_type(self, type_hint):
assert type_hint.value is None
self.write('void')
return

self.dispatch(type_hint)
if isinstance(type_hint, typed_ast3.Index):
if isinstance(type_hint.value, typed_ast3.Name):
self.write('&')

def _Expr(self, tree):
super()._Expr(tree)
self.write(';')

def _Pass(self, tree):
self.fill('/* pass */')

def _Import(self, t):
self.fill('/* Python import')
# raise NotImplementedError('not supported yet')
Expand All @@ -122,7 +142,11 @@ def _Import(self, t):
# #include "boost/multi_array.hpp"

def _ImportFrom(self, t):
raise NotImplementedError('not supported yet')
self.fill('/* Python import')
# raise NotImplementedError('not supported yet')
super()._ImportFrom(t)
self.fill('*/')
# #include "boost/multi_array.hpp"

def _Assign(self, t):
super()._Assign(t)
Expand All @@ -138,14 +162,33 @@ def _AnnAssign(self, t):
self._unsupported_syntax(t, ' which is not simple')
self.dispatch_type(t.annotation)
self.write(' ')
self.dispatch(t.target)
try:
self.dispatch(t.target)
except AttributeError as e:
print(e)
if t.value:
self.write(' = ')
self.dispatch(t.value)
self.write(';')
self.write(';')

def _ClassDef(self, t):
raise NotImplementedError('not supported yet')
if len(t.decorator_list) > 1:
self._unsupported_syntax(t, ' with decorators')
self.write('\n')
self.fill()
is_struct = False
if len(t.decorator_list) == 1:
is_struct = t.decorator_list[0].id=='struct'
if is_struct:
self.write('struct')
else:
self.write('class')

self.write(' {}'.format(t.name))
self.enter()
self.dispatch(t.body)
self.leave()


def _FunctionDef(self, t):
if t.decorator_list:
Expand All @@ -168,12 +211,16 @@ def _AsyncFunctionDef(self, t):

def _For(self, t):
self.fill('for (')
init, cond, increment = for_header_to_tuple(t.target, t.resolved_type_comment, t.iter)
self.dispatch(init)
self.write(', ')
self.dispatch(cond)
self.write(', ')
self.dispatch(increment)
init, cond, increment = for_header_to_tuple(t.target, t.type_comment, t.iter)
#self.dispatch(init)
#self.dispatch(cond)
#self.dispatch(increment)
unparser = Cpp14Unparser()
self.write(unparser.unparse(init).strip('\n\r;)('))
self.write('; ')
self.write(unparser.unparse(cond).strip('\n\r;)('))
self.write('; ')
self.write(unparser.unparse(increment).strip('\n\r;)('))
# self.dispatch(t.iter)
self.write(')')
self.enter()
Expand Down Expand Up @@ -208,7 +255,7 @@ def _If(self, t):
self.dispatch(t.orelse)
self.leave()

raise NotImplementedError('not supported yet')
#raise NotImplementedError('not supported yet')

def _While(self, t):
raise NotImplementedError('not supported yet')
Expand All @@ -221,17 +268,20 @@ def _AsyncWith(self, t):

def _Attribute(self, t):
if isinstance(t.value, typed_ast3.Name):
unparsed = {
('a', 'shape'): '???',
('b', 'shape'): '???',
('c', 'shape'): '???',
('np', 'single'): 'int32_t',
('np', 'double'): 'int64_t',
('np', 'zeros'): 'boost::multi_array',
('st', 'ndarray'): 'boost::multi_array'
}[t.value.id, t.attr]
self.write(unparsed)
return
try:
unparsed = {
('a', 'shape'): '???',
('b', 'shape'): '???',
('c', 'shape'): '???',
('np', 'single'): 'int32_t',
('np', 'double'): 'int64_t',
('np', 'zeros'): 'boost::multi_array',
('st', 'ndarray'): 'boost::multi_array'
}[t.value.id, t.attr]
self.write(unparsed)
return
except Exception:
pass
self.dispatch(t.value)
self.write('.')
self.write(t.attr)
Expand All @@ -257,21 +307,50 @@ def _Subscript(self, t):
def _arg(self, t):
if t.annotation is None:
self._unsupported_syntax(t, ' without annotation')
self.dispatch(t.annotation)
self.dispatch_type(t.annotation)
self.write(' ')
self.write(t.arg)

def _Comment(self, node):
if node.eol:
self.write(' //')
if node.value.s.startswith("pragma"):
if node.eol:
self.write('\n#')
else:
self.fill('#')
else:
self.fill('//')
if node.eol:
self.write(' //')
else:
self.fill('//')
self.write(node.value.s)

def _NameConstant(self, node):
if node.value == 'False':
self.write("false")
elif node.value == 'True':
self.write("true")
elif node.value == 'None':
self.write("null")
else:
self.write(node.value)

def _Str(self, node):
self.write('"')
self.write(node.s.replace('"', '\\"').replace("\0", "\\0").replace("\n", "\\n").replace("\t", "\\t").replace("\r", "\\r"))
self.write('"')

def _Bytes(self, node):
# Char
if len(node.s) == 1:
self.write("'")
self.write(node.s.replace("'", "\\'").replace("\0", "\\0").replace("\n", "\\n").replace("\t", "\\t").replace("\r", "\\r"))
self.write("'")
else:
self._Str(node)

def _unsupported_syntax(self, tree, comment: str = ''):
raise SyntaxError('unparsing {}{} to C++ is not supported'.format(type(tree), comment))


class Cpp14HeaderUnparserBackend(Cpp14UnparserBackend):

def _FunctionDef(self, t):
Expand Down