1
0
forked from GitHub/gf-core

added linearizeAll

This commit is contained in:
krangelov
2021-12-10 09:13:45 +01:00
parent 9b0b038984
commit 494f4c8193
5 changed files with 108 additions and 39 deletions

View File

@@ -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<PgfPResult> 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<PgfPResult> 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<PgfConcrLincat> 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<PgfConcr> 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<PgfConcr> 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;
}
}

View File

@@ -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<PgfConcrLincat> get_lincat() {
return root->get_lincat(this);
return prev->get_lincat(this);
}
~PgfLinearizer();

View File

@@ -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<PgfConcr> 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,

View File

@@ -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)]

View File

@@ -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 ()