Files
wassembly/src/interpret/operanddefinitions.cpp

327 lines
9.1 KiB
C++

#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 GetRegisterOrMemoryArgument(unsigned const index, std::vector<Token::Token> const & tokens)
{
auto const & token = tokens[index];
if (token.type == Token::TokenType::Register || token.type == Token::TokenType::Memory)
{
Value v;
v.CreateFromToken(token);
return v;
}
throw ExpectedRegisterOrMemory(token);
}
Value GetValueArgument(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 || token.type == Token::TokenType::Memory)
{
Value v;
v.CreateFromToken(token);
return v;
}
throw ExpectedValue(token);
}
void AddArithmeticArguments(ArithmeticStatement & statement, unsigned const operandIndex, std::vector<Token::Token> const & tokens)
{
statement.firstArgument = GetValueArgument(operandIndex + 1u, tokens);
statement.secondArgument = GetValueArgument(operandIndex + 2u, tokens);
statement.thirdArgument = GetRegisterOrMemoryArgument(operandIndex + 3u, tokens);
}
void AddLogicArguments(ControlFlowStatement & statement, unsigned const operandIndex, std::vector<Token::Token> const & tokens)
{
statement.firstArgument = GetValueArgument(operandIndex + 1u, tokens);
statement.secondArgument = GetValueArgument(operandIndex + 2u, 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<ArithmeticStatement>();
statement->function = [](int argument1, int argument2, int & argument3)
{
argument3 = argument1 + argument2;
};
AddArithmeticArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::SubtractInteger:
{
auto statement = std::make_unique<ArithmeticStatement>();
statement->function = [](int argument1, int argument2, int & argument3)
{
argument3 = argument1 - argument2;
};
AddArithmeticArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::DivideInteger:
{
auto statement = std::make_unique<ArithmeticStatement>();
statement->function = [](int argument1, int argument2, int & argument3)
{
argument3 = argument1 / argument2;
};
AddArithmeticArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::MultiplyInteger:
{
auto statement = std::make_unique<ArithmeticStatement>();
statement->function = [](int argument1, int argument2, int & argument3)
{
argument3 = argument1 * argument2;
};
AddArithmeticArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::ShiftIntegerLeft:
{
auto statement = std::make_unique<ArithmeticStatement>();
statement->function = [](int argument1, int argument2, int & argument3)
{
argument3 = argument1 << argument2;
};
AddArithmeticArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::ShiftIntegerRight:
{
auto statement = std::make_unique<ArithmeticStatement>();
statement->function = [](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));
}
case Token::OperandType::CallFunction:
{
auto labelToken = tokens[operandIndex + 1u];
if (labelToken.type != Token::TokenType::Label)
{
throw ExpectedLabel(labelToken);
}
return std::make_unique<FunctionCallStatement>(std::get<std::string>(labelToken.data));
}
case Token::OperandType::ReturnFromFunction:
{
return std::make_unique<ReturnFromFunctionStatement>();
}
case Token::OperandType::ExitProgram:
{
return std::make_unique<ExitProgramStatement>();
}
case Token::OperandType::LessThanInteger:
{
auto statement = std::make_unique<ControlFlowStatement>();
statement->function = [](Execute::State & state, int argument1, int argument2)
{
if (argument1 < argument2)
{
state.nextStatement = state.currentStatement + 1u;
}
else
{
state.nextStatement = state.currentStatement + 2u;
}
};
AddLogicArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::GreaterThanInteger:
{
auto statement = std::make_unique<ControlFlowStatement>();
statement->function = [](Execute::State & state, int argument1, int argument2)
{
if (argument1 > argument2)
{
state.nextStatement = state.currentStatement + 1u;
}
else
{
state.nextStatement = state.currentStatement + 2u;
}
};
AddLogicArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::EqualInteger:
{
auto statement = std::make_unique<ControlFlowStatement>();
statement->function = [](Execute::State & state, int argument1, int argument2)
{
if (argument1 == argument2)
{
state.nextStatement = state.currentStatement + 1u;
}
else
{
state.nextStatement = state.currentStatement + 2u;
}
};
AddLogicArguments(*statement, operandIndex, tokens);
return statement;
}
case Token::OperandType::SetInteger:
{
auto statement = std::make_unique<SetStatement>();
statement->firstArgument = GetRegisterOrMemoryArgument(operandIndex + 1u, tokens);
statement->secondArgument = GetValueArgument(operandIndex + 2u, tokens);
return statement;
}
case Token::OperandType::Interrupt:
{
auto statement = std::make_unique<InterruptStatement>();
statement->firstArgument = GetValueArgument(operandIndex + 1u, tokens);
return statement;
}
case Token::OperandType::PopInteger:
{
auto statement = std::make_unique<PopStatement>();
statement->firstArgument = GetRegisterArgument(operandIndex + 1u, tokens);
return statement;
}
case Token::OperandType::PushInteger:
{
auto statement = std::make_unique<PushStatement>();
statement->firstArgument = GetValueArgument(operandIndex + 1u, tokens);
return statement;
}
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;
}
}
}
std::tuple<std::string, int> ExtractDeclaration(unsigned const operatorIndex, std::vector<Token::Token> const & tokens)
{
if (tokens[operatorIndex + 1u].type != Token::TokenType::Label)
{
throw ExpectedLabel(tokens[operatorIndex + 1u]);
}
if (tokens[operatorIndex + 2u].type != Token::TokenType::ImmediateInteger)
{
throw ExpectedImmediate(tokens[operatorIndex + 2u]);
}
auto const label = std::get<std::string>(tokens[operatorIndex + 1u].data);
auto const value = std::get<int>(tokens[operatorIndex + 2u].data);
return std::make_tuple(label, value);
}
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::LessThanInteger:
case Token::OperandType::GreaterThanInteger:
case Token::OperandType::EqualInteger:
case Token::OperandType::SetInteger:
return 2;
case Token::OperandType::Jump:
case Token::OperandType::CallFunction:
case Token::OperandType::Interrupt:
case Token::OperandType::PushInteger:
case Token::OperandType::PopInteger:
return 1;
default:
std::printf("WARNING: returning default argument length of 0 for operand type %i\n", static_cast<int>(type));
case Token::OperandType::ReturnFromFunction:
case Token::OperandType::ExitProgram:
return 0;
}
}
}