diff --git a/src/runtime/c/pgf/linearizer.cxx b/src/runtime/c/pgf/linearizer.cxx index bd6925165..5cb7d5901 100644 --- a/src/runtime/c/pgf/linearizer.cxx +++ b/src/runtime/c/pgf/linearizer.cxx @@ -300,6 +300,11 @@ void PgfLinearizer::TreeLinNode::linearize(PgfLinearizationOutputIface *out, Pgf } } +ref PgfLinearizer::TreeLinNode::get_lincat(PgfLinearizer *linearizer) +{ + return namespace_lookup(linearizer->concr->lincats, &lin->absfun->type->name); +} + PgfLinearizer::TreeLindefNode::TreeLindefNode(PgfLinearizer *linearizer, PgfText *literal) : TreeNode(linearizer) { @@ -310,10 +315,15 @@ PgfLinearizer::TreeLindefNode::TreeLindefNode(PgfLinearizer *linearizer, PgfText bool PgfLinearizer::TreeLindefNode::resolve(PgfLinearizer *linearizer) { - ref pres = *vector_elem(lincat->res, lin_index); - value = eval_param(&pres->param); - lin_index++; - return true; + if (lincat == 0) { + lin_index++; + return (lin_index <= 1); + } else { + ref pres = *vector_elem(lincat->res, lin_index); + value = eval_param(&pres->param); + lin_index++; + return (lin_index <= lincat->n_lindefs); + } } void PgfLinearizer::TreeLindefNode::check_category(PgfLinearizer *linearizer, PgfText *cat) @@ -366,6 +376,42 @@ void PgfLinearizer::TreeLindefNode::linearize(PgfLinearizationOutputIface *out, } } +ref PgfLinearizer::TreeLindefNode::get_lincat(PgfLinearizer *linearizer) +{ + return lincat; +} + +PgfLinearizer::TreeLinrefNode::TreeLinrefNode(PgfLinearizer *linearizer, TreeNode *root) + : TreeNode(linearizer) +{ + args = root; + lin_index=0; +} + +bool PgfLinearizer::TreeLinrefNode::resolve(PgfLinearizer *linearizer) +{ + ref lincat = args->get_lincat(linearizer); + lin_index++; + return (lincat->n_lindefs+lin_index <= lincat->res->len); +} + +void PgfLinearizer::TreeLinrefNode::linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex) +{ + ref lincat = args->get_lincat(linearizer); + if (lincat != 0) { + size_t i = lincat->n_lindefs*lincat->fields->len + (lin_index-1); + ref> syms = *vector_elem(lincat->seqs, i); + linearize_syms(out, linearizer, syms); + } else { + args->linearize(out, linearizer, lindex); + } +} + +ref PgfLinearizer::TreeLinrefNode::get_lincat(PgfLinearizer *linearizer) +{ + return 0; +} + PgfLinearizer::TreeLitNode::TreeLitNode(PgfLinearizer *linearizer, ref lincat, PgfText *lit) : TreeNode(linearizer) { @@ -395,6 +441,11 @@ void PgfLinearizer::TreeLitNode::linearize(PgfLinearizationOutputIface *out, Pgf out->end_phrase(&lincat->name, fid, field, linearizer->wild); } +ref PgfLinearizer::TreeLitNode::get_lincat(PgfLinearizer *linearizer) +{ + return lincat; +} + PgfLinearizer::PgfLinearizer(ref concr, PgfMarshaller *m) { this->concr = concr; this->m = m; @@ -449,6 +500,8 @@ bool PgfLinearizer::resolve() void PgfLinearizer::reverse_and_label() { + new TreeLinrefNode(this, root); + // Reverse the list of nodes and label them with fid; int fid = 0; TreeNode *node = root; diff --git a/src/runtime/c/pgf/linearizer.h b/src/runtime/c/pgf/linearizer.h index 7dc67d877..7df80cac8 100644 --- a/src/runtime/c/pgf/linearizer.h +++ b/src/runtime/c/pgf/linearizer.h @@ -41,6 +41,7 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller { virtual void linearize_syms(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, ref> syms); virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex)=0; size_t eval_param(PgfLParam *param); + virtual ref get_lincat(PgfLinearizer *linearizer)=0; virtual ~TreeNode() { free(var_values); }; }; @@ -52,6 +53,7 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller { virtual bool resolve(PgfLinearizer *linearizer); virtual void check_category(PgfLinearizer *linearizer, PgfText *cat); virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); + virtual ref get_lincat(PgfLinearizer *linearizer); }; struct TreeLindefNode : public TreeNode { @@ -64,9 +66,20 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller { virtual void check_category(PgfLinearizer *linearizer, PgfText *cat); virtual void linearize_arg(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t d, PgfLParam *r); virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); + virtual ref get_lincat(PgfLinearizer *linearizer); ~TreeLindefNode() { free(literal); }; }; + struct TreeLinrefNode : public TreeNode { + size_t lin_index; + + TreeLinrefNode(PgfLinearizer *linearizer, TreeNode *root); + virtual bool resolve(PgfLinearizer *linearizer); + virtual void check_category(PgfLinearizer *linearizer, PgfText *cat) {}; + virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); + virtual ref get_lincat(PgfLinearizer *linearizer); + }; + struct TreeLitNode : public TreeNode { ref lincat; PgfText *literal; @@ -74,6 +87,7 @@ class PGF_INTERNAL_DECL PgfLinearizer : public PgfUnmarshaller { TreeLitNode(PgfLinearizer *linearizer, ref lincat, PgfText *lit); virtual void check_category(PgfLinearizer *linearizer, PgfText *cat); virtual void linearize(PgfLinearizationOutputIface *out, PgfLinearizer *linearizer, size_t lindex); + virtual ref get_lincat(PgfLinearizer *linearizer); ~TreeLitNode() { free(literal); }; };