> - presumably, since it is compiled, it does static checks on the code? How many statically-detectable bugs that are now purely triggered at runtime can be eliminated with LPython?
Yes, it does static checks at compile time. The only thing that we do at runtime (imperfectly right now, eventually perfectly) are array/list bounds checks, integer overflow during arithmetic or casting and such. Those checks would only run in Debug and ReleaseSafe modes, but not in Release mode. So for full performance, you choose the Release mode. For 100% safe mode, you would need to use ReleaseFast.
- does it deal with the unholy amounts of dynamism of Python? Can you call getattr, setattr on random objects? Does eval work? Etc. Quite a few Python packages use these at least once somewhere...
It deals with it by not allowing it. We will support as much as we can, as long as it can be robustly ahead of time compiled to high performance code. The rest you can always use just via our CPython "escape hatch". The idea is that either you want performance (then restrict to the subset that can be compiled to high performance code) or you don't (then just use CPython).
For a system that doesn't intend to handle arbitrary unaltered Python code, I think a post announcing a "Python Compiler" should make this clearer in the first paragraph.
You are right, we should have made that clearer. If you look at all the 25 compilers that we list at the bottom of: https://lpython.org/, some of them are supersets, some of them are subsets. Sometimes the distinction is blurry, since even with LPython you can call arbitrary CPython today, it just doesn't get compiled right now, but perhaps later we can actually compile it like Cython does, just not speed it up much. In that case we become a subset that is fast, the rest is slower, but I think every superset of Python behaves like that too. In a way, I think all of the 25 compilers supports all of Python one way or the other (LPython as well), and I think each of them only gets a subset to be fast.
If you have some ideas how to best communicate this, let me know.
The best approach that I know right now is to say that we support a strict subset of Python, and if it compiles, it will be fast. The rest of Python you have to call explicitly and it will be slow and you get a CPython dependency in the binary that we generate, but you can do it. That way there is a clear distinction what gets compiled via our compiler into high performance machine code and what gets dispatched via CPython (it will eventually get "compiled", but it will just call CPython).
I guess I'd put it like "LPython compiles a type-annotated Python subset (dialect? variant?) to optimized machine code. Interop with CPython is easy: arbitrary Python code can go in the same source file using a decorator." -- just as an example to try to be helpful -- of course you know your system and I don't. It sounds really cool and I'm wishing you luck.
Yes, it does static checks at compile time. The only thing that we do at runtime (imperfectly right now, eventually perfectly) are array/list bounds checks, integer overflow during arithmetic or casting and such. Those checks would only run in Debug and ReleaseSafe modes, but not in Release mode. So for full performance, you choose the Release mode. For 100% safe mode, you would need to use ReleaseFast.
- does it deal with the unholy amounts of dynamism of Python? Can you call getattr, setattr on random objects? Does eval work? Etc. Quite a few Python packages use these at least once somewhere...
It deals with it by not allowing it. We will support as much as we can, as long as it can be robustly ahead of time compiled to high performance code. The rest you can always use just via our CPython "escape hatch". The idea is that either you want performance (then restrict to the subset that can be compiled to high performance code) or you don't (then just use CPython).