Giter VIP home page Giter VIP logo

py2many's Introduction

py2many: Python to many CLike languages transpiler

Build License

Why

Python is popular, easy to program in, but has poor runtime performance. We can fix that by transpiling a subset of the language into a more performant, statically typed language.

A second benefit is security. Writing security sensitive code in a low level language like C is error prone and could lead to privilege escalation. Specialized languages such as wuffs exist to address this use case. py2many can be a more general purpose solution to the problem where you can verify the source via unit tests before you transpile.

A third potential use case is to accelerate python code by transpiling it into an extension

Swift and Kotlin dominate the mobile app development workflow. However, there is no one solution that works well for lower level libraries where there is desire to share code between platforms. Kotlin Mobile Multiplatform (KMM) is a player in this place, but it hasn't really caught on. py2many provides an alternative.

Lastly, it's a great educational tool to learn a new language by implementing a backend for your favorite language.

Status

Rust is the language where the focus of development has been.

C++14 is historically the first language to be supported. C++17 is now required for some features.

Preliminary support exists for Julia, Kotlin, Nim, Go, Dart and V.

py2many can also emit Python 3 code that includes inferred type annotations, and revisions to the syntax intended to simplify parsing of the code.

History

Based on Julian Konchunas' pyrs.

Based on Lukas Martinelli Py14 and Py14/python-3 branch by Valentin Lorentz.

Example

Original Python version.

def fib(i: int) -> int:
    if i == 0 or i == 1:
        return 1
    return fib(i - 1) + fib(i - 2)

Transpiled Rust code:

fn fib(i: i32) -> i32 {
    if i == 0 || i == 1 {
        return 1;
    }
    return (fib((i - 1)) + fib((i - 2)));
}

Transpiled code for other languages:

https://github.com/adsharma/py2many/tree/main/tests/expected (fib*)

Trying it out

Requirements:

  • Python 3.8+

Local installation:

./setup.py install --user  # installs to $HOME/.local

OR

sudo ./setup.py install  # installs systemwide

Add the py2many script to your $PATH and run:

Transpiling:

py2many --cpp=1 tests/cases/fib.py
py2many --rust=1 tests/cases/fib.py
py2many --julia=1 tests/cases/fib.py
py2many --kotlin=1 tests/cases/fib.py
py2many --nim=1 tests/cases/fib.py
py2many --dart=1 tests/cases/fib.py
py2many --go=1 tests/cases/fib.py

Compiling:

clang tests/expected/fib.cpp
rustup run nightly cargo build -Zscript --manifest-path tests/expected/fib.rs
...

Many of the transpilers rely on a language specific formatter to parse the output and reformat it. Typically this is the most prominent formatter for the language, such as rustfmt for Rust.

Most of the transpilers also rely on external libraries to provide bridges from Python constructs to the target language.

The steps to install these external libraries can be found in .github/workflows/main.yml.

Contributing

See CONTRIBUTING.md for how to test your changes and contribute to this project.

py2many's People

Contributors

adsharma avatar cclauss avatar dependabot[bot] avatar div72 avatar ghuls avatar jayvdb avatar john-michaelburke avatar joshmcguigan avatar konchunas avatar lukasmartinelli avatar miguelmarcelino avatar molysgaard avatar nsauzede avatar progval avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

py2many's Issues

Unnecessary import in int_enum.rs

warning: unused import: `flagset::FlagSet`
 --> src/int_enum.rs:2:5
  |
2 | use flagset::FlagSet;
  |     ^^^^^^^^^^^^^^^^

Which also means that the flagset part of the transpiler isnt being tested.

f-string support

f-strings (ast.JoinedStr) are not supported yet. They should be fairly simple to implement the basics for most languages as string interpolation is available and mostly consistent in the target languages.

Simplest test cases is

    var = "Hello world!"
    var2 = f"{var}"
    print(var2)

Because it isnt implement, that transpiles to rust

    let var: &str = "Hello world!";
    let var2: _ = None;
    println!("{}", var2);

Using print(f"{var}") fails due to logic within the visit_print of each transpiler.

I would be happy if either of those two ways of using f-strings worked. It might be simpler to get them working only in the confines of visit_print, where the lifetime of the new string is limited.

str.format

"{} {}".format("foo", "bar") is transpiled literally and fails on all langs except Julia, either because there is no .format method on the str in the target language, or exceptions in the transpiler (cpp) or syntax errors emitted (kotlin).

Due to the importance of str.format, not least the need to use it in creating test cases, it should be transpiled to the appropriate equivalent.

Generated rust for infer-ops is invalid

error[E0308]: mismatched types
 --> src/infer_ops.rs:7:19
  |
7 |     let c4: f32 = (a / b);
  |             ---   ^^^^^^^ expected `f32`, found `i32`
  |             |
  |             expected due to this
  |
help: you can convert an `i32` to an `f32`, producing the floating point representation of the integer, rounded if necessary
  |
7 |     let c4: f32 = ((a / b)) as f32;
  |                   ^^^^^^^^^^^^^^^^

error[E0277]: cannot add `f32` to `i32`
  --> src/infer_ops.rs:10:22
   |
10 |     let e1: f32 = (a + d);
   |                      ^ no implementation for `i32 + f32`
   |
   = help: the trait `Add<f32>` is not implemented for `i32`

error[E0277]: cannot subtract `f32` from `i32`
  --> src/infer_ops.rs:11:22
   |
11 |     let e2: f32 = (a - d);
   |                      ^ no implementation for `i32 - f32`
   |
   = help: the trait `Sub<f32>` is not implemented for `i32`

error[E0277]: cannot multiply `i32` by `f32`
  --> src/infer_ops.rs:12:22
   |
12 |     let e3: f32 = (a * d);
   |                      ^ no implementation for `i32 * f32`
   |
   = help: the trait `Mul<f32>` is not implemented for `i32`

error[E0277]: cannot divide `i32` by `f32`
  --> src/infer_ops.rs:13:22
   |
13 |     let e4: f32 = (a / d);
   |                      ^ no implementation for `i32 / f32`
   |
   = help: the trait `Div<f32>` is not implemented for `i32`

error[E0308]: mismatched types
  --> src/infer_ops.rs:19:12
   |
18 | fn add1(x: i8, y: i8) -> i16 {
   |                          --- expected `i16` because of return type
19 |     return (x + y);
   |            ^^^^^^^
   |            |
   |            expected `i16`, found `i8`
   |            help: you can convert an `i8` to an `i16`: `((x + y)).into()`

error[E0308]: mismatched types
  --> src/infer_ops.rs:23:12
   |
22 | fn add2(x: i16, y: i16) -> i32 {
   |                            --- expected `i32` because of return type
23 |     return (x + y);
   |            ^^^^^^^
   |            |
   |            expected `i32`, found `i16`
   |            help: you can convert an `i16` to an `i32`: `((x + y)).into()`

error[E0308]: mismatched types
  --> src/infer_ops.rs:27:12
   |
26 | fn add3(x: i32, y: i32) -> i64 {
   |                            --- expected `i64` because of return type
27 |     return (x + y);
   |            ^^^^^^^
   |            |
   |            expected `i64`, found `i32`
   |            help: you can convert an `i32` to an `i64`: `((x + y)).into()`

error[E0308]: mismatched types
  --> src/infer_ops.rs:35:12
   |
34 | fn add5(x: u8, y: u8) -> u16 {
   |                          --- expected `u16` because of return type
35 |     return (x + y);
   |            ^^^^^^^
   |            |
   |            expected `u16`, found `u8`
   |            help: you can convert a `u8` to a `u16`: `((x + y)).into()`

error[E0308]: mismatched types
  --> src/infer_ops.rs:39:12
   |
38 | fn add6(x: u16, y: u16) -> u32 {
   |                            --- expected `u32` because of return type
39 |     return (x + y);
   |            ^^^^^^^
   |            |
   |            expected `u32`, found `u16`
   |            help: you can convert a `u16` to a `u32`: `((x + y)).into()`

error[E0308]: mismatched types
  --> src/infer_ops.rs:43:12
   |
42 | fn add7(x: u32, y: u32) -> u64 {
   |                            --- expected `u64` because of return type
43 |     return (x + y);
   |            ^^^^^^^
   |            |
   |            expected `u64`, found `u32`
   |            help: you can convert a `u32` to a `u64`: `((x + y)).into()`

error[E0308]: mismatched types
  --> src/infer_ops.rs:51:17
   |
51 |     return (x + y);
   |                 ^ expected `i8`, found `u16`

error[E0308]: mismatched types
  --> src/infer_ops.rs:51:12
   |
50 | fn add9(x: i8, y: u16) -> u32 {
   |                           --- expected `u32` because of return type
51 |     return (x + y);
   |            ^^^^^^^ expected `u32`, found `i8`
   |
help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit
   |
51 |     return ((x + y)).try_into().unwrap();
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: cannot add `u16` to `i8`
  --> src/infer_ops.rs:51:15
   |
51 |     return (x + y);
   |               ^ no implementation for `i8 + u16`
   |
   = help: the trait `Add<u16>` is not implemented for `i8`

error[E0308]: mismatched types
  --> src/infer_ops.rs:59:12
   |
58 | fn mul(x: i8, y: i8) -> i16 {
   |                         --- expected `i16` because of return type
59 |     return (x * y);
   |            ^^^^^^^
   |            |
   |            expected `i16`, found `i8`
   |            help: you can convert an `i8` to an `i16`: `((x * y)).into()`

error[E0277]: cannot add `f32` to `i8`
  --> src/infer_ops.rs:63:15
   |
63 |     return (x + y);
   |               ^ no implementation for `i8 + f32`
   |
   = help: the trait `Add<f32>` is not implemented for `i8`

Transpile to native extension

When I transpile Python code to say C or Rust, I would like to be able to use the transpiled code from Python. It would be very nice if there was an option (at least for some language that are amenable to this) such that the transpiled code would be a valid Python native extension callable from Python.

Dart int_enum does not compile

cases/int_enum.dart:6:7: Error: 'RED' is already declared in this scope.
  var RED = auto();
      ^^^
cases/int_enum.dart:2:7: Context: Previous declaration of 'RED'.
  ST0 RED;
      ^^^
cases/int_enum.dart:7:7: Error: 'GREEN' is already declared in this scope.
  var GREEN = auto();
      ^^^^^
cases/int_enum.dart:3:7: Context: Previous declaration of 'GREEN'.
  ST1 GREEN;
      ^^^^^
cases/int_enum.dart:8:7: Error: 'BLUE' is already declared in this scope.
  var BLUE = auto();
      ^^^^
cases/int_enum.dart:4:7: Context: Previous declaration of 'BLUE'.
  ST2 BLUE;
      ^^^^
cases/int_enum.dart:16:7: Error: 'R' is already declared in this scope.
  int R = 1;
      ^
cases/int_enum.dart:12:7: Context: Previous declaration of 'R'.
  ST0 R;
      ^
cases/int_enum.dart:17:7: Error: 'W' is already declared in this scope.
  int W = 2;
      ^
cases/int_enum.dart:13:7: Context: Previous declaration of 'W'.
  ST1 W;
      ^

AnnAssign fails on nim

a : float = 2.1

is converted to

a::float = 2.1

error:

Error: undeclared identifier: 'a'

lambda.cpp doesnt compile

cases/lambda.cpp:7:43: error: expected ';' after expression
  auto myfunc = [](auto x, auto y) { x + y };
                                          ^
                                          ;

Instantiation fails on go, rust and nim

For r = Rectangle(height=1, length=1)

go becomes r := Rectangle(1, 1)
error:

too many arguments to conversion to Rectangle: Rectangle(1, 1)`

nim becomes var r = Rectangle(1, 1)
error:

Error: attempting to call routine: 'Rectangle'
found 'rect.Rectangle [declared in /path/to/tests/cases/rect.nim(3, 3)]' of kind 'type'`

rust:

12 |       let mut r: _ = Rectangle(1, 1);
   |                      ^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `Rectangle { height: val, length: val }`

Kotlin print on object attributes is broken

For python

r = Rectangle(height=1, length=2)
print(r.height)

comes out as

r = Rectangle(1, 2)
assert(!r.is_square())
println("$r.height")

which emits

Rectangle(height=1, length=2).height

Generated rust fails when iterating over enums

	for color in Colors:
		print(color)

becomes

for color in Colors {
println!("{:?} ",color);
}

with error

error[E0423]: expected value, found enum `Colors`
  --> int_enum.rs:23:14
   |
23 | for color in Colors {
   |              ^^^^^^
   |
note: the enum is defined here
  --> int_enum.rs:6:1
   |
6  | / enum Colors {
7  | | RED,
8  | | GREEN,
9  | | BLUE,
10 | | }
   | |_^
help: you might have meant to use one of the following enum variants
   |
23 | for color in Colors::RED {
   |              ^^^^^^^^^^^
23 | for color in Colors::GREEN {
   |              ^^^^^^^^^^^^^
23 | for color in Colors::BLUE {
   |              ^^^^^^^^^^^^

Add dart infrastructure to CI

c.f. #44 , the print.dart depends on sprintf being pre-installed, and dart needs to be added to GitHub actions, which then also acts as a reference for people wanting to test locally.

Ideally we find something like rust-script which allows embedding dependencies into the script file.
In lieu of that, a comment at the top with how to set up the dependencies will suffice.

Go annotated assign (AnnAssign) has semantic error in generator and syntax error in output

code is

    def visit_AnnAssign(self, node):
        target = self.visit(node.target)
        type_str = self.visit(node.annotation)
        val = self.visit(node.value)
        return f"var {target} {type_str} := {2}"

Which injects a literal 2 irrespective of the source val.

Changing it to return f"var {target} {type_str} := {val}" doesnt fix it. That causes var a string := "foo" which is invalid go syntax.

There is no test coverage for ann assignments yet.

rect.cpp fails to compile

rect.cpp
------------------------------------------------------------------------------------------------------------------- Captured stderr call -------------------------------------------------------------------------------------------------------------------
cases/rect.cpp:3:16: error: use of undeclared identifier 'None'
  int height = None;
               ^
cases/rect.cpp:4:16: error: use of undeclared identifier 'None'
  int length = None;
               ^
cases/rect.cpp:8:2: error: expected ';' after class
}
 ^
 ;
3 errors generated.

Tests fail on Python 3.9: NotImplementedError: Advanced Slicing not supported

_____________________________________________________________________________________________________________________ test_bubble_sort _____________________________________________________________________________________________________________________

    def test_bubble_sort():
        source = parse(
            "def sort(seq):",
            "    L = len(seq)",
            "    for _ in range(L):",
            "        for n in range(1, L):",
            "            if seq[n] < seq[n - 1]:",
            "                seq[n - 1], seq[n] = seq[n], seq[n - 1]",
            "    return seq",
        )
>       cpp = transpile(source)

py14/tests/test_transpiler.py:166:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
py14/transpiler.py:37: in transpile
    cpp = transpiler.visit(tree)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Cellar/python@3.9/3.9.2_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ast.py:407: in visit
    return visitor(node)
py14/transpiler.py:273: in visit_Module
    buf = [self.visit(b) for b in node.body]
py14/transpiler.py:273: in <listcomp>
    buf = [self.visit(b) for b in node.body]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Cellar/python@3.9/3.9.2_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ast.py:407: in visit
    return visitor(node)
py14/transpiler.py:87: in visit_FunctionDef
    body = "\n".join([self.visit(n) for n in node.body])
py14/transpiler.py:87: in <listcomp>
    body = "\n".join([self.visit(n) for n in node.body])
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Cellar/python@3.9/3.9.2_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ast.py:407: in visit
    return visitor(node)
py14/transpiler.py:168: in visit_For
    buf.extend([self.visit(c) for c in node.body])
py14/transpiler.py:168: in <listcomp>
    buf.extend([self.visit(c) for c in node.body])
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Cellar/python@3.9/3.9.2_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ast.py:407: in visit
    return visitor(node)
py14/transpiler.py:168: in visit_For
    buf.extend([self.visit(c) for c in node.body])
py14/transpiler.py:168: in <listcomp>
    buf.extend([self.visit(c) for c in node.body])
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Cellar/python@3.9/3.9.2_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ast.py:407: in visit
    return visitor(node)
py14/transpiler.py:239: in visit_If
    if self.visit(node.test) == '__name__ == std::string {"__main__"}':
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Cellar/python@3.9/3.9.2_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ast.py:407: in visit
    return visitor(node)
py2many/clike.py:133: in visit_Compare
    left = self.visit(node.left)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Cellar/python@3.9/3.9.2_2/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ast.py:407: in visit
    return visitor(node)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <py14.transpiler.CppTranspiler object at 0x10c05c970>, node = <ast.Subscript object at 0x10c05c040>

    def visit_Subscript(self, node):
        if isinstance(node.slice, ast.Ellipsis):
            raise NotImplementedError("Ellipsis not supported")

        if not isinstance(node.slice, ast.Index):
>           raise NotImplementedError("Advanced Slicing not supported")
E           NotImplementedError: Advanced Slicing not supported

py14/transpiler.py:305: NotImplementedError

py2many incompatible with Python 3.7

Here are the non-cli test failures on Python3.7. I think >3.8 is fine for a tool like this. The ast module has improved a lot and trying to be backwards compatible doesnt seem sensible, as the output will degrade due to less semantic info.

========================================================================================================================= FAILURES =========================================================================================================================
___________________________________________________________________________________________________________ TestValueType.test_direct_assignment ___________________________________________________________________________________________________________

self = <py14.tests.test_tracer.TestValueType object at 0x110940fd0>

    def test_direct_assignment(self):
        source = parse("x = 3")
        x = source.body[0]
        t = value_type(x)
>       assert t == "3"
E       AssertionError: assert None == '3'
E         +None
E         -'3'

py14/tests/test_tracer.py:20: AssertionError
_________________________________________________________________________________________________ TestValueType.test_list_assignment_based_on_later_append _________________________________________________________________________________________________

self = <py14.tests.test_tracer.TestValueType object at 0x11096b510>

    def test_list_assignment_based_on_later_append(self):
        source = parse("x = 3", "results = []", "results.append(x)")
        add_list_calls(source)
        results = source.body[1]
        t = value_type(results)
>       assert t == "3"
E       AssertionError: assert None == '3'
E         +None
E         -'3'

py14/tests/test_tracer.py:51: AssertionError
_______________________________________________________________________________________________ TestValueType.test_list_assignment_with_append_unknown_value _______________________________________________________________________________________________

self = <py14.tests.test_tracer.TestValueType object at 0x11096bad0>

    def test_list_assignment_with_append_unknown_value(self):
        source = parse("results = []", "x = 3", "results.append(x)")
        add_list_calls(source)
        results = source.body[0]
        t = value_type(results)
>       assert t == "3"
E       AssertionError: assert None == '3'
E         +None
E         -'3'

py14/tests/test_tracer.py:58: AssertionError
_______________________________________________________________________________________________ TestValueType.test_global_list_assignment_with_later_append ________________________________________________________________________________________________

self = <py14.tests.test_tracer.TestValueType object at 0x110999210>

    def test_global_list_assignment_with_later_append(self):
        source = parse("results = []", "def add_x():", "   results.append(2)")
        add_list_calls(source)
        results = source.body[0]
        t = value_type(results)
>       assert t == "2"
E       AssertionError: assert None == '2'
E         +None
E         -'2'

py14/tests/test_tracer.py:65: AssertionError
______________________________________________________________________________________________________ TestValueExpr.test_catch_long_expression_chain ______________________________________________________________________________________________________

self = <py14.tests.test_tracer.TestValueExpr object at 0x1109bb5d0>

    def test_catch_long_expression_chain(self):
        source = parse("x = 3 * 1", "y = x - 5", "z = y + 2")
        z = source.body[2]
        t = value_expr(z)
>       assert t == "3 * 1 - 5 + 2"
E       AssertionError: assert 'None * None - None + None' == '3 * 1 - 5 + 2'
E         - 3 * 1 - 5 + 2
E         + None * None - None + None

py14/tests/test_tracer.py:73: AssertionError
_________________________________________________________________________________________________ TestValueExpr.test_catch_expression_chain_with_functions _________________________________________________________________________________________________

self = <py14.tests.test_tracer.TestValueExpr object at 0x11099db10>

    def test_catch_expression_chain_with_functions(self):
        source = parse("x = 3 * 1", "y = foo(x)", "z = y + 2")
        z = source.body[2]
        t = value_expr(z)
>       assert t == "foo(3 * 1) + 2"
E       AssertionError: assert 'foo(None * None) + None' == 'foo(3 * 1) + 2'
E         - foo(3 * 1) + 2
E         + foo(None * None) + None

py14/tests/test_tracer.py:79: AssertionError
__________________________________________________________________________________________________________________ test_decltype_list_var __________________________________________________________________________________________________________________

    def test_decltype_list_var():
        source = parse("results = []", "x = 3", "results.append(x)")
        add_list_calls(source)
        results = source.body[0]
        t = decltype(results)
>       assert t == "std::vector<decltype(3)>"
E       AssertionError: assert 'std::vector<decltype(None)>' == 'std::vector<decltype(3)>'
E         - std::vector<decltype(3)>
E         ?                      ^
E         + std::vector<decltype(None)>
E         ?                      ^^^^

py14/tests/test_tracer.py:94: AssertionError
_______________________________________________________________________________________________________________________ test_declare _______________________________________________________________________________________________________________________

    def test_declare():
        source = parse("x = 3")
        cpp = transpile(source)
>       assert cpp == "auto x = 3;"
E       AssertionError: assert 'auto x = None;' == 'auto x = 3;'
E         - auto x = 3;
E         ?          ^
E         + auto x = None;
E         ?          ^^^^

py14/tests/test_transpiler.py:13: AssertionError
_________________________________________________________________________________________________________________ test_print_multiple_vars _________________________________________________________________________________________________________________

    def test_print_multiple_vars():
        if sys.version_info[0] >= 3:
            source = parse('print(("hi", "there" ))')
        else:
            source = parse('print("hi", "there" )')
>       cpp = transpile(source)

py14/tests/test_transpiler.py:27:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
py14/transpiler.py:39: in transpile
    cpp = transpiler.visit(tree)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:275: in visit_Module
    buf = [self.visit(b) for b in node.body]
py14/transpiler.py:275: in <listcomp>
    buf = [self.visit(b) for b in node.body]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:175: in visit_Expr
    s = self.visit(node.value)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:129: in visit_Call
    args = [self.visit(a) for a in node.args]
py14/transpiler.py:129: in <listcomp>
    args = [self.visit(a) for a in node.args]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:317: in visit_Tuple
    elts = [self.visit(e) for e in node.elts]
py14/transpiler.py:317: in <listcomp>
    elts = [self.visit(e) for e in node.elts]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:212: in visit_Str
    return "std::string {" + super(CppTranspiler, self).visit_Str(node) + "}"
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <py14.transpiler.CppTranspiler object at 0x1105fc4d0>, node = <_ast.Str object at 0x1109cbcd0>

    def visit_Str(self, node):
>       return f'"{node.value}"'
E       AttributeError: 'Str' object has no attribute 'value'

py2many/clike.py:88: AttributeError
_______________________________________________________________________________________________________________________ test_assert ________________________________________________________________________________________________________________________

    def test_assert():
        source = parse("assert 1 == foo(3)")
>       cpp = transpile(source)

py14/tests/test_transpiler.py:35:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
py14/transpiler.py:39: in transpile
    cpp = transpiler.visit(tree)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:275: in visit_Module
    buf = [self.visit(b) for b in node.body]
py14/transpiler.py:275: in <listcomp>
    buf = [self.visit(b) for b in node.body]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:346: in visit_Assert
    return "REQUIRE({0});".format(self.visit(node.test))
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py2many/clike.py:135: in visit_Compare
    right = self.visit(node.comparators[0])
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <py14.transpiler.CppTranspiler object at 0x110a749d0>, node = <_ast.Call object at 0x110a748d0>

    def visit_Call(self, node):
        fname = self.visit(node.func)
        if node.args:
            args = [self.visit(a) for a in node.args]
>           args = ", ".join(args)
E           TypeError: sequence item 0: expected str instance, NoneType found

py14/transpiler.py:130: TypeError
___________________________________________________________________________________________________________ test_augmented_assigns_with_counter ____________________________________________________________________________________________________________

    def test_augmented_assigns_with_counter():
        source = parse(
            "counter = 0", "counter += 5", "counter -= 2", "counter *= 2", "counter /= 3"
        )
        cpp = transpile(source)
>       assert cpp == parse(
            "auto counter = 0;",
            "counter += 5;",
            "counter -= 2;",
            "counter *= 2;",
            "counter /= 3;",
        )
E       AssertionError: assert 'auto counter...nter /= None;' == 'auto counter...counter /= 3;'
E         - auto counter = 0;
E         ?                ^
E         + auto counter = None;
E         ?                ^^^^
E         - counter += 5;
E         ?            ^
E         + counter += None;...
E
E         ...Full output truncated (14 lines hidden), use '-vv' to show

py14/tests/test_transpiler.py:44: AssertionError
_____________________________________________________________________________________________________ test_declare_vars_inside_if_as_long_as_possible ______________________________________________________________________________________________________

    def test_declare_vars_inside_if_as_long_as_possible():
        source = parse("x = 5", "if True:", "   y = 10", "   x *= y")
        cpp = transpile(source)
>       assert cpp == parse("auto x = 5;", "if(true) {", "auto y = 10;", "x *= y;", "}")
E       AssertionError: assert 'auto x = Non...;\nx *= y;\n}' == 'auto x = 5;\...;\nx *= y;\n}'
E         - auto x = 5;
E         ?          ^
E         + auto x = None;
E         ?          ^^^^
E           if(true) {
E         - auto y = 10;
E         ?          ^^...
E
E         ...Full output truncated (5 lines hidden), use '-vv' to show

py14/tests/test_transpiler.py:70: AssertionError
_________________________________________________________________________________________________________________ test_print_program_args __________________________________________________________________________________________________________________

    def test_print_program_args():
        source = parse(
            'if __name__ == "__main__":', "    for arg in sys.argv:", "       print(arg)"
        )
>       cpp = transpile(source)

py14/tests/test_transpiler.py:77:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
py14/transpiler.py:39: in transpile
    cpp = transpiler.visit(tree)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:275: in visit_Module
    buf = [self.visit(b) for b in node.body]
py14/transpiler.py:275: in <listcomp>
    buf = [self.visit(b) for b in node.body]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:241: in visit_If
    if self.visit(node.test) == '__name__ == std::string {"__main__"}':
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py2many/clike.py:135: in visit_Compare
    right = self.visit(node.comparators[0])
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:212: in visit_Str
    return "std::string {" + super(CppTranspiler, self).visit_Str(node) + "}"
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <py14.transpiler.CppTranspiler object at 0x11057e810>, node = <_ast.Str object at 0x110a3e850>

    def visit_Str(self, node):
>       return f'"{node.value}"'
E       AttributeError: 'Str' object has no attribute 'value'

py2many/clike.py:88: AttributeError
_____________________________________________________________________________________________________________________ test_tuple_swap ______________________________________________________________________________________________________________________

    def test_tuple_swap():
        source = parse("x = 3", "y = 1", "x, y = y, x")
        cpp = transpile(source)
>       assert cpp == parse(
            "auto x = 3;", "auto y = 1;", "std::tie(x, y) = std::make_tuple(y, x);"
        )
E       AssertionError: assert 'auto x = Non..._tuple(y, x);' == 'auto x = 3;\..._tuple(y, x);'
E         - auto x = 3;
E         ?          ^
E         + auto x = None;
E         ?          ^^^^
E         - auto y = 1;
E         ?          ^
E         + auto y = None;...
E
E         ...Full output truncated (3 lines hidden), use '-vv' to show

py14/tests/test_transpiler.py:91: AssertionError
_______________________________________________________________________________________________________________________ test_assign ________________________________________________________________________________________________________________________

    def test_assign():
        source = parse("x = 3", "x = 1")
        cpp = transpile(source)
>       assert cpp == parse("auto x = 3;", "x = 1;")
E       AssertionError: assert 'auto x = None;\nx = None;' == 'auto x = 3;\nx = 1;'
E         - auto x = 3;
E         ?          ^
E         + auto x = None;
E         ?          ^^^^
E         - x = 1;
E         + x = None;

py14/tests/test_transpiler.py:99: AssertionError
___________________________________________________________________________________________________________________ test_list_as_vector ____________________________________________________________________________________________________________________

    def test_list_as_vector():
        source = parse("values = [0, 1, 2, 3]")
>       cpp = transpile(source)

py14/tests/test_transpiler.py:124:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
py14/transpiler.py:39: in transpile
    cpp = transpiler.visit(tree)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:275: in visit_Module
    buf = [self.visit(b) for b in node.body]
py14/transpiler.py:275: in <listcomp>
    buf = [self.visit(b) for b in node.body]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <py14.transpiler.CppTranspiler object at 0x11057e350>, node = <_ast.Assign object at 0x1109bbbd0>

    def visit_Assign(self, node):
        target = node.targets[0]

        if isinstance(target, ast.Tuple):
            elts = [self.visit(e) for e in target.elts]
            value = self.visit(node.value)
            return "std::tie({0}) = {1};".format(", ".join(elts), value)

        if isinstance(node.scopes[-1], ast.If):
            outer_if = node.scopes[-1]
            if target.id in outer_if.common_vars:
                value = self.visit(node.value)
                return "{0} = {1};".format(target.id, value)

        if isinstance(target, ast.Subscript):
            target = self.visit(target)
            value = self.visit(node.value)
            return "{0} = {1};".format(target, value)

        definition = node.scopes.find(target.id)
        if isinstance(target, ast.Name) and defined_before(definition, node):
            target = self.visit(target)
            value = self.visit(node.value)
            return "{0} = {1};".format(target, value)
        elif isinstance(node.value, ast.List):
            elements = [self.visit(e) for e in node.value.elts]
            return "{0} {1} {{{2}}};".format(
>               decltype(node), self.visit(target), ", ".join(elements)
            )
E           TypeError: sequence item 0: expected str instance, NoneType found

py14/transpiler.py:375: TypeError
________________________________________________________________________________________________________________ test_vector_find_out_type _________________________________________________________________________________________________________________

    def test_vector_find_out_type():
        source = parse("values = []", "values.append(1)")
>       cpp = transpile(source)

py14/tests/test_transpiler.py:130:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
py14/transpiler.py:39: in transpile
    cpp = transpiler.visit(tree)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:275: in visit_Module
    buf = [self.visit(b) for b in node.body]
py14/transpiler.py:275: in <listcomp>
    buf = [self.visit(b) for b in node.body]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:175: in visit_Expr
    s = self.visit(node.value)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <py14.transpiler.CppTranspiler object at 0x110a03250>, node = <_ast.Call object at 0x110a03110>

    def visit_Call(self, node):
        fname = self.visit(node.func)
        if node.args:
            args = [self.visit(a) for a in node.args]
>           args = ", ".join(args)
E           TypeError: sequence item 0: expected str instance, NoneType found

py14/transpiler.py:130: TypeError
_____________________________________________________________________________________________________________________ test_bubble_sort _____________________________________________________________________________________________________________________

    def test_bubble_sort():
        source = parse(
            "def sort(seq):",
            "    L = len(seq)",
            "    for _ in range(L):",
            "        for n in range(1, L):",
            "            if seq[n] < seq[n - 1]:",
            "                seq[n - 1], seq[n] = seq[n], seq[n - 1]",
            "    return seq",
        )
>       cpp = transpile(source)

py14/tests/test_transpiler.py:166:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
py14/transpiler.py:39: in transpile
    cpp = transpiler.visit(tree)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:275: in visit_Module
    buf = [self.visit(b) for b in node.body]
py14/transpiler.py:275: in <listcomp>
    buf = [self.visit(b) for b in node.body]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:89: in visit_FunctionDef
    body = "\n".join([self.visit(n) for n in node.body])
py14/transpiler.py:89: in <listcomp>
    body = "\n".join([self.visit(n) for n in node.body])
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:170: in visit_For
    buf.extend([self.visit(c) for c in node.body])
py14/transpiler.py:170: in <listcomp>
    buf.extend([self.visit(c) for c in node.body])
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:167: in visit_For
    it = self.visit(node.iter)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <py14.transpiler.CppTranspiler object at 0x11099d750>, node = <_ast.Call object at 0x1109402d0>

    def visit_Call(self, node):
        fname = self.visit(node.func)
        if node.args:
            args = [self.visit(a) for a in node.args]
>           args = ", ".join(args)
E           TypeError: sequence item 0: expected str instance, NoneType found

py14/transpiler.py:130: TypeError
_________________________________________________________________________________________________________________________ test_fib _________________________________________________________________________________________________________________________

    def test_fib():
        source = parse(
            "def fib(n):",
            "    if n == 1:",
            "        return 1",
            "    elif n == 0:",
            "        return 0",
            "    else:",
            "        return fib(n-1) + fib(n-2)",
        )
>       cpp = transpile(source)

py14/tests/test_transpiler.py:194:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
py14/transpiler.py:39: in transpile
    cpp = transpiler.visit(tree)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:275: in visit_Module
    buf = [self.visit(b) for b in node.body]
py14/transpiler.py:275: in <listcomp>
    buf = [self.visit(b) for b in node.body]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:89: in visit_FunctionDef
    body = "\n".join([self.visit(n) for n in node.body])
py14/transpiler.py:89: in <listcomp>
    body = "\n".join([self.visit(n) for n in node.body])
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:250: in visit_If
    return "".join(var_definitions) + super(CppTranspiler, self).visit_If(node)
py2many/clike.py:103: in visit_If
    orelse = [self.visit(child) for child in node.orelse]
py2many/clike.py:103: in <listcomp>
    orelse = [self.visit(child) for child in node.orelse]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:250: in visit_If
    return "".join(var_definitions) + super(CppTranspiler, self).visit_If(node)
py2many/clike.py:103: in visit_If
    orelse = [self.visit(child) for child in node.orelse]
py2many/clike.py:103: in <listcomp>
    orelse = [self.visit(child) for child in node.orelse]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py2many/clike.py:92: in visit_Return
    return "return {0};".format(self.visit(node.value))
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:272: in visit_BinOp
    return super(CppTranspiler, self).visit_BinOp(node)
py14/clike.py:32: in visit_BinOp
    [self.visit(node.left), self.visit(node.op), self.visit(node.right)]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:129: in visit_Call
    args = [self.visit(a) for a in node.args]
py14/transpiler.py:129: in <listcomp>
    args = [self.visit(a) for a in node.args]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:272: in visit_BinOp
    return super(CppTranspiler, self).visit_BinOp(node)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <py14.transpiler.CppTranspiler object at 0x11095fb50>, node = <_ast.BinOp object at 0x110aa50d0>

    def visit_BinOp(self, node):
        if isinstance(node.op, ast.Pow):
            return "std::pow({0}, {1})".format(
                self.visit(node.left), self.visit(node.right)
            )
        return " ".join(
>           [self.visit(node.left), self.visit(node.op), self.visit(node.right)]
        )
E       TypeError: sequence item 2: expected str instance, NoneType found

py14/clike.py:32: TypeError
______________________________________________________________________________________________________________________ test_comb_sort ______________________________________________________________________________________________________________________

    def test_comb_sort():
        source = parse(
            "def sort(seq):",
            "    gap = len(seq)",
            "    swap = True",
            "    while gap > 1 or swap:",
            "        gap = max(1, int(gap / 1.25))",
            "        swap = False",
            "        for i in range(len(seq) - gap):",
            "            if seq[i] > seq[i + gap]:",
            "                seq[i], seq[i + gap] = seq[i + gap], seq[i]",
            "                swap = True",
            "                return seq",
        )
>       cpp = transpile(source)

py14/tests/test_transpiler.py:225:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
py14/transpiler.py:39: in transpile
    cpp = transpiler.visit(tree)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:275: in visit_Module
    buf = [self.visit(b) for b in node.body]
py14/transpiler.py:275: in <listcomp>
    buf = [self.visit(b) for b in node.body]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:89: in visit_FunctionDef
    body = "\n".join([self.visit(n) for n in node.body])
py14/transpiler.py:89: in <listcomp>
    body = "\n".join([self.visit(n) for n in node.body])
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py2many/clike.py:125: in visit_While
    buf.extend([self.visit(n) for n in node.body])
py2many/clike.py:125: in <listcomp>
    buf.extend([self.visit(n) for n in node.body])
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:370: in visit_Assign
    value = self.visit(node.value)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:129: in visit_Call
    args = [self.visit(a) for a in node.args]
py14/transpiler.py:129: in <listcomp>
    args = [self.visit(a) for a in node.args]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:129: in visit_Call
    args = [self.visit(a) for a in node.args]
py14/transpiler.py:129: in <listcomp>
    args = [self.visit(a) for a in node.args]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:272: in visit_BinOp
    return super(CppTranspiler, self).visit_BinOp(node)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <py14.transpiler.CppTranspiler object at 0x11099d410>, node = <_ast.BinOp object at 0x1109eafd0>

    def visit_BinOp(self, node):
        if isinstance(node.op, ast.Pow):
            return "std::pow({0}, {1})".format(
                self.visit(node.left), self.visit(node.right)
            )
        return " ".join(
>           [self.visit(node.left), self.visit(node.op), self.visit(node.right)]
        )
E       TypeError: sequence item 2: expected str instance, NoneType found

py14/clike.py:32: TypeError
_____________________________________________________________________________________________________________________ test_normal_pdf ______________________________________________________________________________________________________________________

    def test_normal_pdf():
        source = parse(
            "def pdf(x, mean, std_dev):",
            "    term1 = 1.0 / ((2 * math.pi) ** 0.5)",
            "    term2 = (math.e ** (-1.0 * (x-mean) ** 2.0 / 2.0",
            "             * (std_dev ** 2.0)))",
            "    return term1 * term2",
        )
>       cpp = transpile(source)

py14/tests/test_transpiler.py:255:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
py14/transpiler.py:39: in transpile
    cpp = transpiler.visit(tree)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:275: in visit_Module
    buf = [self.visit(b) for b in node.body]
py14/transpiler.py:275: in <listcomp>
    buf = [self.visit(b) for b in node.body]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:89: in visit_FunctionDef
    body = "\n".join([self.visit(n) for n in node.body])
py14/transpiler.py:89: in <listcomp>
    body = "\n".join([self.visit(n) for n in node.body])
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:385: in visit_Assign
    value = self.visit(node.value)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:272: in visit_BinOp
    return super(CppTranspiler, self).visit_BinOp(node)
py14/clike.py:32: in visit_BinOp
    [self.visit(node.left), self.visit(node.op), self.visit(node.right)]
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:272: in visit_BinOp
    return super(CppTranspiler, self).visit_BinOp(node)
py14/clike.py:29: in visit_BinOp
    self.visit(node.left), self.visit(node.right)
py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ast.py:271: in visit
    return visitor(node)
py14/transpiler.py:272: in visit_BinOp
    return super(CppTranspiler, self).visit_BinOp(node)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <py14.transpiler.CppTranspiler object at 0x110af8550>, node = <_ast.BinOp object at 0x110a86dd0>

    def visit_BinOp(self, node):
        if isinstance(node.op, ast.Pow):
            return "std::pow({0}, {1})".format(
                self.visit(node.left), self.visit(node.right)
            )
        return " ".join(
>           [self.visit(node.left), self.visit(node.op), self.visit(node.right)]
        )
E       TypeError: sequence item 0: expected str instance, NoneType found

py14/clike.py:32: TypeError
___________________________________________________________________________________________________________ TestValueType.test_direct_assignment ___________________________________________________________________________________________________________

self = <pyrs.tests.test_tracer.TestValueType object at 0x110b0c310>

    def test_direct_assignment(self):
        source = parse("x = 3")
        x = source.body[0]
        t = value_type(x)
>       assert t == "3"
E       AssertionError: assert None == '3'
E         +None
E         -'3'

pyrs/tests/test_tracer.py:19: AssertionError
_________________________________________________________________________________________________ TestValueType.test_list_assignment_based_on_later_append _________________________________________________________________________________________________

self = <pyrs.tests.test_tracer.TestValueType object at 0x110999510>

    def test_list_assignment_based_on_later_append(self):
        source = parse("x = 3", "results = []", "results.append(x)")
        add_list_calls(source)
        results = source.body[1]
        t = value_type(results)
>       assert t == "3"
E       AssertionError: assert None == '3'
E         +None
E         -'3'

pyrs/tests/test_tracer.py:50: AssertionError
_______________________________________________________________________________________________ TestValueType.test_list_assignment_with_append_unknown_value _______________________________________________________________________________________________

self = <pyrs.tests.test_tracer.TestValueType object at 0x1109cebd0>

    def test_list_assignment_with_append_unknown_value(self):
        source = parse("results = []", "x = 3", "results.append(x)")
        add_list_calls(source)
        results = source.body[0]
        t = value_type(results)
>       assert t == "3"
E       AssertionError: assert None == '3'
E         +None
E         -'3'

pyrs/tests/test_tracer.py:57: AssertionError
_______________________________________________________________________________________________ TestValueType.test_global_list_assignment_with_later_append ________________________________________________________________________________________________

self = <pyrs.tests.test_tracer.TestValueType object at 0x1109cb590>

    def test_global_list_assignment_with_later_append(self):
        source = parse("results = []", "def add_x():", "   results.append(2)")
        add_list_calls(source)
        results = source.body[0]
        t = value_type(results)
>       assert t == "2"
E       AssertionError: assert None == '2'
E         +None
E         -'2'

pyrs/tests/test_tracer.py:64: AssertionError
______________________________________________________________________________________________________ TestValueExpr.test_catch_long_expression_chain ______________________________________________________________________________________________________

self = <pyrs.tests.test_tracer.TestValueExpr object at 0x110a26b50>

    def test_catch_long_expression_chain(self):
        source = parse("x = 3 * 1", "y = x - 5", "z = y + 2")
        z = source.body[2]
        t = value_expr(z)
>       assert t == "3 * 1 - 5 + 2"
E       AssertionError: assert 'None * None - None + None' == '3 * 1 - 5 + 2'
E         - 3 * 1 - 5 + 2
E         + None * None - None + None

pyrs/tests/test_tracer.py:72: AssertionError
_________________________________________________________________________________________________ TestValueExpr.test_catch_expression_chain_with_functions _________________________________________________________________________________________________

self = <pyrs.tests.test_tracer.TestValueExpr object at 0x11095fc50>

    def test_catch_expression_chain_with_functions(self):
        source = parse("x = 3 * 1", "y = foo(x)", "z = y + 2")
        z = source.body[2]
        t = value_expr(z)
>       assert t == "foo(3 * 1) + 2"
E       AssertionError: assert 'foo(None * None) + None' == 'foo(3 * 1) + 2'
E         - foo(3 * 1) + 2
E         + foo(None * None) + None

pyrs/tests/test_tracer.py:78: AssertionError

Generated binit.rs has lots of mismatched types

error[E0308]: mismatched types
 --> src/binit.rs:6:18
  |
6 |     while (low < high) {
  |                  ^^^^ expected `i32`, found `usize`
  |
help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit
  |
6 |     while (low < high.try_into().unwrap()) {
  |                  ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
 --> src/binit.rs:7:43
  |
7 |         let middle: _ = i32::from(((low + high) / 2));
  |                                           ^^^^ expected `i32`, found `usize`

error[E0277]: cannot add `usize` to `i32`
 --> src/binit.rs:7:41
  |
7 |         let middle: _ = i32::from(((low + high) / 2));
  |                                         ^ no implementation for `i32 + usize`
  |
  = help: the trait `Add<usize>` is not implemented for `i32`

error[E0277]: the type `[i32]` cannot be indexed by `i32`
 --> src/binit.rs:8:19
  |
8 |         if item < data[middle] {
  |                   ^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
  |
  = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
  = note: required because of the requirements on the impl of `Index<i32>` for `Vec<i32>`

error[E0308]: mismatched types
 --> src/binit.rs:9:20
  |
9 |             high = middle;
  |                    ^^^^^^ expected `usize`, found `i32`
  |
help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit
  |
9 |             high = middle.try_into().unwrap();
  |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the type `[{integer}]` cannot be indexed by `i32`
  --> src/binit.rs:23:9
   |
23 |         bins[bisect_right(limits, d)] += 1;
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
   |
   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
   = note: required because of the requirements on the impl of `Index<i32>` for `Vec<{integer}>`

Julia int_enum does not compile

ERROR: LoadError: UndefVarError: ST0 not defined
Stacktrace:
 [1] top-level scope
   @ ~/python/py2many/tests/cases/int_enum.jl:2

"foo is not None" fails on all languages except Julia

None is mapped to Option on rust, resulting in

error[E0308]: mismatched types
 --> none.rs:3:15
  |
3 |     if var != None {
  |               ^^^^ expected `i32`, found enum `Option`
  |
  = note: expected type `i32`
             found enum `Option<_>`

If this mapping of None to Option has some positive effect, we need a test case for those good scenarios.

Dart:

cases/none.dart:7:15: Error: Getter not found: 'None'.
  if (var_ != None) {
              ^^^^

Go:

cases/none.go:9:13: undefined: None

Kotlin:

cases/none.kt:3:17: error: unresolved reference: None

Nim:

tests/cases/none.nim(2, 7) Error: invalid token: trailing underscore

print in pygo causes: NameError: name 'values' is not defined

Adding print to the Python causes:

/Users/john.vandenberg/python/py2many/tests/test_cli.py:66:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/Users/john.vandenberg/python/py2many/py2many/cli.py:160: in main
    _process_once(settings, source, outdir)
/Users/john.vandenberg/python/py2many/py2many/cli.py:111: in _process_once
    f.write(transpile(source_data, settings.transpiler))
/Users/john.vandenberg/python/py2many/py2many/cli.py:43: in transpile
    code = transpiler.visit(tree) + "\n"
/Users/john.vandenberg/python/py2many/py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Caskroom/miniconda/base/lib/python3.8/ast.py:363: in visit
    return visitor(node)
/Users/john.vandenberg/python/py2many/pygo/transpiler.py:296: in visit_Module
    buf += [self.visit(b) for b in node.body]
/Users/john.vandenberg/python/py2many/pygo/transpiler.py:296: in <listcomp>
    buf += [self.visit(b) for b in node.body]
/Users/john.vandenberg/python/py2many/py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Caskroom/miniconda/base/lib/python3.8/ast.py:363: in visit
    return visitor(node)
/Users/john.vandenberg/python/py2many/pygo/transpiler.py:61: in visit_FunctionDef
    body = "\n".join([self.visit(n) for n in node.body])
/Users/john.vandenberg/python/py2many/pygo/transpiler.py:61: in <listcomp>
    body = "\n".join([self.visit(n) for n in node.body])
/Users/john.vandenberg/python/py2many/py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Caskroom/miniconda/base/lib/python3.8/ast.py:363: in visit
    return visitor(node)
/Users/john.vandenberg/python/py2many/pygo/transpiler.py:206: in visit_For
    buf.extend([self.visit(c) for c in node.body])
/Users/john.vandenberg/python/py2many/pygo/transpiler.py:206: in <listcomp>
    buf.extend([self.visit(c) for c in node.body])
/Users/john.vandenberg/python/py2many/py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Caskroom/miniconda/base/lib/python3.8/ast.py:363: in visit
    return visitor(node)
/Users/john.vandenberg/python/py2many/pygo/transpiler.py:218: in visit_Expr
    return self.visit(node.value)
/Users/john.vandenberg/python/py2many/py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Caskroom/miniconda/base/lib/python3.8/ast.py:363: in visit
    return visitor(node)
/Users/john.vandenberg/python/py2many/pygo/transpiler.py:192: in visit_Call
    ret = self._dispatch(node, fname, vargs)
/Users/john.vandenberg/python/py2many/pygo/transpiler.py:170: in _dispatch
    return dispatch_map[fname](node, vargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <pygo.transpiler.GoTranspiler object at 0x7f86705dc4c0>, node = <_ast.Call object at 0x7f86502d2f40>, vargs = ['color']

    def visit_print(self, node, vargs: List[str]) -> str:
        placeholders = []
        for n in node.args:
            placeholders.append("%v ")
        self._usings.add("fmt")
        return 'fmt.Printf("{0}\n",{1})'.format(
>           "".join(placeholders), ", ".join(values)
        )
E       NameError: name 'values' is not defined

Additional unnecessary parentheses in generated output

Lots of outermost round brackets which could be removed.

Some formatters might help to strip them; rustfmt doesnt.

warning: unnecessary parentheses around `while` condition
 --> src/binit.rs:6:11
  |
6 |     while (low < high) {
  |           ^^^^^^^^^^^^ help: remove these parentheses
  |
  = note: `#[warn(unused_parens)]` on by default
..
warning: unnecessary parentheses around function argument
 --> src/fib.rs:5:17
  |
5 |     return (fib((i - 1)) + fib((i - 2)));
  |                 ^^^^^^^ help: remove these parentheses

..
warning: unnecessary parentheses around assigned value
  --> src/binit.rs:11:19
   |
11 |             low = (middle + 1);
   |                   ^^^^^^^^^^^^ help: remove these parentheses

warning: unnecessary parentheses around `return` value
 --> src/fib.rs:5:17
  |
5 |     return (fib((i - 1)) + fib((i - 2)));
  |                 ^^^^^^^ help: remove these parentheses

CI deps missing

macOS:
SKIPPED [8] tests/test_cli.py:77: clang-format not available
SKIPPED [8] tests/test_cli.py:77: jlfmt not available
SKIPPED [8] tests/test_cli.py:77: nim not available

Windows is missing those and also
SKIPPED [8] tests\test_cli.py:77: ktlint not available

Linux
SKIPPED [8] tests/test_cli.py:77: jlfmt not available
SKIPPED [8] tests/test_cli.py:77: kotlinc not available
SKIPPED [8] tests/test_cli.py:77: nim not available

Four failures in the main branch

self = <test_cli.CodeGeneratorTests testMethod=test_cli__<'fib', 'kotlin'>>, case = 'fib', lang = 'kotlin'
self = <test_cli.CodeGeneratorTests testMethod=test_cli__<'rect', 'kotlin'>>, case = 'rect', lang = 'kotlin'
self = <test_cli.CodeGeneratorTests testMethod=test_cli__<'print', 'kotlin'>>, case = 'print', lang = 'kotlin'
self = <test_cli.CodeGeneratorTests testMethod=test_cli__<'print', 'dart'>>, case = 'print', lang = 'dart'

The last one is caused by not being able to find the package sprintf. I'm not super familiar with how to install packages with dart.

Undefined variables

pykt/transpiler.py:visit_range undefined name 'args'
pykt/transpiler.py:visit_print undefined name 'values'
pygo/transpiler.py:visit_range undefined name 'args'
pygo/transpiler.py:visit_print undefined name 'values'
pydart/transpiler.py:visit_range undefined name 'args'
pydart/transpiler.py:visit_print undefined name 'values'
pyjl/transpiler.py:visit_range undefined name 'args'
pyrs/transpiler.py:visit_range undefined name 'args'
pynim/transpiler.py:visit_range undefined name 'args'

#35 fixes the visit_print's

I've now added the fix for visit_range's to #38

assert not implemented correctly on kotlin, go or dart

def main():
    assert 1 == 1

becomes kotlin

fun main() {
assert!(1 == 1)}

error:

tests/cases/assert.kt:2:7: error: unexpected tokens (use ';' to separate expressions on the same line)
assert!(1 == 1)
      ^
tests/cases/assert.kt:2:1: error: function invocation 'assert(...)' expected
assert!(1 == 1)
^
tests/cases/assert.kt:2:1: error: none of the following functions can be called with the arguments supplied:
public inline fun assert(value: Boolean): Unit defined in kotlin
public inline fun assert(value: Boolean, lazyMessage: () -> Any): Unit defined in kotlin
assert!(1 == 1)
^

go

package todo_naming




func main() {
assert!(1 == 1)}

error

tests/cases/assert.go:7:7: syntax error: unexpected ! at end of statement

dart:

 main() {
assert!(1 == 1)}

error:

tests/cases/assert.dart:2:7: Error: Expected '(' before this.
assert!(1 == 1)}
      ^
tests/cases/assert.dart:2:7: Error: Expected ';' after this.
assert!(1 == 1)}
      ^
tests/cases/assert.dart:2:15: Error: Expected ';' after this.
assert!(1 == 1)}
              ^

py assert True is even worse, as nim and rust fail due to bool literals lacking support.

AttributeError: 'DartTranspiler' object has no attribute '_usings'

Including print in the Python results in

/Users/john.vandenberg/python/py2many/tests/test_cli.py:66:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/Users/john.vandenberg/python/py2many/py2many/cli.py:160: in main
    _process_once(settings, source, outdir)
/Users/john.vandenberg/python/py2many/py2many/cli.py:111: in _process_once
    f.write(transpile(source_data, settings.transpiler))
/Users/john.vandenberg/python/py2many/py2many/cli.py:43: in transpile
    code = transpiler.visit(tree) + "\n"
/Users/john.vandenberg/python/py2many/py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Caskroom/miniconda/base/lib/python3.8/ast.py:363: in visit
    return visitor(node)
/Users/john.vandenberg/python/py2many/pydart/transpiler.py:300: in visit_Module
    buf += [self.visit(b) for b in node.body]
/Users/john.vandenberg/python/py2many/pydart/transpiler.py:300: in <listcomp>
    buf += [self.visit(b) for b in node.body]
/Users/john.vandenberg/python/py2many/py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Caskroom/miniconda/base/lib/python3.8/ast.py:363: in visit
    return visitor(node)
/Users/john.vandenberg/python/py2many/pydart/transpiler.py:49: in visit_FunctionDef
    body = "\n".join([self.visit(n) for n in node.body])
/Users/john.vandenberg/python/py2many/pydart/transpiler.py:49: in <listcomp>
    body = "\n".join([self.visit(n) for n in node.body])
/Users/john.vandenberg/python/py2many/py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Caskroom/miniconda/base/lib/python3.8/ast.py:363: in visit
    return visitor(node)
/Users/john.vandenberg/python/py2many/pydart/transpiler.py:201: in visit_For
    buf.extend([self.visit(c) for c in node.body])
/Users/john.vandenberg/python/py2many/pydart/transpiler.py:201: in <listcomp>
    buf.extend([self.visit(c) for c in node.body])
/Users/john.vandenberg/python/py2many/py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Caskroom/miniconda/base/lib/python3.8/ast.py:363: in visit
    return visitor(node)
/Users/john.vandenberg/python/py2many/pydart/transpiler.py:206: in visit_Expr
    s = self.visit(node.value)
/Users/john.vandenberg/python/py2many/py2many/clike.py:61: in visit
    return super(CLikeTranspiler, self).visit(node)
/usr/local/Caskroom/miniconda/base/lib/python3.8/ast.py:363: in visit
    return visitor(node)
/Users/john.vandenberg/python/py2many/pydart/transpiler.py:187: in visit_Call
    ret = self._dispatch(node, fname, vargs)
/Users/john.vandenberg/python/py2many/pydart/transpiler.py:165: in _dispatch
    return dispatch_map[fname](node, vargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <pydart.transpiler.DartTranspiler object at 0x7f86502d35e0>, node = <_ast.Call object at 0x7f86502d3d30>, vargs = ['color']

    def visit_print(self, node, vargs: List[str]) -> str:
        placeholders = []
        for n in node.args:
            placeholders.append("%v ")
>       self._usings.add("fmt")
E       AttributeError: 'DartTranspiler' object has no attribute '_usings'

/Users/john.vandenberg/python/py2many/pydart/transpiler.py:152: AttributeError

PyPI name

After getting the package ready for release, please upload to PyPI to reserve the name and so it can be easily re-used via a permanent name.

#4 does a lot of the prep needed. README likely needs a few minor adjustments also.

Go int enum values are not accessible

An enum is converted to

type Colors int

const (
	RED   Colors = iota
	GREEN        = iota
	BLUE         = iota
)

That is a reasonable approach, but needs more plumbing to make it workable.

Any other Python code referring to RED needs to use Colors.RED, and the go transpiler doesnt covert those Colors.RED to be just RED. As a result of Colors.RED being copied as-is to the go code, go error is:

Colors.RED undefined (type Colors has no method RED)

Duplicate main

The follow results in two main() functions

def main():
	...


if __name__ == "__main__":
	main()

Generated rust:

fn main() {
    ...
}

fn main() {
    main();
}

Consider adding Dart to the transpilation target languages, enabling discussions

I'm not sure if you are aware of the (abandoned) Medusa project. It is a Python to Dart transpiler. I bring this to your attention for two reasons:

  1. To consider adding Dart as a transpilation target language, possibly making use of parts of the code, or
  2. To take inspiration from their general approach and see if any of the ideas explored have merit, regardless of adding Dart as a target.

Personally, I'm very interested in source to source translation, as it would unlock so much potential value for all languages if we were no longer bound by the traditional boundaries of each language. Perhaps you could consider enabling the discussions page for this project, so that people could freely discuss ideas that are not yet at the stage of implementation (issues, pull requests, code), or do you have some other means to facilitate this type of communication among collaborators.

Nim enum values are not accessible

An enum is converted to

type Colors = enum
  RED,
  GREEN,
  BLUE,

print(Colors.RED) becomes echo Colors::RED which fails on the colons with

Error: invalid indentation

binit.go doesnt compile

cases/infer.go
cases/infer.go:5:6: b declared but not used
cases/binit.go:9:4: high declared but not used
cases/binit.go:11:4: low declared but not used
cases/binit.go:19:6: x declared but not used

Kotlin tests do not compile

cases/binit.kt:6:19: error: this syntax is reserved for future use; to call a reference, enclose it in parentheses: (foo::bar)(args)
middle = i32::from(((low + high)/2))
                  ^
cases/binit.kt:17:4: error: unexpected tokens (use ';' to separate expressions on the same line)
...

cases/infer_ops.kt:63:13: error: unresolved reference: c_int8
fun fadd(x: c_int8, y: Double): Double {
            ^
...
cases/int_enum.kt:7:2: error: expecting member declaration
 RED = auto()
 ^

Generated rust lambda is invalid

test case lambda.py is currently lambda x, y: x + y. This is actually rather useless in Python, as the created lambda is thrown away. Still the result in Rust wont compile.

error: expected item, found `|`
 --> src/lambda.rs:1:1
  |
1 | |x, y| (x + y);
  | ^ expected item

Maybe it should become a comment in Rust (and any other sane language)

A more sensible test case would be

def get_func():
    return lambda x, y: x + y

And for that, the generated rust code also doesnt compile atm

error[E0308]: mismatched types
 --> src/lambda.rs:2:12
  |
1 | fn get_func<RT>() -> RT {
  |             --       -- expected `RT` because of return type
  |             |
  |             this type parameter
2 |     return |x, y| (x + y);
  |            ^^^^^^^^^^^^^^ expected type parameter `RT`, found closure
  |
  = note: expected type parameter `RT`
                    found closure `[closure@src/lambda.rs:2:12: 2:26]`
  = help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `RT`

Python test cases should be runnable scripts

In addition to being compile-able, the generated files should also be runnable and their output should be the same as the Python script. That adds an extra layer of validation.

lambda.dart does not compile

Could not format because the source could not be parsed:

line 3, column 22 of cases/lambda.dart: Expected an identifier.
  ╷
3var myfunc = { x, y -> (x + y) };}
  │                      ^
  ╵
cases/lambda.dart:3:22: Error: Expected an identifier, but got '>'.

AnnAssign with typing.List fails for all langs except Julia

After basic annassign syntax fixes with #71, the next challenge is more typical cases such as using typing.List in an AnnAssign, which causes compilation problems on all languages except Julia.

from typing import List

def show():
    items : List[str] = ["a", "b", "c"]
    for val in items:
    	print(val)

if __name__ == "__main__":
    show()

Julia happy processes items : List[str] = ["a", "b", "c"]

Rust error:

error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `[`
 --> for.rs:4:16
  |
4 | let items: List[str] = vec!["a", "b", "c"];
  |                ^ expected one of 7 possible tokens

dart:

5List[str] items = ["a", "b", "c"];
  │         ^Info: Compiling without sound null safety
cases/for.dart:5:6: Error: Getter not found: 'str'.
List[str] items = ["a", "b", "c"];
     ^^^
cases/for.dart:5:9: Error: Expected ';' after this.
List[str] items = ["a", "b", "c"];
        ^

etc,etc

If just using items: List = ... , dart and julia are happy. But others are not.
e.g. rust

error[E0412]: cannot find type `List` in this scope
 --> for.rs:4:16
  |
4 |     let items: List = vec!["a", "b", "c"];
  |                ^^^^ not found in this scope

Add C support

It should be possible to detect when a python file is using features that are not available in C, and fail, but otherwise generate a C program.

clang-format can be forced into C mode.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.