/* SI 413 Fall 2011
 * ast.cpp
 * Implementations of (longer) functions in the AST class hierarchy.
 */

#include <iostream>
using namespace std;

#include "ast.hpp"

const char* opstring(Oper op) {
  switch(op) {
    case ADD: return "+";   break;
    case SUB: return "-";   break;
    case MUL: return "*";   break;
    case DIV: return "/";   break;
    case LT:  return "<";   break;
    case GT:  return ">";   break;
    case LE:  return "<=";  break;
    case GE:  return ">=";  break;
    case EQ:  return "=";   break;
    case NE:  return "!=";  break;
    case AND: return "and"; break;
    case OR:  return "or";  break;
    case NOTOP: return "not"; break;
    default: return NULL; // will never reach here.
  }
}

int AST::addToDot(ostream& out, int& nodes) {
  int root = ++nodes;
  out << "\tn" << root << " [label=\"";
  writeLabel(out);
  out << "\"];" << endl;
  for (int i = 0; i < numChildren(); ++i) {
    int child = getChild(i)->addToDot(out,nodes);
    out << "\tn" << root << " -> n" << child << ";" << endl;
  }
  return root;
}

void AST::writeDot(const char* fname) {
  ofstream fout(fname);
  int nodes = 0;
  fout << "digraph g {" << endl;
  addToDot(fout,nodes);
  fout << "}" << endl;
  fout.close();
}

Stmt* Stmt::append(Stmt* a, Stmt* b) {
  if (a->isNull()) return b;
  Stmt* n = a;
  while (!n->next->isNull()) n = n->next;
  n->next = b;
  return a;
}

Stmt::Stmt () {
  /* This static declaration means that the same memory will persist between
   * calls to this function. This allows us to re-use the same NullStmt
   * object over and over again.
   */
  static NullStmt nullst;
  next= &nullst;
}

void Atom::writeLabel(ostream& out) {
  out << getType() << ":exp\\n";
  writeValue(out);
  out << flush;
}

AST* IfElse::getPart(int i) {
  switch(i) {
    case 0: return clause;
    case 1: return ifblock;
    case 2: return elseblock;
    default: return NULL;
  }
}