mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 22:46:30 +00:00
test program works
This commit is contained in:
parent
ce91126cb1
commit
2fbccd0bc8
@ -63,7 +63,7 @@ auto compile_asm(const std::vector<AsmLine>& lines) -> std::vector<uint32_t>
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AsmLineType::Loc: {
|
case AsmLineType::Loc: {
|
||||||
locs.insert_or_assign(std::get<Loc>(line.value).value, ip + 1);
|
locs.insert_or_assign(std::get<Loc>(line.value).value, ip);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AsmLineType::Ref: {
|
case AsmLineType::Ref: {
|
||||||
@ -75,9 +75,15 @@ auto compile_asm(const std::vector<AsmLine>& lines) -> std::vector<uint32_t>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < output.size(); ++i) {
|
for (size_t i = 0; i < output.size(); ++i) {
|
||||||
if (refs.contains(i)) {
|
if (!refs.contains(i)) {
|
||||||
output.at(i) = static_cast<uint32_t>(locs.at(refs.at(i)));
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!locs.contains(refs.at(i))) {
|
||||||
|
std::cerr << std::format(
|
||||||
|
"error: label \"{}\" used at {} not defined\n", refs.at(i), i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
output.at(i) = static_cast<uint32_t>(locs.at(refs.at(i)));
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@ -92,6 +98,7 @@ int main()
|
|||||||
// + a b
|
// + a b
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
// fn main() {
|
||||||
// let result = 0;
|
// let result = 0;
|
||||||
// let i = 0;
|
// let i = 0;
|
||||||
// loop {
|
// loop {
|
||||||
@ -99,12 +106,15 @@ int main()
|
|||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
// result = add(result, 5);
|
// result = add(result, 5);
|
||||||
|
// i = + i 1;
|
||||||
|
// }
|
||||||
|
// result
|
||||||
// }
|
// }
|
||||||
auto program_asm = std::vector<AsmLine> {
|
auto program_asm = std::vector<AsmLine> {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
SourceMap, 0, 0, 0,
|
SourceMap, 0, 0, 0,
|
||||||
PushPtr, R("main"),
|
PushPtr, R("main"),
|
||||||
Pop,
|
Call, 0,
|
||||||
PushPtr, R("_exit"),
|
PushPtr, R("_exit"),
|
||||||
Jump,
|
Jump,
|
||||||
Pop,
|
Pop,
|
||||||
@ -112,15 +122,17 @@ int main()
|
|||||||
SourceMap, 19, 2, 5,
|
SourceMap, 19, 2, 5,
|
||||||
Add,
|
Add,
|
||||||
Return,
|
Return,
|
||||||
|
L("main"),
|
||||||
SourceMap, 28, 5, 1,
|
SourceMap, 28, 5, 1,
|
||||||
PushInt, 0,
|
PushInt, 0,
|
||||||
|
PushInt, 0,
|
||||||
SourceMap, 44, 6, 1,
|
SourceMap, 44, 6, 1,
|
||||||
PushInt, 0,
|
PushInt, 0,
|
||||||
SourceMap, 55, 7, 1,
|
SourceMap, 55, 7, 1,
|
||||||
L("1"),
|
L("0"),
|
||||||
SourceMap, 66, 8, 5,
|
SourceMap, 66, 8, 5,
|
||||||
LoadLocal, 1,
|
LoadLocal, 2,
|
||||||
PushInt, 0,
|
PushInt, 10,
|
||||||
LessThan,
|
LessThan,
|
||||||
Not,
|
Not,
|
||||||
PushPtr, R("1"),
|
PushPtr, R("1"),
|
||||||
@ -128,22 +140,25 @@ int main()
|
|||||||
SourceMap, 87, 9, 9,
|
SourceMap, 87, 9, 9,
|
||||||
PushPtr, R("2"),
|
PushPtr, R("2"),
|
||||||
Jump,
|
Jump,
|
||||||
|
L("1"),
|
||||||
SourceMap, 104, 11, 5,
|
SourceMap, 104, 11, 5,
|
||||||
LoadLocal, 0,
|
LoadLocal, 1,
|
||||||
PushInt, 5,
|
PushInt, 5,
|
||||||
PushPtr, R("add"),
|
PushPtr, R("add"),
|
||||||
Call, 2,
|
Call, 2,
|
||||||
StoreLocal, 0,
|
StoreLocal, 1,
|
||||||
SourceMap, 133, 12, 5,
|
SourceMap, 133, 12, 5,
|
||||||
LoadLocal, 1,
|
LoadLocal, 2,
|
||||||
PushInt, 1,
|
PushInt, 1,
|
||||||
Add,
|
Add,
|
||||||
StoreLocal, 1,
|
StoreLocal, 2,
|
||||||
PushPtr, R("0"),
|
PushPtr, R("0"),
|
||||||
Jump,
|
Jump,
|
||||||
L("2"),
|
L("2"),
|
||||||
|
LoadLocal, 1,
|
||||||
|
StoreLocal, 0,
|
||||||
|
Pop,
|
||||||
Pop,
|
Pop,
|
||||||
PushNull,
|
|
||||||
Return,
|
Return,
|
||||||
L("_exit"),
|
L("_exit"),
|
||||||
SourceMap, 147, 15, 1
|
SourceMap, 147, 15, 1
|
||||||
@ -156,6 +171,5 @@ int main()
|
|||||||
.code_coverage = true,
|
.code_coverage = true,
|
||||||
});
|
});
|
||||||
vm.run_until_done();
|
vm.run_until_done();
|
||||||
|
std::cout << std::format("done\n{}\n", vm.stack_repr_string());
|
||||||
vm.print_stack();
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -50,6 +51,15 @@ struct Ptr {
|
|||||||
uint32_t value;
|
uint32_t value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
template <ValueType op> struct ValueTypeToType { };
|
||||||
|
template <> struct ValueTypeToType<ValueType::Null> { using Type = Null; };
|
||||||
|
template <> struct ValueTypeToType<ValueType::Int> { using Type = Int; };
|
||||||
|
template <> struct ValueTypeToType<ValueType::Bool> { using Type = Bool; };
|
||||||
|
template <> struct ValueTypeToType<ValueType::String> { using Type = String; };
|
||||||
|
template <> struct ValueTypeToType<ValueType::Ptr> { using Type = Ptr; };
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
class Value {
|
class Value {
|
||||||
public:
|
public:
|
||||||
Value(Null&& value)
|
Value(Null&& value)
|
||||||
@ -80,120 +90,42 @@ public:
|
|||||||
|
|
||||||
inline auto type() const -> ValueType { return m_type; };
|
inline auto type() const -> ValueType { return m_type; };
|
||||||
|
|
||||||
inline auto as_null() -> Null&
|
template <ValueType VT> inline auto as() -> ValueTypeToType<VT>::Type&
|
||||||
{
|
{
|
||||||
//
|
|
||||||
try {
|
try {
|
||||||
return std::get<Null>(value);
|
return std::get<typename ValueTypeToType<VT>::Type>(value);
|
||||||
} catch (const std::bad_variant_access& ex) {
|
} catch (const std::bad_variant_access& ex) {
|
||||||
std::cout << std::format("tried to unwrap {} as Null\n",
|
std::cerr << std::format("error: tried to unwrap {} as {}\n",
|
||||||
value_type_to_string(this->m_type));
|
value_type_to_string(this->m_type), value_type_to_string(VT));
|
||||||
throw;
|
std::exit(1);
|
||||||
}
|
|
||||||
}
|
|
||||||
inline auto as_null() const -> const Null&
|
|
||||||
{
|
|
||||||
//
|
|
||||||
try {
|
|
||||||
return std::get<Null>(value);
|
|
||||||
} catch (const std::bad_variant_access& ex) {
|
|
||||||
std::cout << std::format("tried to unwrap {} as Null\n",
|
|
||||||
value_type_to_string(this->m_type));
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto as_int() -> Int&
|
template <ValueType VT>
|
||||||
|
inline auto as() const -> const ValueTypeToType<VT>::Type&
|
||||||
{
|
{
|
||||||
//
|
|
||||||
try {
|
try {
|
||||||
return std::get<Int>(value);
|
return std::get<typename ValueTypeToType<VT>::Type>(value);
|
||||||
} catch (const std::bad_variant_access& ex) {
|
} catch (const std::bad_variant_access& ex) {
|
||||||
std::cout << std::format("tried to unwrap {} as Int\n",
|
std::cerr << std::format("error: tried to unwrap {} as {}\n",
|
||||||
value_type_to_string(this->m_type));
|
value_type_to_string(this->m_type), value_type_to_string(VT));
|
||||||
throw;
|
std::exit(1);
|
||||||
}
|
|
||||||
}
|
|
||||||
inline auto as_int() const -> const Int&
|
|
||||||
{
|
|
||||||
//
|
|
||||||
try {
|
|
||||||
return std::get<Int>(value);
|
|
||||||
} catch (const std::bad_variant_access& ex) {
|
|
||||||
std::cout << std::format("tried to unwrap {} as Int\n",
|
|
||||||
value_type_to_string(this->m_type));
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto as_bool() -> Bool&
|
// clang-format off
|
||||||
{
|
inline auto as_null() -> Null& { return as<ValueType::Null>(); }
|
||||||
//
|
inline auto as_int() -> Int& { return as<ValueType::Int>(); }
|
||||||
try {
|
inline auto as_bool() -> Bool& { return as<ValueType::Bool>(); }
|
||||||
return std::get<Bool>(value);
|
inline auto as_string() -> String& { return as<ValueType::String>(); }
|
||||||
} catch (const std::bad_variant_access& ex) {
|
inline auto as_ptr() -> Ptr& { return as<ValueType::Ptr>(); }
|
||||||
std::cout << std::format("tried to unwrap {} as Bool\n",
|
|
||||||
value_type_to_string(this->m_type));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inline auto as_bool() const -> const Bool&
|
|
||||||
{
|
|
||||||
//
|
|
||||||
try {
|
|
||||||
return std::get<Bool>(value);
|
|
||||||
} catch (const std::bad_variant_access& ex) {
|
|
||||||
std::cout << std::format("tried to unwrap {} as Bool\n",
|
|
||||||
value_type_to_string(this->m_type));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto as_string() -> String&
|
inline auto as_null() const -> const Null& { return as<ValueType::Null>(); }
|
||||||
{
|
inline auto as_int() const -> const Int& { return as<ValueType::Int>(); }
|
||||||
//
|
inline auto as_bool() const -> const Bool& { return as<ValueType::Bool>(); }
|
||||||
try {
|
inline auto as_string() const -> const String& { return as<ValueType::String>(); }
|
||||||
return std::get<String>(value);
|
inline auto as_ptr() const -> const Ptr& { return as<ValueType::Ptr>(); }
|
||||||
} catch (const std::bad_variant_access& ex) {
|
// clang-format on
|
||||||
std::cout << std::format("tried to unwrap {} as String\n",
|
|
||||||
value_type_to_string(this->m_type));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inline auto as_string() const -> const String&
|
|
||||||
{
|
|
||||||
//
|
|
||||||
try {
|
|
||||||
return std::get<String>(value);
|
|
||||||
} catch (const std::bad_variant_access& ex) {
|
|
||||||
std::cout << std::format("tried to unwrap {} as String\n",
|
|
||||||
value_type_to_string(this->m_type));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto as_ptr() -> Ptr&
|
|
||||||
{
|
|
||||||
//
|
|
||||||
try {
|
|
||||||
return std::get<Ptr>(value);
|
|
||||||
} catch (const std::bad_variant_access& ex) {
|
|
||||||
std::cout << std::format("tried to unwrap {} as Ptr\n",
|
|
||||||
value_type_to_string(this->m_type));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inline auto as_ptr() const -> const Ptr&
|
|
||||||
{
|
|
||||||
//
|
|
||||||
try {
|
|
||||||
return std::get<Ptr>(value);
|
|
||||||
} catch (const std::bad_variant_access& ex) {
|
|
||||||
std::cout << std::format("tried to unwrap {} as Ptr\n",
|
|
||||||
value_type_to_string(this->m_type));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto to_string() const -> std::string
|
inline auto to_string() const -> std::string
|
||||||
{
|
{
|
||||||
|
@ -4,11 +4,70 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace sliger;
|
using namespace sliger;
|
||||||
|
|
||||||
|
inline auto maybe_op_to_string(uint32_t value) -> std::string
|
||||||
|
{
|
||||||
|
switch (static_cast<Op>(value)) {
|
||||||
|
case Op::Nop:
|
||||||
|
return "Nop";
|
||||||
|
case Op::PushNull:
|
||||||
|
return "PushNull";
|
||||||
|
case Op::PushInt:
|
||||||
|
return "PushInt";
|
||||||
|
case Op::PushBool:
|
||||||
|
return "PushBool";
|
||||||
|
case Op::PushString:
|
||||||
|
return "PushString";
|
||||||
|
case Op::PushPtr:
|
||||||
|
return "PushPtr";
|
||||||
|
case Op::Pop:
|
||||||
|
return "Pop";
|
||||||
|
case Op::LoadLocal:
|
||||||
|
return "LoadLocal";
|
||||||
|
case Op::StoreLocal:
|
||||||
|
return "StoreLocal";
|
||||||
|
case Op::Call:
|
||||||
|
return "Call";
|
||||||
|
case Op::Return:
|
||||||
|
return "Return";
|
||||||
|
case Op::Jump:
|
||||||
|
return "Jump";
|
||||||
|
case Op::JumpIfFalse:
|
||||||
|
return "JumpIfFalse";
|
||||||
|
case Op::Add:
|
||||||
|
return "Add";
|
||||||
|
case Op::Subtract:
|
||||||
|
return "Subtract";
|
||||||
|
case Op::Multiply:
|
||||||
|
return "Multiply";
|
||||||
|
case Op::Divide:
|
||||||
|
return "Divide";
|
||||||
|
case Op::Remainder:
|
||||||
|
return "Remainder";
|
||||||
|
case Op::Equal:
|
||||||
|
return "Equal";
|
||||||
|
case Op::LessThan:
|
||||||
|
return "LessThan";
|
||||||
|
case Op::And:
|
||||||
|
return "And";
|
||||||
|
case Op::Or:
|
||||||
|
return "Or";
|
||||||
|
case Op::Xor:
|
||||||
|
return "Xor";
|
||||||
|
case Op::Not:
|
||||||
|
return "Not";
|
||||||
|
case Op::SourceMap:
|
||||||
|
return "SourceMap";
|
||||||
|
default:
|
||||||
|
return std::to_string(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VM::run_until_done()
|
void VM::run_until_done()
|
||||||
{
|
{
|
||||||
while (!done()) {
|
while (!done()) {
|
||||||
@ -19,15 +78,15 @@ void VM::run_until_done()
|
|||||||
void VM::run_n_instructions(size_t amount)
|
void VM::run_n_instructions(size_t amount)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; !done() and i < amount; ++i) {
|
for (size_t i = 0; !done() and i < amount; ++i) {
|
||||||
|
|
||||||
run_instruction();
|
run_instruction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM::run_instruction()
|
void VM::run_instruction()
|
||||||
{
|
{
|
||||||
std::cout << "stack:\n";
|
std::cout << std::format(" {:>4}: {:<12}{}\n", this->pc,
|
||||||
this->print_stack();
|
maybe_op_to_string(this->program[this->pc]), stack_repr_string());
|
||||||
std::cout << std::format("pc = {}\n", this->pc);
|
|
||||||
auto op = eat_op();
|
auto op = eat_op();
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Op::Nop:
|
case Op::Nop:
|
||||||
|
@ -156,11 +156,18 @@ public:
|
|||||||
return this->stack;
|
return this->stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void print_stack() const
|
inline auto stack_repr_string() const -> std::string
|
||||||
{
|
{
|
||||||
for (const auto& value : view_stack()) {
|
auto result = std::string();
|
||||||
std::cout << std::format(" {}\n", value.to_repr_string());
|
result += "→";
|
||||||
|
const auto& stack = view_stack();
|
||||||
|
for (size_t i = 0; i < stack.size(); ++i) {
|
||||||
|
if (i != 0) {
|
||||||
|
result += " ";
|
||||||
}
|
}
|
||||||
|
result += stack[stack.size() - i - 1].to_repr_string();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user