Variables #8
@@ -30,8 +30,9 @@ Stack operations:
|
|||||||
05 dup
|
05 dup
|
||||||
|
|
||||||
Local variables:
|
Local variables:
|
||||||
a3 c3 e3 setl [int] Set stack top as indexed local variable
|
a3 c3 e3 pushv [int] Push n nil values into the stack (used to init local vars)
|
||||||
a4 c4 e4 getl [int] Get indexed local variable and place on stack
|
ab cb eb set [index] Set value in stack position (set local variable)
|
||||||
|
a4 c4 e4 dupv [index] Duplicate stack value (load local variable)
|
||||||
a5 c5 e5 setg [int] Set global variable
|
a5 c5 e5 setg [int] Set global variable
|
||||||
a6 c6 e6 getg [int] Get global variable
|
a6 c6 e6 getg [int] Get global variable
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,9 @@ void Lexer::ingest_next_token()
|
|||||||
} else if (c == ':') {
|
} else if (c == ':') {
|
||||||
type = TokenType::Colon;
|
type = TokenType::Colon;
|
||||||
++pos_;
|
++pos_;
|
||||||
} else if (c == '\n') {
|
} else if (c == '\n' || c == ';') {
|
||||||
|
while (pos_ < source_.size() && source_.at(pos_) != '\n')
|
||||||
|
++pos_;
|
||||||
type = TokenType::Enter;
|
type = TokenType::Enter;
|
||||||
value = "\n";
|
value = "\n";
|
||||||
++pos_;
|
++pos_;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ TEST(Assember, Assembler)
|
|||||||
1: "Hello world"
|
1: "Hello world"
|
||||||
|
|
||||||
.func 0
|
.func 0
|
||||||
pushi 2
|
pushi 2 ; this is a comment
|
||||||
pushi 3
|
pushi 3
|
||||||
sum
|
sum
|
||||||
ret
|
ret
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ const std::unordered_map<std::string, Instruction> instruction_names = {
|
|||||||
{ "newt", Instruction::NewTable },
|
{ "newt", Instruction::NewTable },
|
||||||
{ "pop", Instruction::Pop },
|
{ "pop", Instruction::Pop },
|
||||||
{ "dup", Instruction::Duplicate },
|
{ "dup", Instruction::Duplicate },
|
||||||
{ "setl", Instruction::SetLocal8 },
|
{ "pushv", Instruction::PushValues8 },
|
||||||
{ "getl", Instruction::GetLocal8 },
|
{ "set", Instruction::SetValue8 },
|
||||||
|
{ "dupv", Instruction::DuplicateValue8 },
|
||||||
{ "setg", Instruction::SetGlobal8 },
|
{ "setg", Instruction::SetGlobal8 },
|
||||||
{ "getl", Instruction::GetGlobal8 },
|
{ "getl", Instruction::GetGlobal8 },
|
||||||
{ "call8", Instruction::Call8 },
|
{ "call8", Instruction::Call8 },
|
||||||
@@ -88,15 +89,20 @@ std::pair<std::string, size_t> debug_instruction(Instruction inst, int oper)
|
|||||||
case Instruction::NewTable: out = "newt"; break;
|
case Instruction::NewTable: out = "newt"; break;
|
||||||
case Instruction::Pop: out = "pop"; break;
|
case Instruction::Pop: out = "pop"; break;
|
||||||
case Instruction::Duplicate: out = "dup"; break;
|
case Instruction::Duplicate: out = "dup"; break;
|
||||||
case Instruction::SetLocal8:
|
case Instruction::PushValues8:
|
||||||
case Instruction::SetLocal16:
|
case Instruction::PushValues16:
|
||||||
case Instruction::SetLocal32:
|
case Instruction::PushValues32:
|
||||||
out = "setl";
|
out = "pushv";
|
||||||
break;
|
break;
|
||||||
case Instruction::GetLocal8:
|
case Instruction::SetValue8:
|
||||||
case Instruction::GetLocal16:
|
case Instruction::SetValue16:
|
||||||
case Instruction::GetLocal32:
|
case Instruction::SetValue32:
|
||||||
out = "getl";
|
out = "set";
|
||||||
|
break;
|
||||||
|
case Instruction::DuplicateValue8:
|
||||||
|
case Instruction::DuplicateValue16:
|
||||||
|
case Instruction::DuplicateValue32:
|
||||||
|
out = "dupv";
|
||||||
break;
|
break;
|
||||||
case Instruction::SetGlobal8:
|
case Instruction::SetGlobal8:
|
||||||
case Instruction::SetGlobal16:
|
case Instruction::SetGlobal16:
|
||||||
|
|||||||
@@ -32,12 +32,15 @@ enum class Instruction : uint8_t {
|
|||||||
Duplicate = 0x05,
|
Duplicate = 0x05,
|
||||||
|
|
||||||
// local variables
|
// local variables
|
||||||
SetLocal8 = 0xa3,
|
PushValues8 = 0xa3,
|
||||||
SetLocal16 = 0xc3,
|
PushValues16 = 0xc3,
|
||||||
SetLocal32 = 0xe3,
|
PushValues32 = 0xe3,
|
||||||
GetLocal8 = 0xa4,
|
SetValue8 = 0xab,
|
||||||
GetLocal16 = 0xc4,
|
SetValue16 = 0xcb,
|
||||||
GetLocal32 = 0xe4,
|
SetValue32 = 0xeb,
|
||||||
|
DuplicateValue8 = 0xa4,
|
||||||
|
DuplicateValue16 = 0xc4,
|
||||||
|
DuplicateValue32 = 0xe4,
|
||||||
SetGlobal8 = 0xa5,
|
SetGlobal8 = 0xa5,
|
||||||
SetGlobal16 = 0xc5,
|
SetGlobal16 = 0xc5,
|
||||||
SetGlobal32 = 0xe5,
|
SetGlobal32 = 0xe5,
|
||||||
|
|||||||
@@ -47,6 +47,21 @@ Value Stack::at(int pos) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Stack::set(int pos, Value const& val)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (pos >= 0) {
|
||||||
|
stack_.at(fps_.top() + pos) = val;
|
||||||
|
} else {
|
||||||
|
if ((int) fps_.top() + (int) stack_.size() + pos < 0)
|
||||||
|
throw VMStackOutOfRange();
|
||||||
|
stack_.at(stack_.size() + pos) = val;
|
||||||
|
}
|
||||||
|
} catch (std::out_of_range&) {
|
||||||
|
throw VMStackOutOfRange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t Stack::size() const
|
size_t Stack::size() const
|
||||||
{
|
{
|
||||||
return stack_.size() - fps_.top();
|
return stack_.size() - fps_.top();
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ public:
|
|||||||
[[nodiscard]] Value at(int pos) const;
|
[[nodiscard]] Value at(int pos) const;
|
||||||
[[nodiscard]] size_t size() const;
|
[[nodiscard]] size_t size() const;
|
||||||
|
|
||||||
|
void set(int pos, Value const& val);
|
||||||
|
|
||||||
void push_fp();
|
void push_fp();
|
||||||
void pop_fp();
|
void pop_fp();
|
||||||
|
|
||||||
|
|||||||
@@ -268,6 +268,23 @@ TEST(VM, StringString)
|
|||||||
)").to_integer(-1), 0);
|
)").to_integer(-1), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(VM, LocalVariables)
|
||||||
|
{
|
||||||
|
VM vm = run(R"(
|
||||||
|
.func 0
|
||||||
|
pushv 2 ; local a, b
|
||||||
|
pushi 3 ; a = 3
|
||||||
|
set 0
|
||||||
|
pushi 4 ; b = 4
|
||||||
|
set 1
|
||||||
|
dupv 0 ; return a
|
||||||
|
ret
|
||||||
|
)");
|
||||||
|
|
||||||
|
ASSERT_EQ(vm.stack_sz(), 1);
|
||||||
|
ASSERT_EQ(vm.to_integer(-1), 3);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
testing::InitGoogleTest(&argc, argv);
|
testing::InitGoogleTest(&argc, argv);
|
||||||
|
|||||||
27
src/vm/vm.cc
27
src/vm/vm.cc
@@ -131,6 +131,33 @@ void VM::step()
|
|||||||
stack_.push(stack_.peek());
|
stack_.push(stack_.peek());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
//
|
||||||
|
// variables
|
||||||
|
//
|
||||||
|
|
||||||
|
case Instruction::PushValues8:
|
||||||
|
case Instruction::PushValues16:
|
||||||
|
case Instruction::PushValues32:
|
||||||
|
for (int i = 0; i < op.operator_; ++i)
|
||||||
|
push_nil();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Instruction::SetValue8:
|
||||||
|
case Instruction::SetValue16:
|
||||||
|
case Instruction::SetValue32: {
|
||||||
|
Value a = stack_.pop();
|
||||||
|
stack_.set(op.operator_, a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Instruction::DuplicateValue8:
|
||||||
|
case Instruction::DuplicateValue16:
|
||||||
|
case Instruction::DuplicateValue32: {
|
||||||
|
Value a = stack_.at(op.operator_);
|
||||||
|
stack_.push(a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// logical/arithmetic
|
// logical/arithmetic
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user