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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@
[submodule "lib/dtl"]
path = lib/dtl
url = https://github.com/cubicdaiya/dtl.git
[submodule "lib/ankerl_unordered_dense"]
path = lib/ankerl_unordered_dense
url = https://github.com/martinus/unordered_dense.git
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
- wasm export: we can now run ArkScript code on the web!
- `GET_CURRENT_PAGE_ADDRESS` instruction to push the current page address to the stack
- `CALL_CURRENT_PAGE` super instruction, calling the current page with a given number of arguments (avoid loading a page address on the stack, then popping it to perform the call)
- new data type `Dict`, which can be created with `(dict "key" "value" ...)`, and manipulated with `dict:get`, `dict:add`, `dict:contains`, `dict:remove`, `dict:keys` and `dict:size`

### Changed
- instructions are on 4 bytes: 1 byte for the instruction, 1 byte of padding, 2 bytes for an immediate argument
Expand Down
125 changes: 73 additions & 52 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@ cmake_minimum_required(VERSION 3.16)

project(ark CXX)

# VERSION
# ArkScript version (have to manually update it)
set(ARK_VERSION_MAJOR 4)
set(ARK_VERSION_MINOR 0)
set(ARK_VERSION_PATCH 0)

execute_process(
COMMAND git rev-parse --short=8 HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(ARK_COMMIT ${GIT_COMMIT_HASH})
# determine whether this is a standalone project or included by other projects
if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
execute_process(
COMMAND git rev-parse --short=8 HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(ARK_COMMIT ${GIT_COMMIT_HASH})
else ()
set(ARK_COMMIT "deadbeef")
endif ()

option(ARK_BUILD_EXE "Build a standalone arkscript executable" Off)
option(ARK_ENABLE_SYSTEM "Enable sys:exec" On) # enable use of (sys:exec "command here")
Expand All @@ -34,65 +39,63 @@ if (NOT ARK_EMSCRIPTEN)
include(cmake/sanitizers.cmake)
include(GNUInstallDirs) # Uses GNU Install directory variables
endif ()

include(cmake/CPM.cmake)

# configure installer.iss
#####################################################
# Configure files
#####################################################

## installer.iss
configure_file(
${ark_SOURCE_DIR}/Installer.iss.in
${ark_SOURCE_DIR}/Installer.iss)

# setting up compilations options
## 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)

#####################################################
# Compilations options and project declaration
#####################################################

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
set(CMAKE_COMPILER_IS_CLANG ON)
endif ()

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# files needed for the library ArkReactor
file(GLOB_RECURSE SOURCE_FILES
${ark_SOURCE_DIR}/src/arkreactor/*.cpp
${ark_SOURCE_DIR}/lib/fmt/src/format.cc)

add_library(ArkReactor SHARED ${SOURCE_FILES})

if (NOT ARK_EMSCRIPTEN)
enable_lto(ArkReactor)
endif ()

target_include_directories(ArkReactor
PUBLIC
${ark_SOURCE_DIR}/include)
target_include_directories(ArkReactor
SYSTEM PUBLIC
"${ark_SOURCE_DIR}/lib/picosha2/"
"${ark_SOURCE_DIR}/lib/fmt/include")

target_compile_features(ArkReactor PRIVATE cxx_std_20)

if (ARK_ENABLE_SYSTEM)
target_compile_definitions(ArkReactor PRIVATE ARK_ENABLE_SYSTEM)
endif ()

if (ARK_UNITY_BUILD)
set_target_properties(ArkReactor PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE BATCH UNITY_BUILD_BATCH_SIZE 16)
set_source_files_properties(src/arkreactor/VM/VM.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION true)
endif ()

if (ARK_EMSCRIPTEN)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/public")

# ArkScript lib needs to know if we are building an exe to enable/disable specific code for embedding
target_compile_definitions(ArkReactor PRIVATE ARK_BUILD_EXE=1)

add_executable(ArkEmscripten ${ark_SOURCE_DIR}/src/arkemscripten/main.cpp)
target_link_libraries(ArkEmscripten PUBLIC ArkReactor)
target_compile_features(ArkEmscripten PRIVATE cxx_std_20)

# enable_lto(ArkEmscripten)

if (ARK_JS_ONLY)
message(STATUS "Setting compilation target to native JavaScript")
set(CMAKE_EXECUTABLE_SUFFIX ".js")
set_target_properties(ArkReactor PROPERTIES LINK_FLAGS "-s WASM=0 -s NO_DISABLE_EXCEPTION_CATCHING")
set_target_properties(ArkEmscripten PROPERTIES LINK_FLAGS "-s WASM=0 -s NO_DISABLE_EXCEPTION_CATCHING -s EXPORTED_FUNCTIONS='[_main]' -s EXPORTED_RUNTIME_METHODS=['run'] -lembind")
else ()
message(STATUS "Setting compilation target to WASM")
set(CMAKE_EXECUTABLE_SUFFIX ".wasm.js")
set_target_properties(ArkReactor PROPERTIES LINK_FLAGS "-s WASM=1 -s NO_DISABLE_EXCEPTION_CATCHING")
set_target_properties(ArkEmscripten PROPERTIES LINK_FLAGS "-s WASM=1 -s NO_DISABLE_EXCEPTION_CATCHING -s EXPORTED_FUNCTIONS='[_main]' -s EXPORTED_RUNTIME_METHODS=['run'] -lembind")
endif ()
endif ()

if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG OR APPLE)
message(STATUS "Enabling computed gotos")
target_compile_definitions(ArkReactor PRIVATE ARK_USE_COMPUTED_GOTOS=1)
Expand Down Expand Up @@ -155,25 +158,22 @@ elseif (MSVC)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8000000") # set stack size to 8MB
endif ()

#####################################################
# Link libraries
#####################################################

target_include_directories(ArkReactor
SYSTEM PUBLIC
"${ark_SOURCE_DIR}/lib/picosha2/"
"${ark_SOURCE_DIR}/lib/fmt/include")
add_subdirectory("${ark_SOURCE_DIR}/lib/ankerl_unordered_dense" EXCLUDE_FROM_ALL)
target_link_libraries(ArkReactor PUBLIC unordered_dense::unordered_dense)

if (UNIX OR LINUX)
find_package(Threads)
target_link_libraries(ArkReactor PRIVATE ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif ()

# configuring 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)

#####################################################
# Installation rules
#####################################################

if (NOT ARK_EMSCRIPTEN)
# Installs the dynamic library file.
install(TARGETS ArkReactor
Expand All @@ -193,13 +193,11 @@ if (NOT ARK_EMSCRIPTEN)
endif ()
endif ()

# COMPILATION RELATED

target_compile_definitions(ArkReactor PRIVATE ARK_EXPORT)

if (ARK_ENABLE_SYSTEM)
target_compile_definitions(ArkReactor PRIVATE ARK_ENABLE_SYSTEM)
endif ()
#####################################################
# Create the different (optional) targets
#####################################################

if (ARK_BUILD_MODULES)
get_directory_property(old_dir_compile_options COMPILE_OPTIONS)
Expand All @@ -213,6 +211,29 @@ if (ARK_TESTS OR ARK_BUILD_EXE)
add_subdirectory("${ark_SOURCE_DIR}/lib/clipp" EXCLUDE_FROM_ALL)
endif ()

if (ARK_EMSCRIPTEN)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/public")

# ArkScript lib needs to know if we are building an exe to enable/disable specific code for embedding
target_compile_definitions(ArkReactor PRIVATE ARK_BUILD_EXE=1)

add_executable(ArkEmscripten ${ark_SOURCE_DIR}/src/arkemscripten/main.cpp)
target_link_libraries(ArkEmscripten PUBLIC ArkReactor)
target_compile_features(ArkEmscripten PRIVATE cxx_std_20)

if (ARK_JS_ONLY)
message(STATUS "Setting compilation target to native JavaScript")
set(CMAKE_EXECUTABLE_SUFFIX ".js")
set_target_properties(ArkReactor PROPERTIES LINK_FLAGS "-s WASM=0 -s NO_DISABLE_EXCEPTION_CATCHING")
set_target_properties(ArkEmscripten PROPERTIES LINK_FLAGS "-s WASM=0 -s NO_DISABLE_EXCEPTION_CATCHING -s EXPORTED_FUNCTIONS='[_main]' -s EXPORTED_RUNTIME_METHODS=['run'] -lembind")
else ()
message(STATUS "Setting compilation target to WASM")
set(CMAKE_EXECUTABLE_SUFFIX ".wasm.js")
set_target_properties(ArkReactor PROPERTIES LINK_FLAGS "-s WASM=1 -s NO_DISABLE_EXCEPTION_CATCHING")
set_target_properties(ArkEmscripten PROPERTIES LINK_FLAGS "-s WASM=1 -s NO_DISABLE_EXCEPTION_CATCHING -s EXPORTED_FUNCTIONS='[_main]' -s EXPORTED_RUNTIME_METHODS=['run'] -lembind")
endif ()
endif ()

if (ARK_TESTS)
file(GLOB_RECURSE SOURCES
${ark_SOURCE_DIR}/tests/unittests/*.cpp
Expand Down
116 changes: 65 additions & 51 deletions include/Ark/Builtins/Builtins.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
#include <vector>

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

namespace Ark
{
class VM;
}

#define ARK_BUILTIN(name) Value name(std::vector<Value>& n, VM* vm)

namespace Ark::internal::Builtins
{
extern const Value falseSym;
Expand All @@ -35,88 +36,101 @@ namespace Ark::internal::Builtins
// ------------------------------
namespace List
{
Value reverseList(std::vector<Value>& n, VM* vm); // builtin__list:reverse, single arg
Value findInList(std::vector<Value>& n, VM* vm); // builtin__list:find, 2 arguments
Value sliceList(std::vector<Value>& n, VM* vm); // builtin__list:slice, 4 arguments
Value sort_(std::vector<Value>& n, VM* vm); // builtin__list:sort, 1 argument
Value fill(std::vector<Value>& n, VM* vm); // builtin__list:fill, 2 arguments
Value setListAt(std::vector<Value>& n, VM* vm); // builtin__list:setAt, 3 arguments
ARK_BUILTIN(reverseList);
ARK_BUILTIN(findInList);
ARK_BUILTIN(sliceList);
ARK_BUILTIN(sort_);
ARK_BUILTIN(fill);
ARK_BUILTIN(setListAt);
}

namespace IO
{
Value print(std::vector<Value>& n, VM* vm); // print, multiple arguments
Value puts_(std::vector<Value>& n, VM* vm); // puts, multiple arguments
Value input(std::vector<Value>& n, VM* vm); // input, 0 or 1 argument
Value writeFile(std::vector<Value>& n, VM* vm); // builtin__io:writeFile, 2 arguments
Value appendToFile(std::vector<Value>& n, VM* vm); // builtin__io:appendToFile, 2 arguments
Value readFile(std::vector<Value>& n, VM* vm); // builtin__io:readFile, 1 argument
Value fileExists(std::vector<Value>& n, VM* vm); // builtin__io:fileExists?, 1 argument
Value listFiles(std::vector<Value>& n, VM* vm); // builtin__io:listFiles, 1 argument
Value isDirectory(std::vector<Value>& n, VM* vm); // builtin__io:isDir?, 1 argument
Value makeDir(std::vector<Value>& n, VM* vm); // builtin__io:makeDir, 1 argument
Value removeFile(std::vector<Value>& n, VM* vm); // builtin__io:removeFile, multiple arguments
ARK_BUILTIN(print);
ARK_BUILTIN(puts_);
ARK_BUILTIN(input);
ARK_BUILTIN(writeFile);
ARK_BUILTIN(appendToFile);
ARK_BUILTIN(readFile);
ARK_BUILTIN(fileExists);
ARK_BUILTIN(listFiles);
ARK_BUILTIN(isDirectory);
ARK_BUILTIN(makeDir);
ARK_BUILTIN(removeFile);
}

namespace Time
{
Value timeSinceEpoch(std::vector<Value>& n, VM* vm); // time, 0 argument
ARK_BUILTIN(timeSinceEpoch);
}

namespace System
{
Value system_(std::vector<Value>& n, VM* vm); // builtin__sys:exec, 1 argument
Value sleep(std::vector<Value>& n, VM* vm); // builtin__sys:sleep, 1 argument
Value exit_(std::vector<Value>& n, VM* vm); // builtin__sys:exit, 1 argument
ARK_BUILTIN(system_);
ARK_BUILTIN(sleep);
ARK_BUILTIN(exit_);
}

namespace String
{
Value format(std::vector<Value>& n, VM* vm); // format, multiple arguments
Value findSubStr(std::vector<Value>& n, VM* vm); // builtin__string:find, 2 arguments
Value removeAtStr(std::vector<Value>& n, VM* vm); // builtin__string:removeAt, 2 arguments
Value ord(std::vector<Value>& n, VM* vm); // builtin__string:ord, 1 arguments
Value chr(std::vector<Value>& n, VM* vm); // builtin__string:chr, 1 arguments
Value setStringAt(std::vector<Value>& n, VM* vm); // builtin__string::setAt, 3 arguments
ARK_BUILTIN(format);
ARK_BUILTIN(findSubStr);
ARK_BUILTIN(removeAtStr);
ARK_BUILTIN(ord);
ARK_BUILTIN(chr);
ARK_BUILTIN(setStringAt);
}

namespace Mathematics
{
Value exponential(std::vector<Value>& n, VM* vm); // builtin__math:exp, 1 argument
Value logarithm(std::vector<Value>& n, VM* vm); // builtin__math:ln, 1 argument
Value ceil_(std::vector<Value>& n, VM* vm); // builtin__math:ceil, 1 argument
Value floor_(std::vector<Value>& n, VM* vm); // builtin__math:floor, 1 argument
Value round_(std::vector<Value>& n, VM* vm); // builtin__math:round, 1 argument
Value isnan_(std::vector<Value>& n, VM* vm); // builtin__math:NaN?, 1 argument
Value isinf_(std::vector<Value>& n, VM* vm); // builtin__math:Inf?, 1 argument
ARK_BUILTIN(exponential);
ARK_BUILTIN(logarithm);
ARK_BUILTIN(ceil_);
ARK_BUILTIN(floor_);
ARK_BUILTIN(round_);
ARK_BUILTIN(isnan_);
ARK_BUILTIN(isinf_);

extern const Value pi_;
extern const Value e_;
extern const Value tau_;
extern const Value inf_;
extern const Value nan_;

Value cos_(std::vector<Value>& n, VM* vm); // builtin__math:cos, 1 argument
Value sin_(std::vector<Value>& n, VM* vm); // builtin__math:sin, 1 argument
Value tan_(std::vector<Value>& n, VM* vm); // builtin__math:tan, 1 argument
Value acos_(std::vector<Value>& n, VM* vm); // builtin__math:arccos, 1 argument
Value asin_(std::vector<Value>& n, VM* vm); // builtin__math:arcsin, 1 argument
Value atan_(std::vector<Value>& n, VM* vm); // builtin__math:arctan, 1 argument
Value cosh_(std::vector<Value>& n, VM* vm); // builtin__math:cosh, 1 argument
Value sinh_(std::vector<Value>& n, VM* vm); // builtin__math:sinh, 1 argument
Value tanh_(std::vector<Value>& n, VM* vm); // builtin__math:tanh, 1 argument
Value acosh_(std::vector<Value>& n, VM* vm); // builtin__math:acosh, 1 argument
Value asinh_(std::vector<Value>& n, VM* vm); // builtin__math:asinh, 1 argument
Value atanh_(std::vector<Value>& n, VM* vm); // builtin__math:atanh, 1 argument

Value random(std::vector<Value>& n, VM* vm); // random, 0-2 args
ARK_BUILTIN(cos_);
ARK_BUILTIN(sin_);
ARK_BUILTIN(tan_);
ARK_BUILTIN(acos_);
ARK_BUILTIN(asin_);
ARK_BUILTIN(atan_);
ARK_BUILTIN(cosh_);
ARK_BUILTIN(sinh_);
ARK_BUILTIN(tanh_);
ARK_BUILTIN(acosh_);
ARK_BUILTIN(asinh_);
ARK_BUILTIN(atanh_);

ARK_BUILTIN(random);
}

namespace Async
{
Value async(std::vector<Value>& n, VM* vm); // async, 1+ arguments
Value await(std::vector<Value>& n, VM* vm); // await, 1 argument
ARK_BUILTIN(async);
ARK_BUILTIN(await);
}

namespace Dict
{
ARK_BUILTIN(dict);
ARK_BUILTIN(get);
ARK_BUILTIN(add);
ARK_BUILTIN(contains);
ARK_BUILTIN(remove);
ARK_BUILTIN(keys);
ARK_BUILTIN(size);
}
}

#undef ARK_BUILTIN

#endif
2 changes: 2 additions & 0 deletions include/Ark/VM/VM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ namespace Ark

#include "VM.inl"

// todo: move to a separate file

/// ArkScript Nil value
const auto Nil = Value(ValueType::Nil);
/// ArkScript False value
Expand Down
Loading
Loading