Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
torshepherd committed Aug 17, 2022
0 parents commit 1ed0eb9
Show file tree
Hide file tree
Showing 7 changed files with 744 additions and 0 deletions.
79 changes: 79 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/

# IDEs
.idea/
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"python.testing.pytestArgs": [
"."
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
97 changes: 97 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# C-Py-Py

```python
from cpp import *

x = (cpp)[std::vector<int>v({1, 2, 3})]
x.push_back(4)
(cpp)[std::cout] << "Vector x: " << x << (cpp)[std::endl]
# -> prints 'Vector x: [1, 2, 3]'
for i in auto& x:
(cpp)[std::cout] << "Incrementing " << i << "..." << (cpp)[std::endl]
# -> prints 'Incrementing 1...', 'Incrementing 2...', etc.
i += 1

(cpp)[std::cout] << "Vector after: " << x << (cpp)[std::endl]
# -> prints 'Vector after: [2, 3, 4, 5]'
```

## How?

### Template notation

The `<>` template notation was quite difficult to pull off. Python has a weird concept of multiple-boolean-operators, so the following:

```python
x = (cpp)[std::vector<int>v({1, 2, 3})]
```

is equivalent to

```python
x = (cpp)[std::((vector < int) and (int > v({1, 2, 3})))]
```

We can then overwrite the less than operator for the object `vector` to simply return True, so that it's negligible:

```python
x = (cpp)[std::(True and (int > v({1, 2, 3})))]
x = (cpp)[std::(int > v({1, 2, 3}))]
```

Now we can overwrite the less than operator on a different class (`v`, in this case) so that it simply takes in a fully formed vector object as `self` and a type as the comparison, then tries to transform that into a new vector of the type in the comparison. This would be equivalent to:

```python
x = (cpp)[std::(v({1, 2, 3}))]
```

### C++-style namespacing

Nearly there. For the namespacing (`::`), we turn to the only place in the Python syntax where adjacent colons are allowed: slice notation. The code above is equivalent to:

```python
x = cpp[slice(std, None, v({1, 2, 3}))]
```

We can define `cpp` to be an instance of a class that overrides the `__getitem__` method to simply return the rightmost part of the slice:

```python
class cpp:
def __getitem__(self, other: slice):
return other.step
cpp = cpp()
```

Now the code is equivalent to just:

```python
x = v({1, 2, 3})
```

where `v` is essentially a thin wrapper around `list`.

### cout

`cout` performs a small sleight-of-hand. Since Python is evaluated left-to-right, we have to have the `<<` operator reduce each of the expressions down into a single format string, then pass that to `endl` to actually do the printing. We do this by making `cout`.__lshift__() return a `Coutable`:

```python
class _Coutable:
def __init__(self, o) -> None:
self._total_str: str = format(o)

def __lshift__(self, other: Any) -> Self:
if other is endl:
print(self._total_str)
self._total_str = self._total_str + format(other)
return self
```

This class will just keep accumulating objects' formatted representations until it hits endl, when it will print everything out.

### Taking references

Unfortunately, Python's `for _ in _:` syntax is pretty rigid, and won't allow any operations in-between for and in, so we have to stick the `auto&` on the right side. This

## Why?

Scientists are hard at work trying to come up with an answer to that question.
Loading

0 comments on commit 1ed0eb9

Please sign in to comment.