4 #include <AD/pretty/postream.h>
6 #include "willard-ast.ph"
8 ///////////////////////////////////////////////////////////////////////////////
10 // Constructor for the Paige/Goyal query transformer
12 ///////////////////////////////////////////////////////////////////////////////
13 PaigeGoyal::PaigeGoyal() : log(*new ofstream), errlog(cerr)
14 { True = LIT(BOOL(true));
15 False = LIT(BOOL(false));
19 EmptySet = GENERATOR(#[],#[],Zero);
25 ///////////////////////////////////////////////////////////////////////////////
27 // Destructor for the Paige/Goyal query transformer
29 ///////////////////////////////////////////////////////////////////////////////
30 PaigeGoyal::~PaigeGoyal()
34 ///////////////////////////////////////////////////////////////////////////////
36 // Method to add a subquery
38 ///////////////////////////////////////////////////////////////////////////////
39 void PaigeGoyal::add_subquery(Id x, Exp e)
41 // S << "Subquery: " << x << '=' << e << '\n';
42 subquery_names = #[ x ... subquery_names ];
43 subqueries = #[ e ... subqueries ];
45 Bool PaigeGoyal::has_subqueries() const { return subqueries != #[]; }
47 ///////////////////////////////////////////////////////////////////////////////
49 // Method to collect subqueries into a LET
51 ///////////////////////////////////////////////////////////////////////////////
52 Exp PaigeGoyal::collect_subqueries(Exp exp)
53 { exp = make_let(subquery_names, subqueries, exp);
59 ///////////////////////////////////////////////////////////////////////////////
61 // Method to make a nested LET
63 ///////////////////////////////////////////////////////////////////////////////
64 Exp PaigeGoyal::make_let(Ids xs, Exps es, Exp exp)
65 { match while (xs) and (es) of
66 #[a ... b], #[c ... d]:
76 ///////////////////////////////////////////////////////////////////////////////
78 // Methods to define/lookup the range of a variable
80 ///////////////////////////////////////////////////////////////////////////////
81 void PaigeGoyal::define_range(Id x, Exp e) { var_range.insert(x,e); }
82 void PaigeGoyal::define_range(Ids xs, Exps es)
85 match while (ids) and (exps) of
86 #[x ... xs], #[e ... es]: { define_range(x,e); ids = xs; exps = es; }
88 if (ids != #[] || exps != #[])
89 errlog << "Arity mismatch in " << xs << "in" << es << ::newline;
92 Exp PaigeGoyal::range_of(Id x)
93 { assert(var_range.contains(x));
97 ///////////////////////////////////////////////////////////////////////////////
99 // Method to print messages
101 ///////////////////////////////////////////////////////////////////////////////
102 void PaigeGoyal::message(const char * msg, Exp e)
103 { log << ::indent << e << ::newline << ::newline << ::unindent
104 << '[' << msg << ']' << ::newline << ::newline;
107 void PaigeGoyal::error(const char * msg, Exp e)
108 { errlog << '[' << "ERROR:" << msg << ']' << ::newline << ::indent
109 << e << ::newline << ::unindent;
112 void PaigeGoyal::set_log(ostream& f) { log.set_stream(f); }
113 void PaigeGoyal::set_error(ostream& f) { errlog.set_stream(f); }
115 ///////////////////////////////////////////////////////////////////////////////
117 // Method to add an edge into the query graph
119 ///////////////////////////////////////////////////////////////////////////////
120 void PaigeGoyal::add_edge(Id x, Id y)
121 { if (parent.contains(y))
124 errlog << "Edge: " << x << "->" << y << "conflicts with"
125 << z << "->" << y << "in the query graph\n";
130 Bool PaigeGoyal::has_edge(Id x, Id y) const
131 { if (! parent.contains(y)) return false;
132 return parent[y] == x;
135 void PaigeGoyal::add_edge_query(Id x, Id y, Exp q)
137 edge_queries.insert(.(x,y),q);
140 ///////////////////////////////////////////////////////////////////////////////
142 // Method to compute the transitive closure of the query graph
144 ///////////////////////////////////////////////////////////////////////////////
145 void PaigeGoyal::compute_transitive_closure()
147 { parent_closure.insert(parent.key(i),parent.value(i));
151 ///////////////////////////////////////////////////////////////////////////////
153 // Methods to push/pop from the quantifier stack
155 ///////////////////////////////////////////////////////////////////////////////
156 void PaigeGoyal::push_quantifier(Id x) { quantifier_vars.push(x); }
157 void PaigeGoyal::push_quantifier(Ids xs)
158 { match while (xs) of #[h ... t]: { push_quantifier(h); xs = t; } end match; }
159 void PaigeGoyal::pop_quantifier(Id x) { quantifier_vars.pop(); }
160 void PaigeGoyal::pop_quantifier(Ids xs)
161 { match while (xs) of #[h ... t]: { pop_quantifier(h); xs = t; } end match; }
163 ///////////////////////////////////////////////////////////////////////////////
165 // Method to print the query graph
167 ///////////////////////////////////////////////////////////////////////////////
168 void PaigeGoyal::print_query_graph()
169 { log << ::tab << "[Query Graph]" << ::newline << ::indent;
171 { Id x = parent.value(i);
172 Id y = parent.key(i);
173 log << ::tab << "edge" << x << "->" << y;
174 if (edge_queries.contains(.(x,y)))
175 log << '\t' << edge_queries[.(x,y)];
181 ///////////////////////////////////////////////////////////////////////////////
183 // Main method to decompose a query
185 ///////////////////////////////////////////////////////////////////////////////
186 Exp PaigeGoyal::decompose(Exp e)
190 e = remove_duplicate_names(e);
191 e = phase1(e); // DNF construction
192 e = construct_query_graph(e); // query graph construction
193 e = phase2(e); // quantifier elimination
194 e = phase3(e); // disjunction removal
195 e = phase4(e); // conjunction removal
196 e = projection_recognition(e);
198 if (changed) message("Reiterating the transformation",e);