A lightweight (~5000 LOC) Python interpreter for game engines
github.com
github.com
So I was hoping that PocketPy could do that, but after looking around I can't find any suggestion it's possible, and the API looks very sparse. I'm very happy to see a new Python interpreter built for embedding, but I can't use it. Maybe it can be added easily enough. Keep it up!
If you want to see a scripting language designed from the ground up for embedding, Lua and Squirrel IMO have the most complete APIs (though not the most efficient or easy to use) [2][3], and LuaJIT has even better lua<->C bridging. I've looked at the APIs of many other small scripting languages, and haven't found any others that can do everything that these can.
[1] https://github.com/micropython/micropython/issues/3619
[2] In particular https://www.lua.org/manual/5.4/manual.html#4.5
[3] http://squirrel-lang.org/squirreldoc/reference/embedding_squ...
I think which allows you to write stuff like
const char python_script_foo [] =
{
#embed <foo.py.wav>
};
Would be useful for embedded scripting. Especially for firmware.See [1] for more information (which, btw, also states that #embed is in C23, not C21 (which doesn't exist as far as I know)).
However you might be using "preprocessor directive" in the language semantic phase sense, not in the "preprocessor does it" sense.
[0] http://www.newlisp.org/ [1] http://www.newlisp.org/index.cgi?FAQ
But, the examples are not the kinds of things that I would care about before trying to put this into a game engine. It needs a different set of examples.
* How hard is it to call into a C function from a hook in the py code?
* How hard is it to wrap / unwrap values from their py representation to C?
If you want people to embed the interpreter into an engine then show that it is clean/easy to do the embedding, rather than showing that the interpreter can execute code. I would assume that it executes python, but need to know how well it embeds.
#include "pocketpy.h"
// builtin function that can be called
PyVar test(VM* vm, const pkpy::Args& args) {
printf("called!\n");
return vm->PyStr("hi there");
}
int main(){
// Create a virtual machine
VM* vm = pkpy_new_vm(true);
vm->bind_builtin_func<1>("test", test);
// Hello world!
pkpy_vm_exec(vm, "print(test('Hello world!'))");
// Free the resources
pkpy_delete(vm);
return 0;
}No, it isn't. And it isn't harder, too. They're just different.
Still, I think it's reasonable to say that python is easier to write code for.
I wrote a fairly complete "C" subset as a scripting language for a programmable regression test tool (self-contained test-cases able to evaluate the test-case responses). To make it more friendly I made it dynamically typed (so no need to declare variables) and also added XMLPath syntax support as a type of built-in l-value since the requests/responses it was dealing with were XML/JSON, and this meant you could access any elements of the test request/response(s) as if they were just variables.
Anyhow, "C" may not be what comes to mind for a scripting language, but targeting a group of developers who knew C/C++, and with these minor language tweaks made it very simple to use. My point is that for this type of application I'm not sure that the choice of language makes a huge difference - choose something your target audience is comfortable with, and extend in DSL fashion to make it tightly integrated.
I think it's easier to mentally map concepts between C and Python than Lua
Which means this is not Python but a language that is syntax-compatible ("Python-like"). To prove compatibility something like a (very) extensive set of compatibility tests would have to be written and mentioned in the README. Otherwise it's a minefield of subtle semantic differences.
Still impressive for 5kLOC, of course.
It's amazing for a personal project but not good enough for a serious option.
> Because stack-based virtual machine is used, the performance is hard to reach Lua, where the latter is register-based.
> With the optimizer in place, I think the performance of PkPy can reach 1-2 times that of CPython in the future.
1. source split among numerous files, and
2. partial bootstrapping
affect embeddability? i'm asking in earnest. i thought to embed we (typically) just need a shared lib and to #include a header api.
It's a bit unfortunate that it assumes that you are using Lua's standard library (so you can't use it in cases where you only want to embed Lua-the-language with your own restricted APIs), but other than that it's real nice.
MicroPython [1] is designed for "real" embedding, i.e. in the "embedded development" sense, on microcontrollers and so on and seems quite successful in that niche. Those are often a smaller target than a game running on either a phone/tablet or PC, which would seem to kind of invert things.
Also, micropython, in its hundreds of thousands of lines of code, supports quite a number of microcontrollers and boards; I suspect the core language is smaller, or counting lines used for a single build target would drop it considerably.
Note that to run correctly micropython also needs its python stdlib which is about 15k lines of Python.
It uses https://blueloveth.github.io/pocketpy/lib/pocketpy.wasm which is 766.66 kB - transferred compressed as 240.72 kB
Type `exit()` and press [Enter].
1. What were your motivations for building this?
2. Did you eval any similar projects before writing this one?
3. Can this be compiled to WASM and used in the browser? edit: I see that it already supports WASM!
4. I didn't see this on the README, but does it support IO (either disk or network)?
5. I noticed you linked to byterun. Does this also implement a VM similar to Python? Can I run the bytecode produced from CPython in the pocketpy VM? If so, are there any reasons for that? I thought writing an independent implementation would be faster/easier than a compatible one.
6. Any plans on adding type annotations?
It's _a lot_ of work to make a language like python "superfast", and most of it is really the dynamic typing part. LLVM doesn't do that for you.
Well, actually, I remember being passed on the autobahn by 2CV going well over 200 km/h. That was quite a shocker.
I'd love to see it though.
Option 2 is using C++-style vtables, and putting each value (including primitives) inside an object, with each object inheriting from a common object superclass that has stub methods like __add__, __sub__, __mul__, __div__, __str__, __repr__, etc, etc. You do all the dynamic checks at runtime.
With option 2, I’m sure vtable dispatch is still significantly faster than Python (while substantially slower than static typing).
One could also combine approaches 1 and 2 make the static typing optional.
[1] I realize implementation type inference isn’t trivial.
Type-inference depends on the language. Languages with prepared semantics do it just fine(ML family), it's just that languages like Python and JS didn't consider it from day-1 so we're always stuck with explicit subsets (or extensions like TS, Cython/Mypy) to gain back some order. (I did my thesis work on JS type inference).
In practice, there is nothing that hinders the Python language to be as fast as JS (see PyPy or even faster with Cython annotations). The problem is that C-Python sees the simple FFI as an golden egg (for kind-of good reasons at this point) and this will always limit C-Pythons performance because it touches upon internals that are hard to change out without breaking the FFI contracts.
So, even if one would go about and bolt LLVM onto C-Python we'd still be way behind V8/JSC/Spidermonkey, because
1: The value and FFI model still would hold it back
2: LLVM while awesome at static code, would still have a ton of issues with the dynamic nature of Python. There has been a couple of articles on the new JIT of Erlang that is based on a custom "simple" compiler that is working better than many more "advanced" variations has worked because it's more tailored to the dynamic nature of Erlang rather than try to make a regular JIT make something sane out of Erlang code.
If you want to see improvements to Python there's 4 avenues..
1: Nuitka , this is one(?) guy who's doing a lot of manual engineering work together with some JIT ideas, it probably has a performance ceiling but he seems serious about doing it whilst retaining compatibility. (No idea how it'll fare with the regular series C-Python optimizations).
2: PyPy, Jython and GraalPython. These all depart from mainline C-Python and does deprive you of many C/C++-bound libraries whilst retaining the language semantics. The PyPy team has suggested a new better FFI that I do hope gets adopted by C-Python as the way forward for new modules (and ports of older ones) that would allow PyPy and C-Python to share modules as a transition way.
3: Cython, here you have the original source (iirc?) of the MyPy like annotations and an actual compiler that will specialize and should be mostly compatible with C-Python.
4: Shedskin, this is probably the fastest "Python", but it's a specialized subset that's mendable to full type-inference.
Disclaimer: I worked on Cinder.
Should be expected from the size of codebase but should also be clearly mentioned. And this isn't about just lacking Python's modules. Plain language features are also not there. For example reversing a string with "abcd"[-1::-1] doesn't work. Now there's a features list on README, but not sure whether this is meant to be the comprehensive list this subset has or just a TODO.
Still looking for a replacement for the excellent Jython project [1] on the JVM, which has been fantastic for adding scripting to Java/Scala based projects, but sadly stuck on Python 2.7. I wonder if this could be bolted onto or run inside a JVM somehow (perhaps the WebAssembly version?)
Was I wrong?
Of these two low complexity is probably the main selling point.
Small also implies generally "an elegant engineering solution to a problem that generally may involve layers of accidental complexity" and hence also incites a sense of beauty. Aesthetics can be important for people that are hand crafting their codebases.
I was trying to build my own python interpreter to my project and this saved me a lot of work!
super nice-to-have ask: could you replace the is_prime test on the README from range(2,x) to range(2,int(math.sqrt(x)))?
Exceptions are marked as supported … but `raise Exception()` is a syntax error? (Re-raise and binding exceptions also fails to parse.)