mbdevpl / transpyle

HPC-oriented transpiler for C, C++, Cython, Fortran, OpenCL and Python.
Apache License 2.0
139 stars 23 forks source link

C AST generalizer doesn't allow void functions #13

Open sanjit-bhat opened 3 years ago

sanjit-bhat commented 3 years ago

TLDR: If you run the Transpyler AST Generalizer on a C program with void functions, it will throw an isinstance assertion error because pycparser returns None for the function declaration, while the AST Generalizer expects a typed_ast3.arguments type. Here's a link to the relevant Transpyler function.

Transpyle version: 0.8.0
Pycparser version: 2.19

Minimal code example:

import pathlib
import transpyle

path = pathlib.Path('my_script.c')
code_reader = transpyle.general.code_reader.CodeReader()
code = code_reader.read_file(path)

from_language = transpyle.Language.find('C11')
to_language = transpyle.Language.find('Python 3.6')
translator = transpyle.AutoTranslator(from_language, to_language)
c_code = translator.translate(code, path)
print(c_code)

with my_script.c set to

void foo() {
    int hello = 6;
}

My traceback is

Traceback (most recent call last):
  File "test.py", line 11, in <module>
    c_code = translator.translate(code, path)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/general/translator.py", line 26, in translate
    general_ast = self.ast_generalizer.generalize(specific_ast, **ast_generalizer_kwargs)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/c/ast_generalizer.py", line 435, in generalize
    general_ast = backend.visit(syntax)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/c/ast_generalizer.py", line 80, in visit
    return super().visit(node)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/pycparser/c_ast.py", line 158, in visit
    return visitor(node)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/c/ast_generalizer.py", line 83, in visit_FileAST
    ext = [self.visit(subnode) for subnode in node.ext]
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/c/ast_generalizer.py", line 83, in <listcomp>
    ext = [self.visit(subnode) for subnode in node.ext]
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/c/ast_generalizer.py", line 80, in visit
    return super().visit(node)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/pycparser/c_ast.py", line 158, in visit
    return visitor(node)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/c/ast_generalizer.py", line 91, in visit_FuncDef
    name, args, return_type = self.visit(node.decl)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/c/ast_generalizer.py", line 80, in visit
    return super().visit(node)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/pycparser/c_ast.py", line 158, in visit
    return visitor(node)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/c/ast_generalizer.py", line 266, in visit_Decl
    type_data = self.visit(node.type)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/c/ast_generalizer.py", line 80, in visit
    return super().visit(node)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/pycparser/c_ast.py", line 158, in visit
    return visitor(node)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/c/ast_generalizer.py", line 106, in visit_FuncDecl
    assert isinstance(args, typed_ast3.arguments)
AssertionError
sanjit-bhat commented 3 years ago

Note: it looks like simply commenting out that assertion doesn't work. While it passes the AST Generalization phase, the unparser then throws this error:

Traceback (most recent call last):
  File "test.py", line 11, in <module>
    c_code = translator.translate(code, path)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/general/translator.py", line 27, in translate
    to_code = self.unparser.unparse(general_ast, **unparser_kwargs)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/transpyle/python/unparser.py", line 45, in unparse
    code = horast.unparse(tree)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/horast/unparser.py", line 159, in unparse
    Unparser(tree, *args, file=stream, **kwargs)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/astunparse/unparser.py", line 38, in __init__
    self.dispatch(tree)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/static_typing/unparser.py", line 21, in dispatch
    super().dispatch(tree)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/astunparse/unparser.py", line 66, in dispatch
    meth(tree)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/astunparse/unparser.py", line 78, in _Module
    self.dispatch(stmt)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/static_typing/unparser.py", line 21, in dispatch
    super().dispatch(tree)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/astunparse/unparser.py", line 66, in dispatch
    meth(tree)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/astunparse/unparser.py", line 347, in _FunctionDef
    self.__FunctionDef_helper(t, "def")
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/astunparse/unparser.py", line 359, in __FunctionDef_helper
    self.dispatch(t.args)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/static_typing/unparser.py", line 21, in dispatch
    super().dispatch(tree)
  File "/Users/sanjit/.pyenv/versions/3.8.1/lib/python3.8/site-packages/astunparse/unparser.py", line 65, in dispatch
    meth = getattr(self, "_"+tree.__class__.__name__)
AttributeError: 'Unparser' object has no attribute '_NoneType'