Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- new `ptr` command for the debugger, printing the VM pointers (ip, pp, sp)
- compile time arity check when performing a tail call
- `string:utf8len` to compute the number of codepoints in a string
- new `trace` command for the debugger, printing the last executed instructions

### Changed
- all paths inside `if` should return a value, when used as an expression. If an `else` branch is missing, `nil` will be returned
Expand Down
46 changes: 45 additions & 1 deletion include/Ark/Compiler/BytecodeReader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include <Ark/Utils/Platform.hpp>
#include <Ark/Compiler/Common.hpp>
#include <Ark/Compiler/Instructions.hpp>
#include <Ark/VM/Value/Value.hpp>
#include <Ark/Compiler/IntermediateRepresentation/InstLoc.hpp>

Expand Down Expand Up @@ -76,6 +77,46 @@ namespace Ark
std::size_t start {}; ///< Point to the CODE_SEGMENT_START byte in the bytecode
};

namespace internal
{
enum class ArgKind
{
Symbol,
Constant,
Builtin,
Raw, ///< eg: Stack index, jump address, number
RawHex,
ConstConst,
ConstSym,
SymConst,
SymSym,
BuiltinRaw, ///< Builtin, number
ConstRaw, ///< Constant, number
SymRaw, ///< Symbol, number
RawSym, ///< Symbol index, symbol
RawConst, ///< Symbol index, constant
RawRaw, ///< Symbol index, symbol index
RawRawRaw
};

struct Arg
{
ArgKind kind;
uint8_t padding;
uint16_t arg;

[[nodiscard]] uint16_t primary() const
{
return arg & 0x0fff;
}

[[nodiscard]] uint16_t secondary() const
{
return static_cast<uint16_t>((padding << 4) | (arg & 0xf000) >> 12);
}
};
}

/**
* @brief This class is just a helper to
* - check if a bytecode is valid
Expand All @@ -89,7 +130,7 @@ namespace Ark
* @brief Construct a new Bytecode Reader object
*
*/
BytecodeReader() = default;
BytecodeReader();

/**
* @brief Construct needed data before displaying information about a given file
Expand Down Expand Up @@ -182,10 +223,13 @@ namespace Ark
std::optional<uint16_t> sEnd = std::nullopt,
std::optional<uint16_t> cPage = std::nullopt) const;

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;

friend class Ark::State;

private:
bytecode_t m_bytecode;
std::unordered_map<internal::Instruction, internal::ArgKind> m_arg_kinds;

/**
* @brief Read a number from the bytecode, under the instruction pointer i
Expand Down
28 changes: 19 additions & 9 deletions include/Ark/VM/Debugger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ namespace Ark::internal
*/
void run(VM& vm, ExecutionContext& context, bool from_breakpoint);

void registerInstruction(uint32_t word) noexcept;

[[nodiscard]] inline bool isRunning() const noexcept
{
return m_running;
Expand All @@ -105,23 +107,28 @@ namespace Ark::internal
}

private:
struct Command;
struct CommandArgs
{
VM* vm_ptr;
ExecutionContext* ctx_ptr;
std::size_t ip, pp;
const Command& me;
};

struct StartsWith_t
struct StartsWith
{
} StartsWith;
std::string prefix;
};

struct Command
{
using Action_t = std::function<bool(const std::string&, const CommandArgs&)>;
using Args_t = std::vector<std::pair<std::string, std::string>>;

bool is_exact;
std::vector<std::string> names;
Args_t args;
std::string description;
Action_t action;

Expand All @@ -133,9 +140,13 @@ namespace Ark::internal
is_exact(true), names(list_of_names), description(std::move(desc)), action(do_this)
{}

Command(StartsWith_t, std::string start, std::string desc, Action_t&& do_this) :
is_exact(false), names({ std::move(start) }), description(std::move(desc)), action(std::move(do_this))
Command(StartsWith start, std::vector<std::pair<std::string, std::string>> arguments, std::string desc, Action_t&& do_this) :
is_exact(false), names({ std::move(start.prefix) }), args(std::move(arguments)), description(std::move(desc)), action(std::move(do_this))
{}

[[nodiscard]] std::optional<Args_t> getArgs(const std::string& line, std::ostream& os) const;

[[nodiscard]] std::optional<std::size_t> argAsCount(const std::string& line, std::size_t idx, std::ostream& os) const;
};

std::vector<Command> m_commands;
Expand All @@ -147,22 +158,21 @@ namespace Ark::internal
bool m_running { false };
bool m_quit_vm { false };

std::vector<uint32_t> m_previous_insts;

std::ostream& m_os;
bool m_colorize;
std::unique_ptr<std::istream> m_prompt_stream;
std::string m_code; ///< Code added while inside the debugger
std::size_t m_line_count { 0 };

void initCommands();
std::optional<Command> matchCommand(const std::string& line) const;
[[nodiscard]] std::optional<Command> matchCommand(const std::string& line) const;

void showContext(const VM& vm, const ExecutionContext& context) const;
void showStack(VM& vm, const ExecutionContext& context, std::size_t count) const;
void showLocals(VM& vm, ExecutionContext& context, std::size_t count) const;

static std::optional<std::string> getCommandArg(const std::string& command, const std::string& line);
static std::optional<std::size_t> parseStringAsInt(const std::string& str);
[[nodiscard]] std::optional<std::size_t> getArgAndParseOrError(const std::string& command, const std::string& line, std::size_t default_value) const;
void showPreviousInstructions(const VM& vm, std::size_t count) const;

std::optional<std::string> prompt(std::size_t ip, std::size_t pp, VM& vm, ExecutionContext& context);

Expand Down
5 changes: 4 additions & 1 deletion include/Ark/VM/VM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ namespace Ark
* @brief Return a pointer to the first execution context, for the main thread of the app
* @return internal::ExecutionContext*
*/
inline internal::ExecutionContext* getDefaultContext()
inline internal::ExecutionContext* getDefaultContext() const
{
return m_execution_contexts.front().get();
}
Expand Down Expand Up @@ -201,6 +201,9 @@ namespace Ark
*/
int safeRun(internal::ExecutionContext& context, std::size_t untilFrameCount = 0, bool fail_with_exception = false);

template <bool WithDebugger>
void unsafeRun(internal::ExecutionContext& context, std::size_t untilFrameCount = 0);

/**
* @brief Initialize the VM according to the parameters
*
Expand Down
Loading
Loading