#include "Interpreter.hpp"
using namespace std;
void interpreter::load_commands() {
while (input_.good()) {
string line;
getline(input_, line);
process_line_(line);
}
}
void interpreter::execute_commands() {
while (current_instruction_ < instructions_.size()) {
instructions_.at(current_instruction_)->execute(*this);
current_instruction_++;
}
}
void interpreter::process_line_(const std::string& line) {
// Nejdriv se zbavim pripadnych komentaru.
string line_ = line;
for (int i = 0; i < line.size(); i++) {
if (line_.at(i) == '#') {
line_ = line.substr(0, i);
break;
}
}
if (line_ == "") return; // Prazdna radka, jenom komentar.
// Nyni odeberu prebytecne whitespace a rozdelim radku na jednotlive tokeny. Na to mam funkci.
vector<string> tokens_with_label = get_tokens_(line_);
vector<string> tokens;
// Nyni se podivam, jestli radka obsahuje navesti. Muze byt pouze v prvnim tokenu.
if (tokens_with_label.at(0)[tokens_with_label.at(0).size() - 1] == ':') {
labels_.insert(make_pair(tokens_with_label.at(0), instructions_.size() - 1));
for (int i = 1; i < tokens_with_label.size(); i++) {
tokens.push_back(tokens_with_label.at(i));
}
}
else tokens = tokens_with_label;
if (tokens_with_label.at(tokens.size() - 1) == "") tokens.pop_back();
if (tokens.at(tokens.size() - 1) == "") tokens.pop_back();
if (tokens.size() == 0 && tokens_with_label.size() > 0) throw invalid_argument("Label found but no instruction given.");
// Na nultem miste ve vektoru by mel byt vzdy nazev instrukce.
if (tokens.size() == 0) return; // Prazdna radka -> skip.
if (tokens.at(0) == "ldconst") {
if (tokens.size() != 2) throw invalid_argument("Invalid argument count.");
int value;
try {
value = stoi(tokens.at(1));
}
catch (exception ex) {
throw invalid_argument("Error while parsing constant.");
}
instructions_.push_back(make_unique<ldconst>(value));
}
else if (tokens.at(0) == "stloc") {
if (tokens.size() != 2) throw invalid_argument("Invalid argument count.");
int index;
try {
index = stoi(tokens.at(1));
}
catch (exception ex) {
throw invalid_argument("Error while parsing constant.");
}
if (index < 0 || index > 9) throw invalid_argument("Invalid index of variable.");
instructions_.push_back(make_unique<stloc>(index));
}
else if (tokens.at(0) == "ldloc") {
if (tokens.size() != 2) throw invalid_argument("Invalid argument count.");
int index;
try {
index = stoi(tokens.at(1));
}
catch (exception ex) {
throw invalid_argument("Error while parsing constant.");
}
if (index < 0 || index > 9) throw invalid_argument("Invalid index of variable.");
instructions_.push_back(make_unique<ldloc>(index));
}
else if (tokens.at(0) == "pop") {
if (tokens.size() != 1) throw invalid_argument("Invalid argument count.");
instructions_.push_back(make_unique<pop>());
}
else if (tokens.at(0) == "out") {
if (tokens.size() != 1) throw invalid_argument("Invalid argument count.");
instructions_.push_back(make_unique<out>());
}
else if (tokens.at(0) == "add") {
if (tokens.size() != 1) throw invalid_argument("Invalid argument count.");
instructions_.push_back(make_unique<add>());
}
else if (tokens.at(0) == "sub") {
if (tokens.size() != 1) throw invalid_argument("Invalid argument count.");
instructions_.push_back(make_unique<sub>());
}
else if (tokens.at(0) == "div") {
if (tokens.size() != 1) throw invalid_argument("Invalid argument count.");
instructions_.push_back(make_unique<div>());
}
else if (tokens.at(0) == "mul") {
if (tokens.size() != 1) throw invalid_argument("Invalid argument count.");
instructions_.push_back(make_unique<mul>());
}
else if (tokens.at(0) == "lt") {
if (tokens.size() != 1) throw invalid_argument("Invalid argument count.");
instructions_.push_back(make_unique<lt>());
}
else if (tokens.at(0) == "gt") {
if (tokens.size() != 1) throw invalid_argument("Invalid argument count.");
instructions_.push_back(make_unique<gt>());
}
else if (tokens.at(0) == "goto") {
if (tokens.size() != 2) throw invalid_argument("Invalid argument count.");
string label = tokens.at(1);
instructions_.push_back(make_unique<gotoi>(label));
}
else if (tokens.at(0) == "brt") {
if (tokens.size() != 2) throw invalid_argument("Invalid argument count.");
string label = tokens.at(1);
instructions_.push_back(make_unique<brt>(label));
}
else if (tokens.at(0) == "brf") {
if (tokens.size() != 2) throw invalid_argument("Invalid argument count.");
string label = tokens.at(1);
instructions_.push_back(make_unique<brf>(label));
}
else throw invalid_argument("Unknown token.");
}
std::vector<std::string> interpreter::get_tokens_(const std::string& line) {
vector<string> tokens;
tokens.push_back(string());
for (auto&& c : line) {
if (c == ' ' || c == '\t') {
if (tokens.at(tokens.size() - 1) != "") { // Pokud je posledni token prazdny, tzn. ze zatim tam byly pouze whitespace, nedelame nic. Jinak vytvorime novy token.
tokens.push_back(string());
}
}
else
tokens.at(tokens.size() - 1) += c; // Jinak pridame znak do posledniho tokenu.
}
return tokens;
}