/******************************************************************************** * * File: basic.h * The interface of the classes used in OPTGEN and the query optimizers * Programmer: Leonidas Fegaras, UTA * Date: 4/12/97 * ********************************************************************************/ #include #include #include static int name_counter = 0; /*-------------------------------------------------------------------------------- - Strings ---------------------------------------------------------------------------------*/ class string: public gc { char* sp; /* the string content */ unsigned long hash_value; /* the hash key of the string */ public: /* string constructors */ string() { sp = 0; hash_value = 0; } string( string& b ) { sp = b.sp; hash_value = 0; }; string( const char* s ) { sp = new (GC) char[strlen(s)+1]; strcpy(sp,s); hash_value = 0; }; /* access the string content */ inline char* value() { return sp; } /* various string equalities */ inline bool eq( string* a ) { return strcmp(sp,a->sp)==0; }; inline bool eq( string a ) { return strcmp(sp,a.sp)==0; }; inline bool eq( const char* a ) { return strcmp(sp,a)==0; }; /* string concatenation */ friend string operator+( const string&, const string& ); /* map a string into an integer; it is used in hashing */ unsigned long hash (); /* new_name() returns a name that hasn't been used before */ friend inline string* new_name () { return new string(form("X_%i",name_counter++)); } /* I/O functions */ write ( ofstream& to ); friend string* reads ( ifstream& from ); friend ostream& operator<<( ostream& s, const string& a ) { return s << a.sp; }; friend ostream& operator<<( ostream& s, const string* a ) { return s << a->sp; }; }; typedef string* String; /*-------------------------------------------------------------------------------- - pair is a pair with two elements: one of type T and one of type S ----------------------------------------------------------------------------------*/ template class pair: public gc { public: T first; S second; pair ( T x, S y ) { first = x; second = y; }; inline friend pair* Pair ( T x, S y ) { return new pair(x,y); }; friend ostream& operator<< ( ostream& s, pair* p ) { return s << p->first << ": " << p->second; }; }; /*-------------------------------------------------------------------------------- - list is a list of elements of type T ----------------------------------------------------------------------------------*/ template class list: public gc { public: enum { Nil, Cons } tag; T hd; /* list head */ list *tl; /* list tail */ /* list constructor */ list () { tag = Nil; }; /* construct a list from a vector of values */ list ( const T[] ); /* test whether the list is null or not */ inline nullp () { return (tag==Nil); }; inline consp () { return (tag==Cons); }; /* construct a new list cell */ list* cons ( T ); friend inline list* Cons ( T x, list* r ) { return r->cons(x); }; /* list size */ int length(); /* append the argument to the end of the list forming a new list */ list* append ( list* ); friend inline list* Append ( list* x, list* y ) { return x->append(y); }; /* list reverse */ list* reverse (); /* sort the list using bubble sort */ list* sort ( bool (less_than)(T,T) ); /* display a list */ friend ostream& operator<< ( ostream&, list* ); }; typedef list* Names; /*-------------------------------------------------------------------------------- - binding lists associate names with values of type T --------------------------------------------------------------------------------*/ template class binding: public gc { public: list*>* env; /* binding constructors */ binding () { env = new list*>; }; binding ( binding* e ) { env = e->env; }; binding ( list*>* e ) { env = e; }; binding ( pair* x ); binding ( String, T ); /* extend the binding list with a new binding */ binding* extend ( pair* x ); inline binding* extend ( String s, T c ) { return extend(new pair(s,c)); }; /* append two binding lists */ binding* extend ( binding* r ); /* get the current element of the binding list */ inline pair* current () { return env->hd; }; /* get the next element of the binding list */ inline binding* next () { return new binding(env->tl); }; /* are there more elements in the binding list? */ inline bool more () { return env->consp(); } /* find a value T given its name */ T find ( String ); /* find a value T given its name; if you don't find return a default value */ T find ( String, T ); /* is name bound in the binding list? */ bool in ( String ); /* return the list of all the names bound in the binding list */ Names names (); inline int length () { return env->length(); }; /* display a binding list */ friend ostream& operator<< ( ostream&, binding* ); }; /*-------------------------------------------------------------------------------- - This is the data structure for graphs --------------------------------------------------------------------------------*/ template class graph; template class node: public gc { typedef pair* edge; public: T info; /* the content of a node */ list* edges; /* the edges attached to a node */ /* constructor */ node( T v ) { info = v; edges = new list; }; /* attach a new directed edge (from this to x) to the node */ inline node* new_edge ( node* x, S v ) { edges = edges->cons(new pair(x,v)); }; inline bool eq ( node* x ) { return this == x; }; bool member ( list* n ); inline bool member ( graph* n ) { return member(n->nodes); }; /* display a node */ friend ostream& operator<< ( ostream& s, node* n ) { s << n->info; return s; }; }; template class graph: public gc { public: list*>* nodes; /* constructor */ graph () { nodes = new list*>; }; /* insert a new node in the graph */ inline node* new_node ( T v ) { node* n = new node(v); nodes = nodes->cons(n); return n; }; /* attach a new directed edge x->y with label v to the graph */ inline new_edge ( node* x, node* y, S v ) { x->new_edge(y,v); }; inline new_bedge ( node* x, node* y, S v ) { x->new_edge(y,v); y->new_edge(x,v); }; /* number of nodes in a graph */ inline int size () { return nodes->length(); }; /* display a graph */ friend ostream& operator<< ( ostream&, graph* ); }; /*-------------------------------------------------------------------------------- - This is the data structure to represent algebraic forms, plans, etc --------------------------------------------------------------------------------*/ class expr; typedef expr* Expr; typedef list* Params; class expr: public gc { enum { ERROR, VAR, INT, STRING, FNC } tag; /* the type of expression */ unsigned long hash_value; /* the hash key of the Expr */ const screen_size = 100; /* used in pretty printing */ int size (); public: union { String Variable; int Integer; String Estring; struct { Expr Name; Params Parameters; } Function; } info; /* expr constructors */ expr () { hash_value = 0; tag = ERROR; }; friend Expr variable (String); friend inline Expr variable (string s) { return variable(&s); }; friend Expr integer (const int); friend Expr estring (String); friend inline Expr estring (string s) { return estring(&s); }; friend Expr function (Expr,list*); /* accessors */ inline String name () { return info.Variable; }; inline list* arguments () { return info.Function.Parameters; }; /* testing the type of expr */ inline variablep () { return (tag==VAR); }; inline integerp () { return (tag==INT); }; inline stringp () { return (tag==STRING); }; inline functionp () { return (tag==FNC); }; /* expr deep equality */ bool eq ( Expr ); /* check if an expr is a member of a list of exprs or a list of strings */ friend bool member (Expr,list*); friend bool member (Expr,list*); /* substitute value for variable terms(s) */ friend Expr subst_expr ( Expr variable, Expr value, Expr term ); friend list* subst_list ( Expr variable, Expr value, list* terms ); friend inline Expr substitute ( Expr e, Expr term ) { return subst_expr(e->arguments()->hd,term,e->arguments()->tl->hd); } /* new_variable() returns a variable name that hasn't been used before */ friend inline Expr new_variable () { return variable(new_name()); } /* map an expr to integer; use for hashing in memoization */ unsigned long hash (); /* print with indentations to look nice */ pretty_print ( int ); /* I/O functions */ friend ostream& operator<< ( ostream&, Expr ); friend Expr read ( ifstream& ); write ( ofstream& ); }; #define Nil (new list) /*-------------------------------------------------------------------------------- - The template method's code. - Must be included here, since templates are macros --------------------------------------------------------------------------------*/ template list::list ( const T x[] ) { list* n = new list; for(short i=sizeof(x)-1; i>=0; i--) n = n->cons(x[i]); if ( n->nullp() ) tag = Nil; else { tag = Cons; hd = n->hd; tl = n->tl; }; }; template list* list::cons ( T a ) { list *n = new list; n->tag = Cons; n->hd = a; n->tl = this; return n; }; template int list::length () { int n = 0; for(list* r = this; r->consp(); r=r->tl) n++; return n; }; template list* list::append ( list* x ) { if ( nullp() ) return x; else return tl->append(x)->cons(hd); }; template list* rev ( list* x, list* y ) { if ( x->nullp() ) return y; else return rev(x->tl,y->cons(x->hd)); }; template list* list::reverse () { return rev(this,new list); }; template list* list::sort ( bool (less_than) (T,T) ) { int len = length(); T A[len]; int k = 0; for(list* r = this; r->consp(); r=r->tl) A[k++] = r->hd; for(int j = len-1; j>=1; j--) for(int i = 1; i<=j; i++) if (less_than(A[i],A[i-1])) { T tmp = A[i-1]; A[i-1] = A[i]; A[i] = tmp; }; list* res = new list; for(int i = len-1; i>=0; i--) res = res->cons(A[i]); return res; }; template ostream& operator<<( ostream& s, list *lst ) { if (lst->nullp()) return s << "()"; s << "(" << lst->hd; for( list* r = lst->tl; r->consp(); r = r->tl) s << "," << r->hd; return s << ")"; }; template binding::binding ( String s, T c ) { env = (new list*>)->cons(new pair(s,c)); }; template binding* binding::extend ( pair* x ) { binding* res = new binding(this); res->env = res->env->cons(x); return res; }; template binding* binding::extend ( binding* r ) { binding* res = new binding(this); res->env = res->env->append(r->env); return res; }; template T binding::find ( String n ) { for(list*>* r = env; r->consp(); r=r->tl) if (r->hd->first->eq(n)) return r->hd->second; }; template T binding::find ( String n, T def ) { for(list*>* r = env; r->consp(); r=r->tl) if (r->hd->first->eq(n)) return r->hd->second; return def; }; template Names binding::names () { list* s = new list; for(list*>* r = env; r->consp(); r=r->tl) s = s->cons(r->hd->first); return s->reverse(); }; template bool binding::in ( String n ) { for(list*>* r = env; r->consp(); r=r->tl) if (r->hd->first->eq(n)) return true; return false; }; template ostream& operator<<( ostream& s, binding *lst ) { if (lst->env->nullp()) return s << "[]"; s << "[" << lst->env->hd; for( list*>* r = lst->env->tl; r->consp(); r = r->tl) s << "," << r->hd; return s << "]"; }; template bool node::member ( list*>* n ) { for(list* r = n; r->consp(); r=r->tl) if (r->hd == this) return true; return false; }; template ostream& operator<< ( ostream& s, graph* n ) { for(list*>* r = n->nodes; r->consp(); r=r->tl) { s << "{" << r->hd->info << ","; for(list*,S>*>* t = r->hd->edges; t->consp(); t=t->tl) s << "(" << t->hd->first->info << "," << t->hd->second << ")"; s << "}"; }; return s; };