Add call operand

This commit is contained in:
2020-05-16 11:22:47 +02:00
parent 9337c95b09
commit 41fb08373c
10 changed files with 77 additions and 16 deletions

View File

@@ -39,7 +39,7 @@ int $0;
pushi $68; # D pushi $68; # D
pushi $76; # L pushi $76; # L
pushi $82; # R pushi $82; # R
pushi $79; # O pushi $79; # O
pushi $87; # W pushi $87; # W
seti %B $5; seti %B $5;
@@ -72,17 +72,23 @@ seti %A [$1024];
int $2; int $2;
# Push the string "hell" into register A # Push the string "hell" into register A
seti %A $108; seti %A $108; # l
shli %A $8 %A; shli %A $8 %A;
addi %A $108 %A; addi %A $108 %A; # l
shli %A $8 %A; shli %A $8 %A;
addi %A $101 %A; addi %A $101 %A; # e
shli %A $8 %A; shli %A $8 %A;
addi %A $104 %A; addi %A $104 %A; # h
# Store A at 900 # Store A at memory location 900
seti [$900] %A; seti [$900] %A;
# Setup to print a string from position 900 # Setup to print a string from position 900
seti %A $900; seti %A $900;
seti %B $4; seti %B $4;
int $3; int $3;
# Jump over the interrupt
call program_exit;
int $3;
program_exit:

View File

@@ -27,7 +27,7 @@ namespace Execute
Registers const & GetRegisters() const; Registers const & GetRegisters() const;
State const & GetState() const; State const & GetState() const;
Interpret::Statement const * const GetCurrentStatement() const; Interpret::Statement const * const GetCurrentStatement() const;
bool IsTerminated() const; bool IsTerminated() const;
static VirtualMachine CreateFromCode(Interpret::Code const & code); static VirtualMachine CreateFromCode(Interpret::Code const & code);

View File

@@ -30,7 +30,7 @@ namespace Interpret
void (* function)(Execute::State & state, int argument1, int argument2); void (* function)(Execute::State & state, int argument1, int argument2);
Value firstArgument; Value firstArgument;
Value secondArgument; Value secondArgument;
void Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) override; void Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) override;
}; };
@@ -40,7 +40,7 @@ namespace Interpret
Value firstArgument; Value firstArgument;
Value secondArgument; Value secondArgument;
Value thirdArgument; Value thirdArgument;
void Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) override; void Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) override;
}; };
@@ -55,6 +55,17 @@ namespace Interpret
JumpStatement(std::string const & label); JumpStatement(std::string const & label);
}; };
struct FunctionCallStatement : Statement
{
private:
std::string const label;
public:
void Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) override;
FunctionCallStatement(std::string const & label);
};
struct SetStatement : Statement struct SetStatement : Statement
{ {
Value firstArgument; Value firstArgument;

View File

@@ -13,6 +13,7 @@ namespace Token
ShiftIntegerLeft, ShiftIntegerLeft,
ShiftIntegerRight, ShiftIntegerRight,
Jump, Jump,
CallFunction,
LessThanInteger, LessThanInteger,
GreaterThanInteger, GreaterThanInteger,
EqualInteger, EqualInteger,

View File

@@ -5,9 +5,9 @@ namespace Execute
void VirtualMachine::Step() void VirtualMachine::Step()
{ {
state.nextStatement = state.currentStatement + 1u; state.nextStatement = state.currentStatement + 1u;
code.statements[state.currentStatement]->Execute(flags, state, registers); code.statements[state.currentStatement]->Execute(flags, state, registers);
state.currentStatement = state.nextStatement; state.currentStatement = state.nextStatement;
if (state.currentStatement >= code.statements.size()) if (state.currentStatement >= code.statements.size())
{ {
@@ -48,7 +48,7 @@ namespace Execute
return code.statements[state.currentStatement].get(); return code.statements[state.currentStatement].get();
} }
bool VirtualMachine::IsTerminated() const { return terminated; } bool VirtualMachine::IsTerminated() const { return terminated; }
VirtualMachine VirtualMachine::CreateFromCode(Interpret::Code const & code) VirtualMachine VirtualMachine::CreateFromCode(Interpret::Code const & code)
{ {

View File

@@ -150,9 +150,21 @@ namespace Interpret
{ {
throw ExpectedLabel(labelToken); throw ExpectedLabel(labelToken);
} }
return std::make_unique<JumpStatement>(std::get<std::string>(labelToken.data)); 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::LessThanInteger: case Token::OperandType::LessThanInteger:
{ {
auto statement = std::make_unique<ControlFlowStatement>(); auto statement = std::make_unique<ControlFlowStatement>();
@@ -243,9 +255,12 @@ namespace Interpret
default: default:
{ {
auto statement = std::make_unique<NoArgumentStatement>(); auto statement = std::make_unique<NoArgumentStatement>();
// TODO throw error? // TODO throw error?
statement->function = [](Execute::Flags & flags, Execute::Registers & registers) { std::puts("ExtractStatement: Extracted unhandled operator type"); }; statement->function = [](Execute::Flags & flags, Execute::Registers & registers)
{
std::puts("ExtractStatement: Extracted unhandled operator type");
};
return statement; return statement;
} }
} }
@@ -287,6 +302,7 @@ namespace Interpret
return 2; return 2;
case Token::OperandType::Jump: case Token::OperandType::Jump:
case Token::OperandType::CallFunction:
case Token::OperandType::Interrupt: case Token::OperandType::Interrupt:
case Token::OperandType::PushInteger: case Token::OperandType::PushInteger:
case Token::OperandType::PopInteger: case Token::OperandType::PopInteger:

View File

@@ -1,5 +1,6 @@
#include <execute/error.hpp> #include <execute/error.hpp>
#include <interpret/statement.hpp> #include <interpret/statement.hpp>
#include <stdexcept>
namespace Interpret namespace Interpret
{ {
@@ -41,6 +42,30 @@ namespace Interpret
{ {
} }
void FunctionCallStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers)
{
auto const & elem = state.labelStatementIndice.find(label);
if (elem == state.labelStatementIndice.end())
{
throw std::runtime_error("Attempted call nonexisting function (missing label)");
}
if ((state.memory.size() - state.stackPointer) < sizeof(unsigned))
{
throw Execute::StackOverflow();
}
*(reinterpret_cast<unsigned *>(state.memory.data() + state.stackPointer + (sizeof(unsigned) - 1))) = state.nextStatement;
state.stackPointer += sizeof(int);
state.nextStatement = elem->second;
}
FunctionCallStatement::FunctionCallStatement(std::string const & _label)
: label(_label)
{
}
void SetStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) void SetStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers)
{ {
firstArgument.GetValue(state, registers) = secondArgument.GetValue(state, registers); firstArgument.GetValue(state, registers) = secondArgument.GetValue(state, registers);

View File

@@ -14,6 +14,7 @@ namespace Token
{ "shri", OperandType::ShiftIntegerRight }, { "shri", OperandType::ShiftIntegerRight },
{ "shli", OperandType::ShiftIntegerLeft }, { "shli", OperandType::ShiftIntegerLeft },
{ "jmp", OperandType::Jump }, { "jmp", OperandType::Jump },
{ "call", OperandType::CallFunction },
{ "lti", OperandType::LessThanInteger }, { "lti", OperandType::LessThanInteger },
{ "gti", OperandType::GreaterThanInteger }, { "gti", OperandType::GreaterThanInteger },
{ "eqi", OperandType::EqualInteger }, { "eqi", OperandType::EqualInteger },

View File

@@ -57,8 +57,8 @@ namespace Token
: lineNumber(other.lineNumber), : lineNumber(other.lineNumber),
lineColumn(other.lineColumn), lineColumn(other.lineColumn),
type(other.type), type(other.type),
isValid(other.isValid),
valueType(other.valueType), valueType(other.valueType),
isValid(other.isValid),
data(other.data) data(other.data)
{ {
} }

View File

@@ -1,4 +1,5 @@
#include <map> #include <map>
#include <stdexcept>
#include <token/tokenizer.hpp> #include <token/tokenizer.hpp>
namespace Token namespace Token