/************************************************
  Team: Jon Gregory, Gor Nishanov
  Project #2 Part 2
    for RPI course 66-648 Compiler Design Theory

  tree.h:

    Here we have large classes representing
      classes, methods, packages and whole compiling environment

      **/

#include "consts.h"
#include "utils.h"

class Field;

#include "type.h"
#include "expr.h"
#include "stmts.h"

class Field : public QuickNew {
public:
	Identifier name;
	int        modifiers;
	Type *     type;

	Field * nextInOwner;
};

class Parameter : public QuickNew {
  Type *    type_;
  Expression * altnam;
public:
  Parameter(Expression* nam, Type* type):
    altnam(nam), type_(type) {}

  friend ostream& operator << (ostream& o, const Parameter* p) {
     return o << p->type_ << " " << p->altnam; 
  }

  Parameter * nextInOwner;
};

class Method : public QuickNew {
  Identifier name;
public:
  Method(Identifier nam):name(nam),dims(0){}

  int dims;
  TypeList throwz;
  int             modifiers;
  List<Parameter> params;
  Statement*      body;
  Type*           type;

  friend ostream& operator << (ostream& o, Method* m) {
    o << endl << "  "; 
    printMod(o, m->modifiers);
    o << m->name << '(' <<  m->params << ")" << m->type << ' ';
    if(m -> body != 0) m->body->print2(o, 1);
    return o;
  }

  Method*  nextInOwner;
};

class Class : public QuickNew {
  Identifier name;
  int        modifiers;

public:
  Class(Identifier nam, int mods):name(nam),modifiers(mods){}

  TypeList interfaces;
  List<Statement> fields;
  List<Method> methods;
  List<Statement> inits;

  Type * super;

  friend ostream& operator << (ostream& o, Class* c) {
    o << endl << "class " << c->name << " extends " 
      << c->super << " implements " << c->interfaces << " {";

    if(c->fields.count > 0) o << "\n  ";
    c->fields.print(o, "\n  ");
    o << c->methods;

    return o << endl <<'}' << endl;
  }

  Class * nextInOwner;
};

class Package : public QuickNew {
  Expression * name;
public:
  Package(Expression * nam): name(nam){}

  List<Expression> imports;
  List<Class>      classes;  

  friend ostream& operator << (ostream& o, const Package* p) {
    o << "package " << p->name << ';'  << endl;
    if (p->imports.count > 0) 
      o << "import " << p->imports << ';' << endl;
    o << p->classes << endl << "---- end package ---" << endl;
    return o;
  };

  Package * nextInOwner;
};

class Environment : public QuickNew {
	Package * findPackage(const char * id) {
	 return (Package*) 0; // Later we package search here
	}

public:
        Statement * empty_block;
	Environment():pkg(0),clazz(0),empty_block(new EmptyStatement()){
          cout << "Environment has been created" << endl;
        }
        void addNewClass(Class * cl) {
          pkg->classes.add(cl);
          clazz = cl;
        }
        void addMethod(Method * m) {
          clazz -> methods.add(m);
          method = m;
        }

	Package * pkg; // currentPackage
	Class * clazz; // currentClass
	Method * method; // currentMethod

	int modifiers; // This two holds modifiers
	Type * type;   // and types in variable declarations
	int dims;      // count dims

	Expression * arrayElem; // used in New Array
};






