Add control flow operands
This commit is contained in:
@@ -45,13 +45,19 @@ namespace Interpret
|
||||
throw ExpectedRegister(token);
|
||||
}
|
||||
|
||||
void AddArithmeticArguments(ThreeArgumentStatement & statement, unsigned const operandIndex, std::vector<Token::Token> const & tokens)
|
||||
void AddArithmeticArguments(ArithmeticStatement & 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);
|
||||
}
|
||||
|
||||
void AddLogicArguments(ControlFlowStatement & statement, unsigned const operandIndex, std::vector<Token::Token> const & tokens)
|
||||
{
|
||||
statement.firstArgument = GetImmediateOrRegisterArgument(operandIndex + 1u, tokens);
|
||||
statement.secondArgument = GetImmediateOrRegisterArgument(operandIndex + 2u, tokens);
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> ExtractStatement(unsigned const operandIndex, std::vector<Token::Token> const & tokens)
|
||||
{
|
||||
auto const & token = tokens[operandIndex];
|
||||
@@ -59,8 +65,8 @@ namespace Interpret
|
||||
{
|
||||
case Token::OperandType::AddInteger:
|
||||
{
|
||||
auto statement = std::make_unique<ThreeArgumentStatement>();
|
||||
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
|
||||
auto statement = std::make_unique<ArithmeticStatement>();
|
||||
statement->function = [](int argument1, int argument2, int & argument3)
|
||||
{
|
||||
argument3 = argument1 + argument2;
|
||||
};
|
||||
@@ -70,8 +76,8 @@ namespace Interpret
|
||||
|
||||
case Token::OperandType::SubtractInteger:
|
||||
{
|
||||
auto statement = std::make_unique<ThreeArgumentStatement>();
|
||||
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
|
||||
auto statement = std::make_unique<ArithmeticStatement>();
|
||||
statement->function = [](int argument1, int argument2, int & argument3)
|
||||
{
|
||||
argument3 = argument1 - argument2;
|
||||
};
|
||||
@@ -81,8 +87,8 @@ namespace Interpret
|
||||
|
||||
case Token::OperandType::DivideInteger:
|
||||
{
|
||||
auto statement = std::make_unique<ThreeArgumentStatement>();
|
||||
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
|
||||
auto statement = std::make_unique<ArithmeticStatement>();
|
||||
statement->function = [](int argument1, int argument2, int & argument3)
|
||||
{
|
||||
argument3 = argument1 / argument2;
|
||||
};
|
||||
@@ -92,8 +98,8 @@ namespace Interpret
|
||||
|
||||
case Token::OperandType::MultiplyInteger:
|
||||
{
|
||||
auto statement = std::make_unique<ThreeArgumentStatement>();
|
||||
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
|
||||
auto statement = std::make_unique<ArithmeticStatement>();
|
||||
statement->function = [](int argument1, int argument2, int & argument3)
|
||||
{
|
||||
argument3 = argument1 * argument2;
|
||||
};
|
||||
@@ -103,8 +109,8 @@ namespace Interpret
|
||||
|
||||
case Token::OperandType::ShiftIntegerLeft:
|
||||
{
|
||||
auto statement = std::make_unique<ThreeArgumentStatement>();
|
||||
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
|
||||
auto statement = std::make_unique<ArithmeticStatement>();
|
||||
statement->function = [](int argument1, int argument2, int & argument3)
|
||||
{
|
||||
argument3 = argument1 << argument2;
|
||||
};
|
||||
@@ -114,8 +120,8 @@ namespace Interpret
|
||||
|
||||
case Token::OperandType::ShiftIntegerRight:
|
||||
{
|
||||
auto statement = std::make_unique<ThreeArgumentStatement>();
|
||||
statement->function = [](Execute::Flags & flags, int argument1, int argument2, int & argument3)
|
||||
auto statement = std::make_unique<ArithmeticStatement>();
|
||||
statement->function = [](int argument1, int argument2, int & argument3)
|
||||
{
|
||||
argument3 = argument1 >> argument2;
|
||||
};
|
||||
@@ -133,6 +139,60 @@ namespace Interpret
|
||||
return std::make_unique<JumpStatement>(std::get<std::string>(labelToken.data));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
auto statement = std::make_unique<NoArgumentStatement>();
|
||||
@@ -155,6 +215,11 @@ namespace Interpret
|
||||
case Token::OperandType::ShiftIntegerRight:
|
||||
return 3;
|
||||
|
||||
case Token::OperandType::LessThanInteger:
|
||||
case Token::OperandType::GreaterThanInteger:
|
||||
case Token::OperandType::EqualInteger:
|
||||
return 2;
|
||||
|
||||
case Token::OperandType::Jump:
|
||||
return 1;
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@ namespace Interpret
|
||||
function(flags, firstArgument.GetValue(registers));
|
||||
}
|
||||
|
||||
void TwoArgumentStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers)
|
||||
void ControlFlowStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers)
|
||||
{
|
||||
function(flags, firstArgument.GetValue(registers), secondArgument.GetValue(registers));
|
||||
function(state, firstArgument.GetValue(registers), secondArgument.GetValue(registers));
|
||||
}
|
||||
|
||||
void ThreeArgumentStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers)
|
||||
void ArithmeticStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers)
|
||||
{
|
||||
function(flags, firstArgument.GetValue(registers), secondArgument.GetValue(registers), thirdArgument.GetValue(registers));
|
||||
function(firstArgument.GetValue(registers), secondArgument.GetValue(registers), thirdArgument.GetValue(registers));
|
||||
}
|
||||
|
||||
void JumpStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers)
|
||||
|
||||
@@ -114,13 +114,11 @@ int main(int argc, char ** argv)
|
||||
|
||||
std::puts("\n*** Execution ***");
|
||||
Execute::VirtualMachine vm(code);
|
||||
for(unsigned i = 0u; i < 900000; ++i)
|
||||
while(!vm.IsTerminated())
|
||||
{
|
||||
vm.SingleStep();
|
||||
auto const & registers = vm.GetRegisters();
|
||||
std::printf("A=%i B=%i C=%i D=%i\n", registers.A, registers.B, registers.C, registers.D);
|
||||
auto const & flags = vm.GetFlags();
|
||||
std::printf("-\n"); // TODO
|
||||
auto const & state = vm.GetState();
|
||||
std::printf("current_statement=%i\n", state.currentStatement);
|
||||
|
||||
|
||||
@@ -13,7 +13,10 @@ namespace Token
|
||||
{ "muli", OperandType::MultiplyInteger },
|
||||
{ "shri", OperandType::ShiftIntegerRight },
|
||||
{ "shli", OperandType::ShiftIntegerLeft },
|
||||
{ "jmp", OperandType::Jump }
|
||||
{ "jmp", OperandType::Jump },
|
||||
{ "lti", OperandType::LessThanInteger },
|
||||
{ "gti", OperandType::GreaterThanInteger },
|
||||
{ "eqi", OperandType::EqualInteger },
|
||||
};
|
||||
|
||||
auto const & result = operations.find(op);
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace Token
|
||||
char const postfix = string[string.size() - 1];
|
||||
if (postfix == ':')
|
||||
{
|
||||
// TODO check if label is an Operand?
|
||||
return Token(lineNumber, lineColumn, string.substr(0, string.size() - 1), true);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user