From aa5566f2567b500130e8838c5513ee7106065135 Mon Sep 17 00:00:00 2001 From: Krasimir Angelov Date: Thu, 2 Mar 2023 09:46:19 +0100 Subject: [PATCH] forgot to add probspace.(cxx|h) --- src/runtime/c/pgf/probspace.cxx | 210 ++++++++++++++++++++++++++++++++ src/runtime/c/pgf/probspace.h | 73 +++++++++++ 2 files changed, 283 insertions(+) create mode 100644 src/runtime/c/pgf/probspace.cxx create mode 100644 src/runtime/c/pgf/probspace.h diff --git a/src/runtime/c/pgf/probspace.cxx b/src/runtime/c/pgf/probspace.cxx new file mode 100644 index 000000000..bcfc43b5b --- /dev/null +++ b/src/runtime/c/pgf/probspace.cxx @@ -0,0 +1,210 @@ +#include "data.h" + +static +int entry_cmp(PgfProbspaceEntry *entry1, PgfProbspaceEntry *entry2) +{ + int cmp = textcmp(&(*entry1->cat), &(*entry2->cat)); + if (cmp != 0) + return cmp; + + if (entry1->fun->prob < entry2->fun->prob) + return -1; + else if (entry1->fun->prob > entry2->fun->prob) + return 1; + + return textcmp(&entry1->fun->name, &entry2->fun->name); +} + +static +PgfProbspace probspace_insert(PgfProbspace space, + PgfProbspaceEntry *entry) +{ + if (space == 0) { + return Node::new_node(*entry); + } + + int cmp = entry_cmp(entry,&space->value); + if (cmp < 0) { + PgfProbspace left = probspace_insert(space->left,entry); + space = Node::upd_node(space,left,space->right); + return Node::balanceL(space); + } else if (cmp > 0) { + PgfProbspace right = probspace_insert(space->right,entry); + space = Node::upd_node(space, space->left, right); + return Node::balanceR(space); + } else { + space = Node::upd_node(space,space->left,space->right); + space->value = *entry; + return space; + } +} + +static +PgfProbspace probspace_insert(PgfProbspace space, + ref fun, + ref type) +{ + for (size_t i = 0; i < type->hypos->len; i++) { + ref hypo = vector_elem(type->hypos,i); + space = probspace_insert(space,fun,hypo->type); + } + + PgfProbspaceEntry entry; + entry.cat = ref::from_ptr(&type->name); + entry.fun = fun; + space = probspace_insert(space,&entry); + + return space; +} + +PGF_INTERNAL +PgfProbspace probspace_insert(PgfProbspace space, + ref fun) +{ + return probspace_insert(space,fun,fun->type); +} + +static +PgfProbspace probspace_delete(PgfProbspace space, PgfProbspaceEntry *entry) +{ + if (space == 0) { + return 0; + } + + int cmp = entry_cmp(entry,&space->value); + if (cmp < 0) { + PgfProbspace left = probspace_delete(space->left, entry); + space = Node::upd_node(space,left,space->right); + return Node::balanceR(space); + } else if (cmp > 0) { + PgfProbspace right = probspace_delete(space->right, entry); + space = Node::upd_node(space,space->left,right); + return Node::balanceL(space); + } else { + if (space->left == 0) { + Node::release(space); + return space->right; + } else if (space->right == 0) { + Node::release(space); + return space->left; + } else if (space->left->sz > space->right->sz) { + PgfProbspace node; + PgfProbspace left = Node::pop_last(space->left, &node); + node = Node::upd_node(node, left, space->right); + Node::release(space); + return Node::balanceR(node); + } else { + PgfProbspace node; + PgfProbspace right = Node::pop_first(space->right, &node); + node = Node::upd_node(node, space->left, right); + Node::release(space); + return Node::balanceL(node); + } + } +} + +static +PgfProbspace probspace_delete(PgfProbspace space, + ref fun, + ref type) +{ + for (size_t i = 0; i < type->hypos->len; i++) { + ref hypo = vector_elem(type->hypos,i); + space = probspace_delete(space,fun,hypo->type); + } + + PgfProbspaceEntry entry; + entry.cat = ref::from_ptr(&type->name); + entry.fun = fun; + space = probspace_delete(space,&entry); + + return space; +} + +PGF_INTERNAL +PgfProbspace probspace_delete(PgfProbspace space, ref fun) +{ + return probspace_delete(space,fun,fun->type); +} + +PGF_INTERNAL_DECL +PgfProbspace probspace_delete_by_cat(PgfProbspace space, PgfText *cat, + PgfItor* itor, PgfExn *err) +{ + if (space == 0) { + return 0; + } + + int cmp = textcmp(cat,&(*space->value.cat)); + if (cmp < 0) { + PgfProbspace left = probspace_delete_by_cat(space->left, cat, itor, err); + if (err->type != PGF_EXN_NONE) + return 0; + + return Node::link(space,left,space->right); + } else if (cmp > 0) { + PgfProbspace right = probspace_delete_by_cat(space->right, cat, itor, err); + if (err->type != PGF_EXN_NONE) + return 0; + + return Node::link(space,space->left,right); + } else { + itor->fn(itor, &space->value.fun->name, space->value.fun.as_object(), err); + if (err->type != PGF_EXN_NONE) + return 0; + + PgfProbspace left = probspace_delete_by_cat(space->left, cat, itor, err); + if (err->type != PGF_EXN_NONE) + return 0; + + PgfProbspace right = probspace_delete_by_cat(space->right, cat, itor, err); + if (err->type != PGF_EXN_NONE) + return 0; + + Node::release(space); + + return Node::link(left,right); + } +} + +void probspace_iter(PgfProbspace space, PgfText *cat, + PgfItor* itor, bool all, PgfExn *err) +{ + if (space == 0) + return; + + int cmp = textcmp(cat,&(*space->value.cat)); + if (cmp < 0) { + probspace_iter(space->left, cat, itor, all, err); + if (err->type != PGF_EXN_NONE) + return; + } else if (cmp > 0) { + probspace_iter(space->right, cat, itor, all, err); + if (err->type != PGF_EXN_NONE) + return; + } else { + probspace_iter(space->left, cat, itor, all, err); + if (err->type != PGF_EXN_NONE) + return; + + if (all || space->value.cat == ref::from_ptr(&space->value.fun->type->name)) { + itor->fn(itor, &space->value.fun->name, space->value.fun.as_object(), err); + if (err->type != PGF_EXN_NONE) + return; + } + + probspace_iter(space->right, cat, itor, all, err); + if (err->type != PGF_EXN_NONE) + return; + } +} + +PGF_INTERNAL +void probspace_release(PgfProbspace space) +{ + if (space == 0) + return; + probspace_release(space->left); + probspace_release(space->right); + Node::release(space); +} diff --git a/src/runtime/c/pgf/probspace.h b/src/runtime/c/pgf/probspace.h new file mode 100644 index 000000000..b0c93cf12 --- /dev/null +++ b/src/runtime/c/pgf/probspace.h @@ -0,0 +1,73 @@ +#ifndef PROBSPACE_H +#define PROBSPACE_H + +/* + * The probspace is an index where abstract functions are ordered by + * the tripple of (category,probability,name). Here the category is + * any of the categories used in the type of the function. + * + * When a new function is created, it is inserted first in + * the namespace of functions and after that in the probspace. + * The insertion in the probspace is done once for every category in + * the type of the function. The insertion with a result category is + * always done after the insertion with the argument categories. + * This means that we can easily identify functions which return a given + * category by just checking that: + * + * entry->cat == ref::from_ptr(&fun->type->name); + * + * The later is important when the index is used in tree generation + * and parsing. + * + * The index has the following uses: + * + * - When a category is removed we must also remove all functions that + * use it in their types, otherwise the data will be inconsistant. + * We use the index to find which functions to remove. + * + * - When a lincat is removed we must remove all lins from the same + * language which depend on the lincat. We identify them through + * the abstract types and whence through this index. + * + * - When we do exhaustive or random generation, we need to know + * which functions return a given category. We simply go through + * the index but also check the above condition to distinguish the case + * where the category is consumed from the case where the category is + * returned. In exhaustive generation, to ensure that all results + * are returned in decreasing probability order, we must consume + * functions in the same order. This is the reason why we keep the + * index sorted by probability. + * + * - When a function is removed, we must remove it both from + * the namespace as well as from the probspace. Since the index is + * sorted by function name, as well, we use that to find which entry + * to remove. + * + */ +struct PGF_INTERNAL_DECL PgfProbspaceEntry { + ref cat; + ref fun; +}; + +typedef ref> PgfProbspace; + +PGF_INTERNAL_DECL +PgfProbspace probspace_insert(PgfProbspace space, + ref fun); + +PGF_INTERNAL_DECL +PgfProbspace probspace_delete(PgfProbspace space, + ref fun); + +PGF_INTERNAL_DECL +PgfProbspace probspace_delete_by_cat(PgfProbspace space, PgfText *cat, + PgfItor* itor, PgfExn *err); + +PGF_INTERNAL_DECL +void probspace_iter(PgfProbspace space, PgfText *cat, + PgfItor* itor, bool all, PgfExn *err); + +PGF_INTERNAL_DECL +void probspace_release(PgfProbspace space); + +#endif