Basic arithmetic and jump labels
This commit is contained in:
165
src/interpret/operanddefinitions.cpp
Normal file
165
src/interpret/operanddefinitions.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user