17 std::ifstream ifs(file, std::ios::binary | std::ios::ate);
19 throw std::runtime_error(
"[BytecodeReader] Couldn't open file '" + file +
"'");
20 std::size_t pos = ifs.tellg();
22 std::vector<char> temp(pos);
23 ifs.seekg(0, std::ios::beg);
24 ifs.read(&temp[0], pos);
28 for (std::size_t i = 0; i < pos; ++i)
43 if (!(b.size() > 4 && b[i++] ==
'a' && b[i++] ==
'r' && b[i++] ==
'k' && b[i++] == Instruction::NOP))
55 using timestamp_t =
unsigned long long;
57 auto aa = (
static_cast<timestamp_t
>(
m_bytecode[i]) << 56),
58 ba = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 48),
59 ca = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 40),
60 da = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 32),
61 ea = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 24),
62 fa = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 16),
63 ga = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 8),
64 ha = (
static_cast<timestamp_t
>(
m_bytecode[++i]));
66 timestamp = aa + ba + ca + da + ea + fa + ga + ha;
72 const std::optional<uint16_t> sStart,
73 const std::optional<uint16_t> sEnd,
74 const std::optional<uint16_t> cPage)
79 std::ostream& os = std::cout;
81 if (!(b.size() > 4 && b[i++] ==
'a' && b[i++] ==
'r' && b[i++] ==
'k' && b[i++] == Instruction::NOP))
83 os <<
"Invalid format";
93 os <<
"Version: " << major <<
"." << minor <<
"." << patch <<
"\n";
95 using timestamp_t =
unsigned long long;
97 auto aa = (
static_cast<timestamp_t
>(
m_bytecode[i]) << 56),
98 ba = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 48),
99 ca = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 40),
100 da = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 32),
101 ea = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 24),
102 fa = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 16),
103 ga = (
static_cast<timestamp_t
>(
m_bytecode[++i]) << 8),
104 ha = (
static_cast<timestamp_t
>(
m_bytecode[++i]));
106 timestamp = aa + ba + ca + da + ea + fa + ga + ha;
107 os <<
"Timestamp: " <<
timestamp <<
"\n";
110 for (std::size_t j = 0; j < picosha2::k_digest_size; ++j)
112 os << std::hex << static_cast<int>(
m_bytecode[i]) << std::dec;
117 std::vector<std::string> symbols;
118 std::vector<std::string> values;
122 if ((sStart.has_value() && !sEnd.has_value()) || (!sStart.has_value() && sEnd.has_value()))
124 os << termcolor::red <<
"Both start and end parameter need to be provided together\n"
128 else if (sStart.has_value() && sEnd.has_value() && sStart.value() >= sEnd.value())
130 os << termcolor::red <<
"Invalid slice start and end arguments\n"
135 if (b[i] == Instruction::SYM_TABLE_START)
140 uint16_t sliceSize = size;
143 if (showSym && sStart.has_value() && sEnd.has_value() && (sStart.value() > size || sEnd.value() > size))
144 os << termcolor::red <<
"Slice start or end can't be greater than the segment size: " << size <<
"\n";
145 else if (showSym && sStart.has_value() && sEnd.has_value())
146 sliceSize = sEnd.value() - sStart.value() + 1;
149 os << termcolor::cyan <<
"Symbols table" << termcolor::reset <<
" (length: " << sliceSize <<
")\n";
151 for (uint16_t j = 0; j < size; ++j)
153 if (
auto start = sStart;
auto end = sEnd)
154 showSym = showSym && (j >= start.value() && j <= end.value());
163 os << static_cast<int>(j) <<
") ";
164 os << content <<
"\n";
167 symbols.push_back(content);
174 os << termcolor::red <<
"Missing symbole table entry point\n"
182 if (b[i] == Instruction::VAL_TABLE_START)
187 uint16_t sliceSize = size;
190 if (showVal && sStart.has_value() && sEnd.has_value() && (sStart.value() > size || sEnd.value() > size))
191 os << termcolor::red <<
"Slice start or end can't be greater than the segment size: " << size <<
"\n";
192 else if (showVal && sStart.has_value() && sEnd.has_value())
193 sliceSize = sEnd.value() - sStart.value() + 1;
196 os << termcolor::green <<
"Constants table" << termcolor::reset <<
" (length: " << sliceSize <<
")\n";
198 for (uint16_t j = 0; j < size; ++j)
200 if (
auto start = sStart;
auto end = sEnd)
201 showVal = showVal && (j >= start.value() && j <= end.value());
204 os << static_cast<int>(j) <<
") ";
208 if (type == Instruction::NUMBER_TYPE)
212 val.push_back(b[i++]);
215 os <<
"(Number) " << val;
216 values.push_back(
"(Number) " + val);
218 else if (type == Instruction::STRING_TYPE)
222 val.push_back(b[i++]);
225 os <<
"(String) " << val;
226 values.push_back(
"(String) " + val);
228 else if (type == Instruction::FUNC_TYPE)
233 os <<
"(PageAddr) " << addr;
234 values.push_back(
"(PageAddr) " + std::to_string(addr));
239 os << termcolor::red <<
"Unknown value type: " <<
static_cast<int>(type) <<
'\n'
253 os << termcolor::red <<
"Missing constant table entry point\n"
268 uint16_t sliceSize = size;
270 if (sStart.has_value() && sEnd.has_value())
271 sliceSize = sEnd.value() - sStart.value() + 1;
273 bool displayCode =
true;
275 if (
auto page = cPage)
276 displayCode = pp == page.value();
279 os << termcolor::magenta <<
"Code segment " << pp << termcolor::reset <<
" (length: " << sliceSize <<
")\n";
293 uint16_t line_number = i - j;
294 if (sStart.has_value() && sEnd.has_value() && ((sStart.value() > size) || (sEnd.value() > size)))
296 os << termcolor::red <<
"Slice start or end can't be greater than the segment size: " << size << termcolor::reset <<
"\n";
299 else if (sStart.has_value() && sEnd.has_value() && cPage.has_value())
300 displayLine = displayCode && (line_number >= sStart.value() && line_number <= sEnd.value());
303 os << termcolor::cyan << line_number << termcolor::reset <<
" " << termcolor::yellow;
307 if (inst == Instruction::NOP)
312 else if (inst == Instruction::LOAD_SYMBOL)
316 os <<
"LOAD_SYMBOL " << termcolor::green << symbols[index] <<
"\n";
319 else if (inst == Instruction::LOAD_CONST)
323 os <<
"LOAD_CONST " << termcolor::magenta << values[index] <<
"\n";
326 else if (inst == Instruction::POP_JUMP_IF_TRUE)
330 os <<
"POP_JUMP_IF_TRUE " << termcolor::red <<
"(" << value <<
")\n";
333 else if (inst == Instruction::STORE)
337 os <<
"STORE " << termcolor::green << symbols[index] <<
"\n";
340 else if (inst == Instruction::LET)
344 os <<
"LET " << termcolor::green << symbols[index] <<
"\n";
347 else if (inst == Instruction::POP_JUMP_IF_FALSE)
351 os <<
"POP_JUMP_IF_FALSE " << termcolor::red <<
"(" << value <<
")\n";
354 else if (inst == Instruction::JUMP)
358 os <<
"JUMP " << termcolor::red <<
"(" << value <<
")\n";
361 else if (inst == Instruction::RET)
366 else if (inst == Instruction::HALT)
371 else if (inst == Instruction::CALL)
375 os <<
"CALL " << termcolor::reset <<
"(" << value <<
")\n";
378 else if (inst == Instruction::CAPTURE)
382 os <<
"CAPTURE " << termcolor::reset << symbols[index] <<
"\n";
385 else if (inst == Instruction::BUILTIN)
392 else if (inst == Instruction::MUT)
396 os <<
"MUT " << termcolor::green << symbols[index] <<
"\n";
399 else if (inst == Instruction::DEL)
403 os <<
"DEL " << termcolor::green << symbols[index] <<
"\n";
406 else if (inst == Instruction::SAVE_ENV)
411 else if (inst == Instruction::GET_FIELD)
415 os <<
"GET_FIELD " << termcolor::green << symbols[index] <<
"\n";
418 else if (inst == Instruction::PLUGIN)
422 os <<
"PLUGIN " << termcolor::magenta << values[index] <<
"\n";
425 else if (inst == Instruction::LIST)
429 os <<
"LIST " << termcolor::reset <<
"(" << value <<
")\n";
432 else if (inst == Instruction::APPEND)
436 os <<
"APPEND " << termcolor::reset <<
"(" << value <<
")\n";
439 else if (inst == Instruction::CONCAT)
443 os <<
"CONCAT " << termcolor::reset <<
"(" << value <<
")\n";
446 else if (inst == Instruction::APPEND_IN_PLACE)
450 os <<
"APPEND_IN_PLACE " << termcolor::reset <<
"(" << value <<
")\n";
453 else if (inst == Instruction::CONCAT_IN_PLACE)
457 os <<
"CONCAT_IN_PLACE " << termcolor::reset <<
"(" << value <<
")\n";
460 else if (inst == Instruction::POP_LIST)
463 os <<
"POP_LIST " << termcolor::reset <<
"\n";
466 else if (inst == Instruction::POP_LIST_IN_PLACE)
469 os <<
"POP_LIST_IN_PLACE " << termcolor::reset <<
"\n";
472 else if (inst == Instruction::POP)
477 else if (inst == Instruction::ADD)
482 else if (inst == Instruction::SUB)
487 else if (inst == Instruction::MUL)
492 else if (inst == Instruction::DIV)
497 else if (inst == Instruction::GT)
502 else if (inst == Instruction::LT)
507 else if (inst == Instruction::LE)
512 else if (inst == Instruction::GE)
517 else if (inst == Instruction::NEQ)
522 else if (inst == Instruction::EQ)
527 else if (inst == Instruction::LEN)
532 else if (inst == Instruction::EMPTY)
537 else if (inst == Instruction::TAIL)
542 else if (inst == Instruction::HEAD)
547 else if (inst == Instruction::ISNIL)
552 else if (inst == Instruction::ASSERT)
557 else if (inst == Instruction::TO_NUM)
562 else if (inst == Instruction::TO_STR)
567 else if (inst == Instruction::AT)
572 else if (inst == Instruction::AND_)
577 else if (inst == Instruction::OR_)
582 else if (inst == Instruction::MOD)
587 else if (inst == Instruction::TYPE)
592 else if (inst == Instruction::HASFIELD)
597 else if (inst == Instruction::NOT)
605 os << termcolor::reset <<
"Unknown instruction: " <<
static_cast<int>(inst) <<
'\n'
618 if (cPage.has_value() && pp == cPage)
630 uint16_t x = (
static_cast<uint16_t
>(
m_bytecode[i]) << 8),
Host the declaration of all the ArkScript builtins.
A bytecode disassembler for ArkScript.
The different instructions used by the compiler and virtual machine.
Lots of utilities about string, filesystem and more.
const bytecode_t & bytecode() noexcept
Return the bytecode object constructed.
unsigned long long timestamp()
Return the read timestamp from the bytecode file.
void display(BytecodeSegment segment=BytecodeSegment::All, std::optional< uint16_t > sStart=std::nullopt, std::optional< uint16_t > sEnd=std::nullopt, std::optional< uint16_t > cPage=std::nullopt)
Display the bytecode opcode in a human friendly way.
void feed(const std::string &file)
Construct needed data before displaying information about a given file.
uint16_t readNumber(std::size_t &i)
Read a number from the bytecode, under the instruction pointer i.
const std::vector< std::pair< std::string, Value > > builtins
std::vector< uint8_t > bytecode_t