Compare commits
No commits in common. "3d89031748aac8b9ed958112de036cef7ff16a2b" and "ce91126cb150e12ae0a15f8bbc4eebd754080d10" have entirely different histories.
3d89031748
...
ce91126cb1
@ -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);
|
locs.insert_or_assign(std::get<Loc>(line.value).value, ip + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AsmLineType::Ref: {
|
case AsmLineType::Ref: {
|
||||||
@ -75,16 +75,10 @@ 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)) {
|
||||||
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)));
|
output.at(i) = static_cast<uint32_t>(locs.at(refs.at(i)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +92,6 @@ int main()
|
|||||||
// + a b
|
// + a b
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// fn main() {
|
|
||||||
// let result = 0;
|
// let result = 0;
|
||||||
// let i = 0;
|
// let i = 0;
|
||||||
// loop {
|
// loop {
|
||||||
@ -106,15 +99,12 @@ 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"),
|
||||||
Call, 0,
|
Pop,
|
||||||
PushPtr, R("_exit"),
|
PushPtr, R("_exit"),
|
||||||
Jump,
|
Jump,
|
||||||
Pop,
|
Pop,
|
||||||
@ -122,17 +112,15 @@ 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("0"),
|
L("1"),
|
||||||
SourceMap, 66, 8, 5,
|
SourceMap, 66, 8, 5,
|
||||||
LoadLocal, 2,
|
LoadLocal, 1,
|
||||||
PushInt, 10,
|
PushInt, 0,
|
||||||
LessThan,
|
LessThan,
|
||||||
Not,
|
Not,
|
||||||
PushPtr, R("1"),
|
PushPtr, R("1"),
|
||||||
@ -140,25 +128,22 @@ 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, 1,
|
LoadLocal, 0,
|
||||||
PushInt, 5,
|
PushInt, 5,
|
||||||
PushPtr, R("add"),
|
PushPtr, R("add"),
|
||||||
Call, 2,
|
Call, 2,
|
||||||
StoreLocal, 1,
|
StoreLocal, 0,
|
||||||
SourceMap, 133, 12, 5,
|
SourceMap, 133, 12, 5,
|
||||||
LoadLocal, 2,
|
LoadLocal, 1,
|
||||||
PushInt, 1,
|
PushInt, 1,
|
||||||
Add,
|
Add,
|
||||||
StoreLocal, 2,
|
StoreLocal, 1,
|
||||||
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
|
||||||
@ -171,7 +156,6 @@ 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(4));
|
|
||||||
auto flame_graph = vm.flame_graph_json();
|
vm.print_stack();
|
||||||
std::cout << std::format("flame graph: {}\n", flame_graph);
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -51,15 +50,6 @@ 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)
|
||||||
@ -90,42 +80,120 @@ public:
|
|||||||
|
|
||||||
inline auto type() const -> ValueType { return m_type; };
|
inline auto type() const -> ValueType { return m_type; };
|
||||||
|
|
||||||
template <ValueType VT> inline auto as() -> ValueTypeToType<VT>::Type&
|
inline auto as_null() -> Null&
|
||||||
{
|
{
|
||||||
|
//
|
||||||
try {
|
try {
|
||||||
return std::get<typename ValueTypeToType<VT>::Type>(value);
|
return std::get<Null>(value);
|
||||||
} catch (const std::bad_variant_access& ex) {
|
} catch (const std::bad_variant_access& ex) {
|
||||||
std::cerr << std::format("error: tried to unwrap {} as {}\n",
|
std::cout << std::format("tried to unwrap {} as Null\n",
|
||||||
value_type_to_string(this->m_type), value_type_to_string(VT));
|
value_type_to_string(this->m_type));
|
||||||
std::exit(1);
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inline auto as_null() const -> const Null&
|
||||||
template <ValueType VT>
|
|
||||||
inline auto as() const -> const ValueTypeToType<VT>::Type&
|
|
||||||
{
|
{
|
||||||
|
//
|
||||||
try {
|
try {
|
||||||
return std::get<typename ValueTypeToType<VT>::Type>(value);
|
return std::get<Null>(value);
|
||||||
} catch (const std::bad_variant_access& ex) {
|
} catch (const std::bad_variant_access& ex) {
|
||||||
std::cerr << std::format("error: tried to unwrap {} as {}\n",
|
std::cout << std::format("tried to unwrap {} as Null\n",
|
||||||
value_type_to_string(this->m_type), value_type_to_string(VT));
|
value_type_to_string(this->m_type));
|
||||||
std::exit(1);
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clang-format off
|
inline auto as_int() -> Int&
|
||||||
inline auto as_null() -> Null& { return as<ValueType::Null>(); }
|
{
|
||||||
inline auto as_int() -> Int& { return as<ValueType::Int>(); }
|
//
|
||||||
inline auto as_bool() -> Bool& { return as<ValueType::Bool>(); }
|
try {
|
||||||
inline auto as_string() -> String& { return as<ValueType::String>(); }
|
return std::get<Int>(value);
|
||||||
inline auto as_ptr() -> Ptr& { return as<ValueType::Ptr>(); }
|
} 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_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_null() const -> const Null& { return as<ValueType::Null>(); }
|
inline auto as_bool() -> Bool&
|
||||||
inline auto as_int() const -> const Int& { return as<ValueType::Int>(); }
|
{
|
||||||
inline auto as_bool() const -> const Bool& { return as<ValueType::Bool>(); }
|
//
|
||||||
inline auto as_string() const -> const String& { return as<ValueType::String>(); }
|
try {
|
||||||
inline auto as_ptr() const -> const Ptr& { return as<ValueType::Ptr>(); }
|
return std::get<Bool>(value);
|
||||||
// clang-format on
|
} 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_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&
|
||||||
|
{
|
||||||
|
//
|
||||||
|
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_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,70 +4,11 @@
|
|||||||
#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()) {
|
||||||
@ -78,15 +19,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 << std::format(" {:>4}: {:<12}{}\n", this->pc,
|
std::cout << "stack:\n";
|
||||||
maybe_op_to_string(this->program[this->pc]), stack_repr_string(4));
|
this->print_stack();
|
||||||
|
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,22 +156,11 @@ public:
|
|||||||
return this->stack;
|
return this->stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto stack_repr_string(size_t max_items) const -> std::string
|
inline void print_stack() const
|
||||||
{
|
{
|
||||||
auto result = std::string();
|
for (const auto& value : view_stack()) {
|
||||||
result += "→";
|
std::cout << std::format(" {}\n", value.to_repr_string());
|
||||||
const auto& stack = view_stack();
|
|
||||||
for (size_t i = 0; i < stack.size() and i < max_items; ++i) {
|
|
||||||
if (i != 0) {
|
|
||||||
result += " ";
|
|
||||||
}
|
}
|
||||||
result += std::format(
|
|
||||||
"{:<11}", stack[stack.size() - i - 1].to_repr_string());
|
|
||||||
}
|
|
||||||
if (stack.size() >= max_items) {
|
|
||||||
result += std::format(" ... + {}", stack.size() - max_items + 1);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user