Skip to content
Draft
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Change Log

## [Unreleased changes] - 20XX-XX-XX
### Breaking changes
- `assert` is no longer an instruction but a builtin

### Added
- added `BREAKPOINT` instruction

## [4.1.2] - 2026-01-09
### Added
- the repl prints the output of the last expression it ran
Expand Down
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ if (NOT ARK_EMSCRIPTEN)
endif ()

include(cmake/CPM.cmake)
message(STATUS "ArkScript version ${ARK_VERSION_MAJOR}.${ARK_VERSION_MINOR}.${ARK_VERSION_PATCH}-${ARK_COMMIT}")

#####################################################
# Configure files
Expand All @@ -55,9 +56,7 @@ include(cmake/CPM.cmake)
configure_file(
${ark_SOURCE_DIR}/Installer.iss.in
${ark_SOURCE_DIR}/Installer.iss)

## Ark/Constants.hpp
message(STATUS "ArkScript version ${ARK_VERSION_MAJOR}.${ARK_VERSION_MINOR}.${ARK_VERSION_PATCH}-${ARK_COMMIT}")
configure_file(
${ark_SOURCE_DIR}/include/Ark/Constants.hpp.in
${ark_SOURCE_DIR}/include/Ark/Constants.hpp)
Expand Down
3 changes: 2 additions & 1 deletion include/Ark/Ark.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
#include <Ark/Error/Exceptions.hpp>
#include <Ark/Constants.hpp>
#include <Ark/Utils/Utils.hpp>
#include <Ark/Compiler/Welder.hpp>
#include <Ark/State.hpp>
#include <Ark/VM/VM.hpp>
#include <Ark/VM/DefaultValues.hpp>
#include <Ark/Compiler/Welder.hpp>
#include <Ark/TypeChecker.hpp>

#endif // ARK_ARK_HPP
3 changes: 2 additions & 1 deletion include/Ark/Builtins/Builtins.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include <vector>

#include <Ark/VM/Value.hpp>
#include <Ark/VM/Value/Value.hpp>

namespace Ark
{
Expand Down Expand Up @@ -70,6 +70,7 @@ namespace Ark::internal::Builtins
ARK_BUILTIN(system_);
ARK_BUILTIN(sleep);
ARK_BUILTIN(exit_);
ARK_BUILTIN(assert_);
}

namespace String
Expand Down
2 changes: 1 addition & 1 deletion include/Ark/Compiler/BytecodeReader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

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

namespace Ark
Expand Down
4 changes: 2 additions & 2 deletions include/Ark/Compiler/Common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,10 @@ namespace Ark::internal
// from FIRST_OPERATOR, to LAST_OPERATOR
// The order is very important
constexpr std::array<std::string_view, 24> operators = {
"breakpoint",
"+", "-", "*", "/",
">", "<", "<=", ">=", "!=", "=",
"len", "empty?", "tail", "head",
"nil?", "assert",
"len", "empty?", "tail", "head", "nil?",
"toNumber", "toString",
"@", "@@", "mod",
"type", "hasField",
Expand Down
38 changes: 19 additions & 19 deletions include/Ark/Compiler/Instructions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,53 +173,53 @@ namespace Ark::internal

FIRST_OPERATOR = 0x26,

// @role Pop the top of the stack, if it's true, trigger the debugger
BREAKPOINT = 0x26,

// @role Push `TS1 + TS`
ADD = 0x26,
ADD = 0x27,

// @role Push `TS1 - TS`
SUB = 0x27,
SUB = 0x28,

// @role Push `TS1 * TS`
MUL = 0x28,
MUL = 0x29,

// @role Push `TS1 / TS`
DIV = 0x29,
DIV = 0x2a,

// @role Push `TS1 > TS`
GT = 0x2a,
GT = 0x2b,

// @role Push `TS1 < TS`
LT = 0x2b,
LT = 0x2c,

// @role Push `TS1 <= TS`
LE = 0x2c,
LE = 0x2d,

// @role Push `TS1 >= TS`
GE = 0x2d,
GE = 0x2e,

// @role Push `TS1 != TS`
NEQ = 0x2e,
NEQ = 0x2f,

// @role Push `TS1 == TS`
EQ = 0x2f,
EQ = 0x30,

// @role Push `len(TS)`, TS must be a list
LEN = 0x30,
LEN = 0x31,

// @role Push `empty?(TS)`, TS must be a list or string
IS_EMPTY = 0x31,
IS_EMPTY = 0x32,

// @role Push `tail(TS)`, all the elements of TS except the first one. TS must be a list or string
TAIL = 0x32,
TAIL = 0x33,

// @role Push `head(TS)`, the first element of TS or nil if empty. TS must be a list or string
HEAD = 0x33,
HEAD = 0x34,

// @role Push true if TS is nil, false otherwise
IS_NIL = 0x34,

// @role Throw an exception if TS1 is false, and display TS (must be a string). Do not push anything on the stack
ASSERT = 0x35,
IS_NIL = 0x35,

// @role Convert TS to number (must be a string)
TO_NUM = 0x36,
Expand Down Expand Up @@ -492,6 +492,7 @@ namespace Ark::internal
"POP_SCOPE",
"GET_CURRENT_PAGE_ADDR",
// operators
"BREAKPOINT",
"ADD",
"SUB",
"MUL",
Expand All @@ -507,7 +508,6 @@ namespace Ark::internal
"TAIL",
"HEAD",
"IS_NIL",
"ASSERT",
"TO_NUM",
"TO_STR",
"AT",
Expand Down
43 changes: 41 additions & 2 deletions include/Ark/Compiler/Lowerer/ASTLowerer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@
#include <Ark/Compiler/ValTableElem.hpp>
#include <Ark/Compiler/Lowerer/LocalsLocator.hpp>

namespace Ark::internal
namespace Ark
{
class State;
class Welder;
}

namespace Ark::internal
{
/**
* @brief The ArkScript AST to IR compiler
*
Expand All @@ -44,6 +47,21 @@ namespace Ark::internal
*/
explicit ASTLowerer(unsigned debug);

/**
* @brief Pre-fill tables (used by the debugger)
*
* @param symbols
* @param constants
*/
void addToTables(const std::vector<std::string>& symbols, const std::vector<ValTableElem>& constants);

/**
* @brief Start bytecode pages at a given offset (by default, 0)
*
* @param offset
*/
void offsetPagesBy(std::size_t offset);

/**
* @brief Start the compilation
*
Expand Down Expand Up @@ -84,13 +102,26 @@ namespace Ark::internal
// tables: symbols, values, plugins and codes
std::vector<std::string> m_symbols;
std::vector<ValTableElem> m_values;
std::size_t m_start_page_at_offset = 0; ///< Used to offset the page numbers when compiling code in the debugger
std::vector<IR::Block> m_code_pages;
std::vector<IR::Block> m_temp_pages; ///< we need temporary code pages for some compilations passes
IR::label_t m_current_label = 0;
std::stack<std::string> m_opened_vars; ///< stack of vars we are currently declaring

Logger m_logger;

Page createNewCodePage(const bool temp = false) noexcept
{
if (!temp)
{
m_code_pages.emplace_back();
return Page { .index = m_start_page_at_offset + m_code_pages.size() - 1u, .is_temp = false };
}

m_temp_pages.emplace_back();
return Page { .index = m_temp_pages.size() - 1u, .is_temp = true };
}

/**
* @brief helper functions to get a temp or finalized code page
*
Expand All @@ -100,7 +131,7 @@ namespace Ark::internal
IR::Block& page(const Page page) noexcept
{
if (!page.is_temp)
return m_code_pages[page.index];
return m_code_pages[page.index - m_start_page_at_offset];
return m_temp_pages[page.index];
}

Expand Down Expand Up @@ -128,6 +159,14 @@ namespace Ark::internal
*/
static std::optional<Instruction> getListInstruction(const std::string& name) noexcept;

/**
* Checks if a node is a list and is a call to 'breakpoint'
* @param node node to check
* @return true if the node is a 'breakpoint' call: (breakpoint <cond>)
* @return false otherwise
*/
static bool isBreakpoint(const Node& node);

/**
* Checks if a node is a list and has a keyboard as its first node, indicating if it's producing a value on the stack or not
* @param node node to check
Expand Down
4 changes: 4 additions & 0 deletions include/Ark/Compiler/ValTableElem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ namespace Ark::internal

// automatic handling (Number/String/Function)
explicit ValTableElem(const Node& node) noexcept;
// Numbers
explicit ValTableElem(double n) noexcept;
// Strings
explicit ValTableElem(const std::string& str) noexcept;
// Functions
explicit ValTableElem(std::size_t page) noexcept;

Expand Down
22 changes: 22 additions & 0 deletions include/Ark/Compiler/Welder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

namespace Ark
{
class Value;

/**
* @brief The welder joins all the compiler passes
*/
Expand Down Expand Up @@ -65,12 +67,32 @@ namespace Ark
*/
bool computeASTFromString(const std::string& code);

/**
* @brief Compile code from a string, with a set of known symbols (useful for the debugger)
*
* @param code
* @param symbols
* @return true on success
*/
bool computeASTFromStringWithKnownSymbols(const std::string& code, const std::vector<std::string>& symbols);

/**
* @brief Compile the AST processed by computeASTFromFile / computeASTFromString
*
* @return true on success
*/
bool generateBytecode();

/**
* @brief Compile the AST processed by computeASTFromFile / computeASTFromString, with prefilled symbols and constants tables (useful for the debugger)
*
* @param symbols
* @param constants
* @param start_page_at_offset
* @return true on success
*/
bool generateBytecodeUsingTables(const std::vector<std::string>& symbols, const std::vector<Value>& constants, std::size_t start_page_at_offset);

/**
* @brief Save the generated bytecode to a given file
* @param filename
Expand Down
1 change: 1 addition & 0 deletions include/Ark/Constants.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ namespace Ark
constexpr uint16_t FeatureASTOptimizer = 1 << 2; ///< This is disabled so that embedding ArkScript does not prune nodes from the AST ; it is active in the `arkscript` executable
constexpr uint16_t FeatureIROptimizer = 1 << 3;
constexpr uint16_t FeatureNameResolver = 1 << 4;
constexpr uint16_t FeatureVMDebugger = 1 << 5; ///< This is disabled so that embedding ArkScript does not launch the debugger on every error when running code

constexpr uint16_t FeatureDumpIR = 1 << 14;
/// This feature should only be used in tests, to disable diagnostics generation and enable exceptions to be thrown
Expand Down
Loading
Loading