Home
 

emit.C

emit.C

/*
 *  emit.C
 */

#include <iostream.h>

#include "symtab.h"

extern bool debugFlag;

int SymtabCls :: emit() {
   if (debugFlag) cout << "SymtabCls::emit()" << endl;

   cerr << "Nothing to emit in symbol table!" << endl;
   exit(1);

   return 0;
}

#include "p_tree.h"
   
int PTreeCls :: emit() {
   if (debugFlag) cout << "PTreeCls::emit() " << endl;
   if (! root) {
      cerr << "PTreeCls::emit - LOGIC ERROR" << endl;
      return 0;
   } else {
      return root -> emit();
   }
}

#ifdef MULT_ARR
int DataItemCls::emit()
{
   typeEmit();

   return 0;
}

PDataTypeCls DataItemCls::typeEmit()
{
   if (debugFlag) cout << "DataItemCls::typeEmit()" << endl;

   if (dynamic_cast<PIdentCls>(item) != NULL) {  // basic type
      PSymtabCls scp = ScopeCls::get_vista();
      char *name = PIdentCls(item)->get_name();
      PSymtabEntryCls found_it = scp -> lookup(name);
      if (!found_it) {
     cerr << "error: undeclared variable: " << name << endl;
     exit(1);
      }

      PDataTypeCls type = PSymbolCls(found_it)->getDataType();
      PAddressCls addr = PSymbolCls(found_it)->getAddress();

      // Too many modifiers?
      if (type == NULL || sub != NULL) {
     cerr << "Type and reference mismatch" << endl;
     exit(1);
      }

      cout << "push" << endl
       << addr->getAddr() << endl;

      return type;
   }
   else {  // array type
      PDataTypeCls this_type = PDataItemCls(item)->typeEmit();

      // Too many modifiers?
      if (this_type == NULL || sub == NULL || 
      dynamic_cast<PCompTypeCls>(this_type) == NULL) {
     cerr << "Type and reference mismatch" << endl;
     exit(1);
      }

      sub->emit();
      cout << "push" << endl
       << PArrayTypeCls(this_type)->getRangeFrom()->get_value() << endl
       << "-" << endl;
      
      cout << "push" << endl
       << PArrayTypeCls(this_type)->getItemSize() << endl
       << "*" << endl
       << "+" << endl;
      
      return PArrayTypeCls(this_type)->getItemDataType();
   }
}

#else /* !MULT_ARR */
int DataItemCls::emit()
{
   if (debugFlag) cout << "DataItemCls::emit()" << endl;

   PSymtabCls scp = ScopeCls::get_vista();
   char *name = PIdentCls(item)->get_name();
   PSymtabEntryCls found_it = scp -> lookup(name);
   if (!found_it) {
      cerr << "error: undeclared variable: " << name << endl;
      exit(1);
   }

   PDataTypeCls type = PSymbolCls(found_it)->getDataType();
   PAddressCls addr = PSymbolCls(found_it)->getAddress();
   cout << "push" << endl
    << addr->getAddr() << endl;

   if (sub) {
      sub->emit();
      cout << "push" << endl
       << PArrayTypeCls(type)->getRangeFrom()->get_value() << endl
       << "-" << endl;

      cout << "push" << endl
       << PArrayTypeCls(type)->getItemSize() << endl
       << "*" << endl
       << "+" << endl;
   }

   return 0;
}
#endif /* MULT_ARR */

int StatementCls :: emit() {
   if (debugFlag) cout << "! " << stmt_text << endl;
   return 0;
}

int StatementSeqCls :: emit() {
   if (debugFlag) cout << "StatementSeqCls::emit() " << endl;
   PPTreeNodeCls p = this -> seq_head;
   while (p) {
      p -> emit();
      p = PStatementCls(PStatementCls(p) -> get_next());
   }
   return 0;
}

int EmptyStmtCls :: emit() {
   if (debugFlag) cout << "EmptyStmtCls::emit()" << endl;
   return 0;
}

int WriteStmtCls :: emit() {
   if (debugFlag) cout << "WriteStmtCls::emit()" << endl;
   StatementCls::emit();

   expr -> emit();
   cout << "write" << endl;

   return 0;
}

int AssignmentStmtCls :: emit() {
   if (debugFlag) cout << "AssignmentStmtCls::emit()" << endl;
   StatementCls::emit();

  
   assign_seq->emit();
   expr->emit();
  
   for (int i=0; i<PAssignmentSeqCls(assign_seq)->getLength(); i++)
      cout << ":=" << endl;
  
   cout << "pop" << endl;
  
   return 0;
}

int AssignmentSeqCls::emit() {
   if (debugFlag) cout << "AssignmentSeqCls::emit() " << endl;
   PPTreeNodeCls p = this->seq_head;
   while (p) {
      p -> emit();
      p = PDataItemCls(PDataItemCls(p)->get_next());
   }

   return 0;
}

int LoopStmtCls::emit() {
   if (debugFlag) cout << "LoopStmtCls::emit()" << endl;

   cout << "loop" << endl;
   statements->emit();
   cout << "endloop" << endl;
  
   return 0;
}

int ExitStmtCls::emit() {
   if (debugFlag) cout << "ExitStmtCls::emit()" << endl;

   cout << "exit" << endl;

   return 0;
}

int IfStmtCls::emit()
{
   if (debugFlag) cout << "IfStmtCls::emit()" << endl;

   condition->emit();
   cout << "test" << endl;

   statements->emit();
   elseStmts->emit();

   cout << "endif" << endl;

   return 0;
}

int ElseStmtCls::emit()
{
   if (debugFlag) cout << "ElseStmtCls::emit()" << endl;

   if (statements) {
      cout << "else" << endl;
      statements->emit();
   }

   return 0;
}

int RelOpCls::emit()
{
   if (debugFlag) cout << "RelOpCls::emit()" << endl;

   switch(op) {
   case ltOp:
      cout << "<" << endl;
      break;

   case leOp:
      cout << "<=" << endl;
      break;

   case eqOp:
      cout << "=" << endl;
      break;

   case neOp:
      cout << "<>" << endl;
      break;

   case geOp:
      cout << ">=" << endl;
      break;

   case gtOp:
      cout << ">" << endl;
      break;

   default:
      cerr << "error: unsupported relational operator: " << op << endl;
      exit(1);
   }

   return 0;
}

int ConditionCls::emit()
{
   if (debugFlag) cout << "ConditionCls::emit()" << endl;
  
   expr1->emit();
   expr2->emit();
   relOp->emit();

   return 0;
}

int NumFactorCls :: emit() {
   if (debugFlag) cout << "NumFactorCls::emit()" << endl;
   cout << "push" << endl
    << ExprCls::value << endl;

   return 0;
}

int VarAccessFactorCls :: emit() {
   if (debugFlag) cout << "VarAccessFactorCls::emit()" << endl;

   item->emit();
   cout << "getValue" << endl;

   return 0;
}

int ArithmCls::emit()
{
   left->emit();
   right->emit();

   switch (op) {
   case PlusOp:
      cout << "+" << endl;
      break;

   case MinusOp:
      cout << "-" << endl;
      break;

   case MultOp:
      cout << "*" << endl;
      break;

   case DivOp:
      cout << "/" << endl;
      break;

   default:
      cerr << "error: unsupported arithmetic operator: " << op << endl;
      exit(1);
   }

   return 0;
}

int IdentSeqCls::emit()
{
   return 0;
}

int DeclarationCls::emit()
{
   return 0;
}

int DeclarationSeqCls::emit()
{
   if (debugFlag) cout << "DeclarationSeqCls::emit()" << endl;
   PDeclarationCls p = this -> seq_head;
   while (p) {
      p -> emit();
      p = PDeclarationCls(p->get_next());
   }

   return 0;
}

int BlockCls :: emit() {
   if (debugFlag) cout << "BlockCls::emit() " << endl;
   return this -> stmt_seq -> emit();
}

int ProgramCls :: emit() {
   if (debugFlag) cout << "ProgramCls::emit() " << endl;
   if (block && std_table) {
      this -> block -> emit();

      cout << "finish" << endl;

      return 0;
   } else {
      cerr << "ProgramCls::emit - LOGIC ERROR" << endl;
      return 0;
   }
}