From e0288f46dc7ce40f68d6a83a5a14f378ef177e1e Mon Sep 17 00:00:00 2001 From: krangelov Date: Tue, 31 Aug 2021 09:31:06 +0200 Subject: [PATCH] the namespace iterator now takes a PgfExn parameter like in the old runtime --- src/runtime/c/pgf/namespace.h | 16 ++++++-- src/runtime/c/pgf/pgf.cxx | 21 ++++++---- src/runtime/c/pgf/pgf.h | 66 ++++++++++++++++---------------- src/runtime/haskell/PGF2.hsc | 15 +++++--- src/runtime/haskell/PGF2/FFI.hsc | 8 ++-- src/runtime/python/pypgf.c | 28 ++++---------- 6 files changed, 80 insertions(+), 74 deletions(-) diff --git a/src/runtime/c/pgf/namespace.h b/src/runtime/c/pgf/namespace.h index 38243fb29..1d1be21fa 100644 --- a/src/runtime/c/pgf/namespace.h +++ b/src/runtime/c/pgf/namespace.h @@ -239,13 +239,21 @@ size_t namespace_size(Namespace map) } template -void namespace_iter(Namespace map, PgfItor* itor) +void namespace_iter(Namespace map, PgfItor* itor, PgfExn *err) { if (map == 0) return; - namespace_iter(map->left, itor); - itor->fn(itor, &map->value->name, &(*map->value)); - namespace_iter(map->right, itor); + namespace_iter(map->left, itor, err); + if (err->type != PGF_EXN_NONE) + 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 diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index f69cc48a9..a0e161f25 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -159,11 +159,12 @@ PgfText *pgf_abstract_name(PgfPGF* pgf) } 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); - namespace_iter(pgf->get_root()->abstract.cats, itor); + err->type = PGF_EXN_NONE; + namespace_iter(pgf->get_root()->abstract.cats, itor, err); } PGF_API @@ -239,11 +240,12 @@ prob_t pgf_category_prob(PgfPGF *pgf, PgfText *catname) } 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); - namespace_iter(pgf->get_root()->abstract.funs, itor); + err->type = PGF_EXN_NONE; + namespace_iter(pgf->get_root()->abstract.funs, itor, err); } struct PgfItorHelper : PgfItor @@ -253,16 +255,17 @@ struct PgfItorHelper : PgfItor }; 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; PgfAbsFun* absfun = (PgfAbsFun*) value; 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 -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); @@ -270,7 +273,9 @@ void pgf_iter_functions_by_cat(PgfPGF *pgf, PgfText *cat, PgfItor *itor) helper.fn = iter_by_cat_helper; helper.cat = cat; helper.itor = itor; - namespace_iter(pgf->get_root()->abstract.funs, &helper); + + err->type = PGF_EXN_NONE; + namespace_iter(pgf->get_root()->abstract.funs, &helper, err); } PGF_API diff --git a/src/runtime/c/pgf/pgf.h b/src/runtime/c/pgf/pgf.h index d67e5ae23..36997aa48 100644 --- a/src/runtime/c/pgf/pgf.h +++ b/src/runtime/c/pgf/pgf.h @@ -46,11 +46,41 @@ typedef struct { char text[]; } 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 */ typedef struct PgfItor 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; @@ -179,34 +209,6 @@ typedef float prob_t; 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. */ PGF_API_DECL PgfPGF *pgf_read_pgf(const char* fpath, @@ -236,7 +238,7 @@ PGF_API_DECL PgfText *pgf_abstract_name(PgfPGF *pgf); PGF_API_DECL -void pgf_iter_categories(PgfPGF *pgf, PgfItor *itor); +void pgf_iter_categories(PgfPGF *pgf, PgfItor *itor, PgfExn *err); PGF_API_DECL PgfType pgf_start_cat(PgfPGF *pgf, PgfUnmarshaller *u); @@ -248,10 +250,10 @@ PGF_API_DECL prob_t pgf_category_prob(PgfPGF* pgf, PgfText *catname); PGF_API_DECL -void pgf_iter_functions(PgfPGF *pgf, PgfItor *itor); +void pgf_iter_functions(PgfPGF *pgf, PgfItor *itor, PgfExn *err); 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 PgfType pgf_function_type(PgfPGF *pgf, PgfText *funname, PgfUnmarshaller *u); diff --git a/src/runtime/haskell/PGF2.hsc b/src/runtime/haskell/PGF2.hsc index a59cf37cd..b51da3740 100644 --- a/src/runtime/haskell/PGF2.hsc +++ b/src/runtime/haskell/PGF2.hsc @@ -187,15 +187,16 @@ categories p = unsafePerformIO $ do ref <- newIORef [] (allocaBytes (#size PgfItor) $ \itor -> + allocaBytes (#size PgfExn) $ \c_exn -> bracket (wrapItorCallback (getCategories ref)) freeHaskellFunPtr $ \fptr -> withForeignPtr (a_pgf p) $ \p_pgf -> do (#poke PgfItor, fn) itor fptr - pgf_iter_categories p_pgf itor + pgf_iter_categories p_pgf itor c_exn cs <- readIORef ref return (reverse cs)) where getCategories :: IORef [String] -> ItorCallback - getCategories ref itor key = do + getCategories ref itor key exn = do names <- readIORef ref name <- peekText key writeIORef ref $ (name : names) @@ -243,15 +244,16 @@ functions p = unsafePerformIO $ do ref <- newIORef [] (allocaBytes (#size PgfItor) $ \itor -> + allocaBytes (#size PgfExn) $ \c_exn -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> withForeignPtr (a_pgf p) $ \p_pgf -> do (#poke PgfItor, fn) itor fptr - pgf_iter_functions p_pgf itor + pgf_iter_functions p_pgf itor c_exn fs <- readIORef ref return (reverse fs)) where getFunctions :: IORef [String] -> ItorCallback - getFunctions ref itor key = do + getFunctions ref itor key exn = do names <- readIORef ref name <- peekText key writeIORef ref $ (name : names) @@ -263,15 +265,16 @@ functionsByCat p cat = ref <- newIORef [] (withText cat $ \c_cat -> allocaBytes (#size PgfItor) $ \itor -> + allocaBytes (#size PgfExn) $ \c_exn -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> withForeignPtr (a_pgf p) $ \p_pgf -> do (#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 return (reverse fs)) where getFunctions :: IORef [String] -> ItorCallback - getFunctions ref itor key = do + getFunctions ref itor key exn = do names <- readIORef ref name <- peekText key writeIORef ref $ (name : names) diff --git a/src/runtime/haskell/PGF2/FFI.hsc b/src/runtime/haskell/PGF2/FFI.hsc index d16f93fca..d52445c56 100644 --- a/src/runtime/haskell/PGF2/FFI.hsc +++ b/src/runtime/haskell/PGF2/FFI.hsc @@ -68,13 +68,13 @@ foreign import ccall "pgf_print_type" foreign import ccall "pgf_read_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" wrapItorCallback :: ItorCallback -> IO (FunPtr ItorCallback) 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" 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) 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" - 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" pgf_function_type :: Ptr PgfPGF -> Ptr PgfText -> Ptr PgfUnmarshaller -> IO (StablePtr Type) diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c index 142a66495..eb6845bdb 100644 --- a/src/runtime/python/pypgf.c +++ b/src/runtime/python/pypgf.c @@ -2958,7 +2958,7 @@ PGF_getAbstractName(PGFObject *self, void *closure) // } 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; PyPGFClosure* clo = (PyPGFClosure*) fn; @@ -2987,13 +2987,9 @@ PGF_getCategories(PGFObject *self, void *closure) if (categories == NULL) return NULL; - // GuPool* tmp_pool = gu_local_pool(); - // - // Create an exception frame that catches all errors. - // GuExn* err = gu_new_exn(tmp_pool); - + PgfExn err; 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)) { // Py_DECREF(categories); @@ -3026,7 +3022,7 @@ PGF_getCategories(PGFObject *self, void *closure) // } 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; PyPGFClosure* clo = (PyPGFClosure*) fn; @@ -3055,13 +3051,9 @@ PGF_getFunctions(PGFObject *self, void *closure) if (functions == NULL) return NULL; - // GuPool* tmp_pool = gu_local_pool(); - - // Create an exception frame that catches all errors. - // GuExn* err = gu_new_exn(tmp_pool); - + PgfExn err; 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)) { // Py_DECREF(functions); // gu_pool_free(tmp_pool); @@ -3090,13 +3082,9 @@ PGF_functionsByCat(PGFObject* self, PyObject *args) return NULL; } - // GuPool *tmp_pool = gu_local_pool(); - - // Create an exception frame that catches all errors. - // GuExn* err = gu_new_exn(tmp_pool); - + PgfExn err; 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)) { // Py_DECREF(functions); // gu_pool_free(tmp_pool);