Basic arithmetic and jump labels

This commit is contained in:
2019-11-17 21:02:35 +01:00
commit b84557b3e1
34 changed files with 1350 additions and 0 deletions

View File

@@ -0,0 +1,165 @@
#include <interpret/operanddefinitions.hpp>
#include <interpret/errors.hpp>
namespace Interpret
{
Value GetImmediateArgument(unsigned const index, std::vector<Token::Token> const & tokens)
{
auto const & token = tokens[index];
if (token.type == Token::TokenType::ImmediateInteger)
{
Value v;
v.CreateFromToken(token);
return v;
}
throw ExpectedImmediate(token);
}
Value GetRegisterArgument(unsigned const index, std::vector<Token::Token> const & tokens)
{
auto const & token = tokens[index];
if (token.type == Token::TokenType::Register)
{
Value v;
v.CreateFromToken(token);
return v;
}
throw ExpectedRegister(token);
}
Value GetImmediateOrRegisterArgument(unsigned const index, std::vector<Token::Token> const & tokens)
{
auto const & token = tokens[index];
if (token.type == Token::TokenType::ImmediateInteger || token.type == Token::TokenType::Register)
{
Value v;
v.CreateFromToken(token);
return v;
}
throw ExpectedRegister(token);
}
void AddArithmeticArguments(ThreeArgumentStatement & statement, unsigned const operandIndex, std::vector<Token::Token> const & tokens)
{
statement.firstArgument = GetImmediateOrRegisterArgument(operandIndex + 1u, tokens);
statement.secondArgument = GetImmediateOrRegisterArgument(operandIndex + 2u, tokens);
statement.thirdArgument = GetRegisterArgument(operandIndex + 3u, tokens);
}
std::unique_ptr<Statement> ExtractStatement(unsigned const operandIndex, std::vector<Token::Token> const & tokens)
{
auto const & token = tokens[operandIndex];
switch(std::get<Token::OperandType>(token.data))
{
case Token::OperandType::AddInteger:
{
auto statement = std::make_unique<ThreeArgumentStatement>();
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
{
argument3 = argument1 + argument2;
};
AddArithmeticArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::SubtractInteger:
{
auto statement = std::make_unique<ThreeArgumentStatement>();
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
{
argument3 = argument1 - argument2;
};
AddArithmeticArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::DivideInteger:
{
auto statement = std::make_unique<ThreeArgumentStatement>();
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
{
argument3 = argument1 / argument2;
};
AddArithmeticArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::MultiplyInteger:
{
auto statement = std::make_unique<ThreeArgumentStatement>();
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
{
argument3 = argument1 * argument2;
};
AddArithmeticArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::ShiftIntegerLeft:
{
auto statement = std::make_unique<ThreeArgumentStatement>();
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
{
argument3 = argument1 << argument2;
};
AddArithmeticArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::ShiftIntegerRight:
{
auto statement = std::make_unique<ThreeArgumentStatement>();
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
{
argument3 = argument1 >> argument2;
};
AddArithmeticArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::Jump:
{
auto labelToken = tokens[operandIndex + 1u];
if (labelToken.type != Token::TokenType::Label)
{
throw ExpectedLabel(labelToken);
}
return std::make_unique<JumpStatement>(std::get<std::string>(labelToken.data));
}
default:
{
auto statement = std::make_unique<NoArgumentStatement>();
// TODO throw error?
statement->function = [](Execute::Flags & flags, Execute::Registers & registers) { std::puts("ExtractStatement: Extracted unhandled operator type"); };
return statement;
}
}
}
int GetRequiredNumberOfArguments(Token::OperandType const type)
{
switch (type)
{
case Token::OperandType::AddInteger:
case Token::OperandType::SubtractInteger:
case Token::OperandType::DivideInteger:
case Token::OperandType::MultiplyInteger:
case Token::OperandType::ShiftIntegerLeft:
case Token::OperandType::ShiftIntegerRight:
return 3;
case Token::OperandType::Jump:
return 1;
default:
return 0;
}
}
}