/*****************************************************************\
*                                                                *
*  Copyright (C) Regents of University of California, 2003       *
*  This source code is a part of EXPRESSION project and is       *
*  copyrighted by the Regents of the University of California,   *
*  Irvine.                                                       *
*  The authors hereby grant permission to use this description   *
*  and its documentation for educational and non-commercial      *
*  purpose under the BSD license                                 *
*  (http://www.cecs.uci.edu/~express/BSD_License.txt). 	         *
*  The source code comes with no warranty and no author or       *
*  distributor accepts any responsibility for the consequences   *
*  of its use. Permission is granted to distribute this file in  *
*  compiled or executable form under the same conditions that    *
*  apply for source code. Permission is granted	to anyone to     *
*  make or distribute copies of this source code, either as      *
*  received or modified, in any medium, provided that all        *
*  copyright notices, permission and non warranty notices are    *
*  preserved, and that the distributor grants the recipient      *
*  permission for further redistribution as permitted by this    *
*  document. No written agreement, license, or royalty fee is    *
*  required for authorized use of this software.                 *
*                                                                *
*******************************************************************/
#include "parser.h"
#include "errors.h"
#include "symbols.h"
#include "node.h"
#include <string.h>
#include <iostream.h>


SymbolPtr Symtab::Declare(char *name,NodePtr node){ // high-level declaration with symbol construction
	SymbolPtr p=FindSymbol(name);
	if(p==NULL){
		SymbolPtr sym=new Symbol(name,node);
		_symlist.push_back(sym);
		return sym;
	}
	else{
		p->AddDef(node);
		return p;
	}
}

SymbolPtr Symtab::FindSymbol(char * name){
	SymbolList::iterator i;
	for(i=_symlist.begin();i!=_symlist.end();i++){
		if(strcmp((*i)->Name(),name)==0) 
			return *i;
	}
	return NULL;
}

SymbolPtr Symtab::GetSymbol(char * name){
	SymbolList::iterator i;
	for(i=_symlist.begin();i!=_symlist.end();i++){
		if(strcmp((*i)->Name(),name)==0) 
			return *i;
	}
	char buf[1000];
	sprintf(buf,"%s symbol not declared",name);
	semantic_error(buf);
	return NULL;
}


void Symtab :: Print()
{
	SymbolList::iterator i;
	NodeList::iterator j;
	for(i=_symlist.begin();i!=_symlist.end();i++){
		printf("%s\n",(*i)->Name());
		printf("\t(Defs: ");
		for(j=(*i)->GetDefList()->begin();j!=(*i)->GetDefList()->end();j++)
			printf("%s ",node_kind_names[(*j)->Kind()]);
		printf(",Uses: ");
		for(j=(*i)->GetUseList()->begin();j!=(*i)->GetUseList()->end();j++)
			printf("%s ",node_kind_names[(*j)->Kind()]);
		printf(")\n");
	}
}

int Symtab :: Traverse(int(*func)(SymbolPtr))
{
	SymbolList::iterator i;
	for(i=_symlist.begin();i!=_symlist.end();i++){
		if(func(*i)) return 1;
	}
	return 0;
}

void Symtab::patchForwRefs()
{
	SymbolList::iterator i;
	for(i=_symlist.begin();i!=_symlist.end();i++)
	{
		Symbol *s = (*i);
		if (s->any_def_is(nke_regs) && s->any_def_is(nke_component))
		{
			// cout << s->Name() << endl;

			// nke_component is the true definition
			// rest are uses
			NodeList::iterator j;
			int done = 0;
			while(!done)
			{
				done = 1;
				for(j = s->GetDefList()->begin(); j != s->GetDefList()->end(); j++)
				{
					NodePtr def = (*j);
					if (def->Kind() == nke_regs)
					{
						s->RemoveDef(def);
						s->AddUse(def);
						done = 0;
						break;
					}
				}
			}
		}
	}
}