Instructions
Requirements and Specifications
Source Code
// Your implementation of the Stack class goes here!!!!
#include "Stack.hpp"
#include <iostream>
using namespace std;
ActivationRecord* Stack::pop() {
ActivationRecord* ar = back();
pop_back();
return ar;
}
void Stack::push(ActivationRecord *newAR) {
push_back(newAR);
}
ActivationRecord* Stack::top() const {
return back();
}
ActivationRecord* Stack::peek() const {
return top();
}
bool Stack::isEmpty() const {
return empty();
}
ostream& operator<<(ostream &os, const Stack &s) {
for (auto it = s.rbegin(); it != s.rend(); ++it) {
os << *(*it) << endl;
}
return os;
}
STATEMENT
// !!!!!! You will have to add code inside of this class. Some of
// the code provided here is designed to help you, but you
// do not need to use it if you do not want to.
#include "Statement.hpp"
#include <cstdlib>
#include <iomanip>
#include <iostream>
using namespace std;
int __nextSnum=0; // keeps track of the next statement number to use.
int __paramValue; // this is a global to help with passing a parameter.
/****
**** If you are following project specifications, then you will likley
**** find this function quite useful. When given an ActivationRecord
**** (pointer) and a string containing an operand, this function returns
**** the operand's value (as found in the ActivationRecord.)
****/
int getValue(ActivationRecord *ar, const std::string &operand)
{
if (operand == "$$") // looking for the parameter
return ar->parameterValue();
else if (isdigit(operand[0]) || operand[0]=='-') // constant value (int)
{
return atoi(operand.c_str());
}
else // ID
{
// find the variable in the activation record
Variable *var = (Variable *) ar->getVariable(operand);
// if the variable was not found, let the user know.
if (var==NULL)
{
cerr << "Attempt to use an uninitialized variable: "
<< operand << endl;
return 0;
}
else
return var->value(); //return value of the associated variable
}
}
/****
**** If you are following project specifications, then you will likley
**** find this function quite useful. When given an ActivationRecord
**** (pointer), a string containing an variable name, and a new value,
**** this function sets that variable to the new value (in the associated
**** ActivationRecord.) If the variable isn't found in the Activation
*** Record, it is added to the ActivationRecord.
****/
void setValue(ActivationRecord *ar, const std::string &varName, int toVal)
{
if (varName == "$$") // parameter
ar->parameterValue() = toVal;
else // anything else must be a variable
{
// get the Variable from the ActivationRecord
Variable *var = (Variable *) ar->getVariable(varName);
// no such variable? Means we need to add it to the ActivationRecord
if (var==NULL)
{
ar->addVariable(varName);
var = (Variable *) ar->getVariable(varName);
}
// now that we know we have a variable, set its value ...
var->value()=toVal;
}
}
//
// ******** YOU MUST CODE LARGE PARTS OF THIS !!!! **********
//
// Executes a statement. See the project handout for details. Some
// initial statements are given as examples.
//
// withStack - The ActivationRecord (i.e. execution) stack to use
// ft - the table of function names & starting points
//
// *should return the statement number (ddress) of the next statement to run
int
Statement::execute(Stack &withStack, const FunctionTable &ft) const
{
// the next statement will be 1 after this one ... with the exception
// of calls, rets, and skips (see project handout.)
int nextAddr = _snum+1;
if (_operation=="printS") // print string.
{
cout << _operands.front();
}
else if (_operation=="printN") // print number
{
// get the value to print from the current activation record.
int valueOfN = getValue(withStack.top(), _operands.front());
// print that value
cout << valueOfN;
}
else if (_operation=="printNL") // drop down a line in output
{
cout << endl; // yep, it's that simple!
}
else if (_operation=="call")
{
// getting function name
string fName = _operands.front();
// creating new activation record for this function call
ActivationRecord* ar = new ActivationRecord(fName, nextAddr, __paramValue);
// pushing record into the stack
withStack.push(ar);
// updating next address
nextAddr = ft.lookup(fName).firstInstruction();
}
else if (_operation=="ret")
{
// removing top record
ActivationRecord* ar = withStack.pop();
// changing next address according to record address
nextAddr = ar->returnAddress();
}
else if (_operation=="retv")
{
// removing top record
ActivationRecord* ar = withStack.pop();
// updating incoming return value in the next top record
ActivationRecord* ar2 = withStack.top();
ar2->incomingReturnValue() = getValue(ar, _operands.front());
// updating address
nextAddr = ar->returnAddress();
}
else if (_operation=="storet")
{
// getting current record
ActivationRecord* ar = withStack.top();
// setting value to variable with incoming return value
setValue(ar, _operands.front(), ar->incomingReturnValue());
}
else if (_operation=="param")
{
// getting current record
ActivationRecord* ar = withStack.top();
__paramValue = getValue(ar, _operands.front());
}
else if (_operation=="sub")
{
// getting each operand string value
auto it = _operands.begin();
string a = *it;
it++;
string b = *it;
it++;
string c = *it;
// getting current record
ActivationRecord* ar = withStack.top();
// updating value of operand c
setValue(ar, c, getValue(ar, a) - getValue(ar, b));
}
else if (_operation=="add")
{
// getting each operand string value
auto it = _operands.begin();
string a = *it;
it++;
string b = *it;
it++;
string c = *it;
// getting current record
ActivationRecord* ar = withStack.top();
// updating value of operand c
setValue(ar, c, getValue(ar, a) + getValue(ar, b));
}
else if (_operation=="mul")
{
// getting each operand string value
auto it = _operands.begin();
string a = *it;
it++;
string b = *it;
it++;
string c = *it;
// getting current record
ActivationRecord* ar = withStack.top();
// updating value of operand c
setValue(ar, c, getValue(ar, a) * getValue(ar, b));
}
else if (_operation=="div")
{
// getting each operand string value
auto it = _operands.begin();
string a = *it;
it++;
string b = *it;
it++;
string c = *it;
// getting current record
ActivationRecord* ar = withStack.top();
// updating value of operand c
setValue(ar, c, getValue(ar, a) / getValue(ar, b));
}
else if (_operation=="skipz")
{
// getting string values of both operands
auto it = _operands.begin();
string a = *it;
it++;
string b = *it;
// getting current record
ActivationRecord* ar = withStack.top();
// evaluating first operand
int firstVal = getValue(ar, a);
// evaluating second operand
int secondVal = getValue(ar, b);
// moving next address if first operand is 0
if (firstVal == 0) {
nextAddr += secondVal;
}
}
else if (_operation=="skipnz")
{
// getting string values of both operands
auto it = _operands.begin();
string a = *it;
it++;
string b = *it;
// getting current record
ActivationRecord* ar = withStack.top();
// evaluating first operand
int firstVal = getValue(ar, a);
// evaluating second operand
int secondVal = getValue(ar, b);
// moving next address if first operand is NOT 0
if (firstVal != 0) {
nextAddr += secondVal;
}
}
else if (_operation=="read")
{
// getting current record
ActivationRecord* ar = withStack.top();
// reading value from console
int val;
cin >> val;
// setting variable to this value
setValue(ar, _operands.front(), val);
}
else if (_operation=="dump")
{
// outputting current stack state
cout << withStack << endl;
}
else
{
cout << _operation << ": not implememnted" << endl;
}
return nextAddr;
}
// prints out this statement to the specified stream (overloads <<)
ostream& operator<<(ostream &os, const Statement &s)
{
// print the statement number in the specified width.
os.width(5);
os << s._snum << " ";
// print the operation
os << s._operation << '\t';
// print each operand ..
list<string>::const_iterator lsci = s._operands.begin();
for (int i=0; i< s._operandCount; i++)
{
os << *lsci << " ";
lsci++;
}
return os;
}