Add call operand
This commit is contained in:
@@ -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:
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace Token
|
|||||||
ShiftIntegerLeft,
|
ShiftIntegerLeft,
|
||||||
ShiftIntegerRight,
|
ShiftIntegerRight,
|
||||||
Jump,
|
Jump,
|
||||||
|
CallFunction,
|
||||||
LessThanInteger,
|
LessThanInteger,
|
||||||
GreaterThanInteger,
|
GreaterThanInteger,
|
||||||
EqualInteger,
|
EqualInteger,
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
#include <stdexcept>
|
||||||
#include <token/tokenizer.hpp>
|
#include <token/tokenizer.hpp>
|
||||||
|
|
||||||
namespace Token
|
namespace Token
|
||||||
|
|||||||
Reference in New Issue
Block a user