Pickora
🐰
A small compiler that can convert Python scripts to pickle bytecode.
Requirements
- Python 3.8+
No third-party modules are required.
Usage
usage: pickora.py [-h] [-d] [-r] [-l {none,python,pickle}] [-o OUTPUT] file
A toy compiler that can convert Python scripts to pickle bytecode.
positional arguments:
file the Python script to compile
optional arguments:
-h, --help show this help message and exit
-d, --dis disassamble compiled pickle bytecode
-r, --eval, --run run the pickle bytecode
-l {none,python,pickle}, --lambda {none,python,pickle}
choose lambda compiling mode
-o OUTPUT, --output OUTPUT
write compiled pickle to file
Lambda syntax is disabled (
--lambda=none) by default.
For exmple, you can run:
python3 pickora.py -d samples/hello.py -o output.pkl
to compile samples/hello.py to output.pkl and show the disassamble result of the compiled pickle bytecode.
But this won't run the pickle for you. If you want you should add -r option, or execute the following command after compile:
python3 -m pickle output.pkl
Special Syntax
RETURN
RETURN is a keyword reserved for specifying pickle.load(s) result. This keyword should only be put in the last statement alone, and you can assign any value / expression to it.
For example, after you compile the following code and use pickle.loads to load the compiled pickle, it returns a string 'INT_MAX=2147483647'.
# source.py
n = pow(2, 31) - 1
RETURN = "INT_MAX=%d" % n
It might look like this:
$ python3 pickora.py source.py -o output.pkl
Saving pickle to output.pkl
$ python3 -m pickle output.pkl
'INT_MAX=2147483647'
Todos
- Operators (
compare,unary,binary,subscript) - Unpacking assignment
- Augmented assignment
- Macros (directly using GLOBAL, OBJECT bytecodes)
- Lambda (I don't want to support normal function, because it seems not "picklic" for me)
- Python bytecode mode
- Pickle bytecode mode
Impracticable
- Function call with kwargs
NEWOBJ_EXonly support type object (it calls__new__)
FAQ
What is pickle?
RTFM.
Why?
It's cool.
Is it useful?
No, not at all, it's definitely useless.
So, is this garbage?
Yep, it's cool garbage.
Would it support syntaxes like if / while / for ?
No. All pickle can do is just simply define a variable or call a function, so this kind of syntax wouldn't exist.
But if you want to do things like:
ans = input("Yes/No: ")
if ans == 'Yes':
print("Great!")
elif ans == 'No':
exit()
It's still achievable! You can rewrite your code to this:
from functools import partial
condition = {'Yes': partial(print, 'Great!'), 'No': exit}
ans = input("Yes/No: ")
condition.get(ans, repr)()
ta-da!
For the loop syntax, you can try to use map / reduce ... .
And yes, you are right, it's functional programming time!