🐰
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_EX
only 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.
if
/ while
/ for
?
Would it support syntaxes like 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!