diff --git a/src/common.cpp b/src/common.cpp index b40fedf..a2d3445 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -376,6 +376,56 @@ Result Opcode::copy_value() const { return Value(Opcode(TRY(_value.copy()))); } +Result Opcode::to_string() const { + String res = TRY(String::create("")); + + const char* name = opcode_name(opcode()); + OpcodeType ot = opcode_type(opcode()); + + char buf[256]; + switch (ot) { + case OpcodeType::Unknown: + return ERROR(TypeMismatch); + case OpcodeType::Reg0: + sprintf(buf, "%s", name); + break; + case OpcodeType::Reg0I: + sprintf(buf, "%s %ld", name, arg1().arg); + break; + case OpcodeType::Reg1: + sprintf(buf, "%s %s%ld", name, (arg1().is_const) ? "c" : "r", arg1().arg); + break; + case OpcodeType::Reg1I: + sprintf(buf, "%s %s%ld %ld", name, (arg1().is_const) ? "c" : "r", + arg1().arg, arg2().arg); + break; + case OpcodeType::Reg2: + sprintf(buf, "%s %s%ld %s%ld", name, (arg1().is_const) ? "c" : "r", + arg1().arg, (arg2().is_const) ? "c" : "r", arg2().arg); + break; + case OpcodeType::Reg2I: + sprintf(buf, "%s %s%ld %s%ld %ld", name, (arg1().is_const) ? "c" : "r", + arg1().arg, (arg2().is_const) ? "c" : "r", arg2().arg, + arg3().arg); + break; + case OpcodeType::Reg3: + sprintf(buf, "%s %s%ld %s%ld %s%ld", name, (arg1().is_const) ? "c" : "r", + arg1().arg, (arg2().is_const) ? "c" : "r", arg2().arg, + (arg3().is_const) ? "c" : "r", arg3().arg); + break; + case OpcodeType::Reg4: + sprintf(buf, "%s %s%ld %s%ld %s%ld %s%ld", name, + (arg1().is_const) ? "c" : "r", arg1().arg, + (arg2().is_const) ? "c" : "r", arg2().arg, + (arg3().is_const) ? "c" : "r", arg3().arg, + (arg4().is_const) ? "c" : "r", arg4().arg); + break; + } + res = TRY(res.concat(buf)); + + return res; +} + Result Function::copy_value() const { return Value(Function(TRY(_value.copy()))); } @@ -947,6 +997,58 @@ Result Function::closure() const { return Array::create((PodArray*)_value->closure.get()); } +Result Function::disassemble() const { + auto code_arr = TRY(code()); + auto constants_arr = TRY(constants()); + auto closure_arr = TRY(closure()); + + auto res = TRY(String::create("")); + + char buf[256]; + + auto constants_size = TRY(constants_arr.size()); + if (constants_size > 0) { + res = TRY(res.concat("constants:\n")); + for (uint64_t i = 0; i < constants_size; ++i) { + sprintf(buf, " c%ld: ", i); + res = TRY(res.concat(buf)); + auto val = TRY(constants_arr.get(i)); + auto val_str = TRY(write_one(val)); + res = TRY(res.concat(val_str)); + res = TRY(res.concat("\n")); + } + res = TRY(res.concat("\n")); + } + + auto closure_size = TRY(closure_arr.size()); + if (closure_size > 0) { + res = TRY(res.concat("closure:\n")); + for (uint64_t i = 0; i < closure_size; ++i) { + sprintf(buf, " %ld: ", i); + res = TRY(res.concat(buf)); + auto val = TRY(closure_arr.get(i)); + auto val_str = TRY(write_one(val)); + res = TRY(res.concat(val_str)); + res = TRY(res.concat("\n")); + } + res = TRY(res.concat("\n")); + } + + auto code_size = TRY(code_arr.size()); + if (code_size > 0) { + res = TRY(res.concat("code:\n")); + for (uint64_t i = 0; i < code_size; ++i) { + res = TRY(res.concat(" ")); + auto val = TRY(code_arr.get(i)); + if (!val.is()) return ERROR(TypeMismatch); + auto val_str = TRY(val.to()->to_string()); + res = TRY(res.concat(val_str)); + res = TRY(res.concat("\n")); + } + } + return res; +} + Result StdlibFunction::create(StdlibFunctionId fun_id) { auto pod = TRY(arena_alloc()); pod->fun_id = (uint64_t)fun_id; diff --git a/src/common.hpp b/src/common.hpp index 9923fbe..48a2c0c 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -981,6 +981,8 @@ class Opcode : public Object { virtual Result copy_value() const final; Result copy() const; + Result to_string() const; + private: GcRoot _value; }; @@ -1025,6 +1027,8 @@ class Function : public Object { Result constants() const; Result closure() const; + Result disassemble() const; + virtual Result copy_value() const final; Result copy() const; diff --git a/src/stdlib.cpp b/src/stdlib.cpp index b666074..44210f8 100644 --- a/src/stdlib.cpp +++ b/src/stdlib.cpp @@ -532,6 +532,26 @@ Result stdlib_deserialize(const StackFrame& stack) { return res; } + +Result stdlib_disassemble(const StackFrame& stack) { + auto stack_size = TRY(stack.size()); + auto params = TRY(stack.get(0)); + Array& params_array = *params.to(); + + auto size = TRY(params.size()); + if (size != 1) return ERROR(ArgumentCountMismatch); + + auto val = TRY(params.get(0)); + + if (!val.is()) return ERROR(TypeMismatch); + auto disassembled = Value(TRY(val.to()->disassemble())); + + auto res = TRY(stack.set(0, disassembled)); + + res = TRY(res.ret(0)); + + return res; +} #define STDLIB_FUNCTION(name, id) \ [(uint64_t)StdlibFunctionId::id] = {#name, StdlibFunctionId::id, \ stdlib_##name} @@ -558,6 +578,7 @@ static StdlibFunctionEntry function_entries[] = { STDLIB_FUNCTION(guard, Guard), STDLIB_FUNCTION(serialize, Serialize), STDLIB_FUNCTION(deserialize, Deserialize), + STDLIB_FUNCTION(disassemble, Disassemble), [(uint64_t)StdlibFunctionId::Max] = {0, StdlibFunctionId::Max, stdlib_unknown}, }; diff --git a/src/stdlib.hpp b/src/stdlib.hpp index d27c56c..a7192a4 100644 --- a/src/stdlib.hpp +++ b/src/stdlib.hpp @@ -26,6 +26,7 @@ enum class StdlibFunctionId : uint64_t { Guard, Serialize, Deserialize, + Disassemble, Max, }; diff --git a/src/writer.cpp b/src/writer.cpp index b591194..e3b787a 100644 --- a/src/writer.cpp +++ b/src/writer.cpp @@ -295,53 +295,7 @@ Result Writer::write_dict(const Dict& val) { Result Writer::write_opcode(const Opcode& val) { String res = TRY(String::create("#")); return res;