This is the successor to my works of Idris-Python.
Idris didn't provide me metadata such as source code positions hence debugging(especially FFI) is horrible, but PureScript's IR output is pretty nice.
Besides, Idris FFI, though designed smart, but to be honest not that "industrially" practical, while
PureScript's Haskell-like foreign import mechanism is extremely straightforward and flexible.
Then I found PureScript, and now I think I love it.
The code generation itself is finished, but still needs testing.
Currently I'm working on the support of some FFI libraries, for example, Prelude. Without Prelude
we cannot even print anything or proceed testing.
The first binary release(v0.1) will be available after
- passing the testcases provided by PureScript GitHub repository, and
- implementing an extensible and customizable Python FFI providing mechanism.
After slightly modifying a JavaScript-like IR produced by the builtin compiler,
PureScript gets compiled to PySExpr and shall work since Python 3.5.
The reason why we generate the IR PySExpr instead of Python source code,
is for getting better cross-Python-version compatibility, Python-version-specific optimizations,
source code positioning for using existing Python debuggers in PureScript, and expression-first expressiveness. You could check out this reddit post for more details.
Given a PureScript module, not losing the generality, we abbreviate it as A.B.
After processing this module via the command
# `output` is the directory produced by the PureScript build tool `spago`.
pspy-blueprint --out-python aaa/bbb/output_top_dir --corefn-entry A.B --out-ffi-dep ffi-requires.txtCommand pspy-blueprint generates following directory tree(all __init__.py will be added later, but not in Haskell side):
- aaa/bbb/output_top_dir
- A
- B
- pure.py
- pure.src.py
- ffi
- ffi-requires.txt # lines of paths from which FFI files are required
This Python module creates Python code/bytecode object.
In CPython, every Python file will be compiled to a Python code object, which will finally be executed in CPython virtual machine.
In pure.src.py, we just create the code object,
but don't execute it, for achieving the further flexibility of caching and composition of our compilation.
This is, actually the loader for corresponding pure.src.py.
This module implements the concrete code caching system which avoids the redundant Python source code to bytecode compilation, and finally greatly reduce the module loading time.
Hence, a PureScript module A.B compiled by PureScript-Python
will be able to imported by the statement import output_top_dir.A.B.pure.
The code of pure.py, corresponding to a PureScript module, is fixed to be
from purescripto import LoadPureScript
__py__ = globals()
__ps__ = LoadPureScript(__file__, __name__)
__all__ = list(__ps__)
__py__.update(__ps__)which relies on the Python package purescripto.
The Python package purescripto provides a common RTS and supplements all required functionalities for being a full featured PureScript backend.