#include #include namespace Interpret { Value GetImmediateArgument(unsigned const index, std::vector 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 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 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 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 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 const & tokens) { statement.firstArgument = GetValueArgument(operandIndex + 1u, tokens); statement.secondArgument = GetValueArgument(operandIndex + 2u, tokens); } std::unique_ptr ExtractStatement(unsigned const operandIndex, std::vector const & tokens) { auto const & token = tokens[operandIndex]; switch(std::get(token.data)) { case Token::OperandType::AddInteger: { auto statement = std::make_unique(); 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(); 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(); 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(); 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(); 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(); 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(std::get(labelToken.data)); } case Token::OperandType::CallFunction: { auto labelToken = tokens[operandIndex + 1u]; if (labelToken.type != Token::TokenType::Label) { throw ExpectedLabel(labelToken); } return std::make_unique(std::get(labelToken.data)); } case Token::OperandType::ReturnFromFunction: { return std::make_unique(); } case Token::OperandType::ExitProgram: { return std::make_unique(); } case Token::OperandType::LessThanInteger: { auto statement = std::make_unique(); 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(); 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(); 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(); statement->firstArgument = GetRegisterOrMemoryArgument(operandIndex + 1u, tokens); statement->secondArgument = GetValueArgument(operandIndex + 2u, tokens); return statement; } case Token::OperandType::Interrupt: { auto statement = std::make_unique(); statement->firstArgument = GetValueArgument(operandIndex + 1u, tokens); return statement; } case Token::OperandType::PopInteger: { auto statement = std::make_unique(); statement->firstArgument = GetRegisterArgument(operandIndex + 1u, tokens); return statement; } case Token::OperandType::PushInteger: { auto statement = std::make_unique(); statement->firstArgument = GetValueArgument(operandIndex + 1u, tokens); return statement; } default: { auto statement = std::make_unique(); // TODO throw error? statement->function = [](Execute::Flags & flags, Execute::Registers & registers) { std::puts("ExtractStatement: Extracted unhandled operator type"); }; return statement; } } } std::tuple ExtractDeclaration(unsigned const operatorIndex, std::vector 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(tokens[operatorIndex + 1u].data); auto const value = std::get(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(type)); case Token::OperandType::ReturnFromFunction: case Token::OperandType::ExitProgram: return 0; } } }