version 0.1

This commit is contained in:
Hans 2021-11-17 19:19:49 +01:00
parent eddfeb7bfc
commit dbfdde72ab
20 changed files with 740 additions and 55 deletions

150
src/runtime.cpp Normal file
View file

@ -0,0 +1,150 @@
#include <iostream>
#include <cmath>
#include "runtime.hpp"
#include "exceptions.hpp"
bool Runtime::var_exists(const std::string& identifier)
{
return std::any_of(variables.begin(), variables.end(),
[&identifier](auto& var) {
return var.name == identifier;
});
}
const std::vector<Variable>::iterator Runtime::var_find(const std::string& identifier)
{
auto it = std::find_if(variables.begin(), variables.end(),
[&identifier](auto& var) {
return var.name == identifier;
});
if(it == variables.end())
throw UndeclaredVariableExcept(identifier);
return it;
}
ValueType Runtime::resolve_var_type(const std::string& identifier)
{
for(auto& var : variables)
{
if(var.name == identifier)
return var.type;
}
throw UndeclaredVariableExcept(identifier);
}
const std::string Runtime::resolve_var_str(const std::string& identifier)
{
if(resolve_var_type(identifier) != ValueType::STRING)
throw TypeErrorExcept(identifier, ValueType::STRING, ValueType::NUMBER);
return var_find(identifier)->val_string;
}
float Runtime::resolve_var_num(const std::string& identifier)
{
if(resolve_var_type(identifier) != ValueType::NUMBER)
throw TypeErrorExcept(identifier, ValueType::NUMBER, ValueType::STRING);
return var_find(identifier)->val_number;
}
void Runtime::assign_var_num(const std::string& identifier, float num)
{
// Because redeclaration of variables is allowed
if(var_exists(identifier))
{
auto it = std::find_if(variables.begin(), variables.end(),
[&identifier](auto& var) {
return identifier == var.name;
});
it->type = ValueType::NUMBER;
it->val_number = num;
it->val_string = "";
}
else
variables.emplace_back(identifier, ValueType::NUMBER, "", num);
}
void Runtime::assign_var_str(const std::string& identifier, const std::string& str)
{
// Because redeclaration of variables is allowed
if(var_exists(identifier))
{
auto it = std::find_if(variables.begin(), variables.end(),
[&identifier](auto& var) {
return identifier == var.name;
});
it->type = ValueType::NUMBER;
it->val_number = 0;
it->val_string = str;
}
else
variables.emplace_back(identifier, ValueType::STRING, str, 0);
}
void Runtime::execute_instruction(const Instruction& instruction)
{
instruction.keyword_ptr->func(*this, instruction.tokens);
}
void Runtime::jump_instructions(int new_instr_counter)
{
if(new_instr_counter > instructions.size() || new_instr_counter < 1)
throw JumpOutOfBoundsExcept(instruction_counter + 1, new_instr_counter);
else
instruction_counter = new_instr_counter - 2; // -1 to account for increment after each instr
}
int Runtime::run()
{
// reset everything
instruction_counter = 0;
variables.clear();
for(;;)
{
if(instruction_counter >= instructions.size())
{
std::cout << "ERROR: Unexpected end of instructions!" << std::endl;
std::exit(EXIT_FAILURE);
}
try // Execute our instruction
{
execute_instruction(instructions[instruction_counter]);
}
catch(TypeErrorExcept& e)
{
std::cout << "ERROR: In line " << instruction_counter + 1 << ": "
<< "Type mismatch. Argument '" << e.token_str
<< "' has type " << resolve_ValueType_str(e.got)
<< " but " << resolve_ValueType_str(e.expected)
<< " was expected." << std::endl;
std::exit(EXIT_FAILURE);
}
catch(UndeclaredVariableExcept& e)
{
std::cout << "ERROR: In line " << instruction_counter + 1 << ": "
<< "Undefined variable '" << e.identifier_str
<< "'" << std::endl;
std::exit(EXIT_FAILURE);
}
catch(JumpOutOfBoundsExcept& e)
{
std::cout << "ERROR: In line " << e.from << ": "
<< "Jump target '" << e.to << "' is out of bounds."
<< std::endl;
std::exit(EXIT_FAILURE);
}
// Increment instruction counter
++instruction_counter;
}
return 0;
}