ArkScript
A small, lisp-inspired, functional scripting language
BytecodeReader.hpp
Go to the documentation of this file.
1/**
2 * @file BytecodeReader.hpp
3 * @author Lexy Plateau (lexplt.dev@gmail.com)
4 * @brief A bytecode disassembler for ArkScript
5 * @date 2020-10-27
6 *
7 * @copyright Copyright (c) 2020-2026
8 *
9 */
10
11#ifndef ARK_COMPILER_BYTECODEREADER_HPP
12#define ARK_COMPILER_BYTECODEREADER_HPP
13
14#include <vector>
15#include <string>
16#include <cinttypes>
17#include <optional>
18
24
25namespace Ark
26{
27 class State;
28
29 enum class BytecodeSegment
30 {
31 All,
32 Symbols,
33 Values,
34 Code,
37 };
38
39 struct Version
40 {
41 uint16_t major;
42 uint16_t minor;
43 uint16_t patch;
44 };
45
46 struct Symbols
47 {
48 std::vector<std::string> symbols {};
49 std::size_t start {}; ///< Point to the SYM_TABLE_START byte in the bytecode
50 std::size_t end {}; ///< Point to the byte following the last byte of the table in the bytecode
51 };
52
53 struct Values
54 {
55 std::vector<Value> values {};
56 std::size_t start {}; ///< Point to the VAL_TABLE_START byte in the bytecode
57 std::size_t end {}; ///< Point to the byte following the last byte of the table in the bytecode
58 };
59
60 struct Filenames
61 {
62 std::vector<std::string> filenames {};
63 std::size_t start {}; ///< Point to the FILENAMES_TABLE_START byte in the bytecode
64 std::size_t end {}; ///< Point to the byte following the last byte of the table in the bytecode
65 };
66
68 {
69 std::vector<internal::InstLoc> locations {};
70 std::size_t start {}; ///< Point to the INST_LOC_TABLE_START byte in the bytecode
71 std::size_t end {}; ///< Point to the byte following the last byte of the table in the bytecode
72 };
73
74 struct Code
75 {
76 std::vector<bytecode_t> pages {};
77 std::size_t start {}; ///< Point to the CODE_SEGMENT_START byte in the bytecode
78 };
79
80 namespace internal
81 {
82 enum class ArgKind
83 {
84 Symbol,
86 Builtin,
87 Raw, ///< eg: Stack index, jump address, number
88 RawHex,
92 SymSym,
93 BuiltinRaw, ///< Builtin, number
94 ConstRaw, ///< Constant, number
95 SymRaw, ///< Symbol, number
96 RawSym, ///< Symbol index, symbol
97 RawConst, ///< Symbol index, constant
98 RawRaw, ///< Symbol index, symbol index
100 };
101
102 struct Arg
103 {
105 uint8_t padding;
106 uint16_t arg;
107
108 [[nodiscard]] uint16_t primary() const
109 {
110 return arg & 0x0fff;
111 }
112
113 [[nodiscard]] uint16_t secondary() const
114 {
115 return static_cast<uint16_t>((padding << 4) | (arg & 0xf000) >> 12);
116 }
117 };
118 }
119
120 /**
121 * @brief This class is just a helper to
122 * - check if a bytecode is valid
123 * - display it in a human-readable way by using the opcode names
124 *
125 */
127 {
128 public:
129 /**
130 * @brief Construct a new Bytecode Reader object
131 *
132 */
134
135 /**
136 * @brief Construct needed data before displaying information about a given file
137 *
138 * @param file filename of the bytecode file
139 */
140 void feed(const std::string& file);
141
142 /**
143 * @brief Construct needed data before displaying information about a given bytecode
144 *
145 * @param bytecode
146 */
147 void feed(const bytecode_t& bytecode);
148
149 /**
150 * Check for the presence of the magic header
151 * @return true if the magic 'ark\0' was found
152 */
153 [[nodiscard]] bool checkMagic() const;
154
155 /**
156 *
157 * @return Version compiler version used to create the given bytecode file
158 */
159 [[nodiscard]] Version version() const;
160
161 /**
162 * @brief Return the read timestamp from the bytecode file
163 *
164 * @return unsigned long long
165 */
166 [[nodiscard]] unsigned long long timestamp() const;
167
168 /**
169 *
170 * @return std::vector<unsigned char> bytecode sha
171 */
172 [[nodiscard]] std::vector<unsigned char> sha256() const;
173
174 /**
175 *
176 * @return Symbols
177 */
178 [[nodiscard]] Symbols symbols() const;
179
180 /**
181 * @param symbols
182 * @return Values
183 */
184 [[nodiscard]] Values values(const Symbols& symbols) const;
185
186 /**
187 * @param values
188 * @return Filenames
189 */
190 [[nodiscard]] Filenames filenames(const Values& values) const;
191
192 /**
193 * @param filenames
194 * @return InstLocations
195 */
196 [[nodiscard]] InstLocations instLocations(const Filenames& filenames) const;
197
198 /**
199 * @param instLocations
200 * @return Code
201 */
202 [[nodiscard]] Code code(const InstLocations& instLocations) const;
203
204 /**
205 * @brief Find the location of an instruction
206 * @param inst_locations
207 * @param ip
208 * @param pp
209 * @return
210 */
211 std::optional<internal::InstLoc> findSourceLocation(const std::vector<internal::InstLoc>& inst_locations, std::size_t ip, std::size_t pp) const;
212
213 /**
214 * @brief Display the bytecode opcode in a human friendly way.
215 *
216 * @param segment selected bytecode segment that will be displayed
217 * @param sStart start of the segment slice to display (Ignored in code segment if no page is available)
218 * @param sEnd end of the segment slice to display (Ignored in code segment if no page is available)
219 * @param cPage selected page of the code segment (Used only for the code segment)
220 */
221 void display(BytecodeSegment segment = BytecodeSegment::All,
222 std::optional<uint16_t> sStart = std::nullopt,
223 std::optional<uint16_t> sEnd = std::nullopt,
224 std::optional<uint16_t> cPage = std::nullopt) const;
225
226 void printInstruction(std::ostream& os, uint8_t inst, uint8_t padding, uint16_t imm_arg, const Symbols& syms, const Values& vals, bool colorize = true) const;
227
228 friend class Ark::State;
229
230 private:
232 std::unordered_map<internal::Instruction, internal::ArgKind> m_arg_kinds;
233
234 /**
235 * @brief Read a number from the bytecode, under the instruction pointer i
236 *
237 * @param i this parameter is being modified to point to the next value
238 * @return uint16_t the number we read (big endian)
239 */
240 [[nodiscard]] uint16_t readNumber(std::size_t& i) const;
241 };
242}
243
244#endif
Common code for the compiler.
The different instructions used by the compiler and virtual machine.
#define ARK_API
Definition Module.hpp:22
ArkScript configuration macros.
Default value type handled by the virtual machine.
This class is just a helper to.
std::unordered_map< internal::Instruction, internal::ArgKind > m_arg_kinds
Ark state to handle the dirty job of loading and compiling ArkScript code.
Definition State.hpp:38
@ Raw
Keep all text as is without modifying it (useful for the code formatter)
@ RawSym
Symbol index, symbol.
@ RawRaw
Symbol index, symbol index.
@ BuiltinRaw
Builtin, number.
@ SymRaw
Symbol, number.
@ RawConst
Symbol index, constant.
@ ConstRaw
Constant, number.
std::vector< uint8_t > bytecode_t
Definition Common.hpp:22
std::vector< bytecode_t > pages
std::size_t start
Point to the CODE_SEGMENT_START byte in the bytecode.
std::size_t end
Point to the byte following the last byte of the table in the bytecode.
std::vector< std::string > filenames
std::size_t start
Point to the FILENAMES_TABLE_START byte in the bytecode.
std::size_t end
Point to the byte following the last byte of the table in the bytecode.
std::size_t start
Point to the INST_LOC_TABLE_START byte in the bytecode.
std::vector< internal::InstLoc > locations
std::vector< std::string > symbols
std::size_t end
Point to the byte following the last byte of the table in the bytecode.
std::size_t start
Point to the SYM_TABLE_START byte in the bytecode.
std::vector< Value > values
std::size_t end
Point to the byte following the last byte of the table in the bytecode.
std::size_t start
Point to the VAL_TABLE_START byte in the bytecode.
uint16_t secondary() const
uint16_t primary() const