Variables #8

Merged
andre merged 2 commits from variables into master 2026-05-02 20:12:15 -05:00
10 changed files with 100 additions and 27 deletions

View File

@@ -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

View File

@@ -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_;

View File

@@ -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

View File

@@ -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:

View File

@@ -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,

View File

@@ -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();

View File

@@ -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();

View File

@@ -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);

View File

@@ -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
// //