Writing A Python Interpreter For Fun and Profit - Shy Shalom
Writing A Python Interpreter For Fun and Profit - Shy Shalom
Writing a Python
Interpreter for Fun and
Profit
Shy Shalom
Intigua Inc., Israel
[email protected]
Dynamically typed
Interpreted
CPython (python.org)
Pops a,b
Byte-code Adds
Push result
PUSH a
Python text PUSH b
BINARY_ADD
def func(a, b): POP c
c = a + b CPython CPython
print c compiler PUSH c Interpreter
return c PRINT_ITEM
PRINT_NEWLINE
PUSH c
RETURN_VALUE
object
Everything
dict list bool int str
Is an Object
module class method func
a = "Hello!"
b = a
Everything
Is Reference a
object
Counted b
count=2
type=str
"Hello!"
shared_ptr<>
Python CPython byte My
text compiler code Interpreter
void test()
{
Interpreter vm
Ref module = vm.import(R"**(
def pyfunc(a,b):
return a+b
)**");
Ref resObj = module.call("pyfunc", 1, 2);
int result = extract<int>(resObj);
}
int cxxfunc(const string& msg) {
cout << msg;
return 42
}
void test()
{
Interpreter vm
vm.builtins.def("cxxfunc", cxxfunc);
Ref module = vm.import(R"**(
def pyfunc(a,b):
cxxfunc("Hello!")
return a+b
)**");
Ref resObj = module.call("pyfunc", 1, 2);
}
struct Thing {
void action(int a, int b);
};
void test()
{
Interpreter vm
Ref m = vm.builtins
Ref c = m.class_<Thing>("Thing")
.def("action", &Thing::action);
Thing t;
Ref wrap_t = c.wrapInstance(t)
wrap_t.call("action", 1, 2)
}
void unpack(vector<Ref>& v) {}
Template<typename ...Args>
Ref call(const string& name, const Args&&... args) {
vector<Ref> argv;
unpack(argv, args...);
runCode(lookup(name), argv);
}
Ref runCode(ByteCode code, vector<Ref> args) {
Frame f(args)
int pc = 0
while(true) {
byte opcode = code[pc];
byte param = code[pc + 1]
switch(opcode) { runCode()
case PUSH:
f.stack.push(f.vars[param]);
break;
case POP:
f.vars[param] = f.stack.pop(); runCode()
break;
case JUMP_TO:
pc = param
continue;
case CALL_FUNCTION: runCode()
runCode(pop(), popArgs(param))
break;
case RETURN_VALUE:
return frame.pop();
}
pc += 2;
}
}
(boost::intrusive_ptr)
struct Object { struct Ref {
int m_refcount; Object *m_ptr;
}; };
template<typename T>
T extract(Ref ref);
template<>
std::string extract(Ref ref) {
return dynamic_cast<Str>(ref.m_ptr)->v;
}
Why?
• Need scripting but don’t want to write a compiler?
• LUA is too strange, Everybody knows python.