From 494f4c8193624dfc893dafffe6def558a81b599a Mon Sep 17 00:00:00 2001 From: krangelov Date: Fri, 10 Dec 2021 09:13:45 +0100 Subject: [PATCH] added linearizeAll --- src/runtime/c/pgf/linearizer.cxx | 88 ++++++++++++++++++++------------ src/runtime/c/pgf/linearizer.h | 8 +-- src/runtime/c/pgf/pgf.cxx | 31 +++++++++++ src/runtime/haskell/PGF2.hsc | 18 ++++++- src/runtime/haskell/PGF2/FFI.hsc | 2 + 5 files changed, 108 insertions(+), 39 deletions(-) diff --git a/src/runtime/c/pgf/linearizer.cxx b/src/runtime/c/pgf/linearizer.cxx index e698ece12..1ae4de8d4 100644 --- a/src/runtime/c/pgf/linearizer.cxx +++ b/src/runtime/c/pgf/linearizer.cxx @@ -4,7 +4,7 @@ PgfLinearizer::TreeNode::TreeNode(PgfLinearizer *linearizer) { - this->next = linearizer->root; + this->next = linearizer->prev; this->next_arg = NULL; this->args = linearizer->args; @@ -17,7 +17,7 @@ PgfLinearizer::TreeNode::TreeNode(PgfLinearizer *linearizer) this->n_hoas_vars = 0; this->hoas_vars = NULL; - linearizer->root= this; + linearizer->prev = this; } void PgfLinearizer::TreeNode::linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, PgfLParam *r) @@ -202,6 +202,11 @@ bool PgfLinearizer::TreeLinNode::resolve(PgfLinearizer *linearizer) ref pres = *vector_elem(lin->res, lin_index); + // Unbind all variables + for (size_t j = 0; j < var_count; j++) { + var_values[j] = (size_t) -1; + } + int i = 0; TreeNode *arg = args; while (arg != NULL) { @@ -265,16 +270,12 @@ bool PgfLinearizer::TreeLinNode::resolve(PgfLinearizer *linearizer) if (arg == NULL) { value = eval_param(&pres->param); - break; - } - - // Unbind all variables - for (size_t j = 0; j < var_count; j++) { - var_values[j] = (size_t) -1; + return true; } } - return (lin_index <= lin->res->len); + lin_index = 0; + return false; } void PgfLinearizer::TreeLinNode::check_category(PgfLinearizer *linearizer, PgfText *cat) @@ -339,13 +340,15 @@ PgfLinearizer::TreeLindefNode::TreeLindefNode(PgfLinearizer *linearizer, PgfText bool PgfLinearizer::TreeLindefNode::resolve(PgfLinearizer *linearizer) { if (lincat == 0) { - lin_index++; - return (lin_index <= 1); + return (lin_index = !lin_index); } else { ref pres = *vector_elem(lincat->res, lin_index); value = eval_param(&pres->param); lin_index++; - return (lin_index <= lincat->n_lindefs); + if (lin_index <= lincat->n_lindefs) + return true; + lin_index = 0; + return false; } } @@ -415,7 +418,10 @@ bool PgfLinearizer::TreeLinrefNode::resolve(PgfLinearizer *linearizer) { ref lincat = args->get_lincat(linearizer); lin_index++; - return (lincat->n_lindefs+lin_index <= lincat->res->len); + if (lincat->n_lindefs+lin_index <= lincat->res->len) + return true; + lin_index = 0; + return false; } void PgfLinearizer::TreeLinrefNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex) @@ -474,8 +480,8 @@ PgfLinearizer::PgfLinearizer(PgfPrintContext *ctxt, ref concr, PgfMars { this->concr = concr; this->m = m; - this->root = NULL; - this->first = NULL; + this->prev = NULL; + this->next = NULL; this->args = NULL; this->capit = CAPIT_NONE; this->pre_stack = NULL; @@ -487,10 +493,16 @@ PgfLinearizer::PgfLinearizer(PgfPrintContext *ctxt, ref concr, PgfMars PgfLinearizer::~PgfLinearizer() { - while (first != NULL) { - TreeNode *next = first->next; - delete first; - first = next; + while (prev != NULL) { + TreeNode *prev_next = prev->next; + delete prev; + prev = prev_next; + } + + while (next != NULL) { + TreeNode *next_next = next->next; + delete next; + next = next_next; } while (pre_stack != NULL) { @@ -512,32 +524,40 @@ PgfLinearizer::~PgfLinearizer() bool PgfLinearizer::resolve() { - TreeNode *node = first; - while (node != NULL) { - if (!node->resolve(this)) - return false; - node = node->next; + for (;;) { + if (!prev || prev->resolve(this)) { + if (next == NULL) + return true; + TreeNode *next_next = next->next; + next->next = prev; + prev = next; + next = next_next; + } else { + TreeNode *prev_next = prev->next; + prev->next = next; + next = prev; + prev = prev_next; + if (prev == NULL) + return false; + } } - - return true; } void PgfLinearizer::reverse_and_label(bool add_linref) { if (add_linref) - new TreeLinrefNode(this, root); + new TreeLinrefNode(this, prev); // Reverse the list of nodes and label them with fid; int fid = 0; - TreeNode *node = root; - while (node != NULL) { - TreeNode *tmp = node->next; + while (prev != NULL) { + TreeNode *tmp = prev->next; - node->fid = fid++; - node->next = first; + prev->fid = fid++; + prev->next = next; - first = node; - node = tmp; + next = prev; + prev = tmp; } } diff --git a/src/runtime/c/pgf/linearizer.h b/src/runtime/c/pgf/linearizer.h index 816a83fb9..166d0cec8 100644 --- a/src/runtime/c/pgf/linearizer.h +++ b/src/runtime/c/pgf/linearizer.h @@ -97,8 +97,8 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller { ~TreeLitNode() { free(literal); }; }; - TreeNode *root; - TreeNode *first; + TreeNode *prev; + TreeNode *next; TreeNode *args; enum CapitState { CAPIT_NONE, CAPIT_FIRST, CAPIT_ALL }; @@ -136,11 +136,11 @@ public: bool resolve(); void reverse_and_label(bool add_linref); void linearize(PgfLinearizationOutputIface *out, size_t lindex) { - root->linearize(out, this, lindex); + prev->linearize(out, this, lindex); flush_pre_stack(out, NULL); } ref get_lincat() { - return root->get_lincat(this); + return prev->get_lincat(this); } ~PgfLinearizer(); diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index 2321cf025..fcbb275c8 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -2015,6 +2015,37 @@ PgfText *pgf_linearize(PgfDB *db, PgfConcrRevision revision, return NULL; } +PGF_API +PgfText **pgf_linearize_all(PgfDB *db, PgfConcrRevision revision, + PgfExpr expr, PgfPrintContext *ctxt, + PgfMarshaller *m, size_t *n_variants, + PgfExn* err) +{ + *n_variants = 0; + PgfText **variants = NULL; + + PGF_API_BEGIN { + DB_scope scope(db, READER_SCOPE); + + ref concr = PgfDB::revision2concr(revision); + PgfLinearizationOutput out; + PgfLinearizer linearizer(ctxt, concr, m); + m->match_expr(&linearizer, expr); + linearizer.reverse_and_label(true); + + while (linearizer.resolve()) { + linearizer.linearize(&out, 0); + variants = (PgfText **) realloc(variants, ((*n_variants)+1)*sizeof(PgfText **)); + variants[(*n_variants)++] = out.get_text(); + } + + return variants; + } PGF_API_END + + free(variants); + return NULL; +} + PGF_API PgfText **pgf_tabular_linearize(PgfDB *db, PgfConcrRevision revision, PgfExpr expr, PgfPrintContext *ctxt, diff --git a/src/runtime/haskell/PGF2.hsc b/src/runtime/haskell/PGF2.hsc index 63c6c5a83..e13dc334b 100644 --- a/src/runtime/haskell/PGF2.hsc +++ b/src/runtime/haskell/PGF2.hsc @@ -622,7 +622,23 @@ linearize c e = -- | Generates all possible linearizations of an expression linearizeAll :: Concr -> Expr -> [String] -linearizeAll lang e = error "TODO: linearizeAll" +linearizeAll c e = + unsafePerformIO $ + withForeignPtr (c_revision c) $ \c_revision -> + bracket (newStablePtr e) freeStablePtr $ \c_e -> + withForeignPtr marshaller $ \m -> + alloca $ \p_n_fields -> + bracket (withPgfExn "linearizeAll" (pgf_linearize_all (c_db c) c_revision c_e nullPtr m p_n_fields)) free $ \c_texts -> do + n_fields <- peek p_n_fields + peekTexts n_fields c_texts + where + peekTexts 0 c_texts = return [] + peekTexts n c_texts = do + c_text <- peek c_texts + text <- peekText c_text + free c_text + texts <- peekTexts (n-1) (c_texts `plusPtr` (#size PgfText*)) + return (text:texts) -- | Generates a table of linearizations for an expression tabularLinearize :: Concr -> Expr -> [(String, String)] diff --git a/src/runtime/haskell/PGF2/FFI.hsc b/src/runtime/haskell/PGF2/FFI.hsc index 7d91dcac7..e3b1a3570 100644 --- a/src/runtime/haskell/PGF2/FFI.hsc +++ b/src/runtime/haskell/PGF2/FFI.hsc @@ -209,6 +209,8 @@ foreign import ccall pgf_has_linearization :: Ptr PgfDB -> Ptr Concr -> Ptr PgfT foreign import ccall pgf_linearize :: Ptr PgfDB -> Ptr Concr -> StablePtr Expr -> Ptr PgfPrintContext -> Ptr PgfMarshaller -> Ptr PgfExn -> IO (Ptr PgfText) +foreign import ccall pgf_linearize_all :: Ptr PgfDB -> Ptr Concr -> StablePtr Expr -> Ptr PgfPrintContext -> Ptr PgfMarshaller -> Ptr CSize -> Ptr PgfExn -> IO (Ptr (Ptr PgfText)) + foreign import ccall pgf_tabular_linearize :: Ptr PgfDB -> Ptr Concr -> StablePtr Expr -> Ptr PgfPrintContext -> Ptr PgfMarshaller -> Ptr CSize -> Ptr PgfExn -> IO (Ptr (Ptr PgfText)) foreign import ccall pgf_bracketed_linearize :: Ptr PgfDB -> Ptr Concr -> StablePtr Expr -> Ptr PgfPrintContext -> Ptr PgfMarshaller -> Ptr PgfLinearizationOutputIface -> Ptr PgfExn -> IO ()