Пример #1
0
bool Or::transform(
    MergeGraph&        merge_graph,
    const CallFactory& call_factory,
    NodeReporter       reporter
)
{
    node_p me = shared_from_this();
    bool result = false;

    node_list_t to_remove;
    BOOST_FOREACH(const node_p& child, children()) {
        if (child->is_literal()) {
            if (! child->eval(EvalContext()).empty()) {
                node_p replacement = c_true;
                merge_graph.replace(me, replacement);
                return true;
            }
            else {
                to_remove.push_back(child);
            }
        }
    }

    BOOST_FOREACH(const node_p& child, to_remove) {
        result = true;
        merge_graph.remove(me, child);
    }
Пример #2
0
TEST_F(TestMergeGraph, DoubleReplace)
{
    MergeGraph g;
    node_p n = parse("(A (B (C)))");
    node_p m = parse("(B (C))");
    node_p m2 = parse("(A)");
    node_p m3 = parse("(B)");
    size_t n_i = 0;
    size_t m_i = 0;

    EXPECT_NO_THROW(n_i = g.add_root(n));
    EXPECT_NO_THROW(m_i = g.add_root(m));

    EXPECT_NO_THROW(g.replace(m, m2));
    EXPECT_NO_THROW(g.replace(m2, m3));

    EXPECT_EQ("(A (B))", g.root(n_i)->to_s());
    EXPECT_EQ("(B)",     g.root(m_i)->to_s());

    EXPECT_TRUE(g.write_validation_report(cerr));

    EXPECT_EQ(m3, g.find_transform(m));
    g.clear_transform_record();
    EXPECT_THROW(g.find_transform(m), IronBee::enoent);
}
Пример #3
0
void pre_eval_graph(
    reporter_t  reporter,
    MergeGraph& graph,
    Environment environment
)
{
    bfs_down(
        graph.roots().first, graph.roots().second,
        boost::make_function_output_iterator(
            pre_eval_graph_helper(reporter, environment)
        )
    );
}
Пример #4
0
TEST_F(TestMergeGraph, KnownRoot)
{
    MergeGraph g;
    node_p n = parse("(A (B (C)) (B (C)))");
    node_p m = parse("(B (C))");
    node_p backup_m = m;

    EXPECT_NO_THROW(g.add_root(n));
    EXPECT_NO_THROW(g.add_root(m));
    EXPECT_NE(backup_m, m);

    EXPECT_TRUE(g.write_validation_report(cerr));
}
Пример #5
0
TEST_F(TestMergeGraph, Easy)
{
    node_p n = parse("(A (B (C)))");
    MergeGraph g;
    size_t n_i = 0;

    EXPECT_TRUE(g.empty());
    EXPECT_NO_THROW(n_i = g.add_root(n));
    EXPECT_EQ(n, g.root(n_i));
    EXPECT_EQ(1UL, g.root_indices(n).size());
    EXPECT_EQ(n_i, *g.root_indices(n).begin());
    EXPECT_FALSE(g.empty());

    EXPECT_TRUE(g.write_validation_report(cerr));
}
Пример #6
0
TEST_F(TestMergeGraph, Basic)
{
    node_p n = parse("(A (B (C)) (B (C)))");
    MergeGraph g;
    size_t n_i = 0;

    EXPECT_NO_THROW(n_i = g.add_root(n));
    EXPECT_EQ(n, g.root(n_i));
    EXPECT_EQ(1UL, g.root_indices(n).size());
    EXPECT_EQ(n_i, *g.root_indices(n).begin());

    EXPECT_EQ(3UL, num_descendants(n));

    EXPECT_TRUE(g.write_validation_report(cerr));
}
Пример #7
0
TEST_F(TestMergeGraph, ReplaceLoop)
{
    MergeGraph g;
    node_p n = parse("(A (B (C)))");
    node_p m = parse("(B (C))");
    node_p m2 = parse("(A (B (C)))");
    size_t n_i = 0;
    size_t m_i = 0;

    EXPECT_NO_THROW(n_i = g.add_root(n));
    EXPECT_NO_THROW(m_i = g.add_root(m));

    EXPECT_TRUE(g.write_validation_report(cerr));
    EXPECT_NO_THROW(g.replace(m, m2));
    EXPECT_EQ("(A (A (B (C))))", g.root(n_i)->to_s());
    EXPECT_EQ("(A (B (C)))",     g.root(m_i)->to_s());

    EXPECT_TRUE(g.write_validation_report(cerr));
    EXPECT_EQ(m2, g.find_transform(m));
}
Пример #8
0
TEST_F(TestMergeGraph, AddLoop)
{
    MergeGraph g;
    node_p n = parse("(A (B (C)))");
    node_p m = parse("(B (C))");
    node_p o = parse("(B (C))");
    size_t n_i = 0;
    size_t m_i = 0;

    EXPECT_NO_THROW(n_i = g.add_root(n));
    EXPECT_NO_THROW(m_i = g.add_root(m));

    EXPECT_NO_THROW(g.add(m, o));
    EXPECT_EQ("(A (B (C) (B (C))))", g.root(n_i)->to_s());
    EXPECT_EQ("(B (C) (B (C)))",    g.root(m_i)->to_s());

    EXPECT_TRUE(g.write_validation_report(cerr));
}
Пример #9
0
bool Template::transform(
    MergeGraph&        merge_graph,
    const CallFactory& call_factory,
    Environment        environment,
    NodeReporter       reporter
)
{
    node_p me = shared_from_this();

    // Construct map of argument name to children.
    typedef map<string, node_p> arg_map_t;
    arg_map_t arg_map;

    {
        template_arg_list_t::const_iterator arg_i = m_args.begin();
        node_list_t::const_iterator children_i = children().begin();

        while (arg_i != m_args.end() && children_i != children().end()) {
            arg_map.insert(make_pair(*arg_i, tree_copy(*children_i, call_factory)));
            ++arg_i;
            ++children_i;
        }

        if (arg_i != m_args.end() || children_i != children().end()) {
            reporter.error(
                "Number of children not equal to number of arguments.  "
                "Should have been caught in validation."
            );
            return false;
        }
    }

    // Construct copy of body to replace me with.
    node_p replacement = tree_copy(m_body, call_factory);

    // Special case.  Body might be itself a ref node.
    {
        string top_ref = template_ref(m_body);
        if (! top_ref.empty()) {
            arg_map_t::const_iterator arg_i = arg_map.find(top_ref);
            if (arg_i == arg_map.end()) {
                reporter.error(
                    "Reference to \"" + top_ref + "\" but not such "
                    "argument to template " + name() = "."
                );
                return false;
            }

            node_p replacement = arg_i->second;
            merge_graph.replace(me, replacement);
            merge_graph.add_origin(
                replacement,
                m_origin_prefix + m_body->to_s()
            );
            return true;
        }
    }

    // Replace arguments.
    typedef map<node_p, string> origin_info_t;
    origin_info_t origin_info;
    {
        node_list_t todo;
        todo.push_back(replacement);

        while (! todo.empty()) {
            node_p n = todo.front();
            todo.pop_front();

            // Enforce that we are working on a tree, not a dag.
            assert(n->parents().size() <= 1);

            string ref_param = template_ref(n);
            if (! ref_param.empty()) {
                arg_map_t::const_iterator arg_i = arg_map.find(ref_param);
                if (arg_i == arg_map.end()) {
                    reporter.error(
                        "Reference to \"" + ref_param + "\" but not such "
                        "argument to template " + name() = "."
                    );
                    continue;
                }

                node_p arg = arg_i->second;
                n->parents().front().lock()->replace_child(n, arg);
                origin_info[arg] = m_origin_prefix + n->to_s();
            }
            else {
                copy(
                    n->children().begin(), n->children().end(),
                    back_inserter(todo)
                );
                origin_info[n] = m_origin_prefix + n->to_s();
            }
        }
    }

    // Replace with body.
    merge_graph.replace(me, replacement);
    BOOST_FOREACH(origin_info_t::const_reference v, origin_info) {
        merge_graph.add_origin(v.first, v.second);
    }
Пример #10
0
TEST_F(TestMergeGraph, MultipleRoots)
{
    MergeGraph g;
    node_p n = parse("(A (B (C)) (B (C)))");
    size_t n_i = 0;
    node_p m = parse("(C (B (C)))");
    size_t m_i = 0;

    EXPECT_NO_THROW(n_i = g.add_root(n));
    EXPECT_NO_THROW(m_i = g.add_root(m));
    EXPECT_EQ(n, g.root(n_i));
    EXPECT_EQ(1UL, g.root_indices(n).size());
    EXPECT_EQ(n_i, *g.root_indices(n).begin());
    EXPECT_EQ(m, g.root(m_i));
    EXPECT_EQ(1UL, g.root_indices(m).size());
    EXPECT_EQ(m_i, *g.root_indices(m).begin());

    EXPECT_EQ(2UL, g.size());
    EXPECT_EQ(n, *g.roots().first);
    EXPECT_EQ(m, *boost::next(g.roots().first));

    EXPECT_TRUE(g.write_validation_report(cerr));
}
Пример #11
0
TEST_F(TestMergeGraph, Remove)
{
    MergeGraph g;
    node_p n = parse("(A (B (C)))");
    node_p m = parse("(B (C))");
    size_t n_i = 0;
    size_t m_i = 0;

    EXPECT_NO_THROW(n_i = g.add_root(n));
    EXPECT_NO_THROW(m_i = g.add_root(m));

    node_p to_remove = parse("(C)");
    EXPECT_NO_THROW(g.remove(m, to_remove));
    EXPECT_EQ("(A (B))", g.root(n_i)->to_s());
    EXPECT_EQ("(B)",    g.root(m_i)->to_s());

    EXPECT_TRUE(g.write_validation_report(cerr));

    EXPECT_NO_THROW(g.remove(n, m));
    EXPECT_EQ(2UL, g.size());
    EXPECT_EQ("(A)", g.root(n_i)->to_s());
    EXPECT_EQ("(B)", g.root(m_i)->to_s());

    EXPECT_TRUE(g.write_validation_report(cerr));

    EXPECT_FALSE(g.find_transform(to_remove));
}
Пример #12
0
bool Template::transform(
    MergeGraph&        merge_graph,
    const CallFactory& call_factory,
    NodeReporter       reporter
)
{
    node_p me = shared_from_this();

    // Construct map of argument name to children.
    typedef map<string, node_p> arg_map_t;
    arg_map_t arg_map;

    {
        template_arg_list_t::const_iterator arg_i = m_args.begin();
        node_list_t::const_iterator children_i = children().begin();

        while (arg_i != m_args.end() && children_i != children().end()) {
            arg_map.insert(make_pair(*arg_i, *children_i));
            ++arg_i;
            ++children_i;
        }

        if (arg_i != m_args.end() || children_i != children().end()) {
            reporter.error(
                "Number of children not equal to number of arguments.  "
                "Should have been caught in validation."
            );
            return false;
        }
    }

    // Construct copy of body to replace me with.
    node_p replacement = tree_copy(m_body, call_factory);

    // Special case.  Body might be itself a ref node.
    {
        string top_ref = template_ref(m_body);
        if (! top_ref.empty()) {
            arg_map_t::const_iterator arg_i = arg_map.find(top_ref);
            if (arg_i == arg_map.end()) {
                reporter.error(
                    "Reference to \"" + top_ref + "\" but not such "
                    "argument to template " + name() = "."
                );
                return false;
            }

            node_p replacement = arg_i->second;
            merge_graph.replace(me, replacement);
            return true;
        }
    }

    // Make list of all descendants.  We don't want to iterate over the
    // replacements, so we make the entire list in advance.
    list<node_p> to_transform;
    bfs_down(replacement, back_inserter(to_transform));
    BOOST_FOREACH(const node_p& node, to_transform) {
        BOOST_FOREACH(const node_p& child, node->children()) {
            string ref_param = template_ref(child);
            if (! ref_param.empty()) {
                arg_map_t::const_iterator arg_i = arg_map.find(ref_param);
                if (arg_i == arg_map.end()) {
                    reporter.error(
                        "Reference to \"" + ref_param + "\" but not such "
                        "argument to template " + name() = "."
                    );
                    continue;
                }

                node->replace_child(child, arg_i->second);
            }
        }
    }