
#include <iostream.h>
#include "CPU.h"
#include "Array.h"

	CPU::CPU()
	:	_storage(),
		_runStack()
	{
	}

	void CPU::declare(unsigned int c) // OK to call more than once.
	{	if(!_storage.element(c)) _storage.atPut(c, 0);
	}

	void CPU::pushv(unsigned int c)
	{	int val;
		if( ! _storage.at(c,val)) userERROR("No such variable.");
		_runStack.push(val);
	}

	void CPU::pushi(int i)
	{	_runStack.push(i);
	}

	void CPU::pop(unsigned int c)
	{	int val;
		if(! _storage.at(c,val)) userERROR("No such variable.");
		_storage.atPut(c, _runStack.pop());
	}

	void CPU::add()
	{	int second = _runStack.pop();
		_runStack.push(_runStack.pop() + second);
	}

	void CPU::sub()
	{	int second = _runStack.pop();
		_runStack.push(_runStack.pop() - second);
	}

	void CPU::mult()
	{	int second = _runStack.pop();
		_runStack.push(_runStack.pop() * second);
	}

	void CPU::div()
	{	int second = _runStack.pop();
		_runStack.push(_runStack.pop() / second);
	}

	void CPU::negate()
	{	_runStack.push( - _runStack.pop() );
	}

	void CPU::output()
	{	cout << _runStack.top()<<endl;
	}

	void CPU::input()
	{	int x;
		cin >> x;
		_runStack.push(x);
	}

	void CPU::toss()
	{	_runStack.pop();
	}

	void CPU::dup()
	{	_runStack.push(_runStack.top());
	}
	
	Boolean CPU::pos()
	{	return Boolean(_runStack.top() > 0);
	}

	Boolean CPU::zero()
	{	return Boolean(_runStack.top() == 0);
	}

	void CPU::swap()
	{	int second = _runStack.pop();
		int first = _runStack.pop();
		_runStack.push(second);
		_runStack.push(first);
	}
	
	void CPU::outputAscii()
	{	cout<< char(_runStack.top())<<endl;
	}

	void CPU::inputAscii()
	{	char in;
		cin >> in;
		_runStack.push(int(in));
	}

	void CPU::halt()
	{	Array<Association<unsigned int,int> > memory(_storage.asArray());
		cout << endl<<"Memory dump"<<endl;
		for(int i = 0; i< memory.length(); ++i)
			cout<< memory[i].key()<<": "<<memory[i].value()<<endl;	
		userERROR("CPU halted.");
	}

