[![PyPI version](https://badge.fury.io/py/evalo.svg)](https://pypi.org/project/evalo/)
# Python code synthesis

This project is used to interpret Python code and generate Python code based on given values.

This project is heavily influenced by [Barliman](https://github.com/webyrd/Barliman), which implemented
this exact idea for Scheme. While Barliman works wonders, I don't think Scheme is a programming
language that is widely used in production environments. This is the reason I created this
project, so that the principle of Barliman could be applied to Python.


## Examples
This project can do both interpreting from Python code to values and vica versa. For example, AST
values will be converted to the correct interpreted values:

```
> from evalo import *
> x = var()
> run(1, x, eval_expro(ast.BinOp(left=ast.Num(n=1), op=ast.Add(), right=ast.Num(n=1)), [], x))

(2,)
```

Interpreting from values to Python code will generate AST objects, which can be directly translated
to Python code using external libraries. For example, if we want 5 different versions of Python code
that are interpreted to the value `2`, we can do the following:

```
> from evalo import *
> x = var()
> run(5, x, eval_expro(x, [], 2))

(<_ast.Num at 0x7fdf44aabe48>,
 <_ast.BinOp at 0x7fdf44a87fd0>,
 <_ast.BinOp at 0x7fdf44a1d320>,
 <_ast.BinOp at 0x7fdf44a444e0>,
 <_ast.BinOp at 0x7fdf46ee36a0>)
```

To translate this to human-readable values, we can use `ast_dump_if_possible`:
```
> [ast_dump_if_possible(y) for y in run(5, x, eval_expro(x, [], 2, maxdepth=3))]

['Num(n=2)',
 'BinOp(left=Num(n=0), op=Add(), right=Num(n=2))',
 'BinOp(left=Num(n=0), op=Sub(), right=BinOp(left=Num(n=0), op=Sub(), right=Num(n=2)))',
 'BinOp(left=Num(n=1), op=Mult(), right=Num(n=2))',
 'BinOp(left=BinOp(left=Num(n=0), op=Add(), right=Num(n=0)), op=Add(), right=Num(n=2))']
```

Using the [astunparse](https://github.com/simonpercivall/astunparse) library we can directly translate this output to Python source code:

```
> [astunparse.unparse(y).strip() for y in run(10, x, eval_expro(x, [], 2, maxdepth=3))]

['2',
 '(0 + 2)',
 '(0 - (0 - 2))',
 '(1 * 2)',
 '((0 + 0) + 2)',
 '((0 + 0) - (0 - 2))',
 '((1 + 0) * 2)',
 '((0 - 0) + 2)',
 '((0 - 0) - (0 - 2))',
 '((1 - 0) * 2)']
```

## Development
If you want to help develop on this project, you can install it like so using Python 3.7:
```
mkvirtualenv -a $(pwd) $(basename $(pwd)) -p python3
pip install -r requirements.txt
```

This project uses `tox` with `pytest` for testing, so just run `tox` to run all tests.
