Implement "disassemble" function in stdlib
This commit is contained in:
parent
be4224a22b
commit
a01a4d0574
5 changed files with 129 additions and 47 deletions
102
src/common.cpp
102
src/common.cpp
|
@ -376,6 +376,56 @@ Result<Value> Opcode::copy_value() const {
|
|||
return Value(Opcode(TRY(_value.copy())));
|
||||
}
|
||||
|
||||
Result<String> 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<Value> Function::copy_value() const {
|
||||
return Value(Function(TRY(_value.copy())));
|
||||
}
|
||||
|
@ -947,6 +997,58 @@ Result<Array> Function::closure() const {
|
|||
return Array::create((PodArray*)_value->closure.get());
|
||||
}
|
||||
|
||||
Result<String> 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<Opcode>()) return ERROR(TypeMismatch);
|
||||
auto val_str = TRY(val.to<Opcode>()->to_string());
|
||||
res = TRY(res.concat(val_str));
|
||||
res = TRY(res.concat("\n"));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Result<StdlibFunction> StdlibFunction::create(StdlibFunctionId fun_id) {
|
||||
auto pod = TRY(arena_alloc<PodStdlibFunction>());
|
||||
pod->fun_id = (uint64_t)fun_id;
|
||||
|
|
|
@ -981,6 +981,8 @@ class Opcode : public Object {
|
|||
virtual Result<Value> copy_value() const final;
|
||||
Result<Opcode> copy() const;
|
||||
|
||||
Result<String> to_string() const;
|
||||
|
||||
private:
|
||||
GcRoot<PodOpcode> _value;
|
||||
};
|
||||
|
@ -1025,6 +1027,8 @@ class Function : public Object {
|
|||
Result<Array> constants() const;
|
||||
Result<Array> closure() const;
|
||||
|
||||
Result<String> disassemble() const;
|
||||
|
||||
virtual Result<Value> copy_value() const final;
|
||||
Result<Function> copy() const;
|
||||
|
||||
|
|
|
@ -532,6 +532,26 @@ Result<StackFrame> stdlib_deserialize(const StackFrame& stack) {
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
Result<StackFrame> stdlib_disassemble(const StackFrame& stack) {
|
||||
auto stack_size = TRY(stack.size());
|
||||
auto params = TRY(stack.get(0));
|
||||
Array& params_array = *params.to<Array>();
|
||||
|
||||
auto size = TRY(params.size());
|
||||
if (size != 1) return ERROR(ArgumentCountMismatch);
|
||||
|
||||
auto val = TRY(params.get(0));
|
||||
|
||||
if (!val.is<Function>()) return ERROR(TypeMismatch);
|
||||
auto disassembled = Value(TRY(val.to<Function>()->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},
|
||||
};
|
||||
|
|
|
@ -26,6 +26,7 @@ enum class StdlibFunctionId : uint64_t {
|
|||
Guard,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Disassemble,
|
||||
Max,
|
||||
};
|
||||
|
||||
|
|
|
@ -295,53 +295,7 @@ Result<String> Writer::write_dict(const Dict& val) {
|
|||
Result<String> Writer::write_opcode(const Opcode& val) {
|
||||
String res = TRY(String::create("#<opcode "));
|
||||
|
||||
const char* name = opcode_name(val.opcode());
|
||||
OpcodeType ot = opcode_type(val.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, val.arg1().arg);
|
||||
break;
|
||||
case OpcodeType::Reg1:
|
||||
sprintf(buf, "%s %s%ld", name, (val.arg1().is_const) ? "c" : "r",
|
||||
val.arg1().arg);
|
||||
break;
|
||||
case OpcodeType::Reg1I:
|
||||
sprintf(buf, "%s %s%ld %ld", name, (val.arg1().is_const) ? "c" : "r",
|
||||
val.arg1().arg, val.arg2().arg);
|
||||
break;
|
||||
case OpcodeType::Reg2:
|
||||
sprintf(buf, "%s %s%ld %s%ld", name, (val.arg1().is_const) ? "c" : "r",
|
||||
val.arg1().arg, (val.arg2().is_const) ? "c" : "r",
|
||||
val.arg2().arg);
|
||||
break;
|
||||
case OpcodeType::Reg2I:
|
||||
sprintf(buf, "%s %s%ld %s%ld %ld", name,
|
||||
(val.arg1().is_const) ? "c" : "r", val.arg1().arg,
|
||||
(val.arg2().is_const) ? "c" : "r", val.arg2().arg,
|
||||
val.arg3().arg);
|
||||
break;
|
||||
case OpcodeType::Reg3:
|
||||
sprintf(buf, "%s %s%ld %s%ld %s%ld", name,
|
||||
(val.arg1().is_const) ? "c" : "r", val.arg1().arg,
|
||||
(val.arg2().is_const) ? "c" : "r", val.arg2().arg,
|
||||
(val.arg3().is_const) ? "c" : "r", val.arg3().arg);
|
||||
break;
|
||||
case OpcodeType::Reg4:
|
||||
sprintf(buf, "%s %s%ld %s%ld %s%ld %s%ld", name,
|
||||
(val.arg1().is_const) ? "c" : "r", val.arg1().arg,
|
||||
(val.arg2().is_const) ? "c" : "r", val.arg2().arg,
|
||||
(val.arg3().is_const) ? "c" : "r", val.arg3().arg,
|
||||
(val.arg4().is_const) ? "c" : "r", val.arg4().arg);
|
||||
break;
|
||||
}
|
||||
res = TRY(res.concat(buf));
|
||||
res = TRY(res.concat(TRY(val.to_string())));
|
||||
|
||||
res = TRY(res.concat(">"));
|
||||
return res;
|
||||
|
|
Loading…
Reference in a new issue