#include #include "structmember.h" #include #include #include #include #define PYMETHOD(name, FROM, method, TO) \ static PyObject * name(PyObject *, PyObject *args) { \ try { \ FROM(med) \ return TO(method(med)); \ } \ catch (std::string e) { \ PyErr_SetString(PyExc_Exception, e.c_str()); \ return NULL; \ } \ } #define FROMSTR(v) \ const char *command; \ int len; \ if (!PyArg_ParseTuple(args, "s#", &command, &len)) \ return NULL; \ std::string v = std::string(command, len); \ #define FROMNODE(v) \ PyObject *node; \ if (!PyArg_ParseTuple(args, "O", &node)) \ return NULL; \ Node v = cppifyNode(node); #define FROMLIST(v) \ PyObject *node; \ if (!PyArg_ParseTuple(args, "O", &node)) \ return NULL; \ std::vector v = cppifyNodeList(node); // Convert metadata into python wrapper form [file, ln, ch] PyObject* pyifyMetadata(Metadata m) { PyObject* a = PyList_New(0); PyList_Append(a, Py_BuildValue("s#", m.file.c_str(), m.file.length())); PyList_Append(a, Py_BuildValue("i", m.ln)); PyList_Append(a, Py_BuildValue("i", m.ch)); return a; } // Convert node into python wrapper form // [token=0/astnode=1, val, metadata, args] PyObject* pyifyNode(Node n) { PyObject* a = PyList_New(0); PyList_Append(a, Py_BuildValue("i", n.type == ASTNODE)); PyList_Append(a, Py_BuildValue("s#", n.val.c_str(), n.val.length())); PyList_Append(a, pyifyMetadata(n.metadata)); for (unsigned i = 0; i < n.args.size(); i++) PyList_Append(a, pyifyNode(n.args[i])); return a; } // Convert string into python wrapper form PyObject* pyifyString(std::string s) { return Py_BuildValue("s#", s.c_str(), s.length()); } // Convert list of nodes into python wrapper form PyObject* pyifyNodeList(std::vector n) { PyObject* a = PyList_New(0); for (unsigned i = 0; i < n.size(); i++) PyList_Append(a, pyifyNode(n[i])); return a; } // Convert pyobject int into normal form int cppifyInt(PyObject* o) { int out; if (!PyArg_Parse(o, "i", &out)) err("Argument should be integer", Metadata()); return out; } // Convert pyobject string into normal form std::string cppifyString(PyObject* o) { const char *command; if (!PyArg_Parse(o, "s", &command)) err("Argument should be string", Metadata()); return std::string(command); } // Convert metadata from python wrapper form Metadata cppifyMetadata(PyObject* o) { std::string file = cppifyString(PyList_GetItem(o, 0)); int ln = cppifyInt(PyList_GetItem(o, 1)); int ch = cppifyInt(PyList_GetItem(o, 2)); return Metadata(file, ln, ch); } // Convert node from python wrapper form Node cppifyNode(PyObject* o) { Node n; int isAstNode = cppifyInt(PyList_GetItem(o, 0)); n.type = isAstNode ? ASTNODE : TOKEN; n.val = cppifyString(PyList_GetItem(o, 1)); n.metadata = cppifyMetadata(PyList_GetItem(o, 2)); std::vector args; for (int i = 3; i < PyList_Size(o); i++) { args.push_back(cppifyNode(PyList_GetItem(o, i))); } n.args = args; return n; } //Convert list of nodes into normal form std::vector cppifyNodeList(PyObject* o) { std::vector out; for (int i = 0; i < PyList_Size(o); i++) { out.push_back(cppifyNode(PyList_GetItem(o,i))); } return out; } PYMETHOD(ps_compile, FROMSTR, compile, pyifyString) PYMETHOD(ps_compile_chunk, FROMSTR, compileChunk, pyifyString) PYMETHOD(ps_compile_to_lll, FROMSTR, compileToLLL, pyifyNode) PYMETHOD(ps_compile_chunk_to_lll, FROMSTR, compileChunkToLLL, pyifyNode) PYMETHOD(ps_compile_lll, FROMNODE, compileLLL, pyifyString) PYMETHOD(ps_parse, FROMSTR, parseSerpent, pyifyNode) PYMETHOD(ps_rewrite, FROMNODE, rewrite, pyifyNode) PYMETHOD(ps_rewrite_chunk, FROMNODE, rewriteChunk, pyifyNode) PYMETHOD(ps_pretty_compile, FROMSTR, prettyCompile, pyifyNodeList) PYMETHOD(ps_pretty_compile_chunk, FROMSTR, prettyCompileChunk, pyifyNodeList) PYMETHOD(ps_pretty_compile_lll, FROMNODE, prettyCompileLLL, pyifyNodeList) PYMETHOD(ps_serialize, FROMLIST, serialize, pyifyString) PYMETHOD(ps_deserialize, FROMSTR, deserialize, pyifyNodeList) PYMETHOD(ps_parse_lll, FROMSTR, parseLLL, pyifyNode) static PyMethodDef PyextMethods[] = { {"compile", ps_compile, METH_VARARGS, "Compile code."}, {"compile_chunk", ps_compile_chunk, METH_VARARGS, "Compile code chunk (no wrappers)."}, {"compile_to_lll", ps_compile_to_lll, METH_VARARGS, "Compile code to LLL."}, {"compile_chunk_to_lll", ps_compile_chunk_to_lll, METH_VARARGS, "Compile code chunk to LLL (no wrappers)."}, {"compile_lll", ps_compile_lll, METH_VARARGS, "Compile LLL to EVM."}, {"parse", ps_parse, METH_VARARGS, "Parse serpent"}, {"rewrite", ps_rewrite, METH_VARARGS, "Rewrite parsed serpent to LLL"}, {"rewrite_chunk", ps_rewrite_chunk, METH_VARARGS, "Rewrite parsed serpent to LLL (no wrappers)"}, {"pretty_compile", ps_pretty_compile, METH_VARARGS, "Compile to EVM opcodes"}, {"pretty_compile_chunk", ps_pretty_compile_chunk, METH_VARARGS, "Compile chunk to EVM opcodes (no wrappers)"}, {"pretty_compile_lll", ps_pretty_compile_lll, METH_VARARGS, "Compile LLL to EVM opcodes"}, {"serialize", ps_serialize, METH_VARARGS, "Convert EVM opcodes to bin"}, {"deserialize", ps_deserialize, METH_VARARGS, "Convert EVM bin to opcodes"}, {"parse_lll", ps_parse_lll, METH_VARARGS, "Parse LLL"}, {NULL, NULL, 0, NULL} /* Sentinel */ }; PyMODINIT_FUNC initserpent_pyext(void) { Py_InitModule( "serpent_pyext", PyextMethods ); }