Hacker News new | comments | show | ask | jobs | submit login

I found this code very useful. I've been spelunking in CPython and mostly I understand it, and can find my way around.

But ceval.c is another beast entirely, being full of macros and gotos, not to mention being 5000 lines long.

The interpreter loop starts here: https://github.com/python/cpython/blob/master/Python/ceval.c...

So I appreciate seeing the algorithm laid out in Python. In particular it clarifies that there are three separate stacks:

1. call stack

2. block stack for try/except, loops, etc.

3. value stack for evaluating expressions

It also clarifies how generators work, which IMO is very difficult to follow from the C source (i.e. without a design doc to go along).

I wrote about some of my recent work here: https://www.reddit.com/r/oilshell/comments/8b0n6z/opyreadmem...

BTW I have shell scripts running under triple interpretation: CPython, byterun, and OSH itself :) This is just an experiment toward writing my own VM, not for the final product. The release binary doesn't use byterun at all.

EDIT: There is also a companion bytecode compiler that I mention here: http://www.oilshell.org/blog/2018/03/27.html (but I'm not using it, I'm using the one that used to be in the Python 2 stdlib, which is entirely separate from the one used by the interpreter itself.)




Philip Guo has an excellent set of video lectures on CPython internals, which includes an overview of parts of ceval.c: http://pgbovine.net/cpython-internals.htm


I've watched several of those, and they are good. Though for me, playing with code is a different type of learning than watching videos. I should go back and watch the one on ceval though.


There are some changes to ceval in 3.8 that should make it a bit simpler:

  The interpreter loop has been simplified by moving the logic of unrolling the stack of blocks into the compiler. The compiler emits now explicit instructions for adjusting the stack of values and calling the cleaning up code for break, continue and return.
  Removed opcodes BREAK_LOOP, CONTINUE_LOOP, SETUP_LOOP and SETUP_EXCEPT. Added new opcodes ROT_FOUR, BEGIN_FINALLY, CALL_FINALLY and POP_FINALLY. Changed the behavior of END_FINALLY and WITH_CLEANUP_START.
  (Contributed by Mark Shannon, Antoine Pitrou and Serhiy Storchaka in bpo-17611.)
https://docs.python.org/3.8/whatsnew/3.8.html

https://bugs.python.org/issue17611


Wow thanks for the pointer! This is great. I want to move more stuff to compile-time, like name resolution, and moving some control flow to compile time is something I've also wondered about.

I watched a few talks [1] about how C++ exception handling works, and they try to avoid branches/setup blocks in the "happy path". It works a little like longjmp() in C, where you just set the instruction pointer say three function calls down in the stack. But then you have to look up all the exception handlers to run in precomputed tables (which doesn't happen in C). So I wonder if something like that would speed up (my subset of) Python, since exceptions are quite common.

[1] https://www.youtube.com/watch?v=_Ivd3qzgT7U


You may find this useful:

https://leanpub.com/insidethepythonvirtualmachine

I read through it, and the Python-interpreter-in-Python article, and all the documentation of the 'dis' module, while prepping the talk I'm giving at PyCon next month (which is on bytecode). They were all good resources.




Applications are open for YC Winter 2019

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

Search: