-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbuild_context.cpp
More file actions
89 lines (71 loc) · 2.61 KB
/
Copy pathbuild_context.cpp
File metadata and controls
89 lines (71 loc) · 2.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include "parser/build_context.h"
#include <algorithm>
#include <set>
#include "dag/dag_builder.h"
#include "dag/node.h"
#include "dag/tally.h"
#include "parser/ast.h"
namespace ccs {
class Descendant : public BuildContext {
Node &node_;
public:
Descendant(DagBuilder &dag, Node &node) :
BuildContext(dag),
node_(node) {}
virtual Node &node() { return node_; }
// this copy-into-new-shared-ptr thing is ugly, but enable_shared_from_this
// is just as bad, or worse...
virtual Node &traverse(ast::SelectorLeaf &selector)
{ return selector.traverse(std::make_shared<Descendant>(*this)); }
};
template <typename T>
class TallyBuildContext : public BuildContext {
Node &firstNode_;
BuildContext::P baseContext_;
public:
TallyBuildContext(DagBuilder &dag, Node &node, BuildContext::P baseContext) :
BuildContext(dag),
firstNode_(node),
baseContext_(baseContext) {}
virtual Node &node() { return firstNode_; }
virtual Node &traverse(ast::SelectorLeaf &selector) {
Node &secondNode = selector.traverse(baseContext_);
// we've arrived at the same node by two different paths. no tally is
// actually needed here...
if (&firstNode_ == &secondNode) return firstNode_;
std::set<std::shared_ptr<Tally>> tallies;
std::set_intersection(
firstNode_.tallies<T>().begin(), firstNode_.tallies<T>().end(),
secondNode.tallies<T>().begin(), secondNode.tallies<T>().end(),
std::inserter(tallies, tallies.end()));
// result will be either empty or have exactly one entry.
if (tallies.empty()) {
std::shared_ptr<T> tally = std::make_shared<T>(firstNode_,
secondNode);
firstNode_.addTally(tally);
secondNode.addTally(tally);
return tally->node();
} else {
return (*tallies.begin())->node();
}
}
};
BuildContext::P BuildContext::descendant(DagBuilder &dag, Node &node)
{ return std::make_shared<Descendant>(dag, node); }
BuildContext::P BuildContext::descendant(Node &node)
{ return std::make_shared<Descendant>(dag_, node); }
BuildContext::P BuildContext::conjunction(Node &node,
BuildContext::P baseContext)
{ return std::make_shared<TallyBuildContext<AndTally>>(dag_, node,
baseContext); }
BuildContext::P BuildContext::disjunction(Node &node,
BuildContext::P baseContext)
{ return std::make_shared<TallyBuildContext<OrTally>>(dag_, node,
baseContext); }
void BuildContext::addProperty(const ast::PropDef &propDef) {
Value value(propDef.value_);
value.setName(propDef.name_);
node().addProperty(propDef.name_, Property(value,
propDef.origin_, dag_.nextProperty(), propDef.override_));
}
}