the namespace iterator now takes a PgfExn parameter like in the old runtime

This commit is contained in:
krangelov
2021-08-31 09:31:06 +02:00
parent aecaa422ec
commit e0288f46dc
6 changed files with 80 additions and 74 deletions

View File

@@ -239,13 +239,21 @@ size_t namespace_size(Namespace<V> map)
} }
template <class V> template <class V>
void namespace_iter(Namespace<V> map, PgfItor* itor) void namespace_iter(Namespace<V> map, PgfItor* itor, PgfExn *err)
{ {
if (map == 0) if (map == 0)
return; return;
namespace_iter(map->left, itor); namespace_iter(map->left, itor, err);
itor->fn(itor, &map->value->name, &(*map->value)); if (err->type != PGF_EXN_NONE)
namespace_iter(map->right, itor); return;
itor->fn(itor, &map->value->name, &(*map->value), err);
if (err->type != PGF_EXN_NONE)
return;
namespace_iter(map->right, itor, err);
if (err->type != PGF_EXN_NONE)
return;
} }
#endif #endif

View File

@@ -159,11 +159,12 @@ PgfText *pgf_abstract_name(PgfPGF* pgf)
} }
PGF_API PGF_API
void pgf_iter_categories(PgfPGF *pgf, PgfItor *itor) void pgf_iter_categories(PgfPGF *pgf, PgfItor *itor, PgfExn *err)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(pgf, READER_SCOPE);
namespace_iter(pgf->get_root<PgfPGFRoot>()->abstract.cats, itor); err->type = PGF_EXN_NONE;
namespace_iter(pgf->get_root<PgfPGFRoot>()->abstract.cats, itor, err);
} }
PGF_API PGF_API
@@ -239,11 +240,12 @@ prob_t pgf_category_prob(PgfPGF *pgf, PgfText *catname)
} }
PGF_API PGF_API
void pgf_iter_functions(PgfPGF *pgf, PgfItor *itor) void pgf_iter_functions(PgfPGF *pgf, PgfItor *itor, PgfExn *err)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(pgf, READER_SCOPE);
namespace_iter(pgf->get_root<PgfPGFRoot>()->abstract.funs, itor); err->type = PGF_EXN_NONE;
namespace_iter(pgf->get_root<PgfPGFRoot>()->abstract.funs, itor, err);
} }
struct PgfItorHelper : PgfItor struct PgfItorHelper : PgfItor
@@ -253,16 +255,17 @@ struct PgfItorHelper : PgfItor
}; };
static static
void iter_by_cat_helper(PgfItor *itor, PgfText *key, void *value) void iter_by_cat_helper(PgfItor *itor, PgfText *key, void *value,
PgfExn *err)
{ {
PgfItorHelper* helper = (PgfItorHelper*) itor; PgfItorHelper* helper = (PgfItorHelper*) itor;
PgfAbsFun* absfun = (PgfAbsFun*) value; PgfAbsFun* absfun = (PgfAbsFun*) value;
if (textcmp(helper->cat, &absfun->type->name) == 0) if (textcmp(helper->cat, &absfun->type->name) == 0)
helper->itor->fn(helper->itor, key, value); helper->itor->fn(helper->itor, key, value, err);
} }
PGF_API PGF_API
void pgf_iter_functions_by_cat(PgfPGF *pgf, PgfText *cat, PgfItor *itor) void pgf_iter_functions_by_cat(PgfPGF *pgf, PgfText *cat, PgfItor *itor, PgfExn *err)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(pgf, READER_SCOPE);
@@ -270,7 +273,9 @@ void pgf_iter_functions_by_cat(PgfPGF *pgf, PgfText *cat, PgfItor *itor)
helper.fn = iter_by_cat_helper; helper.fn = iter_by_cat_helper;
helper.cat = cat; helper.cat = cat;
helper.itor = itor; helper.itor = itor;
namespace_iter(pgf->get_root<PgfPGFRoot>()->abstract.funs, &helper);
err->type = PGF_EXN_NONE;
namespace_iter(pgf->get_root<PgfPGFRoot>()->abstract.funs, &helper, err);
} }
PGF_API PGF_API

View File

@@ -46,11 +46,41 @@ typedef struct {
char text[]; char text[];
} PgfText; } PgfText;
/* All functions that may fail take a reference to a PgfExn structure.
* It is used as follows:
*
* - If everything went fine, the field type will be equal to
* PGF_EXN_NONE and all other fields will be zeroed.
*
* - If the exception was caused by external factors such as an error
* from a system call, then type will be PGF_EXN_SYSTEM_ERROR and
* the field code will contain the value of errno from the C runtime.
*
* - If the exception was caused by factors related to the GF runtime
* itself, then the error type is PGF_EXN_PGF_ERROR, and the field
* msg will contain a newly allocated string which must be freed from
* the caller.
*/
typedef enum {
PGF_EXN_NONE,
PGF_EXN_SYSTEM_ERROR,
PGF_EXN_PGF_ERROR,
PGF_EXN_OTHER_ERROR
} PgfExnType;
typedef struct {
PgfExnType type;
int code;
const char *msg;
} PgfExn;
/* A generic structure to pass a callback for iteration over a collection */ /* A generic structure to pass a callback for iteration over a collection */
typedef struct PgfItor PgfItor; typedef struct PgfItor PgfItor;
struct PgfItor { struct PgfItor {
void (*fn)(PgfItor* self, PgfText* key, void *value); void (*fn)(PgfItor* self, PgfText* key, void *value,
PgfExn *err);
}; };
typedef uintptr_t object; typedef uintptr_t object;
@@ -179,34 +209,6 @@ typedef float prob_t;
typedef struct PgfPGF PgfPGF; typedef struct PgfPGF PgfPGF;
/* All functions that may fail take a reference to a PgfExn structure.
* It is used as follows:
*
* - If everything went fine, the field type will be equal to
* PGF_EXN_NONE and all other fields will be zeroed.
*
* - If the exception was caused by external factors such as an error
* from a system call, then type will be PGF_EXN_SYSTEM_ERROR and
* the field code will contain the value of errno from the C runtime.
*
* - If the exception was caused by factors related to the GF runtime
* itself, then the error type is PGF_EXN_PGF_ERROR, and the field
* msg will contain a newly allocated string which must be freed from
* the caller.
*/
typedef enum {
PGF_EXN_NONE,
PGF_EXN_SYSTEM_ERROR,
PGF_EXN_PGF_ERROR
} PgfExnType;
typedef struct {
PgfExnType type;
int code;
const char *msg;
} PgfExn;
/* Reads a PGF file and keeps it in memory. */ /* Reads a PGF file and keeps it in memory. */
PGF_API_DECL PGF_API_DECL
PgfPGF *pgf_read_pgf(const char* fpath, PgfPGF *pgf_read_pgf(const char* fpath,
@@ -236,7 +238,7 @@ PGF_API_DECL
PgfText *pgf_abstract_name(PgfPGF *pgf); PgfText *pgf_abstract_name(PgfPGF *pgf);
PGF_API_DECL PGF_API_DECL
void pgf_iter_categories(PgfPGF *pgf, PgfItor *itor); void pgf_iter_categories(PgfPGF *pgf, PgfItor *itor, PgfExn *err);
PGF_API_DECL PGF_API_DECL
PgfType pgf_start_cat(PgfPGF *pgf, PgfUnmarshaller *u); PgfType pgf_start_cat(PgfPGF *pgf, PgfUnmarshaller *u);
@@ -248,10 +250,10 @@ PGF_API_DECL
prob_t pgf_category_prob(PgfPGF* pgf, PgfText *catname); prob_t pgf_category_prob(PgfPGF* pgf, PgfText *catname);
PGF_API_DECL PGF_API_DECL
void pgf_iter_functions(PgfPGF *pgf, PgfItor *itor); void pgf_iter_functions(PgfPGF *pgf, PgfItor *itor, PgfExn *err);
PGF_API_DECL PGF_API_DECL
void pgf_iter_functions_by_cat(PgfPGF *pgf, PgfText *cat, PgfItor *itor); void pgf_iter_functions_by_cat(PgfPGF *pgf, PgfText *cat, PgfItor *itor, PgfExn *err);
PGF_API_DECL PGF_API_DECL
PgfType pgf_function_type(PgfPGF *pgf, PgfText *funname, PgfUnmarshaller *u); PgfType pgf_function_type(PgfPGF *pgf, PgfText *funname, PgfUnmarshaller *u);

View File

@@ -187,15 +187,16 @@ categories p =
unsafePerformIO $ do unsafePerformIO $ do
ref <- newIORef [] ref <- newIORef []
(allocaBytes (#size PgfItor) $ \itor -> (allocaBytes (#size PgfItor) $ \itor ->
allocaBytes (#size PgfExn) $ \c_exn ->
bracket (wrapItorCallback (getCategories ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getCategories ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_pgf p) $ \p_pgf -> do withForeignPtr (a_pgf p) $ \p_pgf -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
pgf_iter_categories p_pgf itor pgf_iter_categories p_pgf itor c_exn
cs <- readIORef ref cs <- readIORef ref
return (reverse cs)) return (reverse cs))
where where
getCategories :: IORef [String] -> ItorCallback getCategories :: IORef [String] -> ItorCallback
getCategories ref itor key = do getCategories ref itor key exn = do
names <- readIORef ref names <- readIORef ref
name <- peekText key name <- peekText key
writeIORef ref $ (name : names) writeIORef ref $ (name : names)
@@ -243,15 +244,16 @@ functions p =
unsafePerformIO $ do unsafePerformIO $ do
ref <- newIORef [] ref <- newIORef []
(allocaBytes (#size PgfItor) $ \itor -> (allocaBytes (#size PgfItor) $ \itor ->
allocaBytes (#size PgfExn) $ \c_exn ->
bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_pgf p) $ \p_pgf -> do withForeignPtr (a_pgf p) $ \p_pgf -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
pgf_iter_functions p_pgf itor pgf_iter_functions p_pgf itor c_exn
fs <- readIORef ref fs <- readIORef ref
return (reverse fs)) return (reverse fs))
where where
getFunctions :: IORef [String] -> ItorCallback getFunctions :: IORef [String] -> ItorCallback
getFunctions ref itor key = do getFunctions ref itor key exn = do
names <- readIORef ref names <- readIORef ref
name <- peekText key name <- peekText key
writeIORef ref $ (name : names) writeIORef ref $ (name : names)
@@ -263,15 +265,16 @@ functionsByCat p cat =
ref <- newIORef [] ref <- newIORef []
(withText cat $ \c_cat -> (withText cat $ \c_cat ->
allocaBytes (#size PgfItor) $ \itor -> allocaBytes (#size PgfItor) $ \itor ->
allocaBytes (#size PgfExn) $ \c_exn ->
bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_pgf p) $ \p_pgf -> do withForeignPtr (a_pgf p) $ \p_pgf -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
pgf_iter_functions_by_cat p_pgf c_cat itor pgf_iter_functions_by_cat p_pgf c_cat itor c_exn
fs <- readIORef ref fs <- readIORef ref
return (reverse fs)) return (reverse fs))
where where
getFunctions :: IORef [String] -> ItorCallback getFunctions :: IORef [String] -> ItorCallback
getFunctions ref itor key = do getFunctions ref itor key exn = do
names <- readIORef ref names <- readIORef ref
name <- peekText key name <- peekText key
writeIORef ref $ (name : names) writeIORef ref $ (name : names)

View File

@@ -68,13 +68,13 @@ foreign import ccall "pgf_print_type"
foreign import ccall "pgf_read_type" foreign import ccall "pgf_read_type"
pgf_read_type :: Ptr PgfText -> Ptr PgfUnmarshaller -> IO (StablePtr Type) pgf_read_type :: Ptr PgfText -> Ptr PgfUnmarshaller -> IO (StablePtr Type)
type ItorCallback = Ptr PgfItor -> Ptr PgfText -> IO () type ItorCallback = Ptr PgfItor -> Ptr PgfText -> Ptr PgfExn -> IO ()
foreign import ccall "wrapper" foreign import ccall "wrapper"
wrapItorCallback :: ItorCallback -> IO (FunPtr ItorCallback) wrapItorCallback :: ItorCallback -> IO (FunPtr ItorCallback)
foreign import ccall "pgf_iter_categories" foreign import ccall "pgf_iter_categories"
pgf_iter_categories :: Ptr PgfPGF -> Ptr PgfItor -> IO () pgf_iter_categories :: Ptr PgfPGF -> Ptr PgfItor -> Ptr PgfExn -> IO ()
foreign import ccall "pgf_start_cat" foreign import ccall "pgf_start_cat"
pgf_start_cat :: Ptr PgfPGF -> Ptr PgfUnmarshaller -> IO (StablePtr Type) pgf_start_cat :: Ptr PgfPGF -> Ptr PgfUnmarshaller -> IO (StablePtr Type)
@@ -86,10 +86,10 @@ foreign import ccall "pgf/pgf.h pgf_category_prob"
pgf_category_prob :: Ptr PgfPGF -> Ptr PgfText -> IO (#type prob_t) pgf_category_prob :: Ptr PgfPGF -> Ptr PgfText -> IO (#type prob_t)
foreign import ccall "pgf_iter_functions" foreign import ccall "pgf_iter_functions"
pgf_iter_functions :: Ptr PgfPGF -> Ptr PgfItor -> IO () pgf_iter_functions :: Ptr PgfPGF -> Ptr PgfItor -> Ptr PgfExn -> IO ()
foreign import ccall "pgf_iter_functions_by_cat" foreign import ccall "pgf_iter_functions_by_cat"
pgf_iter_functions_by_cat :: Ptr PgfPGF -> Ptr PgfText -> Ptr PgfItor -> IO () pgf_iter_functions_by_cat :: Ptr PgfPGF -> Ptr PgfText -> Ptr PgfItor -> Ptr PgfExn -> IO ()
foreign import ccall "pgf/pgf.h pgf_function_type" foreign import ccall "pgf/pgf.h pgf_function_type"
pgf_function_type :: Ptr PgfPGF -> Ptr PgfText -> Ptr PgfUnmarshaller -> IO (StablePtr Type) pgf_function_type :: Ptr PgfPGF -> Ptr PgfText -> Ptr PgfUnmarshaller -> IO (StablePtr Type)

View File

@@ -2958,7 +2958,7 @@ PGF_getAbstractName(PGFObject *self, void *closure)
// } // }
static void static void
pgf_collect_cats(PgfItor* fn, PgfText* key, void* value) pgf_collect_cats(PgfItor* fn, PgfText* key, void* value, PgfExn *err)
{ {
PgfText* name = key; PgfText* name = key;
PyPGFClosure* clo = (PyPGFClosure*) fn; PyPGFClosure* clo = (PyPGFClosure*) fn;
@@ -2987,13 +2987,9 @@ PGF_getCategories(PGFObject *self, void *closure)
if (categories == NULL) if (categories == NULL)
return NULL; return NULL;
// GuPool* tmp_pool = gu_local_pool(); PgfExn err;
//
// Create an exception frame that catches all errors.
// GuExn* err = gu_new_exn(tmp_pool);
PyPGFClosure clo = { { pgf_collect_cats }, self, categories }; PyPGFClosure clo = { { pgf_collect_cats }, self, categories };
pgf_iter_categories(self->pgf, &clo.fn); pgf_iter_categories(self->pgf, &clo.fn, &err);
// if (!gu_ok(err)) { // if (!gu_ok(err)) {
// Py_DECREF(categories); // Py_DECREF(categories);
@@ -3026,7 +3022,7 @@ PGF_getCategories(PGFObject *self, void *closure)
// } // }
static void static void
pgf_collect_funs(PgfItor* fn, PgfText* key, void* value) pgf_collect_funs(PgfItor* fn, PgfText* key, void* value, PgfExn *err)
{ {
PgfText* name = key; PgfText* name = key;
PyPGFClosure* clo = (PyPGFClosure*) fn; PyPGFClosure* clo = (PyPGFClosure*) fn;
@@ -3055,13 +3051,9 @@ PGF_getFunctions(PGFObject *self, void *closure)
if (functions == NULL) if (functions == NULL)
return NULL; return NULL;
// GuPool* tmp_pool = gu_local_pool(); PgfExn err;
// Create an exception frame that catches all errors.
// GuExn* err = gu_new_exn(tmp_pool);
PyPGFClosure clo = { { pgf_collect_funs }, self, functions }; PyPGFClosure clo = { { pgf_collect_funs }, self, functions };
pgf_iter_functions(self->pgf, &clo.fn); pgf_iter_functions(self->pgf, &clo.fn, &err);
// if (!gu_ok(err)) { // if (!gu_ok(err)) {
// Py_DECREF(functions); // Py_DECREF(functions);
// gu_pool_free(tmp_pool); // gu_pool_free(tmp_pool);
@@ -3090,13 +3082,9 @@ PGF_functionsByCat(PGFObject* self, PyObject *args)
return NULL; return NULL;
} }
// GuPool *tmp_pool = gu_local_pool(); PgfExn err;
// Create an exception frame that catches all errors.
// GuExn* err = gu_new_exn(tmp_pool);
PyPGFClosure clo = { { pgf_collect_funs }, self, functions }; PyPGFClosure clo = { { pgf_collect_funs }, self, functions };
pgf_iter_functions_by_cat(self->pgf, catname, &clo.fn); pgf_iter_functions_by_cat(self->pgf, catname, &clo.fn, &err);
// if (!gu_ok(err)) { // if (!gu_ok(err)) {
// Py_DECREF(functions); // Py_DECREF(functions);
// gu_pool_free(tmp_pool); // gu_pool_free(tmp_pool);