Merge branch 'majestic' of github.com:GrammaticalFramework/gf-core into majestic

This commit is contained in:
krangelov
2021-09-14 09:34:22 +02:00
8 changed files with 203 additions and 28 deletions

View File

@@ -21,10 +21,10 @@ main = do
,TestCase (assertBool "type of z" (eqJust (readType "N") (functionType gr "z")))
,TestCase (assertBool "type of s" (eqJust (readType "N->N") (functionType gr "s")))
,TestCase (assertBool "type of c" (eqJust (readType "N->S") (functionType gr "c")))
,TestCase (assertEqual "category context 1" [] (categoryContext gr "N"))
,TestCase (assertEqual "category context 2" [] (categoryContext gr "S"))
,TestCase (assertEqual "category context 3" [(Explicit,"_",DTyp [] "N" [])] (categoryContext gr "P"))
,TestCase (assertEqual "category context 4" [] (categoryContext gr "X")) -- no such category
,TestCase (assertEqual "category context 1" (Just []) (categoryContext gr "N"))
,TestCase (assertEqual "category context 2" (Just []) (categoryContext gr "S"))
,TestCase (assertEqual "category context 3" (Just [(Explicit,"_",DTyp [] "N" [])]) (categoryContext gr "P"))
,TestCase (assertEqual "category context 4" Nothing (categoryContext gr "X")) -- no such category
,TestCase (assertEqual "function is constructor 1" True (functionIsConstructor gr "s"))
,TestCase (assertEqual "function is constructor 2" True (functionIsConstructor gr "z"))
,TestCase (assertEqual "function is constructor 3" True (functionIsConstructor gr "c"))

View File

@@ -28,16 +28,16 @@ main = do
,TestCase (assertEqual "original categories" ["Float","Int","N","P","S","String"] (categories gr1))
,TestCase (assertEqual "extended categories" ["Float","Int","N","P","Q","S","String"] (categories gr2))
,TestCase (assertEqual "branched categories" ["Float","Int","N","P","R","S","String"] (categories gr3))
,TestCase (assertEqual "Q context" [(Explicit,"x",ty)] (categoryContext gr2 "Q"))
,TestCase (assertEqual "R context" [(Explicit,"x",ty)] (categoryContext gr3 "R"))
,TestCase (assertEqual "Q context" (Just [(Explicit,"x",ty)]) (categoryContext gr2 "Q"))
,TestCase (assertEqual "R context" (Just [(Explicit,"x",ty)]) (categoryContext gr3 "R"))
,TestCase (assertEqual "reduced functions" ["c","s","z"] (functions gr6))
,TestCase (assertEqual "reduced categories" ["Float","Int","N","P","String"] (categories gr6))
,TestCase (assertEqual "old function type" Nothing (functionType gr1 "foo"))
,TestCase (assertEqual "new function type" (Just ty) (functionType gr2 "foo"))
,TestCase (assertEqual "old function prob" (-log 0) (functionProb gr1 "foo"))
,TestCase (assertEqual "new function prob" pi (functionProb gr2 "foo"))
,TestCase (assertEqual "old function prob" (-log 0) (functionProbability gr1 "foo"))
,TestCase (assertEqual "new function prob" pi (functionProbability gr2 "foo"))
]
performMajorGC
if (errors c == 0) && (failures c == 0)

View File

@@ -242,10 +242,10 @@ ExprMeta_init(ExprMetaObject *self, PyObject *args, PyObject *kwds)
return -1;
}
if (lit == NULL) {
self->index = PyLong_FromLong(0);
self->id = PyLong_FromLong(0);
return 0;
} else if (PyLong_Check(lit)) {
self->index = lit;
self->id = lit;
return 0;
} else {
PyErr_SetString(PyExc_TypeError, "invalid argument in ExprMeta_init");
@@ -257,7 +257,7 @@ static PyObject *
ExprMeta_richcompare(ExprMetaObject *t1, ExprMetaObject *t2, int op)
{
bool same = false;
if (PyObject_RichCompareBool(t1->index, t2->index, Py_EQ) != 1) goto done;
if (PyObject_RichCompareBool(t1->id, t2->id, Py_EQ) != 1) goto done;
same = true;
done:
@@ -317,6 +317,96 @@ PyTypeObject pgf_ExprMetaType = {
// ----------------------------------------------------------------------------
static ExprVarObject *
ExprVar_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
{
ExprVarObject* self = (ExprVarObject *)subtype->tp_alloc(subtype, 0);
return self;
}
static int
ExprVar_init(ExprVarObject *self, PyObject *args, PyObject *kwds)
{
PyObject* lit = NULL;
if (!PyArg_ParseTuple(args, "|O", &lit)) {
return -1;
}
if (lit == NULL) {
self->index = PyLong_FromLong(0);
return 0;
} else if (PyLong_Check(lit)) {
self->index = lit;
return 0;
} else {
PyErr_SetString(PyExc_TypeError, "invalid argument in ExprVar_init");
return -1;
}
}
static PyObject *
ExprVar_richcompare(ExprVarObject *t1, ExprVarObject *t2, int op)
{
bool same = false;
if (PyObject_RichCompareBool(t1->index, t2->index, Py_EQ) != 1) goto done;
same = true;
done:
if (op == Py_EQ) {
if (same) Py_RETURN_TRUE; else Py_RETURN_FALSE;
} else if (op == Py_NE) {
if (same) Py_RETURN_FALSE; else Py_RETURN_TRUE;
} else {
PyErr_SetString(PyExc_TypeError, "comparison operation not supported");
Py_RETURN_NOTIMPLEMENTED;
}
}
/* static */
PyTypeObject pgf_ExprVarType = {
PyVarObject_HEAD_INIT(NULL, 0)
//0, /*ob_size*/
"pgf.ExprVar", /*tp_name*/
sizeof(ExprVarObject), /*tp_basicsize*/
0, /*tp_itemsize*/
0, //(destructor)Expr_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, //(hashfunc) Expr_hash, /*tp_hash */
0, //(ternaryfunc) Expr_call, /*tp_call*/
0, //(reprfunc) Expr_str, /*tp_str*/
0, //(getattrofunc) Expr_getattro,/*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"variable", /*tp_doc*/
0, /*tp_traverse */
0, /*tp_clear */
(richcmpfunc) ExprVar_richcompare, /*tp_richcompare */
0, /*tp_weaklistoffset */
0, /*tp_iter */
0, /*tp_iternext */
0, //Expr_methods, /*tp_methods */
0, /*tp_members */
0, //Expr_getseters, /*tp_getset */
&pgf_ExprType, /*tp_base */
0, /*tp_dict */
0, /*tp_descr_get */
0, /*tp_descr_set */
0, /*tp_dictoffset */
(initproc) ExprVar_init, /*tp_init */
0, /*tp_alloc */
(newfunc) ExprVar_new, /*tp_new */
};
// ----------------------------------------------------------------------------
static PyObject *
Type_str(TypeObject *self)
{

View File

@@ -28,13 +28,20 @@ typedef struct {
typedef struct {
PyObject_HEAD
PyObject *index;
PyObject *id;
} ExprMetaObject;
typedef struct {
PyObject_HEAD
PyObject *index;
} ExprVarObject;
extern PyTypeObject pgf_ExprType;
extern PyTypeObject pgf_ExprLitType;
extern PyTypeObject pgf_ExprMetaType;
extern PyTypeObject pgf_ExprVarType;
#endif // PYPGF_EXPR_H_

View File

@@ -38,7 +38,7 @@ PgfExpr elit(PgfUnmarshaller *this, PgfLiteral lit)
PgfExpr emeta(PgfUnmarshaller *this, PgfMetaId meta)
{
ExprMetaObject *pyexpr = (ExprMetaObject *)pgf_ExprMetaType.tp_alloc(&pgf_ExprMetaType, 0);
pyexpr->index = PyLong_FromLong(meta);
pyexpr->id = PyLong_FromLong(meta);
return (PgfExpr) pyexpr;
}
@@ -50,8 +50,9 @@ PgfExpr efun(PgfUnmarshaller *this, PgfText *name)
PgfExpr evar(PgfUnmarshaller *this, int index)
{
PyErr_SetString(PyExc_NotImplementedError, "evar not implemented");
return 0;
ExprVarObject *pyexpr = (ExprVarObject *)pgf_ExprVarType.tp_alloc(&pgf_ExprVarType, 0);
pyexpr->index = PyLong_FromLong(index);
return (PgfExpr) pyexpr;
}
PgfExpr etyped(PgfUnmarshaller *this, PgfExpr expr, PgfType typ)
@@ -153,7 +154,7 @@ PgfUnmarshaller unmarshaller = { &unmarshallerVtbl };
// ----------------------------------------------------------------------------
static PgfText *
PgfText *
PyUnicode_AsPgfText(PyObject *pystr)
{
if (!PyUnicode_Check(pystr)) {
@@ -165,7 +166,7 @@ PyUnicode_AsPgfText(PyObject *pystr)
}
Py_ssize_t size;
const char * enc = PyUnicode_AsUTF8AndSize(pystr, &size);
const char *enc = PyUnicode_AsUTF8AndSize(pystr, &size);
PgfText *ptext = malloc(sizeof(PgfText)+size+1);
memcpy(ptext->text, enc, size+1);
ptext->size = size;
@@ -221,14 +222,21 @@ object match_lit(PgfMarshaller *this, PgfUnmarshaller *u, PgfLiteral lit)
}
}
object match_expr(PgfMarshaller *this, PgfUnmarshaller *u, PgfExpr ex)
object match_expr(PgfMarshaller *this, PgfUnmarshaller *u, PgfExpr expr)
{
ExprObject *expr = (ExprObject *)ex;
PyObject *pyobj = (PyObject *)expr;
if (expr->ob_base.ob_type == &pgf_ExprLitType) { // use PyObject_IsInstance ?
ExprLitObject *elit= (ExprLitObject *)expr;
if (PyObject_TypeCheck(pyobj, &pgf_ExprLitType)) {
ExprLitObject *elit = (ExprLitObject *)expr;
return this->vtbl->match_lit(this, u, (PgfLiteral) elit->value);
} else if (PyObject_TypeCheck(pyobj, &pgf_ExprMetaType)) {
ExprMetaObject *emeta = (ExprMetaObject *)expr;
return u->vtbl->emeta(u, (PgfMetaId) PyLong_AsLong(emeta->id));
} else if (PyObject_TypeCheck(pyobj, &pgf_ExprVarType)) {
ExprVarObject *evar = (ExprVarObject *)expr;
return u->vtbl->evar(u, PyLong_AsLong(evar->index));
} else {
PyErr_SetString(PyExc_TypeError, "unable to match on expression");
return 0;
}
}

View File

@@ -6,6 +6,8 @@
#include <pgf/pgf.h>
PgfText *PyUnicode_AsPgfText(PyObject *pystr);
extern PgfUnmarshaller unmarshaller;
extern PgfMarshaller marshaller;

View File

@@ -1917,6 +1917,10 @@ PGF_categoryContext(PGFObject *self, PyObject *args)
return NULL;
}
if (hypos == NULL) {
Py_RETURN_NONE;
}
PyObject *contexts = PyList_New(n_hypos);
if (contexts == NULL) {
return NULL;
@@ -2537,7 +2541,7 @@ const char *fpath;
return py_pgf;
}
static ExprObject*
static ExprObject *
pgf_readExpr(PyObject *self, PyObject *args)
{
const char *s;
@@ -2559,6 +2563,36 @@ pgf_readExpr(PyObject *self, PyObject *args)
return (ExprObject *)expr;
}
static PyObject *
pgf_showExpr(PyObject *self, PyObject *args)
{
PyObject *pylist;
PyObject *pyexpr;
if (!PyArg_ParseTuple(args, "O!O!", &PyList_Type, &pylist, &pgf_ExprType, &pyexpr))
return NULL;
PgfPrintContext *ctxt = NULL;
for (Py_ssize_t i = PyList_Size(pylist); i > 0 ; i--) {
PyObject *item = PyList_GetItem(pylist, i-1);
if (!PyUnicode_Check(item)) {
PyErr_SetString(PyExc_TypeError, "invalid variable argument in showExpr");
return NULL;
}
PgfText *input = PyUnicode_AsPgfText(item);
// TODO a better way to copy into this->name?
PgfPrintContext *this = (PgfPrintContext *)PyMem_Malloc(sizeof(PgfPrintContext *) + sizeof(PgfText) + input->size + 1);
this->next = ctxt;
memcpy(&this->name, input, sizeof(PgfText) + input->size + 1);
ctxt = this;
}
PgfText *s = pgf_print_expr((PgfExpr) pyexpr, ctxt, 0, &marshaller);
PyObject *str = PyUnicode_FromStringAndSize(s->text, s->size);
free(s);
return str;
}
static TypeObject *
pgf_readType(PyObject *self, PyObject *args)
{
@@ -2590,6 +2624,8 @@ static PyMethodDef module_methods[] = {
"Reads an NGF file into memory"},
{"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"},
{NULL, NULL, 0, NULL} /* Sentinel */
@@ -2636,6 +2672,9 @@ MOD_INIT(pgf)
if (PyType_Ready(&pgf_ExprMetaType) < 0)
return MOD_ERROR_VAL;
if (PyType_Ready(&pgf_ExprVarType) < 0)
return MOD_ERROR_VAL;
if (PyType_Ready(&pgf_TypeType) < 0)
return MOD_ERROR_VAL;
@@ -2670,6 +2709,9 @@ MOD_INIT(pgf)
PyModule_AddObject(m, "ExprMeta", (PyObject *) &pgf_ExprMetaType);
Py_INCREF(&pgf_ExprMetaType);
PyModule_AddObject(m, "ExprVar", (PyObject *) &pgf_ExprVarType);
Py_INCREF(&pgf_ExprVarType);
PyModule_AddObject(m, "Type", (PyObject *) &pgf_TypeType);
Py_INCREF(&pgf_TypeType);

View File

@@ -98,7 +98,7 @@ def test_categoryContext_3(PGF):
assert tup[2] == pgf.readType("N")
def test_categoryContext_4(PGF):
assert PGF.categoryContext("X") == []
assert PGF.categoryContext("X") == None
def test_functionIsConstructor_1(PGF):
assert PGF.functionIsConstructor("s") == True
@@ -222,10 +222,30 @@ def test_readExpr_lstr_str():
# expressions: variables
# ,TestCase (assertEqual "show expression 4" "x" (showExpr ["x"] (EVar 0)))
# ,TestCase (assertEqual "show expression 5" "#1" (showExpr ["x"] (EVar 1)))
# ,TestCase (assertEqual "show expression 6" "z" (showExpr ["z","y","x"] (EVar 0)))
# ,TestCase (assertEqual "show expression 7" "y" (showExpr ["z","y","x"] (EVar 1)))
# def test_readExpr_evar_equality_1():
# assert pgf.readExpr("#0") == pgf.ExprVar()
# assert pgf.readExpr("#0") == pgf.ExprVar(0)
# def test_readExpr_evar_equality_2():
# assert pgf.readExpr("#42") == pgf.ExprVar(42)
def test_readExpr_evar_str_1():
assert str(pgf.ExprVar(0)) == "#0"
def test_readExpr_evar_str_2():
assert str(pgf.ExprVar(42)) == "#42"
def test_showExpr_evar_1():
assert pgf.showExpr(["x"], pgf.ExprVar(0)) == "x"
def test_showExpr_evar_2():
assert pgf.showExpr(["x"], pgf.ExprVar(1)) == "#1"
def test_showExpr_evar_3():
assert pgf.showExpr(["z", "y", "x"], pgf.ExprVar(0)) == "z"
def test_showExpr_evar_4():
assert pgf.showExpr(["z", "y", "x"], pgf.ExprVar(1)) == "y"
# expressions: lambda abstractions
@@ -247,6 +267,12 @@ def test_readExpr_emeta_1():
def test_readExpr_emeta_2():
assert pgf.readExpr("?42") == pgf.ExprMeta(42)
def test_readExpr_emeta_str_1():
assert str(pgf.readExpr("?")) == "?"
def test_readExpr_emeta_str_2():
assert str(pgf.readExpr("?42")) == "?42"
# expressions: typed expressions
# ,TestCase (assertEqual "show expression 18" "<z : N>" (showExpr [] (ETyped (EFun "z") (DTyp [] "N" []))))