Commit 2b438a82 by Andrew Dahl

Fixes #11 - Stage 8 Non-recursive functions works perfectly!

parent 2db135f4
......@@ -26,7 +26,7 @@ class Symbol {
union value_t {
int i;
float f;
Symbol* s; // These will be variables for functions...
Symbol* s; // These will be variables for functions in a string
};
Symbol();
......@@ -43,11 +43,13 @@ class Symbol {
void setValue(float value);
void setValue(Symbol* value);
value_t getValue() const;
void setFunctionValue(Symbol* value);
Symbol* getFunctionValue() const;
void setType(enum Type valueType);
enum Type getType() const;
void setReturnType(enum Type returnType);
enum Type getReturnType() const;
int getArguments();
int getArguments(bool isFunction=false);
bool operator==(const Symbol *rhs) const;
string toString() const;
......@@ -57,6 +59,7 @@ private:
value_t value;
Type valueType;
Type returnType;
Symbol* f; // These will be variables for the function
};
#endif /* SYMBOL_H_ */
......@@ -24,7 +24,7 @@ public:
SymbolTable(int parent_table_num = -1, SymbolTable* parent_table = NULL);
int Count() const;
Symbol* Insert(const Symbol *entry); // Variable or Function insertion
Symbol* Insert(Symbol *entry); // Variable or Function insertion
Symbol* Insert(const int value); // Constant Value insertion
Symbol* Insert(const float value); // Constant Value insertion
Symbol* FindConstant(const int value);
......
......@@ -15,7 +15,7 @@
using std::vector;
// Declare yyparse here so we can use it... the actual function is linked later
int yyparse (vector<SymbolTable*> symbol_table, InstructionList* instructions);
int yyparse (vector<SymbolTable*>* symbol_table, InstructionList* instructions);
Compiler::Compiler(int argc, char *argv[])
{
......@@ -38,10 +38,10 @@ void Compiler::Run()
{
// Initialize our symbol table and instruction list
InstructionList* instructions = new InstructionList();
vector<SymbolTable*> symbol_table;
symbol_table.push_back(new SymbolTable());
symbol_table[0]->Insert(new Symbol("readInput", Symbol::INPUT, Symbol::INTEGER));
symbol_table.push_back(new SymbolTable(0, symbol_table[0]));
vector<SymbolTable*>* symbol_table = new vector<SymbolTable*>();
symbol_table->push_back(new SymbolTable());
symbol_table->at(0)->Insert(new Symbol("readInput", Symbol::INPUT, Symbol::INTEGER));
symbol_table->push_back(new SymbolTable(0, symbol_table->at(0)));
// For each source file we have... at this time, we just have one, so this may never be needed
for (vector<string>::iterator i = this->filenames.begin(); i != this->filenames.end(); i++)
......@@ -54,16 +54,20 @@ void Compiler::Run()
throw CompilerException("yyparse() failed");
}
string output = instructions->toString();
#ifdef COMPILER_VERBOSE
for (unsigned int i = 0; i < symbol_table.size(); i++)
for (unsigned int i = 0; i < symbol_table->size(); i++)
{
std::cerr << std::endl << i << std::endl;
symbol_table[i]->Print();
symbol_table->at(i)->Print();
}
instructions->Print();
#endif
string output = instructions->toString();
#ifdef COMPILER_VERBOSE
instructions->Print();
#endif
// Open the output file and write the generated assembly to it
std::ofstream of;
of.open(this->output.c_str());
......
......@@ -75,7 +75,7 @@ Symbol* InstructionList::stackPop(int num)
void InstructionList::levelPush()
{
this->levelStack.push_back(this->levelStack.back() + 1);
this->levelStack.push_back(this->instructions.size());
}
int InstructionList::levelPop()
......@@ -88,11 +88,18 @@ int InstructionList::levelPop()
int InstructionList::stackPushFunctionParam(Symbol* sym)
{
int offset = 0;
Symbol* top = NULL;
if(sym != NULL)
{
top = this->stackPop();
offset = this->stackPushFunctionParam(sym->getValue().s);
this->stackPush(sym);
if(sym->getType() != Symbol::FUNCTION)
{
sym->setReturnType(top->getReturnType());
this->stackPush(sym);
}
else
this->stackPush(top);
if(sym->getReturnType() == Symbol::FLOAT)
offset += 8;
......@@ -153,7 +160,6 @@ string InstructionList::toString()
*/
for(it = this->instructions.begin(); it != this->instructions.end(); it++)
{
this->Print();
varAddrSpace = this->findVarStackSpace(it->second);
if(it->second[0]->getOpcode() != Instruction::FUNCTION_START)
{
......@@ -168,6 +174,7 @@ string InstructionList::toString()
for(itr = it->second.begin(); itr != it->second.end(); itr++)
{
temp = itr->second;
std::cerr << temp->toGenericString() << endl;
//TODO: Some seriously awesome stuff
switch(temp->getOpcode())
......@@ -353,10 +360,8 @@ string InstructionList::toString()
break;
case Instruction::CALL:
//oss << "CALL "<< temp->getArg1().sym->getLexeme() << "\n";
this->stackPop(temp->getArg1().sym->getArguments());
oss << FunctionToString(temp, this->stackPushFunctionParam(temp->getArg2().sym->getValue().s));
std::cerr << "LOOOOOOOOOOOOOOOOOK ATTTTTTTTTTTTTT MEEEEEEEEEEEEEEEEEE\n";
this->PrintStack();
//this->stackPop(temp->getArg1().sym->getArguments(true));
oss << FunctionToString(temp, this->stackPushFunctionParam(temp->getArg2().sym->getFunctionValue()));
/*if(temp->getArg1().sym->getReturnType() == Symbol::FLOAT)
{
this->stackPush(new Symbol("temp", Symbol::FLOAT, Symbol::FLOAT));
......@@ -408,15 +413,13 @@ string InstructionList::FunctionToString(Instruction* inst, int varAddrSpace) {
for(it = this->instructions.begin(); it != this->instructions.end(); it++)
{
std::cerr << "HIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII" << it->second[0]->getArg1().sym->getLexeme() << " " << inst->getArg1().sym->getLexeme() << std::endl;
if(it->second[0]->getArg1().sym->getLexeme() == inst->getArg1().sym->getLexeme())
if(it->second[0]->getOpcode() == Instruction::FUNCTION_START &&
it->second[0]->getArg1().sym->getLexeme() == inst->getArg1().sym->getLexeme())
{
this->Print();
std::cerr << "HIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII";
for(itr = ++(it->second.begin()); itr != it->second.end(); itr++)
{
temp = itr->second;
std::cerr << temp->toGenericString() << endl;
//TODO: Some seriously awesome stuff
switch(temp->getOpcode())
......@@ -601,21 +604,11 @@ string InstructionList::FunctionToString(Instruction* inst, int varAddrSpace) {
}
break;
case Instruction::CALL:
oss << "CALL "<< temp->getArg1().sym->getLexeme() << "\n";
if(temp->getArg1().sym->getReturnType() == Symbol::FLOAT)
{
this->stackPush(new Symbol("temp", Symbol::FLOAT, Symbol::FLOAT));
oss << INSTRUCTION_POP_FPU_TO_STACK;
}
else
{
this->stackPush(new Symbol("temp", Symbol::INTEGER, Symbol::INTEGER));
oss << "PUSH EBX\n";
}
oss << FunctionToString(temp, this->stackPushFunctionParam(temp->getArg2().sym->getFunctionValue()));
break;
case Instruction::FUNCTION_START:
// Do we care? Yes.
oss << endl << temp->getArg1().sym->getLexeme() << ":\n";
//oss << endl << temp->getArg1().sym->getLexeme() << ":\n";
break;
case Instruction::VARDECL:
// This is just a placeholder... the only purpose for VARDECL is for determining space needed on the stack
......@@ -629,7 +622,6 @@ string InstructionList::FunctionToString(Instruction* inst, int varAddrSpace) {
else
oss << "POP EBX\n";
std::cerr << "ONCE AGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIN \n" << varAddrSpace << std::endl;
oss << "ADD ESP, " << varAddrSpace << endl;
Symbol* tmp = this->stackPop();
this->moveStackPointer(varAddrSpace);
......
......@@ -19,7 +19,7 @@
int level = 1;
%}
%parse-param { vector<SymbolTable*> symbol_table }
%parse-param { vector<SymbolTable*>* symbol_table }
%parse-param { InstructionList* instructions }
%union {
......@@ -34,7 +34,7 @@
%token <fnum> FLOAT
%token <name> ID
%type <sym> stat additive_exp mult_exp primary_exp assignment_exp function_define argument_exp_list func_call_args
%type <sym> stat additive_exp mult_exp primary_exp additive_exp_func mult_exp_func primary_exp_func assignment_exp function_define argument_exp_list func_call_args
%% /* Grammer Rules and Actions */
......@@ -51,17 +51,17 @@ external_decl: NEWLINE
| error { yyerrok;}
;
function_define: FUNCTION ID LPAREN argument_exp_list RPAREN EQUALS {
Symbol::value_t symbol_value; symbol_value.s = $4;
Symbol* temp = symbol_table[level]->Insert(new Symbol($2, symbol_value, Symbol::FUNCTION));
symbol_table.push_back(new SymbolTable(level, symbol_table[level]));
level = symbol_table.size()-1;
symbol_table[level]->Insert(temp);
function_define: FUNCTION ID LPAREN {
Symbol* temp = symbol_table->at(level)->Insert(new Symbol($2, Symbol::FUNCTION, Symbol::INTEGER));
symbol_table->push_back(new SymbolTable(level, symbol_table->at(level)));
level = symbol_table->size()-1;
symbol_table->at(level)->Insert(temp);
instructions->levelPush();
instructions->addInstruction(new Instruction(Instruction::FUNCTION_START, temp));
} additive_exp {
Symbol* temp = symbol_table[level]->Find($2);
level = symbol_table[level]->getParentTable();
} argument_exp_list RPAREN EQUALS additive_exp_func NEWLINE {
Symbol* temp = symbol_table->at(level)->Find($2);
temp->setFunctionValue($5);
level = symbol_table->at(level)->getParentTable();
temp->setReturnType($8->getReturnType());
instructions->levelPop();
$$ = temp;
......@@ -70,17 +70,17 @@ function_define: FUNCTION ID LPAREN argument_exp_list RPAREN EQUALS {
argument_exp_list: { $$ = NULL;}
| ID {
$$ = symbol_table[level]->Insert(new Symbol($1, Symbol::VARIABLE, Symbol::INTEGER));
$$ = (symbol_table->at(level))->Insert(new Symbol($1, Symbol::VARIABLE, Symbol::INTEGER));
}
| argument_exp_list COMMA ID {
Symbol::value_t symbol_value; symbol_value.s = $1;
$$ = symbol_table[level]->Insert(new Symbol($3, symbol_value, Symbol::VARIABLE));
$$ = symbol_table->at(level)->Insert(new Symbol($3, symbol_value, Symbol::VARIABLE));
}
;
assignment_exp: additive_exp
| ID EQUALS assignment_exp {
Symbol* temp = symbol_table[level]->Insert(new Symbol($1, Symbol::VARIABLE, $3->getReturnType()));
Symbol* temp = symbol_table->at(level)->Insert(new Symbol($1, Symbol::VARIABLE, $3->getReturnType()));
instructions->addInstruction(new Instruction(Instruction::VARDECL, temp));
instructions->addInstruction(new Instruction(Instruction::MOV, temp));
instructions->addInstruction(new Instruction(Instruction::POP));
......@@ -91,7 +91,7 @@ stat: OUTPUT additive_exp NEWLINE {
instructions->addInstruction(new Instruction(Instruction::OUTPUT));
}
| ID EQUALS assignment_exp NEWLINE {
Symbol* temp = symbol_table[level]->Insert(new Symbol($1, Symbol::VARIABLE, $3->getReturnType()));
Symbol* temp = symbol_table->at(level)->Insert(new Symbol($1, Symbol::VARIABLE, $3->getReturnType()));
instructions->addInstruction(new Instruction(Instruction::VARDECL, temp));
instructions->addInstruction(new Instruction(Instruction::MOV, temp));
instructions->addInstruction(new Instruction(Instruction::POP));
......@@ -147,45 +147,127 @@ primary_exp: LPAREN additive_exp RPAREN {
$$ = $2;
}
| NUMBER {
Symbol* temp = symbol_table[level]->Insert($1);
Symbol* temp = symbol_table->at(level)->Insert($1);
instructions->addInstruction(new Instruction(Instruction::PUSH, temp));
$$ = temp;
}
| FLOAT {
Symbol* temp = symbol_table[level]->Insert($1);
Symbol* temp = symbol_table->at(level)->Insert($1);
instructions->addInstruction(new Instruction(Instruction::PUSH, temp));
$$ = temp;
}
| USERINPUT {
instructions->addInstruction(new Instruction(Instruction::INPUT));
$$ = symbol_table[level]->Find("readInput");
$$ = symbol_table->at(level)->Find("readInput");
}
| ID {
Symbol* temp = symbol_table[level]->Find($1);
Symbol* temp = symbol_table->at(level)->Find($1);
if(temp == NULL) {
yyerror(symbol_table, instructions, "Variable not declared yet!");
} else if (temp->getType() == Symbol::FUNCTION) {
yyerror(symbol_table, instructions, "Function used like variable!");
YYABORT;
} else {
instructions->addInstruction(new Instruction(Instruction::PUSH, temp));
$$ = temp;
}
}
| ID LPAREN func_call_args RPAREN {
Symbol* temp = symbol_table[level]->Find($1);
Symbol* func = new Symbol(temp);
func->setValue($3);
fprintf(stderr, "%d %d", temp->getArguments(), func->getArguments());
| ID LPAREN func_call_args RPAREN {
Symbol* temp = symbol_table->at(level)->Find($1);
if(temp == NULL) {
yyerror(symbol_table, instructions, "Function not declared yet!");
} else if(temp->getArguments() != func->getArguments()) {
yyerror(symbol_table, instructions, "Incorrect number of arguments given!");
} else {
instructions->addInstruction(new Instruction(Instruction::CALL, func, temp));
$$ = func;
Symbol* func = new Symbol(temp);
func->setFunctionValue($3);
if(temp->getArguments(true) != func->getArguments(true)) {
yyerror(symbol_table, instructions, "Incorrect number of arguments given!");
} else {
instructions->addInstruction(new Instruction(Instruction::CALL, func, temp));
$$ = func;
}
}
}
;
additive_exp_func: additive_exp_func PLUS mult_exp_func {
instructions->addInstruction(new Instruction(Instruction::ADD));
if($1->getReturnType() == Symbol::FLOAT || $3->getReturnType() == Symbol::FLOAT)
$$ = new Symbol("temp",static_cast<float>(1.0));
else
$$ = new Symbol("temp",1);
}
| additive_exp_func MINUS mult_exp_func {
instructions->addInstruction(new Instruction(Instruction::SUB));
if($1->getReturnType() == Symbol::FLOAT || $3->getReturnType() == Symbol::FLOAT)
$$ = new Symbol("temp",static_cast<float>(1.0));
else
$$ = new Symbol("temp",1);
}
| mult_exp_func {
$$ = $1;
}
;
mult_exp_func: mult_exp_func ASTERISK primary_exp_func {
instructions->addInstruction(new Instruction(Instruction::MUL));
if($1->getReturnType() == Symbol::FLOAT || $3->getReturnType() == Symbol::FLOAT)
$$ = new Symbol("temp",static_cast<float>(1.0));
else
$$ = new Symbol("temp",1);
}
| mult_exp_func SLASH primary_exp_func {
if($3->getType() == Symbol::INTEGER) {
if($3->getValue().i == 0)
yyerror(symbol_table, instructions, "Cannot divide by 0");
} else if($3->getType() == Symbol::FLOAT) {
if($3->getValue().f == 0)
yyerror(symbol_table, instructions, "Cannot divide by 0");
}
instructions->addInstruction(new Instruction(Instruction::DIV));
if($1->getReturnType() == Symbol::FLOAT || $3->getReturnType() == Symbol::FLOAT)
$$ = new Symbol("temp",static_cast<float>(1.0));
else
$$ = new Symbol("temp",1);
}
| primary_exp_func {
$$ = $1;
}
;
primary_exp_func: LPAREN additive_exp_func RPAREN {
$$ = $2;
}
| NUMBER {
Symbol* temp = symbol_table->at(level)->Insert($1);
instructions->addInstruction(new Instruction(Instruction::PUSH, temp));
$$ = temp;
}
| FLOAT {
Symbol* temp = symbol_table->at(level)->Insert($1);
instructions->addInstruction(new Instruction(Instruction::PUSH, temp));
$$ = temp;
}
| USERINPUT {
instructions->addInstruction(new Instruction(Instruction::INPUT));
$$ = symbol_table->at(level)->Find("readInput");
}
| ID {
Symbol* temp = symbol_table->at(level)->Find($1);
if(temp == NULL) {
yyerror(symbol_table, instructions, "Variable not declared yet!");
} else if (temp->getType() == Symbol::FUNCTION) {
yyerror(symbol_table, instructions, "Function used like variable!");
} else {
instructions->addInstruction(new Instruction(Instruction::PUSH, temp));
$$ = temp;
}
}
| ID LPAREN func_call_args RPAREN {
yyerror(symbol_table, instructions, "Cannot use function within a function!");
}
;
func_call_args: { $$ = NULL; }
| additive_exp {
Symbol* temp = new Symbol($1);
......
......@@ -13,6 +13,7 @@ using std::stringstream;
Symbol::Symbol()
{
this->value.s = NULL;
this->f = NULL;
}
Symbol::Symbol(const Symbol *symbol)
......@@ -22,9 +23,12 @@ Symbol::Symbol(const Symbol *symbol)
Symbol::Symbol(string lexeme, Type valueType, Type returnType)
{
this->value.s = NULL;
this->f = NULL;
this->setType(valueType);
this->setLexeme(lexeme);
this->setReturnType(returnType);
}
Symbol::Symbol(string lexeme, value_t value, Type valueType)
......@@ -32,6 +36,7 @@ Symbol::Symbol(string lexeme, value_t value, Type valueType)
this->setLexeme(lexeme);
this->setType(valueType);
this->value = value;
this->f = NULL;
}
Symbol::Symbol(string lexeme, value_t value, Type valueType, Type returnType)
......@@ -40,6 +45,7 @@ Symbol::Symbol(string lexeme, value_t value, Type valueType, Type returnType)
this->setType(valueType);
this->setReturnType(returnType);
this->value = value;
this->f = NULL;
}
Symbol::Symbol(string lexeme, int value)
......@@ -47,6 +53,7 @@ Symbol::Symbol(string lexeme, int value)
this->setLexeme(lexeme);
this->setValue(value);
this->setReturnType(Symbol::INTEGER);
this->f = NULL;
}
Symbol::Symbol(string lexeme, float value)
......@@ -54,6 +61,7 @@ Symbol::Symbol(string lexeme, float value)
this->setLexeme(lexeme);
this->setValue(value);
this->setReturnType(Symbol::FLOAT);
this->f = NULL;
}
void Symbol::setLexeme(string lexeme)
......@@ -83,6 +91,16 @@ void Symbol::setValue(Symbol* value)
this->value.s = value;
}
void Symbol::setFunctionValue(Symbol* value)
{
this->f = value;
}
Symbol* Symbol::getFunctionValue() const
{
return this->f;
}
Symbol::value_t Symbol::getValue() const
{
return this->value;
......@@ -105,10 +123,12 @@ void Symbol::setReturnType(enum Symbol::Type returnType)
this->returnType = returnType;
}
int Symbol::getArguments()
int Symbol::getArguments(bool isFunction)
{
if((this->getType() == Symbol::FUNCTION || this->getType() == Symbol::VARIABLE) && this->getValue().s != NULL)
return this->getValue().s->getArguments() + 1;
if(this->getType() == Symbol::FUNCTION && this->f != NULL && isFunction)
return this->f->getArguments(false);
else if(((this->getType() == Symbol::FUNCTION && !isFunction) || this->getType() == Symbol::VARIABLE) && this->getValue().s != NULL)
return this->getValue().s->getArguments(false) + 1;
return 0;
}
......@@ -152,13 +172,26 @@ bool Symbol::operator==(const Symbol *rhs) const
if(rhs->getLexeme() == this->getLexeme() &&
rhs->getReturnType() == this->getReturnType())
{
if(rhs->getFunctionValue() != NULL && this->getFunctionValue() != NULL)
{
Symbol a(rhs->getFunctionValue());
if(a == this->getFunctionValue())
return true;
}
}
break;
case Symbol::FUNC_ARG:
if(rhs->getLexeme() == this->getLexeme() &&
rhs->getReturnType() == this->getReturnType())
{
if(rhs->getValue().s != NULL && this->getValue().s != NULL)
{
Symbol a(rhs->getValue().s);
if(a == this->getValue().s)
return true;
return true;
}
}
break;
}
}
......@@ -179,10 +212,27 @@ string Symbol::toString() const
oss << "Variable\t";
if(this->value.s != NULL)
oss << this->value.s->toString();
if(this->f != NULL)
oss << this->f->toString();
break;
case FLOAT:
oss << "Float\t" << this->value.f;
break;
case FUNCTION:
oss << "Function\t";
if(this->value.s != NULL)
oss << this->value.s->toString();
if(this->f != NULL)
oss << this->f->toString();
break;
case FUNC_ARG:
oss << "Function Argument\t";
if(this->value.s != NULL)
oss << this->value.s->toString();
if(this->f != NULL)
oss << this->f->toString();
break;
break;
default:
break;
}
......
......@@ -23,18 +23,18 @@ int SymbolTable::Count() const
return this->table.size();
}
Symbol* SymbolTable::Insert(const Symbol *entry)
Symbol* SymbolTable::Insert(Symbol *entry)
{
Symbol *tmp = new Symbol(entry);
//Symbol *tmp = new Symbol(entry);
map<string,Symbol*>::iterator it;
it = this->table.find(tmp->getLexeme());
it = this->table.find(entry->getLexeme());
if(it == this->table.end())
this->table.insert( std::pair<string,Symbol*>(tmp->getLexeme(),tmp));
this->table.insert( std::pair<string,Symbol*>(entry->getLexeme(),entry));
else
tmp = it->second;
entry = it->second;
return tmp;
return entry;
}
Symbol* SymbolTable::Insert(const int value)
......@@ -108,6 +108,8 @@ void SymbolTable::Print()
break;
case Symbol::FUNCTION:
std::cerr << it->second->getLexeme() << " ";
if(it->second->getFunctionValue() != NULL)
std::cerr << it->second->getFunctionValue()->toString();
if(it->second->getValue().s != NULL)
std::cerr << it->second->getValue().s->toString();
break;
......
var1 = 1.0
var2=1.1
var4=2
function func(a,b,c)=a+b+func(1,2,3)
output var2 + func(1,2,3)
output 1 + 2 + var2 + readInput
output var2
output 1.0 + 2.0 + 3.0 + 4.1
output var2
var4=20.5 - 0.5 + readInput
output var2
var2=50
output var2
output var1
output var4
a=readInput
b=readInput + 1.0
c=readInput + 2.5
function func(a,b,c,d)=a+b+c
function func1(a,b)=a-b
function func2()=0
output readInput + func(func1(readInput,a),2,func2(),0)
output a
output b
output c
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment