Live data from Hacker News

SPy: An interpreter and compiler for a fast statically typed variant of Python

antocuni.eu

51–60 of 133 posts

Re: SPy: An interpreter and compiler for a fast statically typed variant of Python

#51
post #7

Looks very interesting! I remember chatting with one of the creators of PyPy (not the author of TFA) a number of years ago at HPI. He had just given a talk about how RPython was used in PyPy development, and I was fascinated. To me, it seemed completely obvious that RPython itself seemed like a really interesting standalone language, but he would have none of it. Whenever I suggested that RPython might have advantage…

I'm not quite seeing the contradiction either? I sort of get that you're pointing out some kind of tension, but it's not obvious that there's a contradiction. The statements involved don't seem to be interpretable in a self-contained way.

Re: SPy: An interpreter and compiler for a fast statically typed variant of Python

#52
post #45

It's weird, but the pain of moving to a whole new language seems less than the pain of using one of these language subsets. I guess it might be because of "loss aversion": we dislike losing something we have more the value we put on gaining it. In a new language each newly added feature is a gain, but in a language subset you're always encountering things you would have in the full language. So no matter how good the…

> in a language subset you're always encountering things you would have in the full language

Exactly. I once pitched the idea of a Python subset (with a different focus, not performance like SPy), and almost every reaction was "will it support ".

For example, a new language can build its own solution for array math, or maybe that's not something its users need. OTOH many consider a Python subset to be unacceptable if it doesn't specifically support NumPy.

In the end I came to agree with https://pointersgonewild.com/2024/04/20/the-alternative-impl...:

> positioning your project as an alternative implementation of something is a losing proposition

> don't go trying to create a subset of Python [...] Do your own thing. That way, you can evolve your system at your own pace and in your own direction, without being chained by expectations that your language should have to match the performance, feature set, or library ecosystem of another implementation.

Re: SPy: An interpreter and compiler for a fast statically typed variant of Python

#53
Overall this looks very interesting - I always thought more could have been done with RPython, but there was never any documentation for it. I do have some nits though:

> The following silly example happily passes mypy

In fairness that's because Mypy is shit. Pyright catches this mistake.

> As such, we need to treat Python type checkers more like linters than actual theorem provers

Again I think this is true of Mypy but Pyright is much closer to a sound type checker.

> redshifting

This is just constant propagation isn't it? C compilers have been doing this for decades. I don't think we need a silly new term for it. Let's not cause another "tree shaking" situation.

> So far, this is not different than usual constant folding, with the difference that it's guaranteed to happen. What makes it more powerful is the ability to mark some functions as @blue.

That's not different. It's just constant folding with C++'s `consteval`. And @blue is an absolutely abysmal name.

It would be much clearer if @blue were changed to @consteval or @comptime (either's good I think), and you just call it "compile time evaluation" or "constant propagation" instead of "redshifting".

Re: SPy: An interpreter and compiler for a fast statically typed variant of Python

#54
i thought this was super cool and informative thank you so much for writing it.

i work a lot in python and tried to build a runtime type checker for it that basically acted as automatic assertions on all stated types at function boundaries, and it worked really well to bring all TypeErrors in my code to the surface on first run.

but, my knowledge is woefully short on compilers and languages. this definitely gave me a great frame of understanding, so thanks again for writing it

Re: SPy: An interpreter and compiler for a fast statically typed variant of Python

#55
post #33

Common Lisp also allows you to redefine everything at runtime but doesn't suffer from the same performance issues that Python has, does it? Doe anyone have insight into this?

Common Lisp is not a runtime, it’s a specification. Implementations are free to compile everything to fast native code, or to interpret everything. Various available implementations do that and everything in between. That said , SBCL and the commercial implementations can be extremely fast, especially if you specify types on tight loops. SBCL comes with a disassembler that shows you right in the REPL the Assembly a f…

Addedum that having a disassembler is quite common language primitive in most compiled Lisps, since early days.

Re: SPy: An interpreter and compiler for a fast statically typed variant of Python

#56
post #45

It's weird, but the pain of moving to a whole new language seems less than the pain of using one of these language subsets. I guess it might be because of "loss aversion": we dislike losing something we have more the value we put on gaining it. In a new language each newly added feature is a gain, but in a language subset you're always encountering things you would have in the full language. So no matter how good the…

Throwing my hands up and moving to Nim was downright easy next to the excessive effort I put into trying out Nuitka, Numba, and PyInstaller for my use case. If you want static compilation, use a language and libraries built with that assumption as a ground rule. The herculean effort of building a half-compatible compiler for a dynamic language seems like a fool's errand, and would be a fun curiosity if so many people hadn't already tried it, especially with Python.

Re: SPy: An interpreter and compiler for a fast statically typed variant of Python

#57

Earlier quoted context omitted.

Common Lisp doesn't use (expensive) CLOS dispatch in the core language, e.g. to add two numbers or find the right equality operator. That's one known pain point due to CLOS having been "bolted-on" rather than part of the language which makes the divide between internal (using typecase and similar) and external (generic functions) dispatch pretty ugly; and gave use the eql/equal/equalp/etc... hell. Thing is that you n…

> and gave use the eql/equal/equalp/etc... hell. You don't like those? I've always considered them a fairly elegant deconstruction of the problem domain of equality checking. DWIM languages can get very confusing when they DWIM or don't DWIM.

Where's the elegance? Equality is well defined on everything handled by those three, since they only compare the same types without doing coercion. Plus, you can't extend these to handle user types.

Which is why https://cdr.common-lisp.dev/document/8/cleqcmp.html exists, really; all the "copy-x" would benefit from the same fix, in my opinion.

Re: SPy: An interpreter and compiler for a fast statically typed variant of Python

#58
++spy ethos and ideas

But why limit to an interpreter? Translate to other excellent compiled languages and benefit from the optimization work there.

Giving up on C-API and the dynamic parts of python that 1% of the people use is a good trade-off.

In the age of cursor and windsurf it's not hard to auto replace incompatible code with something that works in the static-py ecosystem.

Would love to participate in an effort to standardize such a subset.

Re: SPy: An interpreter and compiler for a fast statically typed variant of Python

#59
I sympathise with the motivations for this, though I don't use Python much. I occasionally work on a toy Ruby compiler that started as a long blog series. More recently I've picked it up again with heavy AI use - I set Claude working on improving Rubyspec pass rates (which are atrocious). It's chugging along right now, actually.

One of the things I've spent a lot of time thinking about are the ways to avoid a lot of the dynamic features of Ruby without affecting actual, real code much.

There's a lot that can be done there - e.g. all of the research on Self and JS VMs is highly applicable.

But I say "real code" because a lot of the "worst" dynamic features of Ruby (and Python) either doesn't appear in production code very often, or at all (there are still aspects of Ruby I have never seen used in real-life use despite having used Ruby for 20 years), or could be mitigated trivially, so I still believe you can do quite decently without a lot of the more complex optimisations.

As an example (from Ruby): You can re-open the Integer class and override +:

  ruby -e 'class Integer; def +(other); 42; end; end; p 2 + 2'
(don't do this in IRB; it crashes)

But nobody does that. The problem with a lot of these features isn't that people use them, but that people might use them.

That leaves two main avenues: We can do like the author of thise post and strip away the costly features that are rarely used.

Or we can provide ways of promising not to use them through code or options.

The first option is perfectly valid, but I quite like the second:

In Ruby, it turns out a lot of the optimisation challenges goes away if you get an app to freeze the most important system classes after setup, because even most of the most horrific examples of Ruby monkeypatching tends to do most of it only during startup, and you then tend to get to a stable state where you can let applications opt in to additional optimisations just by calling "freeze" on a number of objects.

Ruby programs will also do things like dynamically decide which files to load based on reading the directory, but if you compile an application, most of the time you want that to happen ahead of time with a few exceptions (e.g. plugins), and so similarly, if you freeze as many classes as possible at a given point, you can partially evaluate manipulation of the runtime up until that point, and treat it as mostly static afterward, and fall back to slow paths for anything you can't statically resolve the names of, and still end up with lots of optimisation potential for most of the low level code.

I think a lot of the same would work for Python, and might bridge the gap between the categories of alternative implementations the author mentions with more predictability than relying on a JIT doing the right analysis.

E.g. your compiler can eat least potentially guarantee under which circumstances it can statically determine that an Integer can inline the fast path if Integer is frozen so that you can in fact reason about the code.

Re: SPy: An interpreter and compiler for a fast statically typed variant of Python

#60

++spy ethos and ideas But why limit to an interpreter? Translate to other excellent compiled languages and benefit from the optimization work there. Giving up on C-API and the dynamic parts of python that 1% of the people use is a good trade-off. In the age of cursor and windsurf it's not hard to auto replace incompatible code with something that works in the static-py ecosystem. Would love to participate in an effor…

There is a compiler detailed in the page on the link;

> 3. We have a compiler for deployment and performance. The interpreter and the compiler are guaranteed to produce the exact same results at runtime.

Post reply on HN