#define PY_SSIZE_T_CLEAN #include #include #include #include "./expr.h" #include "./ffi.h" #include "./transactions.h" static ConcrObject* Concr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { ConcrObject* self = (ConcrObject *)type->tp_alloc(type, 0); if (self != NULL) { self->grammar = 0; self->concr = 0; } return self; } static void Concr_dealloc(ConcrObject* self) { if (self->grammar != NULL && self->concr != 0) pgf_free_concr_revision(self->grammar->db, self->concr); Py_XDECREF(self->grammar); } static int Concr_init(ConcrObject *self, PyObject *args, PyObject *kwds) { return -1; } static PyObject* Concr_getName(ConcrObject *self, void *closure) { PgfExn err; PgfText *name = pgf_concrete_name(self->grammar->db, self->concr, &err); PyObject *pyname = PyUnicode_FromStringAndSize(name->text, name->size); free(name); return pyname; } /* static PyObject* Concr_getLanguageCode(ConcrObject *self, void *closure) { PgfExn err; PgfText *code = pgf_language_code(self->grammar->db, self->concr, &err); PyObject *pycode = PyUnicode_FromStringAndSize(code->text, code->size); free(code); return pycode; } */ static PyObject* Concr_linearize(ConcrObject* self, PyObject *args) { ExprObject* pyexpr; if (!PyArg_ParseTuple(args, "O!", &pgf_ExprType, &pyexpr)) return NULL; PgfExn err; PgfText *text = pgf_linearize(self->grammar->db, self->concr, (PgfExpr) pyexpr, NULL, &marshaller, &err); if (handleError(err) != PGF_EXN_NONE) { return NULL; } if (text == NULL) { Py_RETURN_NONE; } PyObject* pystr = PyUnicode_FromStringAndSize(text->text, text->size); free(text); return pystr; } static PyGetSetDef Concr_getseters[] = { {"name", (getter)Concr_getName, NULL, "the name of the concrete syntax", }, /* {"languageCode", (getter)Concr_getLanguageCode, NULL, "the language code for this concrete syntax", },*/ {NULL} /* Sentinel */ }; static PyMethodDef Concr_methods[] = { /* {"printName", (PyCFunction)Concr_printName, METH_VARARGS, "Returns the print name of a function or category" }, {"parse", (PyCFunction)Concr_parse, METH_VARARGS | METH_KEYWORDS, "Parses a string and returns an iterator over the abstract trees for this sentence\n\n" "Named arguments:\n" "- sentence (string)\n" "- cat (string); OPTIONAL, default: the startcat of the grammar\n" "- n (int), max. trees; OPTIONAL, default: extract all trees\n" "- heuristics (double >= 0.0); OPTIONAL, default: taken from the flags in the grammar\n" "- callbacks (list of category and callback); OPTIONAL, default: built-in callbacks only for Int, String and Float" }, {"complete", (PyCFunction)Concr_complete, METH_VARARGS | METH_KEYWORDS, "Parses a partial string and returns a list with the top n possible next tokens" "Named arguments:\n" "- sentence (string or a (string,pgf.BIND) tuple. The later indicates that the sentence ends with a BIND token)\n" "- cat (string); OPTIONAL, default: the startcat of the grammar\n" "- prefix (string); OPTIONAL, the prefix of predicted tokens" "- n (int), max. number of predicted tokens" }, {"parseval", (PyCFunction)Concr_parseval, METH_VARARGS, "Computes precision, recall and exact match for the parser on a given abstract tree" }, {"lookupSentence", (PyCFunction)Concr_lookupSentence, METH_VARARGS | METH_KEYWORDS, "Looks up a sentence from the grammar by a sequence of keywords\n\n" "Named arguments:\n" "- sentence (string) or tokens (list of strings)\n" "- cat (string); OPTIONAL, default: the startcat of the grammar\n" "- n (int), max. trees; OPTIONAL, default: extract all trees" },*/ {"linearize", (PyCFunction)Concr_linearize, METH_VARARGS, "Takes an abstract tree and linearizes it to a string" }, /*{"linearizeAll", (PyCFunction)Concr_linearizeAll, METH_VARARGS | METH_KEYWORDS, "Takes an abstract tree and linearizes with all variants" }, {"tabularLinearize", (PyCFunction)Concr_tabularLinearize, METH_VARARGS, "Takes an abstract tree and linearizes it to a table containing all fields" }, {"bracketedLinearize", (PyCFunction)Concr_bracketedLinearize, METH_VARARGS, "Takes an abstract tree and linearizes it to a bracketed string" }, {"bracketedLinearizeAll", (PyCFunction)Concr_bracketedLinearizeAll, METH_VARARGS | METH_KEYWORDS, "Takes an abstract tree and linearizes all variants into bracketed strings" }, {"hasLinearization", (PyCFunction)Concr_hasLinearization, METH_VARARGS, "hasLinearization(f) returns true if the function f has linearization in the concrete syntax" }, {"graphvizParseTree", (PyCFunction)Concr_graphvizParseTree, METH_VARARGS, "Renders an abstract syntax tree as a parse tree in Graphviz format" }, {"lookupMorpho", (PyCFunction)Concr_lookupMorpho, METH_VARARGS, "Looks up a word in the lexicon of the grammar" }, {"lookupCohorts", (PyCFunction)Concr_lookupCohorts, METH_VARARGS, "Takes a sentence and returns all matches for lexical items from the grammar in that sentence" }, {"fullFormLexicon", (PyCFunction)Concr_fullFormLexicon, METH_VARARGS, "Enumerates all words in the lexicon (useful for extracting full form lexicons)" }, {"load", (PyCFunction)Concr_load, METH_VARARGS, "Loads the concrete syntax from a .pgf_c file" }, {"unload", (PyCFunction)Concr_unload, METH_VARARGS, "Unloads the concrete syntax" },*/ {NULL} /* Sentinel */ }; static PyTypeObject pgf_ConcrType = { PyVarObject_HEAD_INIT(NULL, 0) //0, /*ob_size*/ "pgf.Concr", /*tp_name*/ sizeof(ConcrObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Concr_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "concrete syntax", /*tp_doc*/ 0, /*tp_traverse */ 0, /*tp_clear */ 0, /*tp_richcompare */ 0, /*tp_weaklistoffset */ 0, /*tp_iter */ 0, /*tp_iternext */ Concr_methods, /*tp_methods */ 0, /*tp_members */ Concr_getseters, /*tp_getset */ 0, /*tp_base */ 0, /*tp_dict */ 0, /*tp_descr_get */ 0, /*tp_descr_set */ 0, /*tp_dictoffset */ (initproc)Concr_init, /*tp_init */ 0, /*tp_alloc */ (newfunc)Concr_new, /*tp_new */ }; // ---------------------------------------------------------------------------- // PGF: the grammar object static void PGF_dealloc(PGFObject *self) { if (self->db != NULL && self->revision != 0) pgf_free_revision(self->db, self->revision); Py_TYPE(self)->tp_free(self); } static PyObject * PGF_writePGF(PGFObject *self, PyObject *args) { const char *fpath; if (!PyArg_ParseTuple(args, "s", &fpath)) return NULL; PgfExn err; pgf_write_pgf(fpath, self->db, self->revision, &err); if (handleError(err) != PGF_EXN_NONE) { return NULL; } Py_RETURN_NONE; } typedef struct { PgfItor fn; PGFObject *grammar; void *collection; } PyPGFClosure; // static void // pgf_collect_langs_seq(GuMapItor* fn, const void* key, void* value, GuExn* err) // { // PgfConcr* concr = *((PgfConcr**) value); // PyPGFClosure* clo = (PyPGFClosure*) fn; // // gu_buf_push((GuBuf*) clo->collection, PgfConcr*, concr); // } // static PyObject* // PGF_str(PGFObject *self) // { // GuPool* tmp_pool = gu_local_pool(); // // GuExn* err = gu_exn(tmp_pool); // GuStringBuf* sbuf = gu_new_string_buf(tmp_pool); // GuOut* out = gu_string_buf_out(sbuf); // // GuBuf* languages = gu_new_buf(PgfConcr*, tmp_pool); // // PyPGFClosure clo = { { pgf_collect_langs_seq }, self, languages }; // pgf_iter_languages(self->pgf, &clo.fn, err); // // pgf_print(self->pgf, gu_buf_length(languages), // gu_buf_data(languages), // out, err); // // PyObject* pystr = PyString_FromStringAndSize(gu_string_buf_data(sbuf), // gu_string_buf_length(sbuf)); // // gu_pool_free(tmp_pool); // return pystr; // return NULL; // } static PyObject * PGF_getAbstractName(PGFObject *self, void *closure) { PgfExn err; PgfText *txt = pgf_abstract_name(self->db, self->revision, &err); if (handleError(err) != PGF_EXN_NONE) { return NULL; } PyObject *name = PyUnicode_FromStringAndSize(txt->text, txt->size); free(txt); return name; } static void pgf_collect_langs(PgfItor *fn, PgfText *name, PgfConcrRevision concr, PgfExn *err) { PyPGFClosure* clo = (PyPGFClosure*) fn; PyObject* py_name = NULL; PyObject* py_lang = NULL; py_name = PyUnicode_FromStringAndSize(name->text, name->size); if (py_name == NULL) { err->type = PGF_EXN_OTHER_ERROR; goto end; } py_lang = pgf_ConcrType.tp_alloc(&pgf_ConcrType, 0); if (py_lang == NULL) { err->type = PGF_EXN_OTHER_ERROR; goto end; } ((ConcrObject *) py_lang)->concr = concr; ((ConcrObject *) py_lang)->grammar = clo->grammar; Py_INCREF(clo->grammar); if (PyDict_SetItem((PyObject*) clo->collection, py_name, py_lang) != 0) { err->type = PGF_EXN_OTHER_ERROR; goto end; } end: Py_XDECREF(py_lang); Py_XDECREF(py_name); } static PyObject* PGF_getLanguages(PGFObject *self, void *closure) { PyObject* languages = PyDict_New(); if (languages == NULL) return NULL; PgfExn err; PyPGFClosure clo = { { pgf_collect_langs }, self, languages }; pgf_iter_concretes(self->db, self->revision, &clo.fn, &err); if (handleError(err) != PGF_EXN_NONE) { Py_DECREF(languages); return NULL; } PyObject* proxy = PyDictProxy_New(languages); Py_DECREF(languages); return proxy; } static void _collect_cats(PgfItor *fn, PgfText *key, object value, PgfExn *err) { PgfText *name = key; PyPGFClosure *clo = (PyPGFClosure*) fn; PyObject *py_name = PyUnicode_FromStringAndSize(name->text, name->size); if (py_name == NULL) { err->type = PGF_EXN_OTHER_ERROR; return; } if (PyList_Append((PyObject*) clo->collection, py_name) != 0) { err->type = PGF_EXN_OTHER_ERROR; Py_DECREF(py_name); } } static PyObject * PGF_getCategories(PGFObject *self, void *closure) { PyObject *categories = PyList_New(0); if (categories == NULL) return NULL; PgfExn err; PyPGFClosure clo = { { _collect_cats }, self, categories }; pgf_iter_categories(self->db, self->revision, &clo.fn, &err); if (handleError(err) != PGF_EXN_NONE) { Py_DECREF(categories); return NULL; } return categories; } static PyObject * PGF_categoryContext(PGFObject *self, PyObject *args) { const char *s; Py_ssize_t size; if (!PyArg_ParseTuple(args, "s#", &s, &size)) return NULL; PgfText *catname = CString_AsPgfText(s, size); PgfExn err; size_t n_hypos; PgfTypeHypo *hypos = pgf_category_context(self->db, self->revision, catname, &n_hypos, &unmarshaller, &err); FreePgfText(catname); if (handleError(err) != PGF_EXN_NONE) { return NULL; } if (hypos == NULL) { Py_RETURN_NONE; } PyObject *contexts = PyTuple_FromHypos(hypos, n_hypos); for (size_t i = 0; i < n_hypos; i++) { free(hypos[i].cid); Py_DECREF((PyObject *)hypos[i].type); } free(hypos); return contexts; } static TypeObject * PGF_getStartCat(PGFObject *self, void *closure) { PgfExn err; PgfType type = pgf_start_cat(self->db, self->revision, &unmarshaller, &err); if (type == 0) { PyErr_SetString(PGFError, "start category cannot be found"); return NULL; } else if (handleError(err) != PGF_EXN_NONE) { return NULL; } return (TypeObject *)type; } static void _collect_funs(PgfItor *fn, PgfText *key, object value, PgfExn *err) { PgfText *name = key; PyPGFClosure *clo = (PyPGFClosure*) fn; PyObject *py_name = PyUnicode_FromStringAndSize(name->text, name->size); if (py_name == NULL) { err->type = PGF_EXN_OTHER_ERROR; return; } if (PyList_Append((PyObject*) clo->collection, py_name) != 0) { err->type = PGF_EXN_OTHER_ERROR; Py_DECREF(py_name); } } static PyObject * PGF_getFunctions(PGFObject *self, void *closure) { PyObject *functions = PyList_New(0); if (functions == NULL) return NULL; PgfExn err; PyPGFClosure clo = { { _collect_funs }, self, functions }; pgf_iter_functions(self->db, self->revision, &clo.fn, &err); if (handleError(err) != PGF_EXN_NONE) { Py_DECREF(functions); return NULL; } return functions; } static PyObject * PGF_functionsByCat(PGFObject *self, PyObject *args) { const char *s; Py_ssize_t size; if (!PyArg_ParseTuple(args, "s#", &s, &size)) return NULL; PgfText *catname = CString_AsPgfText(s, size); PyObject *functions = PyList_New(0); if (functions == NULL) { FreePgfText(catname); return NULL; } PgfExn err; PyPGFClosure clo = { { _collect_funs }, self, functions }; pgf_iter_functions_by_cat(self->db, self->revision, catname, &clo.fn, &err); FreePgfText(catname); if (handleError(err) != PGF_EXN_NONE) { Py_DECREF(functions); return NULL; } return functions; } static TypeObject * PGF_functionType(PGFObject *self, PyObject *args) { const char *s; Py_ssize_t size; if (!PyArg_ParseTuple(args, "s#", &s, &size)) return NULL; PgfText *funname = CString_AsPgfText(s, size); PgfExn err; PgfType type = pgf_function_type(self->db, self->revision, funname, &unmarshaller, &err); FreePgfText(funname); if (type == 0) { PyErr_Format(PyExc_KeyError, "function '%s' is not defined", s); return NULL; } else if (handleError(err) != PGF_EXN_NONE) { return NULL; } return (TypeObject *)type; } static PyObject * PGF_functionIsConstructor(PGFObject *self, PyObject *args) { const char *s; Py_ssize_t size; if (!PyArg_ParseTuple(args, "s#", &s, &size)) return NULL; PgfText *funname = CString_AsPgfText(s, size); PgfExn err; int isCon = pgf_function_is_constructor(self->db, self->revision, funname, &err); FreePgfText(funname); if (handleError(err) != PGF_EXN_NONE) { return NULL; } return PyBool_FromLong(isCon); } static PyObject * PGF_categoryProbability(PGFObject *self, PyObject *args) { const char *s; Py_ssize_t size; if (!PyArg_ParseTuple(args, "s#", &s, &size)) return NULL; PgfText *catname = CString_AsPgfText(s, size); PgfExn err; prob_t prob = pgf_category_prob(self->db, self->revision, catname, &err); FreePgfText(catname); if (handleError(err) != PGF_EXN_NONE) { return NULL; } double dprob = (double) prob; if (dprob == INFINITY) { PyErr_Format(PyExc_KeyError, "category '%s' is not defined", s); return NULL; } return PyFloat_FromDouble(dprob); } static PyObject * PGF_functionProbability(PGFObject *self, PyObject *args) { const char *s; Py_ssize_t size; if (!PyArg_ParseTuple(args, "s#", &s, &size)) return NULL; PgfText *funname = CString_AsPgfText(s, size); PgfExn err; prob_t prob = pgf_function_prob(self->db, self->revision, funname, &err); FreePgfText(funname); if (handleError(err) != PGF_EXN_NONE) { return NULL; } double dprob = (double) prob; if (dprob == INFINITY) { PyErr_Format(PyExc_KeyError, "function '%s' is not defined", s); return NULL; } return PyFloat_FromDouble(dprob); } static PyObject * PGF_exprProbability(PGFObject *self, PyObject *args) { ExprObject *expr; if (!PyArg_ParseTuple(args, "O!", &pgf_ExprType, &expr)) return NULL; PgfExn err; prob_t prob = pgf_expr_prob(self->db, self->revision, (PgfExpr) expr, &marshaller, &err); if (handleError(err) != PGF_EXN_NONE) { return NULL; } double dprob = (double) prob; return PyFloat_FromDouble(dprob); } static PyGetSetDef PGF_getseters[] = { {"abstractName", (getter)PGF_getAbstractName, NULL, "the abstract syntax name", NULL}, {"languages", (getter)PGF_getLanguages, NULL, "a map containing all concrete languages in the grammar", NULL}, {"categories", (getter)PGF_getCategories, NULL, "a list containing all categories in the grammar", NULL}, {"startCat", (getter)PGF_getStartCat, NULL, "the start category for the grammar", NULL}, {"functions", (getter)PGF_getFunctions, NULL, "a list containing all functions in the grammar", NULL}, {NULL} /* Sentinel */ }; static void pgf_embed_funs(PgfItor* fn, PgfText* name, object value, PgfExn* err) { PyPGFClosure *clo = (PyPGFClosure*) fn; ExprFunObject *pyexpr = (ExprFunObject *) pgf_ExprFunType.tp_alloc(&pgf_ExprFunType, 0); if (pyexpr == NULL) { err->type = PGF_EXN_OTHER_ERROR; return; } pyexpr->name = PyUnicode_FromStringAndSize(name->text, name->size); if (pyexpr->name == NULL) { Py_DECREF(pyexpr); err->type = PGF_EXN_OTHER_ERROR; return; } if (PyModule_AddObject(clo->collection, name->text, (PyObject*) pyexpr) != 0) { Py_DECREF(pyexpr); err->type = PGF_EXN_OTHER_ERROR; } } static PyObject* PGF_embed(PGFObject* self, PyObject *modname) { PyObject *m = PyImport_Import(modname); if (m == NULL) { PyObject *globals = PyEval_GetBuiltins(); if (globals != NULL) { PyObject *exc = PyDict_GetItemString(globals, "ModuleNotFoundError"); if (exc != NULL) { if (PyErr_ExceptionMatches(exc)) { PyErr_Clear(); m = PyImport_AddModuleObject(modname); Py_INCREF(m); } } } } if (m == NULL) return NULL; Py_INCREF(self); if (PyModule_AddObject(m, "__pgf__", (PyObject*) self) != 0) { Py_DECREF(self); Py_DECREF(m); return NULL; } PgfExn err; PyPGFClosure clo = { { pgf_embed_funs }, self, m }; pgf_iter_functions(self->db, self->revision, &clo.fn, &err); if (handleError(err) != PGF_EXN_NONE) { Py_DECREF(m); return NULL; } return m; } static PyMethodDef PGF_methods[] = { {"writePGF", (PyCFunction)PGF_writePGF, METH_VARARGS, "Writes to a PGF file"}, {"categoryContext", (PyCFunction)PGF_categoryContext, METH_VARARGS, "Returns the context for a given category" }, {"functionsByCat", (PyCFunction)PGF_functionsByCat, METH_VARARGS, "Returns the list of functions for a given category" }, {"functionType", (PyCFunction)PGF_functionType, METH_VARARGS, "Returns the type of a function" }, {"functionIsConstructor", (PyCFunction)PGF_functionIsConstructor, METH_VARARGS, "Checks whether a function is a constructor" }, {"categoryProbability", (PyCFunction)PGF_categoryProbability, METH_VARARGS, "Returns the probability of a category" }, {"functionProbability", (PyCFunction)PGF_functionProbability, METH_VARARGS, "Returns the probability of a function" }, {"exprProbability", (PyCFunction)PGF_exprProbability, METH_VARARGS, "Returns the probability of an expression" }, {"checkoutBranch", (PyCFunction)PGF_checkoutBranch, METH_VARARGS, "Switch to a branch" }, {"newTransaction", (PyCFunction)PGF_newTransaction, METH_VARARGS, "Create new transaction" }, {"getGlobalFlag", (PyCFunction)PGF_getGlobalFlag, METH_VARARGS, "Get the value of a global flag" }, {"getAbstractFlag", (PyCFunction)PGF_getAbstractFlag, METH_VARARGS, "Get the value of an abstract flag" }, {"embed", (PyCFunction)PGF_embed, METH_O, "embed(mod_name) creates a Python module with name mod_name, which " "contains one Python object for every abstract function in the grammar. " "The module can be imported to make it easier to construct abstract " "syntax trees." }, {NULL} /* Sentinel */ }; static PyTypeObject pgf_PGFType = { PyVarObject_HEAD_INIT(NULL, 0) //0, /*ob_size*/ "pgf.PGF", /*tp_name*/ sizeof(PGFObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PGF_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, // (reprfunc) PGF_str, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "PGF object", /*tp_doc*/ 0, /*tp_traverse */ 0, /*tp_clear */ 0, /*tp_richcompare */ 0, /*tp_weaklistoffset */ 0, /*tp_iter */ 0, /*tp_iternext */ PGF_methods, /*tp_methods */ 0, /*tp_members */ PGF_getseters, /*tp_getset */ 0, /*tp_base */ 0, /*tp_dict */ 0, /*tp_descr_get */ 0, /*tp_descr_set */ 0, /*tp_dictoffset */ 0, /*tp_init */ 0, /*tp_alloc */ 0, /*tp_new */ }; // ---------------------------------------------------------------------------- // pgf: the module static PGFObject * pgf_readPGF(PyObject *self, PyObject *args) { const char *fpath; if (!PyArg_ParseTuple(args, "s", &fpath)) return NULL; PGFObject *py_pgf = (PGFObject *)pgf_PGFType.tp_alloc(&pgf_PGFType, 0); PgfExn err; py_pgf->db = pgf_read_pgf(fpath, &py_pgf->revision, NULL, &err); if (handleError(err) != PGF_EXN_NONE) { Py_DECREF(py_pgf); return NULL; } return py_pgf; } static PGFObject * pgf_bootNGF(PyObject *self, PyObject *args) { const char *fpath; // pgf const char *npath; // ngf if (!PyArg_ParseTuple(args, "ss", &fpath, &npath)) return NULL; PGFObject *py_pgf = (PGFObject *)pgf_PGFType.tp_alloc(&pgf_PGFType, 0); PgfExn err; py_pgf->db = pgf_boot_ngf(fpath, npath, &py_pgf->revision, NULL, &err); if (handleError(err) != PGF_EXN_NONE) { Py_DECREF(py_pgf); return NULL; } return py_pgf; } static PGFObject * pgf_readNGF(PyObject *self, PyObject *args) { const char *fpath; if (!PyArg_ParseTuple(args, "s", &fpath)) return NULL; PGFObject *py_pgf = (PGFObject *)pgf_PGFType.tp_alloc(&pgf_PGFType, 0); PgfExn err; py_pgf->db = pgf_read_ngf(fpath, &py_pgf->revision, &err); if (handleError(err) != PGF_EXN_NONE) { Py_DECREF(py_pgf); return NULL; } return py_pgf; } static PGFObject * pgf_newNGF(PyObject *self, PyObject *args) { const char *s; Py_ssize_t size; const char *fpath = NULL; if (!PyArg_ParseTuple(args, "s#|s", &s, &size, &fpath)) return NULL; PgfText *absname = CString_AsPgfText(s, size); PGFObject *py_pgf = (PGFObject *)pgf_PGFType.tp_alloc(&pgf_PGFType, 0); PgfExn err; py_pgf->db = pgf_new_ngf(absname, fpath, &py_pgf->revision, &err); FreePgfText(absname); if (handleError(err) != PGF_EXN_NONE) { Py_DECREF(py_pgf); return NULL; } return py_pgf; } static ExprObject * pgf_readExpr(PyObject *self, PyObject *args) { const char *s; Py_ssize_t size; if (!PyArg_ParseTuple(args, "s#", &s, &size)) return NULL; PgfText *input = CString_AsPgfText(s, size); PgfExpr expr = pgf_read_expr(input, &unmarshaller); FreePgfText(input); if (expr == 0) { PyErr_SetString(PGFError, "expression cannot be parsed"); return NULL; } return (ExprObject *)expr; } static PyObject * pgf_showExpr(PyObject *self, PyObject *args) { PyObject *pylist; ExprObject *expr; if (!PyArg_ParseTuple(args, "O!O!", &PyList_Type, &pylist, &pgf_ExprType, &expr)) return NULL; PgfPrintContext *ctxt = PyList_AsPgfPrintContext(pylist); PgfText *s = pgf_print_expr((PgfExpr) expr, ctxt, 0, &marshaller); FreePgfPrintContext(ctxt); PyObject *str = PyUnicode_FromStringAndSize(s->text, s->size); FreePgfText(s); return str; } static TypeObject * pgf_readType(PyObject *self, PyObject *args) { const char *s; Py_ssize_t size; if (!PyArg_ParseTuple(args, "s#", &s, &size)) return NULL; PgfText *input = CString_AsPgfText(s, size); PgfType type = pgf_read_type(input, &unmarshaller); FreePgfText(input); if (type == 0) { PyErr_SetString(PGFError, "type cannot be parsed"); return NULL; } return (TypeObject *)type; } static PyObject * pgf_showType(PyObject *self, PyObject *args) { PyObject *pylist; TypeObject *type; if (!PyArg_ParseTuple(args, "O!O!", &PyList_Type, &pylist, &pgf_TypeType, &type)) return NULL; PgfPrintContext *ctxt = PyList_AsPgfPrintContext(pylist); PgfText *s = pgf_print_type((PgfType) type, ctxt, 0, &marshaller); FreePgfPrintContext(ctxt); PyObject *str = PyUnicode_FromStringAndSize(s->text, s->size); FreePgfText(s); return str; } static PyObject * pgf_mkHypo(PyObject *self, PyObject *args) { PyObject *type; if (!PyArg_ParseTuple(args, "O!", &pgf_TypeType, &type)) return NULL; // HypoObject *hypo = PyObject_New(HypoObject, &pgf_HypoType); // hypo->bind_type = Py_True; // explicit // hypo->cid = PyUnicode_FromStringAndSize("_", 1); // hypo->type = type; // Py_INCREF(hypo->bind_type); // Py_INCREF(hypo->cid); // Py_INCREF(hypo->type); // return hypo; PyObject *tup = PyTuple_New(3); PyTuple_SetItem(tup, 0, Py_True); // explicit PyTuple_SetItem(tup, 1, PyUnicode_FromStringAndSize("_", 1)); PyTuple_SetItem(tup, 2, type); Py_INCREF(Py_True); Py_INCREF(type); return tup; } static PyObject * pgf_mkDepHypo(PyObject *self, PyObject *args) { PyObject *var; PyObject *type; if (!PyArg_ParseTuple(args, "UO!", &var, &pgf_TypeType, &type)) return NULL; // HypoObject *hypo = PyObject_New(HypoObject, &pgf_HypoType); // hypo->bind_type = Py_True; // explicit // hypo->cid = var; // hypo->type = type; // Py_INCREF(hypo->bind_type); // Py_INCREF(hypo->cid); // Py_INCREF(hypo->type); // return hypo; PyObject *tup = PyTuple_New(3); PyTuple_SetItem(tup, 0, Py_True); // explicit PyTuple_SetItem(tup, 1, var); PyTuple_SetItem(tup, 2, type); Py_INCREF(Py_True); Py_INCREF(var); Py_INCREF(type); return tup; } static PyObject * pgf_mkImplHypo(PyObject *self, PyObject *args) { PyObject *var; PyObject *type; if (!PyArg_ParseTuple(args, "UO!", &var, &pgf_TypeType, &type)) return NULL; // HypoObject *hypo = PyObject_New(HypoObject, &pgf_HypoType); // hypo->bind_type = Py_False; // implicit // hypo->cid = var; // hypo->type = type; // Py_INCREF(hypo->bind_type); // Py_INCREF(hypo->cid); // Py_INCREF(hypo->type); // return hypo; PyObject *tup = PyTuple_New(3); PyTuple_SetItem(tup, 0, Py_False); // implicit PyTuple_SetItem(tup, 1, var); PyTuple_SetItem(tup, 2, type); Py_INCREF(Py_True); Py_INCREF(var); Py_INCREF(type); return tup; } static PyMethodDef module_methods[] = { {"readPGF", (void*)pgf_readPGF, METH_VARARGS, "Reads a PGF file into memory"}, {"bootNGF", (void*)pgf_bootNGF, METH_VARARGS, "Reads a PGF file into memory and stores the unpacked data in an NGF file"}, {"readNGF", (void*)pgf_readNGF, METH_VARARGS, "Reads an NGF file into memory"}, {"newNGF", (void*)pgf_newNGF, METH_VARARGS, "Creates a new NGF file with the given name"}, {"readExpr", (void*)pgf_readExpr, METH_VARARGS, "Parses a string as an abstract tree"}, {"showExpr", (void*)pgf_showExpr, METH_VARARGS, "Renders an expression as a string"}, {"readType", (void*)pgf_readType, METH_VARARGS, "Parses a string as an abstract type"}, {"showType", (void*)pgf_showType, METH_VARARGS, "Renders a type as a string"}, {"mkHypo", (void*)pgf_mkHypo, METH_VARARGS, "Creates hypothesis for non-dependent type i.e. A"}, {"mkDepHypo", (void*)pgf_mkDepHypo, METH_VARARGS, "Creates hypothesis for dependent type i.e. (x : A)"}, {"mkImplHypo", (void*)pgf_mkImplHypo, METH_VARARGS, "Creates hypothesis for dependent type with implicit argument i.e. ({x} : A)"}, {NULL, NULL, 0, NULL} /* Sentinel */ }; #define MOD_ERROR_VAL NULL #define MOD_SUCCESS_VAL(val) val #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) #define MOD_DEF(ob, name, doc, methods) \ static struct PyModuleDef moduledef = { \ PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \ ob = PyModule_Create(&moduledef); #define TYPE_READY(type) \ if (PyType_Ready(&type) < 0) \ return MOD_ERROR_VAL; #define ADD_TYPE(name, type) \ if (PyModule_AddObject(m, name, (PyObject *)&type) < 0) { \ Py_DECREF(&type); \ Py_DECREF(m); \ return NULL; \ } #define ADD_TYPE_DIRECT(name, type) \ if (PyModule_AddObject(m, name, (PyObject *)type) < 0) { \ Py_DECREF(type); \ Py_DECREF(m); \ return NULL; \ } MOD_INIT(pgf) { PyObject *m; TYPE_READY(pgf_PGFType); TYPE_READY(pgf_ConcrType); TYPE_READY(pgf_TransactionType); TYPE_READY(pgf_ExprType); TYPE_READY(pgf_ExprAbsType); TYPE_READY(pgf_ExprAppType); TYPE_READY(pgf_ExprLitType); TYPE_READY(pgf_ExprMetaType); TYPE_READY(pgf_ExprFunType); TYPE_READY(pgf_ExprVarType); TYPE_READY(pgf_ExprTypedType); TYPE_READY(pgf_ExprImplArgType); TYPE_READY(pgf_TypeType); MOD_DEF(m, "pgf", "The Runtime for Portable Grammar Format in Python", module_methods); if (m == NULL) return MOD_ERROR_VAL; PGFError = PyErr_NewException("pgf.PGFError", NULL, NULL); ADD_TYPE_DIRECT("PGFError", PGFError); ADD_TYPE("PGF", pgf_PGFType); ADD_TYPE("Concr", pgf_ConcrType); ADD_TYPE("Transaction", pgf_TransactionType); ADD_TYPE("Expr", pgf_ExprType); ADD_TYPE("ExprAbs", pgf_ExprAbsType); ADD_TYPE("ExprApp", pgf_ExprAppType); ADD_TYPE("ExprLit", pgf_ExprLitType); ADD_TYPE("ExprMeta", pgf_ExprMetaType); ADD_TYPE("ExprFun", pgf_ExprFunType); ADD_TYPE("ExprVar", pgf_ExprVarType); ADD_TYPE("ExprTyped", pgf_ExprTypedType); ADD_TYPE("ExprImplArg", pgf_ExprImplArgType); ADD_TYPE("Type", pgf_TypeType); Py_INCREF(Py_True); ADD_TYPE_DIRECT("BIND_TYPE_EXPLICIT", Py_True); Py_INCREF(Py_False); ADD_TYPE_DIRECT("BIND_TYPE_IMPLICIT", Py_False); return MOD_SUCCESS_VAL(m); }