/********************************************************************************
*
* File: evaluation.h
* Title: The evaluator for OQL
* Programmer: Leonidas Fegaras, UTA
* Date: 4/10/97
*
********************************************************************************/

/* change this constant to true if you want to trace the evaluation of a plan */
const bool trace_evaluation = false;

/* the block size in bytes */
const short block_size = 2048;


/*--------------------------------------------------------------------------------
- The interface class describes the interface of an ODL class
- The extent class describes the extent of an ODL class
--------------------------------------------------------------------------------*/

class extent;
class interface;
class object;

typedef object* Object;

typedef Expr Type;

/* the extent schema is a binding of attribute names to types */
typedef binding<Type>* Schema;

typedef extent* Extent;
typedef interface* Interface;

/* a method signature is a pair of the input variable bindings to types with an output type */
typedef pair<Schema,Type>* Signature;

/* a method consists of a signature and a body (Expr) */
typedef pair<Signature,Expr>* Method;

class interface: public gc {
public:
  String name;			/* class name */
  Names primary_key;		/* the primary key of extent */
  Schema schema;		/* the class schema */
  binding<Method>* methods;	/* class methods */
  Interface supertype;		/* its supertype (NULL if none) */
  list<Interface>* subtypes;	/* the list of subtypes */
  Extent data;			/* the class extent (NULL if none) */

  /* constructors */
  interface ();
  interface ( String nm );
  interface ( Interface intrf );

  /* map a class definition into an interface */
  interface ( Expr class_def );

  /* display an interface */
  friend ostream& operator<< ( ostream&, Interface );

  /* I/O stuff */
  friend Interface interface_read ( ifstream& from );
  interface_write ( ofstream& to );

};



class extent: public gc {
public:

  String name;			/* name of the extent */
  list<Object>* data;		/* the extent content is a list of objects */
  Schema schema;		/* the extent type is the schema of the class interface */
  binding<Names>* indexes;	/* the list of indexes (B+-trees) */
  int object_size;		/* the size of an object in bytes */
  int cardinality;		/* number of objects in the extent */

  /* extent constructors */
  extent ( String name, Schema sch );
  extent ( Extent r );

  /* insert a new object in the extent */
  insert ( Object x );

  /* create a collection object that contains all the objects in the extent */
  Object scan( String var, Expr pred );

  /* is the extent empty? */
  inline bool is_empty () { return data->nullp(); }

  /* find an index for this extent that delivers this order */
  Expr find_index ( Names order );

  /* print the data content of an extent */
  friend ostream& operator<< ( ostream&, Extent );

  /* I/O stuff */
  friend Extent extent_read ( ifstream& from );
  extent_write ( ofstream& to );

};


/*--------------------------------------------------------------------------------
-  The object manipulation code; ie. it evaluates an expression or a predicate over
-  an aggregation object or it evaluates NF2 operations over collection objects.
--------------------------------------------------------------------------------*/


/* an environment binds variable names to object values */
typedef binding<Object>* Environment;

typedef enum { ONULL, OINT, OBOOL, OSTRING, AGGREGATION, COLLECTION } otagtype;


class object: public gc {

  otagtype tag;
  static int available_OID = 0;			/* a counter for OIDs */
  const max_level = 20;				/* maximum nesting level of the object printout */

public:

  union{ int			Integer;
         String			Estring;
	 bool			Boolean;
	 struct{ int		OID;
		 list<Object>*	Components;	/* object is an aggregation of objects */
	 }			Aggregation;	/* (one per object attribute) */
	 list<Object>*		Collection;	/* object is a collection of objects */
	}			info;

  Type otype;					/* the object type */

  class evaluation_exception {};		/* used for handling run-time errors */

  /* constructors */
  object () { tag = ONULL; otype = variable(""); };
  object ( int n ) { tag = OINT; info.Integer = n; otype = variable("Short"); };
  object ( bool b ) { tag = OBOOL; info.Boolean = b; otype = variable("bool"); };
  object ( String s ) { tag = OSTRING; info.Estring = s; otype = variable("String"); };
  object ( Type tp, list<Object>* r );
  object ( Type tp );

  /* testing the type of object */
  inline nullp () { return (tag==ONULL); };
  inline integerp () { return (tag==OINT); };
  inline boolp () { return (tag==OBOOL); };
  inline stringp () { return (tag==OSTRING); };
  inline aggregationp () { return (tag==AGGREGATION); };
  inline collectionp () { return (tag==COLLECTION); };

  /* shallow equality */
  bool eq ( Object );

  /* evaluate a projection */
  Object projection ( String attribute );
  Object projection ( Names attributes );

  /* evaluate a method */
  Object method ( String fnc, list<Object>* arguments, Environment &env );

  /* evaluate an OQL expression */
  Object expression ( Expr e, Environment &env );

  /* evaluate an OQL predicate */
  bool predicate ( Expr pred, Environment &env );

  /* C style comparison: it returns attribute-x.attribute */
  int compare ( Object x, String attribute );

  /* true if for all attributes A in attributes: A=x.A (resp. A<x.A) */
  bool equal_to ( Object x, Names attributes );
  bool less_than ( Object x, Names attributes );

  /* reduces a collection to a value or collection */
  Object reduce ( String accumulator, String var, Expr head, Expr pred, Environment &env );

  /* the NF2 unnest operator */
  Object unnest ( String var, Expr path, Expr pred, bool keep, Environment &env );

  /* the NF2 nest operator */
  Object nest ( String accumulator, String var, Expr head, Names groupby_vars, Names other_nestvars, Expr pred, Environment& env );

  /* group by groupby_vars; the input collection object must be sorted by groupby_vars;
     keep also the other_nestvars (from other nestings) */
  Object group_by ( String accumulator, String var, Expr head, Names groupby_vars, Names other_nestvars, Expr pred, Environment& env );

  /* sort a collection object by the attributes */
  Object sort ( list<Expr>* attributes, Environment &env );

  /* nested-loop join */
  Object nested_loop ( Object r, Expr pred, Expr keep, Environment &env );

  /* sort-merge join: it scans the sorted left and right inputs simultaneously */
  Object merge_join ( Object r, Expr pred, list<Expr>* left_order, list<Expr>* right_order, Expr keep, Environment &env );

  /* map the function f (of parameter v) over the collection object */
  Object map ( String v, Expr f, Environment &env );

  /* evaluate a plan */
  friend Object evaluate_plan ( Expr plan, Environment &env );

  /* convert an object to an expr */
  Expr reify (int);

  /* display an object */
  friend ostream& operator<< ( ostream&, Object );

  /* I/O stuff */
  friend Object object_read ( ifstream& from );
  object_write ( ofstream& to );

};


evaluation_error ( string, Object );


/*--------------------------------------------------------------------------------
- a database holds both the database schema and the database content
--------------------------------------------------------------------------------*/


class database: public gc {
public:
  binding<Extent>* content;	/* all extents in database */
  binding<Interface>* schema;	/* all interfaces in database */
  binding<String>* extents;	/* binding from interface names to extent names */
  Schema vartypes;		/* types of global variables */
  Environment varspace;	/* values of global variables */

  database ();

  /* read a database from a file */
  database ( String file_name );

  /* write a database to a file */
  close ( String file_name );

  /* print the entire database schema and content; long output */
  friend ostream& operator<< ( ostream&, database* );

  /* find an extent in the database */
  friend Extent find_extent ( String name );

  friend Names all_extents ();
  friend binding<String>* extent_types ();
  friend Names all_interfaces ();

  /* find an interface in the database */
  friend Interface find_interface ( String name );

};



Type schema_to_type ( Schema sch );
Schema type_to_schema ( Type tp );
class_def ( Expr e );
