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) range_f = "range" if sys.version_info[0] < 3 else "xrange" assert cpp == parse( "template <typename T1>", "auto sort(T1 seq) {", "auto L = seq.size();", "for(auto _ : rangepp::{0}(L)) {{".format(range_f), "for(auto n : rangepp::{0}(1, L)) {{".format(range_f), "if(seq[n] < seq[n - 1]) {", "std::tie(seq[n - 1], seq[n]) = " "std::make_tuple(seq[n], seq[n - 1]);", "}", "}", "}", "return seq;", "}" )
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) assert cpp == parse( "template <typename T1>", "auto fib(T1 n) {", "if(n == 1) {", "return 1;", "} else {", "if(n == 0) {", "return 0;", "} else {", "return fib(n - 1) + fib(n - 2);", "}", "}", "}" )
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) range_f = "range" if sys.version_info[0] < 3 else "xrange" assert cpp == parse( "template <typename T1>", "auto sort(T1 seq) {", "auto gap = seq.size();", "auto swap = true;", "while (gap > 1||swap) {", "gap = std::max(1, pyrs::to_int(gap / 1.25));", "swap = false;", "for(auto i : rangepp::{0}(seq.size() - gap)) {{".format(range_f), "if(seq[i] > seq[i + gap]) {", "std::tie(seq[i], seq[i + gap]) = " "std::make_tuple(seq[i + gap], seq[i]);", "swap = true;", "return seq;", "}", "}", "}", "}" )
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) assert cpp == ('std::cout << std::string {"hi"} ' '<< std::string {"there"} << std::endl;')
def main(): parser = argparse.ArgumentParser(description="Transpile Python to Rust") parser.add_argument("file", metavar='<python file or directory>') args = parser.parse_args() if os.path.isfile(args.file): source = open(args.file).read() rs = transpile(source) sys.stdout.write(rs) else: print("Transpiling whole directiory:") successful = failures = format_errors = 0 basename = os.path.basename(args.file) for root, subdir, filenames in os.walk(args.file): common_prefix = os.path.commonprefix([args.file, root]) relpath = os.path.relpath(root, args.file) target_root = os.path.join(common_prefix + "-pyrs", relpath) for relative_path in filenames: src_file = os.path.join(root,relative_path) basename, extension = os.path.splitext(relative_path) if extension == ".py": dst_file = os.path.join(target_root, basename + ".rs") os.makedirs(os.path.dirname(dst_file), exist_ok=True) try: pysource = open(src_file).read() rs = transpile(pysource) with open(dst_file, "w") as f: f.write(rs) if rust_format(dst_file) != 0: print("Transpiled but not formatted:", dst_file) format_errors += 1 else: successful += 1 except Exception as e: failures += 1 print("Error: Could not transpile:", src_file) print("Due to:", e) print("\nFinished!") print("Successful: ", successful) print("Transpiled, but not formatted: ", format_errors) print("Failed to convert: ", failures)
def test_vector_find_out_type(): source = parse( "values = []", "values.append(1)", ) cpp = transpile(source) assert cpp == parse( "std::vector<decltype(1)> values {};", "values.push_back(1);" )
def test_assign(): source = parse( "x = 3", "x = 1", ) cpp = transpile(source) assert cpp == parse( "auto x = 3;", "x = 1;" )
def test_void_function(): source = parse( "def test_fun():", " assert True", ) cpp = transpile(source) assert cpp == parse( "inline void test_fun() {", "REQUIRE(true);", "}" )
def test_empty_return(): source = parse( "def foo():", " return", ) cpp = transpile(source) assert cpp == parse( "inline auto foo() {", "return;", "}", )
def test_create_catch_test_case(): source = parse( "def test_fun():", " assert True", ) cpp = transpile(source, testing=True) assert cpp == parse( '#include "catch.hpp"', 'TEST_CASE("test_fun") {', "REQUIRE(true);", "}" )
def test_function_with_return(): source = parse( "def fun(x):", " return x", ) cpp = transpile(source) assert cpp == parse( "template <typename T1>", "auto fun(T1 x) {", "return x;", "}" )
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);" )
def test_print_program_args(): source = parse( 'if __name__ == "__main__":', " for arg in sys.argv:", " print(arg)", ) cpp = transpile(source) assert cpp == parse( "int main(int argc, char ** argv) {", "pyrs::sys::argv = std::vector<std::string>(argv, argv + argc);", "for(auto arg : pyrs::sys::argv) {", "std::cout << arg << std::endl;", "}", "}" )
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;", "}" )
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;" )
def test_declare_var_before_if_else_statements(): source = parse( "if True:", " x = True", "else:", " x = False", "y = x", ) cpp = transpile(source) assert cpp == parse( "decltype(true) x;", "if(true) {", "x = true;", "} else {", "x = false;", "}", "auto y = x;" )
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) assert cpp == parse( "template <typename T1, typename T2, typename T3>", "auto pdf(T1 x, T2 mean, T3 std_dev) {", "auto term1 = 1.0 / std::pow(2 * pyrs::math::pi, 0.5);", "auto term2 = std::pow(pyrs::math::e, -1.0 * " "std::pow(x - mean, 2.0) / 2.0 * std::pow(std_dev, 2.0));", "return term1 * term2;", "}" )
def test_map_function(): source = parse( "def map(values, fun):", " results = []", " for v in values:", " results.append(fun(v))", " return results", ) cpp = transpile(source) assert cpp == parse( "template <typename T1, typename T2>", "auto map(T1 values, T2 fun) {", "std::vector<decltype(fun(std::declval" "<typename decltype(values)::value_type>()))> results {};", "for(auto v : values) {", "results.push_back(fun(v));", "}", "return results;", "}" )
import subprocess from pyrs.transpiler import transpile def rust_format(file_path): result = subprocess.call(['rustfmt', file_path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) return result if __name__ == "__main__": parser = argparse.ArgumentParser(description="Transpile Python to Rust") parser.add_argument("file", metavar='<python file or directory>') args = parser.parse_args() if os.path.isfile(args.file): source = open(args.file).read() rs = transpile(source) sys.stdout.write(rs) else: print("Transpiling whole directiory:") successful = failures = format_errors = 0 basename = os.path.basename(args.file) for root, subdir, filenames in os.walk(args.file): common_prefix = os.path.commonprefix([args.file, root]) relpath = os.path.relpath(root, args.file) target_root = os.path.join(common_prefix + "-pyrs", relpath) for relative_path in filenames: src_file = os.path.join(root,relative_path) basename, extension = os.path.splitext(relative_path) if extension == ".py": dst_file = os.path.join(target_root, basename + ".rs")
def test_list_as_vector(): source = parse("values = [0, 1, 2, 3]") cpp = transpile(source) assert cpp == "std::vector<decltype(0)> values {0, 1, 2, 3};"
def test_declare(): source = parse("x = 3") cpp = transpile(source) assert cpp == "auto x = 3;"
def test_assert(): source = parse('assert 1 == foo(3)') cpp = transpile(source) assert cpp == ('REQUIRE(1 == foo(3));')