Hacker News new | past | comments | ask | show | jobs | submit login
500 Lines or Less – A Python Interpreter Written in Python (aosabook.org)
183 points by gkst on Sept 8, 2016 | hide | past | favorite | 45 comments



In the early 2000's, Teemu Kalvas created "Lisp 500": 500 lines of C (plus a .lisp file that provides a library and goes as far as featuring a compiler, which works by emitting C).

I can't find the sources for this.

Incomplete, no .lisp file: http://www.s2.org/~chery/projects/lisp500/

Doesn't connect: http://modeemi.cs.tut.fi/~chery/lisp500/

The most accessible source for this currently seems to be a "lisp5000" project in GitHub: https://github.com/jackpal/lisp5000

This is a derivative work whose C code has been blown up to 1600+ lines.


The Wayback Machine seems to have a copy online. [1]

1: https://web.archive.org/web/20040305005602/http://modeemi.cs...


This is similar, but in C++:

https://github.com/rongarret/Ciel


If you implement Arc in it as a subdialect, you get Arc en Ciel. :)


Look up femtolisp. It's a fast interpreter that was around 1kloc at one point. Julia is built on it. It was LISP internally last I checked.


I count more than 30 000 LOC at https://github.com/JeffBezanson/femtolisp


I was going by the original description. No longer true it seems. I'll retract it then. Thanks. :)


List is inherently easy to parse though.


That is neither here nor there because parsing is a small sub-problem of the overall problem of providing a complete programming language run-time. Lisp500 isn't a "meta-circular" interpreter; it cannot rely on a host Lisp's implementation of things like memory management, I/O streams, hashing, compilation, ...


not sure if troll


Not easy to read.


Shouldn't the title of the article be "500 lines or less - ceval.c written in Python" or "500 lines or less - a python bytecode interpreter written in python" The original one is just misleading.


It is an interpreter and that's absolutely correct. They could've even said "A vm in Python" because that is a VM, just without JIT etc. The compiler includes a parser usually, but interpreters in the purest sense of the word interpret the semantics of some structure corresponding to the code.


It's not an interpreter of the programming language Python, however. It's a VM for Python bytecode, which is not what most people understand as Python, right?


It's as correct as writing a Kernel and call it an OS.

If you use that kind of deception too often, people won't take you seriously any more very quickly.


best "well-actually" of the day


This is awesome. Also see her talk at Pycon here: https://www.youtube.com/watch?v=HVUTjQzESeo


Surely something like, while True: input() would be closer to the mark!


Why not make it work in python 2 and 3?

import sys

if sys.version_info.major >= 3: raw_input = input

eval(raw_input())


I would write it as input = raw_input.

Or, better, just use the six package.


Here's a metacircular bytecode interpreter in Clojure: https://github.com/divs1210/Impala

Wrote this for fun a while back.


The Python VM is elegant and it's kind of well documented. It really helped me understand stack machines.


I'm slightly confused about how it's possible for a language to be written in itself.

Say for instance you want to implement "printf". What's stopping you from just using printf?


Well, for one, you will have to implement the memory/system model for the language. It may or may not have access to the host language's "printf" function.

Initially of course, a shortcut way is to leverage as much of the host language's features as possible, then eventually, as you move further into the bootstrap process, you will want to remove reliance on the host language.


Previous discussion about the book: https://news.ycombinator.com/item?id=12170182


Brownie points for writing another Python interpreter in this Python Interpreter :-)


This is really impressive, until you look at, say, SICP's metacircular evaluator, or McCarthy's original implementation of Lisp.

Python by no means has the monopoly in elegant implementations of itself.


I'm a bit put off by your combination of praise and dismissiveness when I think neither are warranted.

This is a pretty standard stack-based virtual machine. It is not particularly elegant, nor is the underlying language designed to be particularly elegant, much less have a monopoly on such. It's designed more for clarity and practicality.

For something on the same lines which is meant to be an elegant stack-based VM, see Forth. The description at http://yosefk.com/blog/my-history-with-forth-stack-machines.... is frequently cited on HN.


I meant it was impressive that it was so simple to implement the python VM in itself, but becomes less impressive when compared to the simplicity and elegance with which you can do similar feats in other languages. I find that point valid.


Lisp will always be a special case. It's too powerful to give other languages a running. It's not quite the same when the language makes it ridiculously easy to build new languages.

What makes this impressive is the medium of expression, like when an artist blows you away with a Biro drawing.

If someone wrote this in assembly in 500 lines or less (if that's even possible), it would be incredible.


I have a different observation.

This VM is meant to match Python semantics, including support for keyword arguments with defaults, lexical scope, and exceptions. Neither the original McCarthy Lisp description which qwertyuiop924 praised, nor first Lisp implementation by Russell, supported those features. The latter two features came with Lisp 1.5, whose implementations are much larger than 500 lines. http://www.softwarepreservation.org/projects/LISP .

And that's okay - a language doesn't require those features. And a language without them, like Forth, can be much more compact as a result.


I wasn't intending to praise it, just show that other languages did similar things more elegantly.

Also, in case you weren't reading carefully, I also pointed to Scheme's metacircular evaluator, which implements lexical scope, continuations (of which exceptions are a subset), and can implement defaults with relatively simple extension.


I was curious so looked up McCarthy's paper. Appendix B has code and pseudo code for minimal interpreter. Takes one page. Primitives are easy to code, too. It would surpise me if that took much larger than 500loc to implement.


Lexical scope, in particular, is very easy to implement. Call/cc or exceptions are a bit tougher, but it can be done. And all defaults take is a bit of extension to the lambda. In fact, defaults can be added atop the language with a macros, as can keyword arguments. Macro expanders are a bit harder to write than the functionality itself, however. Especially if you want a good one.


That's certainly true. It's a good point. It also means that if we're discussing the elegance with which a language can be expressed within itself, Lisp is a reasonable comparison to make, to show the maximum elegance with which this can be done.


How do you judge that a Lisp implementation in Lisp is more elegant than a Forth implementation in Forth?


I didn't say it was the only language that could implement itself elegantly. Admittedly, I've never seen seen a Forth implementation in Forth, so for all I know, it's incredibly ugly. Or so beautiful it could bring tears to the eyes of god. I don't know.


True, you didn't. But you did say it maximized elegance, which means you think a Forth in Forth cannot be more elegant.

In practice, some people adore Forth. Most do not. Some people adore Prolog. Most do not. Relatively more people adore Lisp than either Forth or Prolog.

Such elegance is therefore in the eye of the beholder, not some god.

Forth's elegance is how it well it matches up to most hardware. The inner loop of a Forth interpreter can be as little as a few dozen lines of assembly, and its eval not much longer.


True enough.

shrug

What did you expect me to do? Argue? You made some good points. :-D

Although you do realize the god part was hyperbolic, showing an absurd maximal beauty. I'm not even very religious, it just seemed a fitting representation of such an absurd beauty. I thought that was pretty clear from the context...


While I don't see what it is that you, who has looked into how other languages are implemented, finds impressive.

It looks like a bog-standard stack VM to me. Why do you think it would be harder than this?


It's impressive that it could fit into 500 lines of Python.


Have you looked into many other stack VM implementations? 500 lines of Python seems entirely reasonable.


No, no I haven't. I know a bit about programming languages, not massive amounts.

Now that you've had some time to stare smugly down your nose at me, my point was that it was a testament to the expressiveness of Python, and the simplicity of the VM that that VM was a reasonable thing to write in 500 lines of python. I also noted that it's sligtly less impressive in light of how Scheme was able to do something similar, but in a significantly more compact manner, as the language was more flexable, and simpler.


I am smug for pointing out that I dislike your original smugness. Understood.


I wasn't trying to be smug. Clearly, I came across that way.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: