
500 Lines or Less – A Python Interpreter Written in Python - gkst
http://www.aosabook.org/en/500L/a-python-interpreter-written-in-python.html
======
kazinator
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/](http://www.s2.org/~chery/projects/lisp500/)

Doesn't connect:
[http://modeemi.cs.tut.fi/~chery/lisp500/](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](https://github.com/jackpal/lisp5000)

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

~~~
thomasahle
List is inherently easy to parse though.

~~~
kazinator
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, ...

------
notsorandomname
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.

~~~
alehander42
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.

~~~
the_af
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?

------
makmanalp
This is awesome. Also see her talk at Pycon here:
[https://www.youtube.com/watch?v=HVUTjQzESeo](https://www.youtube.com/watch?v=HVUTjQzESeo)

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

~~~
Ivoah
Why not make it work in python 2 and 3?

import sys

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

eval(raw_input())

~~~
witty_username
I would write it as input = raw_input.

Or, better, just use the six package.

------
divs1210
Here's a metacircular bytecode interpreter in Clojure:
[https://github.com/divs1210/Impala](https://github.com/divs1210/Impala)

Wrote this for fun a while back.

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

------
grondilu
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?

~~~
chewxy
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.

------
sndean
Previous discussion about the book:
[https://news.ycombinator.com/item?id=12170182](https://news.ycombinator.com/item?id=12170182)

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

------
qwertyuiop924
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.

~~~
dalke
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....](http://yosefk.com/blog/my-history-with-forth-stack-
machines.html) is frequently cited on HN.

~~~
qwertyuiop924
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.

~~~
jwdunne
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.

~~~
dalke
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](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.

~~~
nickpsecurity
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.

~~~
qwertyuiop924
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.

