Python to C++ 14 transpiler
⚠️ This repository is no longer actively maintained by Lukas Martinelli.
This is a little experiment that shows how far you can go with the
C++ 14 auto
return type and templates.
C++14 has such powerful type deduction that it is possible to transpile
Python into C++ without worrying about the missing type annotations in python. Only a small subset of Python is working and you will encounter many bugs. The goal is to showcase the power of C++14 templates and not to create a fully functional transpiler.
Example
Original Python version.
def factorial(num):
if num <= 1:
return num
return factorial(num-1) * num
Transpiled C++ template.
template <typename T1> auto factorial(T1 num) {
if (num <= 1) {
return num;
}
return factorial(num - 1) * num;
}
How it works
Consider a map
implementation.
def map(values, fun):
results = []
for v in values:
results.append(fun(v))
return results
This can be transpiled into the following C++ template.
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;
}
The parameters and the return types are deduced automatically In order to define the results vector we need to:
- Deduce the type for v returned from the values range
using v_type = typename decltype(values)::value_type
- Deduce the return type of
fun
for call with parameter vdecltype(fun(v))
- Because we dont know v at the time of definition we need to fake it
std::declval<v_type>()
- This results in the fully specified value type of the results vector
decltype(fun(std::declval<typename decltype(values)::value_type>()))
Trying it out
Requirements:
- clang 3.5
Transpiling:
./py14.py fib.py > fib.cpp
Compiling:
clang++ -Wall -Wextra -std=c++14 -Ipy14/runtime fib.cpp
Run regression tests:
cd regtests
make
Run tests
pip install -r requirements.txt
py.test --cov=py14
More Examples
Probability Density Function (PDF)
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
template <typename T1, typename T2, typename T3>
auto pdf(T1 x, T2 mean, T3 std_dev) {
auto term1 = 1.0 / std::pow(2 * py14::math::pi, 0.5);
auto term2 = std::pow(py14::math::e, -1.0 * std::pow(x - mean, 2.0) / 2.0 *
std::pow(std_dev, 2.0));
return term1 * term2;
}
Fibonacci
def fib(n):
if n == 1:
return 1
elif n == 0:
return 0
else:
return fib(n-1) + fib(n-2)
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);
}
}
}
Bubble Sort
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
template <typename T1> auto sort(T1 seq) {
auto L = seq.size();
for (auto _ : rangepp::range(L)) {
for (auto n : rangepp::range(1, L)) {
if (seq[n] < seq[n - 1]) {
std::tie(seq[n - 1], seq[n]) = std::make_tuple(seq[n], seq[n - 1]);
}
}
}
return seq;
}
Working Features
Only bare functions using the basic language features are supported.
- classes
- functions
- lambdas
- multiple inheritance
- operator overloading
- function and class decorators
- getter/setter function decorators
- list comprehensions
- yield (generator functions)
- function calls with
*args
and**kwargs
Language Keywords
- global, nonlocal
- while, for, continue, break
- if, elif, else
- try, except, raise
- def, lambda
- new, class
- from, import, as
- pass, assert
- and, or, is, in, not
- return
- yield
Builtins
- dir
- type
- hasattr
- getattr
- setattr
- issubclass
- isinstance
- dict
- list
- tuple
- int
- float
- str
- round
- range
- sum
- len
- map
- filter
- min
- max
- abs
- ord
- chr
- open
Data Structures
- list
- Set
- String
- Dict