├── .clang-format ├── .gitattributes ├── .github └── workflows │ └── unittest.yml ├── .gitignore ├── .gitmodules ├── .rgignore ├── CMakeLists.txt ├── Readme.md ├── benchmark ├── gc-stress-test.ch └── string-concat.ch ├── build.sh ├── build_release.sh ├── clean.sh ├── debug.sh ├── debugp.sh ├── docs ├── .gitkeep └── charly-vm.png ├── examples └── .gitkeep ├── experiments ├── .gitignore ├── block-unwind-prototype.py ├── cooperative_threads.cpp ├── cooperative_threads_refactored.cpp ├── custom-stream.cpp ├── small-tagged-double.cpp └── small_locks.cpp ├── format.sh ├── include └── charly │ ├── atomic.h │ ├── charly.h │ ├── debug.h │ ├── handle.h │ ├── symbol.h │ ├── utf8.h │ ├── utils │ ├── allocator.h │ ├── buffer.h │ ├── cast.h │ ├── guarded_buffer.h │ ├── lock.h │ ├── random_device.h │ ├── timedsection.h │ └── wait_flag.h │ └── value.h ├── install.sh ├── libs └── termcolor │ ├── termcolor.cpp │ └── termcolor.h ├── release.sh ├── scratch-files ├── concurrent_map.ch ├── debug.ch ├── gc-stress-test.ch ├── parsertest.ch ├── scratch.ch └── test.ch ├── src ├── CMakeLists.txt ├── charly │ ├── charly.cpp │ ├── core │ │ ├── compiler │ │ │ ├── ast.cpp │ │ │ ├── ast.h │ │ │ ├── codegenerator.cpp │ │ │ ├── codegenerator.h │ │ │ ├── compiler.cpp │ │ │ ├── compiler.h │ │ │ ├── diagnostic.cpp │ │ │ ├── diagnostic.h │ │ │ ├── ir │ │ │ │ ├── assembler.cpp │ │ │ │ ├── assembler.h │ │ │ │ ├── builder.cpp │ │ │ │ ├── builder.h │ │ │ │ ├── builtin.h │ │ │ │ ├── bytecode.h │ │ │ │ ├── functioninfo.h │ │ │ │ ├── ir.cpp │ │ │ │ ├── ir.h │ │ │ │ └── valuelocation.h │ │ │ ├── lexer.cpp │ │ │ ├── lexer.h │ │ │ ├── location.cpp │ │ │ ├── location.h │ │ │ ├── parser.cpp │ │ │ ├── parser.h │ │ │ ├── pass.h │ │ │ ├── passes │ │ │ │ ├── code_elimination.cpp │ │ │ │ ├── code_elimination.h │ │ │ │ ├── constant_folding_pass.cpp │ │ │ │ ├── constant_folding_pass.h │ │ │ │ ├── desugar_pass.cpp │ │ │ │ ├── desugar_pass.h │ │ │ │ ├── duplicates_check.cpp │ │ │ │ ├── duplicates_check.h │ │ │ │ ├── grammar_validation_check.cpp │ │ │ │ ├── grammar_validation_check.h │ │ │ │ ├── repl_prepare_pass.cpp │ │ │ │ ├── repl_prepare_pass.h │ │ │ │ ├── reserved_identifiers_check.cpp │ │ │ │ ├── reserved_identifiers_check.h │ │ │ │ ├── variable_analyzer_pass.cpp │ │ │ │ └── variable_analyzer_pass.h │ │ │ ├── passmacros.h │ │ │ └── token.h │ │ └── runtime │ │ │ ├── builtins │ │ │ ├── builtin.h │ │ │ ├── core.cpp │ │ │ ├── core.h │ │ │ ├── future.cpp │ │ │ ├── future.h │ │ │ ├── list.cpp │ │ │ ├── list.h │ │ │ ├── readline.cpp │ │ │ ├── readline.h │ │ │ ├── timer.cpp │ │ │ └── timer.h │ │ │ ├── compiled_module.cpp │ │ │ ├── compiled_module.h │ │ │ ├── gc.cpp │ │ │ ├── gc.h │ │ │ ├── heap.cpp │ │ │ ├── heap.h │ │ │ ├── interpreter.cpp │ │ │ ├── interpreter.h │ │ │ ├── processor.cpp │ │ │ ├── processor.h │ │ │ ├── runtime.cpp │ │ │ ├── runtime.h │ │ │ ├── scheduler.cpp │ │ │ ├── scheduler.h │ │ │ ├── thread.cpp │ │ │ ├── thread.h │ │ │ ├── watchdog.cpp │ │ │ ├── watchdog.h │ │ │ ├── worker.cpp │ │ │ └── worker.h │ ├── handle.cpp │ ├── stdlib │ │ ├── boot.ch │ │ ├── libs │ │ │ └── unittest.ch │ │ └── repl.ch │ ├── utils │ │ ├── allocator.cpp │ │ ├── argumentparser.cpp │ │ ├── argumentparser.h │ │ ├── buffer.cpp │ │ ├── colorwriter.h │ │ └── lock.cpp │ └── value.cpp └── main.cpp ├── test ├── .gitkeep ├── charly │ ├── .gitkeep │ ├── assertion.ch │ ├── class.ch │ ├── control-structures.ch │ ├── exception.ch │ ├── fiber.ch │ ├── function.ch │ ├── future.ch │ ├── globals.ch │ ├── import-test │ │ ├── compiler-error.ch │ │ ├── import-test-throws.ch │ │ └── not-readable.ch │ ├── import.ch │ ├── list.ch │ ├── number.ch │ ├── string.ch │ ├── test.ch │ ├── testlib.ch │ ├── truthyness.ch │ ├── tuple.ch │ └── typeof-instanceof.ch └── runtime │ ├── .gitkeep │ ├── core │ └── compiler │ │ ├── astmacros.h │ │ ├── diagnostic.cpp │ │ ├── module.cpp │ │ ├── parser.cpp │ │ ├── pass.cpp │ │ └── semantic.cpp │ ├── utils │ ├── buffer.cpp │ ├── cast.cpp │ ├── random_device.cpp │ └── wait_flag.cpp │ └── value.cpp ├── tests.sh └── todos.md /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | --- 4 | Language: Cpp 5 | AccessModifierOffset: -2 6 | AlignAfterOpenBracket: Align 7 | AlignConsecutiveAssignments: false 8 | AlignConsecutiveDeclarations: false 9 | AlignConsecutiveMacros: false 10 | AlignEscapedNewlines: true 11 | AlignOperands: true 12 | AlignTrailingComments: true 13 | AllowAllArgumentsOnNextLine: false 14 | AllowShortBlocksOnASingleLine: Empty 15 | AllowShortEnumsOnASingleLine: false 16 | AllowShortCaseLabelsOnASingleLine: true 17 | AllowShortFunctionsOnASingleLine: Empty 18 | AllowShortIfStatementsOnASingleLine: Never 19 | AllowShortLambdasOnASingleLine: Empty 20 | AllowShortLoopsOnASingleLine: false 21 | AlwaysBreakAfterReturnType: None 22 | AlwaysBreakBeforeMultilineStrings: false 23 | AlwaysBreakTemplateDeclarations: Yes 24 | BinPackArguments: true 25 | BinPackParameters: false 26 | BreakBeforeBinaryOperators: None 27 | BreakBeforeBraces: Attach 28 | BreakBeforeTernaryOperators: true 29 | BreakConstructorInitializers: AfterColon 30 | BreakInheritanceList: AfterColon 31 | BreakStringLiterals: true 32 | ColumnLimit: 120 33 | CompactNamespaces: true 34 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 35 | ConstructorInitializerIndentWidth: 2 36 | ContinuationIndentWidth: 2 37 | Cpp11BracedListStyle: false 38 | FixNamespaceComments: true 39 | IncludeBlocks: Preserve 40 | IndentCaseLabels: true 41 | IndentGotoLabels: false 42 | IndentPPDirectives: BeforeHash 43 | IndentWidth: 2 44 | IndentWrappedFunctionNames: true 45 | KeepEmptyLinesAtTheStartOfBlocks: false 46 | NamespaceIndentation: Inner 47 | PointerAlignment: Left 48 | ReflowComments: true 49 | SortIncludes: true 50 | SortUsingDeclarations: true 51 | SpaceAfterCStyleCast: false 52 | SpaceAfterLogicalNot: false 53 | SpaceAfterTemplateKeyword: true 54 | SpaceBeforeAssignmentOperators: true 55 | SpaceBeforeCpp11BracedList: false 56 | SpaceBeforeCtorInitializerColon: true 57 | SpaceBeforeInheritanceColon: true 58 | SpaceBeforeParens: ControlStatements 59 | SpaceBeforeRangeBasedForLoopColon: true 60 | SpaceBeforeSquareBrackets: false 61 | SpaceInEmptyBlock: false 62 | SpaceInEmptyParentheses: false 63 | SpacesInAngles: false 64 | SpacesInCStyleCastParentheses: false 65 | SpacesInConditionalStatement: false 66 | SpacesInContainerLiterals: false 67 | SpacesInParentheses: false 68 | SpacesInSquareBrackets: false 69 | Standard: c++17 70 | TabWidth: 2 71 | UseCRLF: false 72 | UseTab: Never 73 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | libs/* linguist-vendored 2 | *.ch linguist-language=Text 3 | -------------------------------------------------------------------------------- /.github/workflows/unittest.yml: -------------------------------------------------------------------------------- 1 | name: Unit Test 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - name: Install clang-10 11 | run: | 12 | sudo apt update 13 | sudo apt install clang-10 14 | sudo apt install libboost-all-dev 15 | shell: bash 16 | 17 | - name: Checkout repository and submodules 18 | uses: actions/checkout@v2 19 | with: 20 | ref: 'rewrite' 21 | submodules: recursive 22 | 23 | - name: Test 24 | working-directory: ${{github.workspace}} 25 | shell: bash 26 | run: ./tests.sh 27 | env: 28 | CHARLYVMDIR: ${{github.workspace}} 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.dSYM 2 | *.lib 3 | *.swo 4 | *.swp 5 | .DS_Store 6 | .idea/ 7 | .vscode/ 8 | bin/ 9 | build/ 10 | cmake-build-debug 11 | cmake-build-minsizerel 12 | cmake-build-release 13 | cmake-build-relwithdebinfo 14 | cmake-build-relwithdebinfo-coverage 15 | code.profdata 16 | default.profraw 17 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libs/catch2"] 2 | path = libs/catch2 3 | url = https://github.com/catchorg/Catch2 4 | -------------------------------------------------------------------------------- /.rgignore: -------------------------------------------------------------------------------- 1 | *.dSYM 2 | *.lib 3 | *.swo 4 | *.swp 5 | .DS_Store 6 | .git/ 7 | bin/ 8 | build/ 9 | build_backup/ 10 | buildrelease/ 11 | buildtest/ 12 | code.profdata 13 | default.profraw 14 | experiments/ 15 | libs/ 16 | test/ 17 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | set(CMAKE_C_COMPILER_NAMES clang) 3 | set(CMAKE_CXX_COMPILER_NAMES clang++) 4 | project(charly-vm) 5 | 6 | # create build directories 7 | file(MAKE_DIRECTORY cmake-build-debug cmake-build-release) 8 | 9 | # osx check 10 | if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 11 | message("-- Detected apple installation") 12 | add_compile_definitions(APPLE) 13 | set(APPLE TRUE) 14 | execute_process(COMMAND xcrun --show-sdk-path OUTPUT_VARIABLE OSXSDKPATH) 15 | include_directories(BEFORE SYSTEM ${OSXSDKPATH}) 16 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/include") 17 | endif () 18 | 19 | # include directories 20 | include_directories(src) 21 | include_directories(include) 22 | include_directories(libs) 23 | 24 | # explicitly enable debug symbols in debug builds 25 | set(CMAKE_CXX_FLAGS_DEBUG "-g") 26 | 27 | # main executable 28 | add_subdirectory(src) 29 | add_executable(charly src/main.cpp) 30 | target_compile_features(charly PRIVATE cxx_std_17) 31 | target_link_libraries(charly libcharly) 32 | target_compile_options(charly PRIVATE 33 | -Wall 34 | -Wextra 35 | -Wpedantic 36 | -Werror 37 | -Wno-vla-extension 38 | -Wno-c++20-designator 39 | -Wno-gnu-zero-variadic-macro-arguments 40 | -Wno-gnu-label-as-value 41 | -Wno-c99-extensions 42 | -Wno-register 43 | -Wno-extra-semi 44 | -Wno-shadow 45 | -ftemplate-backtrace-limit=8 46 | -mllvm -align-all-functions=3 47 | ) 48 | 49 | # enable link-time-optimization for release builds 50 | if (CMAKE_BUILD_TYPE MATCHES Release) 51 | message("-- Enabling LTO for target 'charly'") 52 | target_compile_options(charly PRIVATE -flto -O3) 53 | endif () 54 | 55 | # install to global folder 56 | install(TARGETS charly RUNTIME DESTINATION bin) 57 | 58 | # unit tests 59 | add_subdirectory(libs/catch2) 60 | 61 | file(GLOB tests_SRC 62 | "test/runtime/core/compiler/diagnostic.cpp" 63 | "test/runtime/core/compiler/module.cpp" 64 | "test/runtime/core/compiler/parser.cpp" 65 | "test/runtime/core/compiler/pass.cpp" 66 | "test/runtime/core/compiler/semantic.cpp" 67 | "test/runtime/utils/buffer.cpp" 68 | "test/runtime/utils/cast.cpp" 69 | "test/runtime/utils/cast.cpp" 70 | "test/runtime/utils/random_device.cpp" 71 | "test/runtime/utils/wait_flag.cpp" 72 | "test/runtime/value.cpp" 73 | ) 74 | 75 | add_executable(tests ${tests_SRC}) 76 | target_compile_features(tests PRIVATE cxx_std_17) 77 | target_link_libraries(tests Catch2::Catch2WithMain) 78 | target_link_libraries(tests libcharly) 79 | target_compile_definitions(tests PUBLIC CATCH_CONFIG_PREFIX_ALL) 80 | target_compile_options(tests PRIVATE 81 | -Wall 82 | -Wextra 83 | -Wpedantic 84 | -Werror 85 | -Wno-vla-extension 86 | -Wno-c++20-designator 87 | -Wno-gnu-zero-variadic-macro-arguments 88 | -Wno-gnu-label-as-value 89 | -Wno-c99-extensions 90 | -Wno-register 91 | -Wno-extra-semi 92 | -Wno-shadow 93 | -ftemplate-backtrace-limit=8 94 | -mllvm -align-all-functions=3 95 | ) 96 | 97 | # enable link-time-optimization for release builds 98 | if (CMAKE_BUILD_TYPE MATCHES Release) 99 | message("-- Enabling LTO for target 'tests'") 100 | target_compile_options(tests PRIVATE -flto -O3) 101 | endif () 102 | 103 | if (APPLE) 104 | set_target_properties(charly PROPERTIES LINK_FLAGS -fuse-ld=ld) 105 | set_target_properties(tests PROPERTIES LINK_FLAGS -fuse-ld=ld) 106 | else () 107 | set_target_properties(charly PROPERTIES LINK_FLAGS -fuse-ld=lld) 108 | set_target_properties(tests PROPERTIES LINK_FLAGS -fuse-ld=lld) 109 | endif () 110 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | Charly Programming Language Logo, Image credit: DALL-E 2 | 3 | # Charly Programming Language 4 | 5 | ![Unit Test](https://github.com/KCreate/charly-vm/workflows/Unit%20Test/badge.svg?branch=rewrite) 6 | 7 | > Note: This is the rewrite branch of charly-vm. 8 | > Lots of stuff isn't working yet. 9 | > The [main branch](https://github.com/KCreate/charly-vm/tree/main) contains the previous 10 | > fully functional version of charly-vm. 11 | 12 | This launches a REPL which (at the moment) doesn't do very much. 13 | 14 | This launches a REPL which (at the moment) does some cool stuff, but still not a lot. 15 | 16 | This launches a REPL which supports some cool stuff, but still not a lot 17 | 18 | `./debug.sh [path/to/file.ch]` 19 | 20 | # Dependencies 21 | 22 | - `sudo apt-get install libboost-all-dev` 23 | 24 | # Installation 25 | 26 | Follow the steps below to install the `charly` executable on your system. 27 | 28 | 1. `git clone https://github.com/KCreate/charly-vm charly-vm` 29 | 2. `cd charly-vm` 30 | 3. `git checkout rewrite` 31 | 4. `git submodule init` 32 | 5. `git submodule update` 33 | 6. Set the `CHARLYVMDIR` environment variable to the project's root folder 34 | - e.g. `export CHARLYVMDIR=/home/user/github/KCreate/charly-vm` 35 | 7. `./install.sh` 36 | 37 | > The last step might request sudo permissions in order to access the relevant system directories. 38 | 39 | # Running the unit tests 40 | 41 | ``` 42 | $ ./tests.sh 43 | [ 31%] Built target libcharly 44 | [ 87%] Built target Catch2 45 | [ 89%] Built target Catch2WithMain 46 | [100%] Built target tests 47 | =============================================================================== 48 | All tests passed (1422 assertions in 10 test cases) 49 | ``` 50 | -------------------------------------------------------------------------------- /benchmark/gc-stress-test.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | func foo { 28 | let data 29 | let count = 2000 30 | while (count != 0) { 31 | let index = 0 32 | while (index != count - 1) { 33 | data = (1, 2, 3, 4) 34 | index += 1 35 | } 36 | 37 | count -= 1 38 | } 39 | } 40 | 41 | 16.times(->{ 42 | const fiber_count = 8 43 | Tuple.make_with(fiber_count, ->spawn foo()).each(->(f) await f) 44 | }) -------------------------------------------------------------------------------- /benchmark/string-concat.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | let string = "x" 28 | 29 | const count = 28 30 | 31 | count.times(->{ 32 | string += string 33 | }) 34 | 35 | print("string concat done") 36 | 37 | const empty = "" 38 | const copy = "{string}{empty}" 39 | 40 | 10.times(->{ 41 | print(string == copy) 42 | print("comparison done") 43 | }) 44 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p cmake-build-debug 4 | 5 | # initial cmake run 6 | if ! test -f cmake-build-debug/Makefile; 7 | then 8 | cmake -DCMAKE_BUILD_TYPE=Debug -S . -B cmake-build-debug 9 | fi 10 | 11 | cmake --build cmake-build-debug --target charly 12 | -------------------------------------------------------------------------------- /build_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p cmake-build-release 4 | 5 | # initial cmake run 6 | if ! test -f cmake-build-release/Makefile; 7 | then 8 | cmake -DCMAKE_BUILD_TYPE=Release -S . -B cmake-build-release 9 | fi 10 | 11 | cmake --build cmake-build-release --target charly 12 | -------------------------------------------------------------------------------- /clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -r cmake-build-debug 4 | rm -r cmake-build-release 5 | 6 | mkdir -p cmake-build-debug 7 | mkdir -p cmake-build-release 8 | 9 | exit 10 | 11 | for build_dir in cmake-build-*; do 12 | rm -r "$build_dir" 13 | mkdir -p "$build_dir" 14 | cmake -S . -DCMAKE_BUILD_TYPE=Debug -B "$build_dir" 15 | done -------------------------------------------------------------------------------- /debug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p cmake-build-debug 4 | 5 | # initial cmake run 6 | if ! test -f cmake-build-debug/Makefile; 7 | then 8 | cmake -DCMAKE_BUILD_TYPE=Debug -S . -B cmake-build-debug 9 | fi 10 | 11 | if cmake --build cmake-build-debug --target charly; 12 | then 13 | cmake-build-debug/charly "$@" 14 | fi 15 | -------------------------------------------------------------------------------- /debugp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p cmake-build-debug 4 | 5 | # initial cmake run 6 | if ! test -f cmake-build-debug/Makefile; 7 | then 8 | cmake -DCMAKE_BUILD_TYPE=Debug -S . -B cmake-build-debug 9 | fi 10 | 11 | if cmake --build cmake-build-debug --target charly -j12; 12 | then 13 | cmake-build-debug/charly "$@" 14 | fi 15 | -------------------------------------------------------------------------------- /docs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KCreate/charly-vm/b3dabc25954d5f34660281ca3f634aa7252b8b42/docs/.gitkeep -------------------------------------------------------------------------------- /docs/charly-vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KCreate/charly-vm/b3dabc25954d5f34660281ca3f634aa7252b8b42/docs/charly-vm.png -------------------------------------------------------------------------------- /examples/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KCreate/charly-vm/b3dabc25954d5f34660281ca3f634aa7252b8b42/examples/.gitkeep -------------------------------------------------------------------------------- /experiments/.gitignore: -------------------------------------------------------------------------------- 1 | a.out 2 | -------------------------------------------------------------------------------- /experiments/cooperative_threads_refactored.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | 41 | using namespace boost::context::detail; 42 | using namespace std::chrono_literals; 43 | 44 | /* 45 | * thread-safe printing meant for debugging 46 | * */ 47 | inline void safeprint_impl(const char* format) { 48 | std::cout << format; 49 | } 50 | 51 | template 52 | inline void safeprint_impl(const char* format, T value, Targs... Fargs) { 53 | while (*format != '\0') { 54 | if (*format == '%') { 55 | std::cout << value; 56 | safeprint_impl(format + 1, Fargs...); 57 | return; 58 | } 59 | std::cout << *format; 60 | 61 | format++; 62 | } 63 | } 64 | 65 | std::mutex safeprint_mutex; 66 | auto program_start_time = std::chrono::steady_clock::now(); 67 | 68 | #ifdef NDEBUG 69 | template 70 | inline void safeprint(const char*, Targs...) {} 71 | #else 72 | template 73 | inline void safeprint(const char* format, Targs... Fargs) { 74 | { 75 | std::unique_lock locker(safeprint_mutex); 76 | auto time_elapsed = std::chrono::steady_clock::now() - program_start_time; 77 | auto ticks = std::chrono::duration_cast(time_elapsed).count(); 78 | std::cout << std::setw(12) << std::setfill('_') << ticks << std::setfill(' ') << std::setw(1) << ": "; 79 | safeprint_impl(format, Fargs...); 80 | std::cout << std::endl; 81 | } 82 | } 83 | #endif 84 | 85 | 86 | // actual implementation of scheduler 87 | class SchedulerImpl { 88 | 89 | }; 90 | 91 | // runtime scheduler API into scheduler 92 | class Scheduler { 93 | public: 94 | 95 | struct Transfer { 96 | void* data; 97 | }; 98 | 99 | // initialize the scheduler 100 | static void initialize(); 101 | 102 | // start all the scheduler workers 103 | static void start(); 104 | 105 | static void shutdown(); 106 | 107 | static void yield(); 108 | 109 | private: 110 | inline static const SchedulerImpl* m_instance; 111 | }; 112 | 113 | 114 | void task_fn(Fiber* fiber) { 115 | 116 | for (int i = 0; i < 100; i++) { 117 | safeprint("fiber %: counter = %", fiber->id(), i); 118 | Scheduler::yield(); 119 | } 120 | 121 | } 122 | 123 | 124 | int main() { 125 | 126 | for (int i = 0; i < 100; i++) { 127 | safeprint("counter = %", i); 128 | std::this_thread::sleep_for(10ms); 129 | } 130 | 131 | return 0; 132 | } 133 | -------------------------------------------------------------------------------- /experiments/small-tagged-double.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "math.h" 33 | 34 | static const uintptr_t kTagFloat = 0b00011111; 35 | 36 | static const uintptr_t kMaskSign = (uintptr_t{0b10000000} << 56); 37 | static const uintptr_t kMaskExponent = (uintptr_t{0b0111111111110000} << 48); 38 | static const uintptr_t kMaskSmallExponent = (uintptr_t{0b0000111111110000} << 48); 39 | static const uintptr_t kMaskMantissa = 0x000fffffffffffff; 40 | static const uintptr_t kMaskSmallMantissa = 0x000fffffffffffe0; 41 | static const uintptr_t kMaskTag = 0b00011111; 42 | 43 | // uintptr_t encode(double value) { 44 | // uintptr_t raw = *reinterpret_cast(&value); 45 | // uintptr_t sign = (raw & kMaskSign); 46 | // uintptr_t exponent = (raw & kMaskSmallExponent); 47 | // uintptr_t mantissa = (raw & kMaskMantissa); 48 | // return (exponent << 4) + (mantissa << 4) + (sign >> 60) + kTagFloat; 49 | // } 50 | 51 | // double decode(uintptr_t value) { 52 | // value >>= 3; 53 | // uintptr_t sign_bit = value & 1; 54 | // value >>= 1; 55 | // value |= (sign_bit << 63); 56 | // return *reinterpret_cast(&value); 57 | // } 58 | 59 | uintptr_t encode(double value) { 60 | uintptr_t raw = *reinterpret_cast(&value); 61 | return (raw & ~kMaskTag) + kTagFloat; 62 | } 63 | 64 | double decode(uintptr_t value) { 65 | value -= kTagFloat; 66 | return *reinterpret_cast(&value); 67 | } 68 | 69 | int main() { 70 | double base = 8388608.0; 71 | double step = 1.0; 72 | int n = 100; 73 | 74 | std::cout.precision(30); 75 | 76 | // test precision without boxing 77 | { 78 | double sum = base; 79 | 80 | for (int i = 0; i < n; i++) { 81 | sum += step; 82 | } 83 | 84 | std::cout << "unboxed sum: " << sum << std::endl; 85 | } 86 | 87 | // test precision with boxing 88 | { 89 | double sum = base; 90 | uintptr_t encoded_step = encode(step); 91 | uintptr_t encoded_sum = encode(sum); 92 | 93 | for (int i = 0; i < n; i++) { 94 | double tmp = decode(encoded_sum) + decode(encoded_step); 95 | encoded_sum = encode(tmp); 96 | } 97 | 98 | sum = decode(encoded_sum); 99 | 100 | std::cout << "boxed sum: " << sum << std::endl; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SOURCES=`find src -type f -name '*.cpp'` 4 | PRIVATE_HEADERS=`find src -type f -name '*.h'` 5 | PUBLIC_HEADERS=`find include -type f -name '*.h'` 6 | 7 | TEST_SOURCES=`find test -type f -name '*.cpp'` 8 | TEST_HEADERS=`find test -type f -name '*.h'` 9 | 10 | clang-format -i $SOURCES $PRIVATE_HEADERS $PUBLIC_HEADERS $TEST_SOURCES $TEST_HEADERS --style=file 11 | -------------------------------------------------------------------------------- /include/charly/atomic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "charly/debug.h" 30 | 31 | #pragma once 32 | 33 | namespace charly { 34 | 35 | template 36 | struct atomic : public std::atomic { 37 | using std::atomic::atomic; 38 | using std::atomic::operator=; 39 | 40 | // sane CAS 41 | bool cas(T expected, T desired) { 42 | return std::atomic::compare_exchange_strong(expected, desired, std::memory_order_seq_cst); 43 | } 44 | bool cas_weak(T expected, T desired) { 45 | return std::atomic::compare_exchange_weak(expected, desired, std::memory_order_seq_cst); 46 | } 47 | 48 | // CAS that should not fail 49 | void acas(T expected, T desired) { 50 | bool result = cas(expected, desired); 51 | CHECK(result); 52 | } 53 | 54 | uintptr_t address() const { 55 | return reinterpret_cast(this); 56 | } 57 | }; 58 | 59 | } // namespace charly 60 | -------------------------------------------------------------------------------- /include/charly/charly.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "atomic.h" 37 | #include "debug.h" 38 | #include "symbol.h" 39 | #include "utils/allocator.h" 40 | #include "utils/lock.h" 41 | 42 | #pragma once 43 | 44 | namespace charly { 45 | 46 | #define CHARLY_NON_COPYABLE(C) \ 47 | C(const C&) = delete; \ 48 | C(C&) = delete; \ 49 | C(const C&&) = delete; \ 50 | C(C&&) = delete; \ 51 | C& operator=(C&) = delete; \ 52 | C& operator=(C&&) = delete; \ 53 | C& operator=(const C&) = delete; \ 54 | C& operator=(const C&&) = delete 55 | 56 | /* 57 | * shorthand method for often used shared_ptr stuff 58 | * */ 59 | template 60 | using ref = std::shared_ptr; 61 | template 62 | using weak_ref = std::weak_ptr; 63 | 64 | template 65 | inline ref make(Args&&... params) { 66 | return std::make_shared(std::forward(params)...); 67 | } 68 | 69 | template 70 | inline ref cast(ref node) { 71 | return std::dynamic_pointer_cast(node); 72 | } 73 | 74 | inline size_t get_steady_timestamp() { 75 | auto now = std::chrono::steady_clock::now(); 76 | return std::chrono::duration_cast(now.time_since_epoch()).count(); 77 | } 78 | 79 | inline size_t get_steady_timestamp_micro() { 80 | auto now = std::chrono::steady_clock::now(); 81 | return std::chrono::duration_cast(now.time_since_epoch()).count(); 82 | } 83 | 84 | // helper method to cast one type to another 85 | template 86 | B bitcast(A&& value) { 87 | return *reinterpret_cast(&value); 88 | } 89 | 90 | constexpr int64_t kInt32Min = -2147483647 - 1; 91 | constexpr int64_t kInt32Max = 2147483647; 92 | constexpr int64_t kInt24Min = -8388607 - 1; 93 | constexpr int64_t kInt24Max = 8388607; 94 | constexpr int64_t kInt16Min = -32767 - 1; 95 | constexpr int64_t kInt16Max = 32767; 96 | constexpr int64_t kInt8Min = -127 - 1; 97 | constexpr int64_t kInt8Max = 127; 98 | 99 | constexpr uint64_t kUInt32Min = 0; 100 | constexpr uint64_t kUInt32Max = 0xffffffff; 101 | constexpr uint64_t kUInt24Min = 0; 102 | constexpr uint64_t kUInt24Max = 0x00ffffff; 103 | constexpr uint64_t kUInt16Min = 0; 104 | constexpr uint64_t kUInt16Max = 0x0000ffff; 105 | constexpr uint64_t kUInt8Min = 0; 106 | constexpr uint64_t kUInt8Max = 0x000000ff; 107 | 108 | #ifdef NDEBUG 109 | constexpr bool kIsDebugBuild = false; 110 | #else 111 | constexpr bool kIsDebugBuild = true; 112 | #endif 113 | 114 | inline constexpr bool double_fuzzy_equal(double left, double right) { 115 | if (!std::isfinite(left) || !std::isfinite(right)) { 116 | if (std::isnan(left) && std::isnan(right)) { 117 | return true; 118 | } 119 | 120 | return left == right; 121 | } 122 | 123 | constexpr double epsilon = 0.000001; 124 | return std::fabs(left - right) <= epsilon; 125 | } 126 | 127 | } // namespace charly 128 | -------------------------------------------------------------------------------- /include/charly/handle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "value.h" 28 | 29 | #pragma once 30 | 31 | namespace charly::core::runtime { 32 | 33 | class Thread; 34 | class ThreadLocalHandles; 35 | 36 | class HandleScope { 37 | CHARLY_NON_COPYABLE(HandleScope); 38 | 39 | public: 40 | explicit HandleScope(Thread* thread) : m_thread(thread) {} 41 | 42 | Thread* thread() const { 43 | return m_thread; 44 | } 45 | 46 | private: 47 | Thread* m_thread; 48 | }; 49 | 50 | template 51 | class Handle : public T { 52 | friend class ThreadLocalHandles; 53 | 54 | public: 55 | Handle(HandleScope& scope); 56 | Handle(HandleScope& scope, RawValue value); 57 | ~Handle(); 58 | 59 | static_assert(std::is_base_of::value, "Expected T to be child of RawValue"); 60 | 61 | // disallow copies using another handle 62 | template 63 | Handle(HandleScope*, const Handle&) = delete; 64 | 65 | template 66 | Handle& operator=(Handle& other) { 67 | return *this = *other; 68 | } 69 | 70 | // allow assigning RawValue values to the handle 71 | Handle& operator=(RawValue other) { 72 | *static_cast(this) = other; 73 | DCHECK(is_valid_type(), "expected valid type"); 74 | return *this; 75 | } 76 | 77 | T& operator*() { 78 | return *static_cast(this); 79 | } 80 | 81 | const T& operator*() const { 82 | return *static_cast(this); 83 | } 84 | 85 | // Handle can be casted to Handle if S is a subclass of T 86 | template 87 | explicit operator const Handle&() const { 88 | static_assert(std::is_base_of::value, "Only up-casts are permitted"); 89 | return *reinterpret_cast*>(this); 90 | } 91 | 92 | Handle* next() const { 93 | return m_next; 94 | } 95 | 96 | private: 97 | bool is_valid_type() const { 98 | return T::value_is_type(**this); 99 | } 100 | 101 | Handle* pointer() { 102 | return bitcast*>(this); 103 | } 104 | 105 | Thread* m_thread; 106 | Handle* m_next; 107 | }; 108 | 109 | #define HANDLE_DEF(T) using T = Handle; 110 | TYPE_NAMES(HANDLE_DEF) 111 | #undef HANDLE_DEF 112 | 113 | } // namespace charly::core::runtime 114 | -------------------------------------------------------------------------------- /include/charly/symbol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #pragma once 32 | 33 | namespace charly { 34 | 35 | // compile-time crc32 hash 36 | // source: https://stackoverflow.com/questions/28675727/using-crc32-algorithm-to-hash-string-at-compile-time 37 | namespace crc32 { 38 | namespace internal { 39 | template 40 | struct f : f<((c & 1) ? 0xedb88320 : 0) ^ (c >> 1), k - 1> {}; 41 | template 42 | struct f { 43 | enum { 44 | value = c 45 | }; 46 | }; 47 | 48 | #define A(x) B(x) B(x + 128) 49 | #define B(x) C(x) C(x + 64) 50 | #define C(x) D(x) D(x + 32) 51 | #define D(x) E(x) E(x + 16) 52 | #define E(x) F(x) F(x + 8) 53 | #define F(x) G(x) G(x + 4) 54 | #define G(x) H(x) H(x + 2) 55 | #define H(x) I(x) I(x + 1) 56 | #define I(x) f::value, 57 | constexpr unsigned crc_table[] = { A(0) }; 58 | #undef A 59 | #undef B 60 | #undef C 61 | #undef D 62 | #undef E 63 | #undef F 64 | #undef G 65 | #undef H 66 | #undef I 67 | 68 | namespace constexpr_impl { 69 | constexpr uint32_t crc32_impl(const char* p, size_t len, uint32_t crc) { 70 | return len ? crc32_impl(p + 1, len - 1, (crc >> 8) ^ crc_table[(crc & 0xFF) ^ *p]) : crc; 71 | } 72 | 73 | constexpr uint32_t crc32(const char* data, size_t length) { 74 | return ~crc32_impl(data, length, ~0); 75 | } 76 | 77 | constexpr size_t strlen_c(const char* str) { 78 | return *str ? 1 + strlen_c(str + 1) : 0; 79 | } 80 | } // namespace constexpr_impl 81 | 82 | inline constexpr uint32_t hash_constexpr(const char* str) { 83 | return constexpr_impl::crc32(str, constexpr_impl::strlen_c(str)); 84 | } 85 | 86 | inline uint32_t hash_block(const char* data, size_t size) { 87 | uint32_t c = 0xFFFFFFFF; 88 | auto u = reinterpret_cast(data); 89 | for (size_t i = 0; i < size; i++) { 90 | c = crc_table[(c ^ u[i]) & 0xFF] ^ (c >> 8); 91 | } 92 | return c ^ 0xFFFFFFFF; 93 | } 94 | } // namespace internal 95 | 96 | inline uint32_t hash_block(const char* data, size_t size) { 97 | return internal::hash_block(data, size); 98 | } 99 | 100 | inline uint32_t hash_string(const std::string& string) { 101 | return internal::hash_block(string.data(), string.size()); 102 | } 103 | 104 | inline uint32_t hash_block(const std::string_view& view) { 105 | return internal::hash_block(view.data(), view.size()); 106 | } 107 | } // namespace crc32 108 | 109 | using SYMBOL = uint32_t; 110 | 111 | inline constexpr SYMBOL SYM(const char* str) { 112 | return crc32::internal::hash_constexpr(str); 113 | } 114 | 115 | } // namespace charly 116 | -------------------------------------------------------------------------------- /include/charly/utils/allocator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #pragma once 34 | 35 | namespace charly { 36 | 37 | inline static const size_t kPageSize = sysconf(_SC_PAGESIZE); 38 | constexpr size_t kPointerSize = sizeof(uintptr_t); 39 | inline static size_t kPointersPerPage = kPageSize / kPointerSize; 40 | 41 | constexpr size_t kKb = 1024; 42 | constexpr size_t kMb = kKb * 1024; 43 | constexpr size_t kGb = kMb * 1024; 44 | 45 | namespace utils { 46 | 47 | /* 48 | * Charly allocator class 49 | * 50 | * Handles heap memory allocations and guarded page access 51 | * */ 52 | class Allocator { 53 | public: 54 | // allocate heap memory 55 | static void* alloc(size_t size); 56 | 57 | // allocate aligned heap memory 58 | static void* aligned_alloc(size_t size, size_t alignment = 8); 59 | 60 | // allocates memory via mmap 61 | // mapped memory region is initially protected with PROT_NONE 62 | static void* mmap_page_aligned(size_t size, 63 | int32_t protection = PROT_NONE, 64 | int32_t flags = MAP_PRIVATE | MAP_ANONYMOUS); 65 | static void* mmap_self_aligned(size_t size, 66 | int32_t protection = PROT_NONE, 67 | int32_t flags = MAP_PRIVATE | MAP_ANONYMOUS); 68 | static void* mmap_address(void* address, 69 | size_t size, 70 | int32_t protection = PROT_NONE, 71 | int32_t flags = MAP_PRIVATE | MAP_ANONYMOUS); 72 | 73 | // reallocate pointer to fit a bigger size or change alignment 74 | // acts like alloc if pointer is null 75 | // returns old pointer if it fulfills the new requirements 76 | static void* realloc(void* old_pointer, size_t old_size, size_t new_size, size_t new_alignment = 8); 77 | 78 | // free a pointer allocated by alloc 79 | static void free(void* pointer); 80 | 81 | // munmap a region of memory 82 | static void munmap(void* pointer, size_t size); 83 | 84 | // protect a section of memory as either read-only or read and writeable 85 | static void protect_none(void* pointer, size_t size); 86 | static void protect_read(void* pointer, size_t size); 87 | static void protect_readwrite(void* pointer, size_t size); 88 | static void protect_exec(void* pointer, size_t size); 89 | }; 90 | 91 | } // namespace utils 92 | } // namespace charly 93 | -------------------------------------------------------------------------------- /include/charly/utils/cast.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #pragma once 36 | 37 | namespace charly::utils { 38 | 39 | inline int64_t charptr_to_int(const char* data, size_t length, int base = 10) { 40 | char buffer[length + 1]; 41 | std::memset(buffer, 0, length + 1); 42 | std::memcpy(buffer, data, length); 43 | 44 | char* end_ptr; 45 | int64_t result = std::strtol(buffer, &end_ptr, base); 46 | 47 | if (errno == ERANGE) { 48 | errno = 0; 49 | return 0; 50 | } 51 | 52 | if (end_ptr == buffer) { 53 | return 0; 54 | } 55 | 56 | return result; 57 | } 58 | 59 | inline int64_t string_to_int(const std::string& str, int base = 10) { 60 | return charptr_to_int(str.data(), str.size(), base); 61 | } 62 | 63 | inline int64_t string_view_to_int(const std::string_view& view, int base = 10) { 64 | return charptr_to_int(view.data(), view.size(), base); 65 | } 66 | 67 | inline double charptr_to_double(const char* data, size_t length) { 68 | char buffer[length + 1]; 69 | std::memset(buffer, 0, length + 1); 70 | std::memcpy(buffer, data, length); 71 | 72 | char* end_ptr; 73 | double result = std::strtod(buffer, &end_ptr); 74 | 75 | if (result == HUGE_VAL || end_ptr == buffer) 76 | return NAN; 77 | 78 | return result; 79 | } 80 | 81 | inline double string_to_double(const std::string& str) { 82 | return charptr_to_double(str.data(), str.size()); 83 | } 84 | 85 | inline double string_view_to_double(const std::string_view& view) { 86 | return charptr_to_double(view.data(), view.size()); 87 | } 88 | 89 | } // namespace charly::utils 90 | -------------------------------------------------------------------------------- /include/charly/utils/guarded_buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/utils/allocator.h" 28 | 29 | #pragma once 30 | 31 | namespace charly::utils { 32 | 33 | class GuardedBuffer { 34 | public: 35 | explicit GuardedBuffer(size_t size) : m_size(size) { 36 | DCHECK(size >= kPageSize, "expected size to be at least the page size"); 37 | DCHECK(size % kPageSize == 0, "expected size to be a multiple of the page size"); 38 | m_mapping = Allocator::mmap_page_aligned(size + kPageSize * 2); 39 | Allocator::protect_readwrite((void*)((uintptr_t)m_mapping + kPageSize), size); 40 | } 41 | ~GuardedBuffer() { 42 | DCHECK(m_mapping != nullptr); 43 | Allocator::munmap(m_mapping, m_size); 44 | m_mapping = nullptr; 45 | m_size = 0; 46 | } 47 | 48 | void* data() const { 49 | return (void*)((uintptr_t)m_mapping + kPageSize); 50 | } 51 | 52 | size_t size() const { 53 | return m_size - kPageSize * 2; 54 | } 55 | 56 | private: 57 | void* m_mapping = nullptr; 58 | size_t m_size = 0; 59 | }; 60 | 61 | } // namespace charly::utils 62 | -------------------------------------------------------------------------------- /include/charly/utils/lock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include // std::hash 30 | #include 31 | #include // std::hardware_concurrency 32 | #include 33 | 34 | #include "charly/atomic.h" 35 | 36 | #pragma once 37 | 38 | namespace charly::utils { 39 | 40 | struct ParkingLotThreadData { 41 | bool should_park = false; 42 | std::mutex parking_lock; 43 | std::condition_variable parking_condition; 44 | static ParkingLotThreadData* get_local_thread_data(); 45 | }; 46 | 47 | struct ParkingLotThreadQueue { 48 | using QueueEntry = std::tuple; 49 | std::mutex mutex; 50 | std::list queue; 51 | 52 | void push(ParkingLotThreadData* data, uintptr_t address); 53 | ParkingLotThreadData* pop(uintptr_t address); 54 | bool empty() const; 55 | }; 56 | 57 | class ParkingLot { 58 | public: 59 | ParkingLot(); 60 | 61 | struct UnparkResult { 62 | bool unparked_thread = false; 63 | bool queue_is_empty = false; 64 | }; 65 | 66 | static bool park(uintptr_t address, const std::function& validation); 67 | static void unpark_one(uintptr_t address, const std::function& callback); 68 | static UnparkResult unpark_one(uintptr_t address); 69 | 70 | private: 71 | static constexpr size_t kInitialBucketCount = 1; 72 | using ThreadQueueTable = std::vector>; 73 | 74 | bool park_impl(uintptr_t address, const std::function& validation); 75 | void unpark_one_impl(uintptr_t address, const std::function& callback); 76 | 77 | static ParkingLotThreadQueue* get_queue_for_address(ThreadQueueTable* table, uintptr_t address); 78 | 79 | private: 80 | atomic m_table = nullptr; 81 | std::mutex m_old_tables_mutex; 82 | std::vector m_old_tables; 83 | }; 84 | 85 | enum LockState : uint8_t { 86 | kFreeLock = 0, 87 | kIsLocked = 1, 88 | kHasParked = 2 89 | }; 90 | 91 | // allows threads to barge in and steal the lock away from a parked thread 92 | class TinyLock { 93 | public: 94 | void lock(); 95 | void unlock(); 96 | 97 | bool is_locked() const { 98 | return (m_state & kIsLocked); 99 | } 100 | 101 | TinyLock& operator=(uint8_t value) { 102 | m_state = value; 103 | return *this; 104 | } 105 | 106 | private: 107 | atomic m_state = kFreeLock; 108 | }; 109 | static_assert(sizeof(TinyLock) == 1); 110 | 111 | } // namespace charly::utils 112 | -------------------------------------------------------------------------------- /include/charly/utils/random_device.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #pragma once 31 | 32 | namespace charly::utils { 33 | 34 | class RandomDevice { 35 | public: 36 | RandomDevice() : m_state(std::time(nullptr)) {} 37 | 38 | size_t get() { 39 | size_t x = m_state; 40 | x ^= x << 13; 41 | x ^= x >> 7; 42 | x ^= x << 17; 43 | m_state = x; 44 | return x; 45 | } 46 | 47 | private: 48 | size_t m_state; 49 | }; 50 | 51 | } // namespace charly::utils 52 | -------------------------------------------------------------------------------- /include/charly/utils/timedsection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/charly.h" 28 | 29 | #pragma once 30 | 31 | namespace charly::utils { 32 | 33 | class TimedSection { 34 | public: 35 | // prints the amount of time elapsed inside the callback method to the console 36 | // returns the amount of milliseconds elapsed 37 | template 38 | static double run(const std::string& title, F callback) { 39 | size_t start_time = get_steady_timestamp_micro(); 40 | debuglnf("Begin '%'", title); 41 | callback(); 42 | size_t end_time = get_steady_timestamp_micro(); 43 | double duration = (double)(end_time - start_time) / 1000; 44 | debuglnf("'%' ran for %ms", title, duration); 45 | return duration; 46 | } 47 | }; 48 | 49 | } // namespace charly::utils 50 | -------------------------------------------------------------------------------- /include/charly/utils/wait_flag.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "charly/atomic.h" 33 | 34 | #pragma once 35 | 36 | namespace charly::utils { 37 | 38 | class WaitFlag { 39 | public: 40 | explicit WaitFlag(std::mutex& mutex) : m_mutex(mutex) {} 41 | 42 | bool state() const { 43 | return m_state; 44 | } 45 | 46 | void wait() { 47 | std::unique_lock locker(m_mutex); 48 | m_cv.wait(locker, [&]() -> bool { 49 | return m_state; 50 | }); 51 | } 52 | 53 | bool signal() { 54 | bool first; 55 | { 56 | std::unique_lock locker(m_mutex); 57 | first = m_state.cas(false, true); 58 | } 59 | 60 | m_cv.notify_all(); 61 | 62 | return first; 63 | } 64 | 65 | bool reset() { 66 | bool first; 67 | { 68 | std::unique_lock locker(m_mutex); 69 | first = m_state.cas(true, false); 70 | } 71 | 72 | m_cv.notify_all(); 73 | 74 | return first; 75 | } 76 | 77 | private: 78 | std::mutex& m_mutex; 79 | std::condition_variable m_cv; 80 | atomic m_state = false; 81 | }; 82 | 83 | } // namespace charly::utils 84 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p cmake-build-release 4 | 5 | # initial cmake run 6 | if ! test -f cmake-build-release/Makefile; 7 | then 8 | cmake -DCMAKE_BUILD_TYPE=Release -S . -B cmake-build-release 9 | fi 10 | 11 | if cmake --build cmake-build-release -j12 --target tests charly; 12 | then 13 | if ./cmake-build-release/tests; 14 | then 15 | sudo cmake --install cmake-build-release 16 | fi 17 | fi 18 | -------------------------------------------------------------------------------- /libs/termcolor/termcolor.cpp: -------------------------------------------------------------------------------- 1 | #include "termcolor.h" 2 | 3 | namespace termcolor::_internal { 4 | static int colorize_index = ((std::cout << "xalloc" << std::endl), std::ios_base::xalloc()); 5 | } 6 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p cmake-build-release 4 | 5 | # initial cmake run 6 | if ! test -f cmake-build-release/Makefile; 7 | then 8 | cmake -DCMAKE_BUILD_TYPE=Release -S . -B cmake-build-release 9 | fi 10 | 11 | if cmake --build cmake-build-release --target charly -j12; 12 | then 13 | cmake-build-release/charly "$@" 14 | fi 15 | -------------------------------------------------------------------------------- /scratch-files/concurrent_map.ch: -------------------------------------------------------------------------------- 1 | class Array { 2 | func concurrent_map(block) { 3 | // self = [1, 2, 3, ..., 18, 19, 20] 4 | const results = Array.of_size(@length) 5 | 6 | const partition_size = Math.floor(@length / Fiber.MaxParallelism) 7 | const last_error = @length - (Fiber.MaxParallelism * partition_size) 8 | 9 | const partition_counters = Array.of_size(Fiber.MaxParallelism).map(->(p_index) { 10 | const start = p_index * partition_size 11 | let limit = start + partition_size 12 | 13 | if p_index + 1 == Fiber.MaxParallelism { 14 | limit += last_error 15 | } 16 | 17 | AtomicCounter(start, limit) 18 | }) 19 | 20 | Fiber.MaxParallelism.map(->(i) { 21 | spawn { 22 | 23 | // work through own partition first 24 | const own_counter = partition_counters[i] 25 | loop { 26 | const index = own_counter.next() 27 | if index == null break 28 | results[index] = block(self[index], index, self) 29 | } 30 | 31 | // steal from other partitions 32 | loop { 33 | let stolen_index 34 | partition_counters.find(->(counter) { 35 | stolen_index = counter.next() 36 | return stolen_index != null 37 | }) 38 | 39 | if stolen_index == null break 40 | results[index] = block(self[index], index, self) 41 | } 42 | } 43 | }).each(->(worker) await worker) 44 | 45 | return results 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /scratch-files/gc-stress-test.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | const fiber_count = 60000 28 | const allocator_limit = 10000 29 | 30 | func allocator(index) { 31 | let data 32 | allocator_limit.times(->(i) { 33 | data = (i,) 34 | }) 35 | 36 | data[0] 37 | } 38 | 39 | const list = Tuple.create_with(fiber_count, ->(i) { 40 | spawn allocator(i) 41 | }) 42 | 43 | const result = list.reduce(0, ->(p, f, i) p + await f) 44 | print(result) 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /scratch-files/parsertest.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | let result = 0 28 | 29 | let r1 30 | 31 | func foo { 32 | let r2 33 | 34 | func bar { 35 | let r3 36 | 37 | func baz { 38 | let r4 = result 39 | r3 = r4 + 1 40 | } 41 | 42 | baz() 43 | r2 = r3 + 1 44 | } 45 | 46 | bar() 47 | r1 = r2 + 1 48 | } 49 | 50 | foo() 51 | 52 | return r1 53 | -------------------------------------------------------------------------------- /scratch-files/scratch.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | func times(n, cb) { 28 | let i = 0 29 | while i != n { 30 | cb(i) 31 | i += 1 32 | } 33 | } 34 | 35 | func sleep(n = 1) { 36 | const limit = 1000 37 | let i = 0 38 | let j = 0 39 | 40 | while j != n { 41 | while i != limit { 42 | i += 1 43 | } 44 | j += 1 45 | i = 0 46 | } 47 | } 48 | 49 | func map(size, cb) { 50 | const result = list(size) 51 | times(size, ->(i) { 52 | result[i] = cb(i) 53 | }) 54 | return result 55 | } 56 | 57 | const job = spawn { 58 | return (1, 2, 3) 59 | } 60 | 61 | const result = await job 62 | 63 | echo("result: {result}") 64 | 65 | 66 | 67 | // Represents a basic thread in the charly runtime 68 | // A thread can either run in task mode or generator mode 69 | class Thread { 70 | 71 | 72 | } 73 | 74 | class Task extends Thread { 75 | 76 | } 77 | 78 | class Generator extends Thread { 79 | func next(argument = null) 80 | } 81 | 82 | 83 | 84 | 85 | 86 | 87 | class Container { 88 | property list 89 | 90 | // declaration: signature: error: 91 | func foo() // foo() 92 | func foo(&block) // foo_() 93 | func foo(bar = null) // foo() duplicate function signature 94 | func foo(bar = null, &block) // foo_() duplicate function signature 95 | func foo(bar, baz = null) // foo(_) 96 | func foo(bar, baz = null, &block) // foo_(_) 97 | func foo(bar, baz) // foo(_, _) 98 | func foo(bar, baz, &block) // foo_(_, _) 99 | 100 | // optional parameters do not count towards function signature 101 | // functions that accept a callback block have a different signature 102 | // than functions that do not accept one 103 | } 104 | 105 | func maketask(context, function, args) 106 | func makegenerator(context, function, args) 107 | func taskjoin(task) 108 | func taskyield(arg) 109 | 110 | class Container { 111 | func +(other) // binary + operator 112 | func ==(other) // binary == operator 113 | func !() // unary ! operator (not) 114 | func -() // unary - operator 115 | 116 | func await() // await operator 117 | 118 | func [](index) 119 | func []=(index, value) 120 | } 121 | 122 | 123 | 124 | class Generator { 125 | construct new(&function) { 126 | 127 | } 128 | } 129 | 130 | const counter = async { 131 | let i = 0 132 | loop { 133 | yield i 134 | i++ 135 | } 136 | } 137 | 138 | 139 | 140 | 141 | // use-case: concurrently request and load files from a server 142 | // provided is a list of URLs 143 | // result should be a list of strings 144 | 145 | const urls = get_urls() 146 | 147 | const requests = urls.map -> (url) spawn fetch(url) 148 | 149 | const files = requests.map -> (req) await req 150 | 151 | files.each -> (file) print(file) 152 | 153 | urls.map -> spawn fetch($) 154 | .map -> await $ 155 | .each -> print($) 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /scratch-files/test.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | 28 | const limit = 1000 29 | const tasks = 512.map(->(i) spawn { 30 | limit.times(->sleep(1)) 31 | }) 32 | 33 | const w = Stopwatch() 34 | defer print("waited", w.check(), "ms") 35 | 36 | tasks.each(->(t) await t) 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB charlycore_SRC 2 | "charly/charly.cpp" 3 | "charly/core/compiler/ast.cpp" 4 | "charly/core/compiler/codegenerator.cpp" 5 | "charly/core/compiler/compiler.cpp" 6 | "charly/core/compiler/diagnostic.cpp" 7 | "charly/core/compiler/ir/assembler.cpp" 8 | "charly/core/compiler/ir/builder.cpp" 9 | "charly/core/compiler/ir/ir.cpp" 10 | "charly/core/compiler/lexer.cpp" 11 | "charly/core/compiler/location.cpp" 12 | "charly/core/compiler/parser.cpp" 13 | "charly/core/compiler/passes/constant_folding_pass.cpp" 14 | "charly/core/compiler/passes/desugar_pass.cpp" 15 | "charly/core/compiler/passes/code_elimination.cpp" 16 | "charly/core/compiler/passes/duplicates_check.cpp" 17 | "charly/core/compiler/passes/grammar_validation_check.cpp" 18 | "charly/core/compiler/passes/repl_prepare_pass.cpp" 19 | "charly/core/compiler/passes/reserved_identifiers_check.cpp" 20 | "charly/core/compiler/passes/variable_analyzer_pass.cpp" 21 | "charly/core/runtime/compiled_module.cpp" 22 | "charly/core/runtime/gc.cpp" 23 | "charly/core/runtime/heap.cpp" 24 | "charly/core/runtime/interpreter.cpp" 25 | "charly/core/runtime/processor.cpp" 26 | "charly/core/runtime/runtime.cpp" 27 | "charly/core/runtime/scheduler.cpp" 28 | "charly/core/runtime/watchdog.cpp" 29 | "charly/core/runtime/thread.cpp" 30 | "charly/core/runtime/worker.cpp" 31 | "charly/core/runtime/builtins/core.cpp" 32 | "charly/core/runtime/builtins/future.cpp" 33 | "charly/core/runtime/builtins/list.cpp" 34 | "charly/core/runtime/builtins/timer.cpp" 35 | "charly/core/runtime/builtins/readline.cpp" 36 | "charly/handle.cpp" 37 | "charly/utils/argumentparser.cpp" 38 | "charly/utils/buffer.cpp" 39 | "charly/utils/allocator.cpp" 40 | "charly/utils/lock.cpp" 41 | "charly/value.cpp" 42 | "libs/termcolor/termcolor.cpp" 43 | ) 44 | 45 | # explicitly enable debug symbols in debug builds 46 | set(CMAKE_CXX_FLAGS_DEBUG "-g") 47 | 48 | find_package(Boost REQUIRED COMPONENTS context) 49 | 50 | # osx check 51 | if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 52 | message("-- Detected apple installation") 53 | add_compile_definitions(APPLE) 54 | set(APPLE TRUE) 55 | execute_process(COMMAND xcrun --show-sdk-path OUTPUT_VARIABLE OSXSDKPATH) 56 | include_directories(BEFORE SYSTEM ${OSXSDKPATH}) 57 | endif () 58 | 59 | add_library(libcharly ${charlycore_SRC}) 60 | target_compile_features(libcharly PRIVATE cxx_std_17) 61 | if (Boost_FOUND) 62 | target_include_directories(libcharly PRIVATE ${Boost_INCLUDE_DIRS}) 63 | target_link_libraries(libcharly Boost::context) 64 | endif () 65 | target_link_libraries(libcharly stdc++) 66 | target_link_libraries(libcharly m) 67 | target_link_libraries(libcharly readline) 68 | target_link_libraries(libcharly pthread) 69 | target_include_directories(libcharly PRIVATE "./") 70 | target_compile_options(libcharly PRIVATE 71 | -Wall 72 | -Wextra 73 | -Wpedantic 74 | -Werror 75 | -Wno-vla-extension 76 | -Wno-c++20-designator 77 | -Wno-gnu-zero-variadic-macro-arguments 78 | -Wno-gnu-label-as-value 79 | -Wno-c99-extensions 80 | -Wno-register 81 | -Wno-extra-semi 82 | -Wno-shadow 83 | -ftemplate-backtrace-limit=8 84 | -mllvm -align-all-functions=3 85 | ) 86 | 87 | # enable link-time-optimization for release builds 88 | if (CMAKE_BUILD_TYPE MATCHES Release) 89 | message("-- Enabling LTO for target 'libcharly'") 90 | target_compile_options(libcharly PRIVATE -flto -O3) 91 | endif () 92 | 93 | set_target_properties(libcharly PROPERTIES PREFIX "") 94 | 95 | if (APPLE) 96 | set_target_properties(libcharly PROPERTIES LINK_FLAGS -fuse-ld=ld) 97 | else () 98 | set_target_properties(libcharly PROPERTIES LINK_FLAGS -fuse-ld=lld) 99 | endif () 100 | -------------------------------------------------------------------------------- /src/charly/charly.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "charly/charly.h" 30 | #include "charly/core/runtime/interpreter.h" 31 | #include "charly/core/runtime/runtime.h" 32 | 33 | namespace charly { 34 | 35 | std::recursive_mutex debugln_mutex; 36 | auto program_startup_timestamp = std::chrono::steady_clock::now(); 37 | 38 | void print_runtime_debug_state(std::ostream& stream) { 39 | using namespace core::runtime; 40 | 41 | if (Thread* thread = Thread::current()) { 42 | debugln_impl_time(stream, "\n"); 43 | debugln_impl_time(stream, "Thread: %\n", thread->id()); 44 | 45 | if (Frame* frame = thread->frame()) { 46 | if (frame->is_builtin_frame()) { 47 | auto* builtin_frame = static_cast(frame); 48 | debugln_impl_time(stream, "Builtin Function: %\n", builtin_frame->function); 49 | } else { 50 | auto* interpreter_frame = static_cast(frame); 51 | debugln_impl_time(stream, "IP: %\n", (void*)interpreter_frame->oldip); 52 | debugln_impl_time(stream, "Function: %\n", interpreter_frame->function); 53 | } 54 | 55 | Frame* old = frame; 56 | debugln_impl_time(stream, "Frames:\n", frame); 57 | while (frame) { 58 | if (frame->is_builtin_frame()) { 59 | auto* builtin_frame = static_cast(frame); 60 | debugln_impl_time(stream, " - %\n", builtin_frame->function); 61 | } else { 62 | auto* interpreter_frame = static_cast(frame); 63 | debugln_impl_time(stream, " - %: %\n", interpreter_frame->function, (void*)interpreter_frame->oldip); 64 | } 65 | frame = frame->parent; 66 | } 67 | frame = old; 68 | 69 | if (frame->is_interpreter_frame()) { 70 | auto* interpreter_frame = static_cast(frame); 71 | if (interpreter_frame->stack && interpreter_frame->sp > 0) { 72 | debugln_impl_time(stream, "\n"); 73 | debugln_impl_time(stream, "Stack:\n"); 74 | for (int64_t i = interpreter_frame->sp - 1; i >= 0; i--) { 75 | debugln_impl_time(stream, " - %\n", interpreter_frame->stack[i]); 76 | } 77 | } 78 | } 79 | } else { 80 | debugln_impl_time(stream, "No active frame!\n"); 81 | } 82 | } else { 83 | debugln_impl_time(stream, "No active thread!\n"); 84 | } 85 | 86 | void* callstack[128]; 87 | int frames = backtrace(callstack, 128); 88 | char** frame_symbols = backtrace_symbols(callstack, frames); 89 | debugln_impl_time(stream, "Hardware Stack:\n"); 90 | for (int i = 0; i < frames; ++i) { 91 | debugln_impl_time(stream, " - % %\n", i, frame_symbols[i] + 58); 92 | } 93 | utils::Allocator::free(frame_symbols); 94 | } 95 | 96 | } // namespace charly 97 | -------------------------------------------------------------------------------- /src/charly/core/compiler/compiler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "charly/core/compiler/ast.h" 30 | #include "charly/core/compiler/diagnostic.h" 31 | #include "charly/core/compiler/ir/builder.h" 32 | #include "charly/core/runtime/compiled_module.h" 33 | #include "charly/utils/buffer.h" 34 | 35 | #pragma once 36 | 37 | namespace charly::core::compiler { 38 | 39 | struct CompilationUnit { 40 | enum class Type : uint8_t { 41 | Module, 42 | ReplInput 43 | }; 44 | 45 | CompilationUnit(Type type, const std::string& filepath, utils::Buffer& source) : 46 | type(type), console(filepath, source), filepath(filepath) {} 47 | 48 | Type type; 49 | DiagnosticConsole console; 50 | std::string filepath; 51 | ref ast; 52 | ref ir_module; 53 | ref compiled_module; 54 | }; 55 | 56 | class Compiler { 57 | public: 58 | // compile source code into a compilation unit 59 | static ref compile(const std::string& filepath, 60 | utils::Buffer& source, 61 | CompilationUnit::Type type = CompilationUnit::Type::ReplInput); 62 | }; 63 | 64 | } // namespace charly::core::compiler 65 | -------------------------------------------------------------------------------- /src/charly/core/compiler/ir/assembler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "charly/core/compiler/ir/builder.h" 32 | #include "charly/core/compiler/ir/ir.h" 33 | 34 | #include "charly/utils/buffer.h" 35 | 36 | #include "charly/core/runtime/compiled_module.h" 37 | 38 | #pragma once 39 | 40 | namespace charly::core::compiler::ir { 41 | 42 | class Assembler { 43 | public: 44 | static ref compile_module(const ref& module); 45 | 46 | private: 47 | explicit Assembler(const ref& module) : m_ir_module(module), m_label_counter(module->next_label) {} 48 | 49 | // assemble set ir module 50 | void assemble(); 51 | 52 | // encode op into buffer 53 | void encode_instruction(const ref& op); 54 | 55 | // emit some padding bytes to align the next write to a pointer boundary 56 | void align_to_pointer(); 57 | 58 | // reserve a new label 59 | Label reserve_label(); 60 | void place_label(Label label); 61 | 62 | // resolve all unresolved label references in the bytecode buffer 63 | void patch_unresolved_labels(); 64 | 65 | // returns the offset a given label refers to 66 | // asserts that the label was placed, programming error otherwise 67 | uint32_t offset_of_label(Label label); 68 | 69 | struct UnresolvedLabel { 70 | Label label; 71 | Label base; 72 | }; 73 | 74 | ref m_runtime_module = nullptr; 75 | ref m_ir_module = nullptr; 76 | Label m_label_counter; 77 | std::unordered_map m_placed_labels; 78 | std::unordered_map m_unresolved_labels; 79 | }; 80 | 81 | } // namespace charly::core::compiler::ir 82 | -------------------------------------------------------------------------------- /src/charly/core/compiler/ir/builtin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #pragma once 32 | 33 | namespace charly::core::compiler::ir { 34 | 35 | #define FOREACH_BUILTIN(V) \ 36 | V(makefiber, 3) \ 37 | V(await, 1) \ 38 | V(import, 2) \ 39 | V(iteratornext, 1) \ 40 | V(castbool, 1) \ 41 | V(caststring, 1) \ 42 | V(castsymbol, 1) \ 43 | V(castiterator, 1) \ 44 | V(panic, 0) 45 | 46 | // ids of builtin operations 47 | enum class BuiltinId : uint16_t { 48 | #define ID(name, _) name, 49 | FOREACH_BUILTIN(ID) 50 | #undef ID 51 | }; 52 | 53 | // number of required arguments for the builtin operations 54 | // -1 indicates that there is no min or max limit 55 | constexpr int8_t kBuiltinArgumentCount[] = { 56 | #define COUNT(_, count) count, 57 | FOREACH_BUILTIN(COUNT) 58 | #undef COUNT 59 | }; 60 | 61 | // names of builtin operations 62 | inline static std::string kBuiltinNames[] = { 63 | #define NAME(name, _) #name, 64 | FOREACH_BUILTIN(NAME) 65 | #undef NAME 66 | }; 67 | 68 | // mapping from name of builtin operation to its Id 69 | inline static std::unordered_map kBuiltinNameMapping = { 70 | #define PAIR(name, _) { #name, BuiltinId::name }, 71 | FOREACH_BUILTIN(PAIR) 72 | #undef PAIR 73 | }; 74 | 75 | } // namespace charly::core::compiler::ir 76 | -------------------------------------------------------------------------------- /src/charly/core/compiler/ir/functioninfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "charly/symbol.h" 31 | 32 | #pragma once 33 | 34 | namespace charly::core::compiler::ir { 35 | 36 | // keep track of local variable info of functions 37 | struct FunctionInfo { 38 | SYMBOL name = SYM(""); 39 | bool valid = false; 40 | uint8_t stacksize = 0; 41 | uint8_t local_variables = 0; 42 | uint8_t heap_variables = 0; 43 | uint8_t argc = 0; 44 | uint8_t minargc = 0; 45 | bool has_frame_context = false; 46 | bool spread_argument = false; 47 | bool arrow_function = false; 48 | bool private_function = false; 49 | bool is_constructor = false; 50 | 51 | // write a formatted version to the stream: 52 | // 53 | // (lvars=5, argc=3, minargc=2, spread=false) 54 | friend std::ostream& operator<<(std::ostream& out, const FunctionInfo& info) { 55 | out << "( "; 56 | out << "name=" << bitcast(static_cast(info.name)) << " "; 57 | out << "lvars=" << static_cast(info.local_variables) << " "; 58 | out << "hvars=" << static_cast(info.heap_variables) << " "; 59 | out << "argc=" << static_cast(info.argc) << " "; 60 | out << "minargc=" << static_cast(info.minargc) << " "; 61 | 62 | if (info.has_frame_context) { 63 | out << "has_context "; 64 | } 65 | if (info.spread_argument) { 66 | out << "spread "; 67 | } 68 | if (info.arrow_function) { 69 | out << "arrow "; 70 | } 71 | if (info.private_function) { 72 | out << "private "; 73 | } 74 | if (info.is_constructor) { 75 | out << "constructor "; 76 | } 77 | out << ")"; 78 | 79 | return out; 80 | } 81 | }; 82 | 83 | } // namespace charly::core::compiler::ir 84 | -------------------------------------------------------------------------------- /src/charly/core/compiler/location.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/compiler/location.h" 28 | 29 | namespace charly::core::compiler { 30 | 31 | std::ostream& operator<<(std::ostream& out, const Location& loc) { 32 | if (loc.row == loc.end_row) { 33 | out << loc.row + 1 << ":" << loc.column + 1; 34 | } else { 35 | out << loc.row + 1 << "-" << loc.end_row + 1; 36 | } 37 | 38 | return out; 39 | } 40 | 41 | } // namespace charly::core::compiler 42 | -------------------------------------------------------------------------------- /src/charly/core/compiler/location.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #pragma once 33 | 34 | namespace charly::core::compiler { 35 | 36 | struct Location { 37 | bool valid = false; // wether this location contains actual data 38 | bool compound = false; // wether this location is a mixup of multiple other locations 39 | 40 | // offset in source bytestream 41 | size_t offset = 0; 42 | size_t end_offset = 0; 43 | 44 | // file coordinates 45 | uint32_t row = 0; 46 | uint32_t column = 0; 47 | uint32_t end_row = 0; 48 | uint32_t end_column = 0; 49 | 50 | void set_begin(const Location& other) { 51 | this->valid = other.valid; 52 | this->compound = true; 53 | this->offset = other.offset; 54 | this->row = other.row; 55 | this->column = other.column; 56 | } 57 | 58 | void set_end(const Location& other) { 59 | this->valid = other.valid; 60 | this->compound = true; 61 | this->end_offset = other.end_offset; 62 | this->end_row = other.end_row; 63 | this->end_column = other.end_column; 64 | } 65 | 66 | friend std::ostream& operator<<(std::ostream& out, const Location& loc); 67 | }; 68 | 69 | } // namespace charly::core::compiler 70 | -------------------------------------------------------------------------------- /src/charly/core/compiler/passes/code_elimination.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/compiler/pass.h" 28 | 29 | #pragma once 30 | 31 | namespace charly::core::compiler::ast { 32 | 33 | class CodeEliminationPass : public DiagnosticPass { 34 | public: 35 | using DiagnosticPass::DiagnosticPass; 36 | 37 | private: 38 | ref transform(const ref&) override; 39 | ref transform(const ref&) override; 40 | ref transform(const ref&) override; 41 | }; 42 | 43 | } // namespace charly::core::compiler::ast 44 | -------------------------------------------------------------------------------- /src/charly/core/compiler/passes/constant_folding_pass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/compiler/pass.h" 28 | 29 | #pragma once 30 | 31 | namespace charly::core::compiler::ast { 32 | 33 | class ConstantFoldingPass : public DiagnosticPass { 34 | public: 35 | using DiagnosticPass::DiagnosticPass; 36 | 37 | private: 38 | ref transform(const ref&) override; 39 | ref transform(const ref&) override; 40 | ref transform(const ref&) override; 41 | ref transform(const ref&) override; 42 | ref transform(const ref&) override; 43 | ref transform(const ref&) override; 44 | bool inspect_enter(const ref&) override; 45 | ref transform(const ref&) override; 46 | }; 47 | 48 | } // namespace charly::core::compiler::ast 49 | -------------------------------------------------------------------------------- /src/charly/core/compiler/passes/desugar_pass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/compiler/pass.h" 28 | 29 | #pragma once 30 | 31 | namespace charly::core::compiler::ast { 32 | 33 | class DesugarPass : public DiagnosticPass { 34 | public: 35 | using DiagnosticPass::DiagnosticPass; 36 | 37 | private: 38 | void inspect_leave(const ref&) override; 39 | bool inspect_enter(const ref&) override; 40 | ref transform(const ref&) override; 41 | ref transform(const ref&) override; 42 | ref transform(const ref&) override; 43 | bool inspect_enter(const ref&) override; 44 | void inspect_leave(const ref&) override; 45 | void inspect_leave(const ref&) override; 46 | ref transform(const ref&) override; 47 | ref transform(const ref&) override; 48 | }; 49 | 50 | } // namespace charly::core::compiler::ast 51 | -------------------------------------------------------------------------------- /src/charly/core/compiler/passes/duplicates_check.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/compiler/pass.h" 28 | 29 | #pragma once 30 | 31 | namespace charly::core::compiler::ast { 32 | 33 | class DuplicatesCheck : public DiagnosticPass { 34 | public: 35 | using DiagnosticPass::DiagnosticPass; 36 | 37 | private: 38 | void inspect_leave(const ref& node) override; 39 | void inspect_leave(const ref& node) override; 40 | void inspect_leave(const ref& node) override; 41 | void inspect_leave(const ref& node) override; 42 | }; 43 | 44 | } // namespace charly::core::compiler::ast 45 | -------------------------------------------------------------------------------- /src/charly/core/compiler/passes/grammar_validation_check.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/compiler/pass.h" 28 | 29 | #pragma once 30 | 31 | namespace charly::core::compiler::ast { 32 | 33 | class GrammarValidationCheck : public DiagnosticPass { 34 | public: 35 | using DiagnosticPass::DiagnosticPass; 36 | 37 | void constructor_super_check(const ref& node); 38 | void constructor_return_check(const ref& node); 39 | 40 | private: 41 | void inspect_leave(const ref& node) override; 42 | void inspect_leave(const ref& node) override; 43 | void inspect_leave(const ref& node) override; 44 | }; 45 | 46 | } // namespace charly::core::compiler::ast 47 | -------------------------------------------------------------------------------- /src/charly/core/compiler/passes/repl_prepare_pass.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/compiler/passes/repl_prepare_pass.h" 28 | 29 | namespace charly::core::compiler::ast { 30 | 31 | void ReplPreparePass::inspect_leave(const ref& node) { 32 | // the last expression of the toplevel REPL block is 33 | // wrapped in a return statement 34 | if (node->repl_toplevel_block) { 35 | if (!node->statements.empty() && isa(node->statements.back())) { 36 | ref exp = cast(node->statements.back()); 37 | node->statements.pop_back(); 38 | 39 | ref return_exp = make(exp); 40 | return_exp->set_location(exp); 41 | 42 | node->statements.push_back(return_exp); 43 | } 44 | } 45 | } 46 | 47 | } // namespace charly::core::compiler::ast 48 | -------------------------------------------------------------------------------- /src/charly/core/compiler/passes/repl_prepare_pass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/compiler/pass.h" 28 | 29 | #pragma once 30 | 31 | namespace charly::core::compiler::ast { 32 | 33 | class ReplPreparePass : public DiagnosticPass { 34 | public: 35 | using DiagnosticPass::DiagnosticPass; 36 | 37 | private: 38 | void inspect_leave(const ref&) override; 39 | }; 40 | 41 | } // namespace charly::core::compiler::ast 42 | -------------------------------------------------------------------------------- /src/charly/core/compiler/passes/reserved_identifiers_check.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/compiler/pass.h" 28 | 29 | #pragma once 30 | 31 | namespace charly::core::compiler::ast { 32 | 33 | class ReservedIdentifiersCheck : public DiagnosticPass { 34 | public: 35 | using DiagnosticPass::DiagnosticPass; 36 | 37 | private: 38 | void inspect_leave(const ref& node) override; 39 | void inspect_leave(const ref& node) override; 40 | void inspect_leave(const ref& node) override; 41 | void inspect_leave(const ref& node) override; 42 | }; 43 | 44 | } // namespace charly::core::compiler::ast 45 | -------------------------------------------------------------------------------- /src/charly/core/runtime/builtins/builtin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/value.h" 28 | #include "charly/core/runtime/interpreter.h" 29 | 30 | #pragma once 31 | 32 | namespace charly::core::runtime::builtin { 33 | 34 | #define REGISTER_BUILTIN_FUNCTION(L, N, A) \ 35 | { \ 36 | auto name = runtime->declare_symbol(thread, "charly.builtin." #L "." #N); \ 37 | auto symbol = RawSymbol::create(name.hashcode()); \ 38 | BuiltinFunction builtin_func(scope, RawBuiltinFunction::create(thread, N, name, A)); \ 39 | CHECK(runtime->declare_global_variable(thread, symbol, true, builtin_func).is_error_ok()); \ 40 | } 41 | 42 | #define DEFINE_BUILTIN_METHOD_DECLARATIONS(L, N, A) RawValue N(Thread* thread, BuiltinFrame* frame); 43 | 44 | } // namespace charly::core::runtime::builtin 45 | -------------------------------------------------------------------------------- /src/charly/core/runtime/builtins/core.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/runtime/builtins/builtin.h" 28 | #include "charly/value.h" 29 | 30 | #pragma once 31 | 32 | namespace charly::core::runtime::builtin::core { 33 | 34 | void initialize(Thread* thread); 35 | 36 | #define DEF_BUILTIN_CORE(V) \ 37 | V(core, currentfiber, 0) \ 38 | V(core, transplantbuiltinclass, 2) \ 39 | V(core, writevalue, -1) \ 40 | V(core, currentworkingdirectory, 0) \ 41 | V(core, getbacktrace, 0) \ 42 | V(core, disassemble, 1) \ 43 | V(core, createtuple, 2) \ 44 | V(core, createtuplewith, 2) \ 45 | V(core, exit, 1) \ 46 | V(core, getsteadytimestamp, 0) \ 47 | V(core, getsteadytimestampmicro, 0) \ 48 | V(core, compile, 2) 49 | DEF_BUILTIN_CORE(DEFINE_BUILTIN_METHOD_DECLARATIONS) 50 | 51 | } // namespace charly::core::runtime::builtin::core 52 | -------------------------------------------------------------------------------- /src/charly/core/runtime/builtins/future.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "charly/core/runtime/builtins/future.h" 31 | #include "charly/core/runtime/interpreter.h" 32 | #include "charly/core/runtime/runtime.h" 33 | 34 | namespace charly::core::runtime::builtin::future { 35 | 36 | void initialize(Thread* thread) { 37 | Runtime* runtime = thread->runtime(); 38 | HandleScope scope(thread); 39 | DEF_BUILTIN_FUTURE(REGISTER_BUILTIN_FUNCTION) 40 | } 41 | 42 | RawValue create(Thread* thread, BuiltinFrame*) { 43 | return RawFuture::create(thread); 44 | } 45 | 46 | RawValue resolve(Thread* thread, BuiltinFrame* frame) { 47 | CHECK(frame->arguments[0].isFuture()); 48 | RawFuture future = RawFuture::cast(frame->arguments[0]); 49 | RawValue result = frame->arguments[1]; 50 | return future.resolve(thread, result); 51 | } 52 | 53 | RawValue reject(Thread* thread, BuiltinFrame* frame) { 54 | CHECK(frame->arguments[0].isFuture()); 55 | CHECK(frame->arguments[1].isException()); 56 | 57 | HandleScope scope(thread); 58 | Future future(scope, frame->arguments[0]); 59 | Exception exception(scope, frame->arguments[1]); 60 | return future.reject(thread, exception); 61 | } 62 | 63 | } // namespace charly::core::runtime::builtin::future 64 | -------------------------------------------------------------------------------- /src/charly/core/runtime/builtins/future.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/runtime/builtins/builtin.h" 28 | #include "charly/value.h" 29 | 30 | #pragma once 31 | 32 | namespace charly::core::runtime::builtin::future { 33 | 34 | void initialize(Thread* thread); 35 | 36 | #define DEF_BUILTIN_FUTURE(V) \ 37 | V(future, create, 0) \ 38 | V(future, resolve, 2) \ 39 | V(future, reject, 2) 40 | DEF_BUILTIN_FUTURE(DEFINE_BUILTIN_METHOD_DECLARATIONS) 41 | 42 | } // namespace charly::core::runtime::builtin::future 43 | -------------------------------------------------------------------------------- /src/charly/core/runtime/builtins/list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "charly/core/runtime/builtins/list.h" 31 | #include "charly/core/runtime/interpreter.h" 32 | #include "charly/core/runtime/runtime.h" 33 | 34 | namespace charly::core::runtime::builtin::list { 35 | 36 | void initialize(Thread* thread) { 37 | Runtime* runtime = thread->runtime(); 38 | HandleScope scope(thread); 39 | DEF_BUILTIN_LIST(REGISTER_BUILTIN_FUNCTION) 40 | } 41 | 42 | RawValue create(Thread* thread, BuiltinFrame* frame) { 43 | CHECK(frame->arguments[0].isNumber()); 44 | 45 | RawValue size_value = frame->arguments[0]; 46 | int64_t size = size_value.int_value(); 47 | RawValue initial_value = frame->arguments[1]; 48 | 49 | if (size <= 0) { 50 | return RawList::create(thread, 0); 51 | } 52 | 53 | if (size > (int64_t)RawList::kMaximumCapacity) { 54 | return thread->throw_message("List exceeded max size"); 55 | } 56 | 57 | return RawList::create_with(thread, size, initial_value); 58 | } 59 | 60 | RawValue insert(Thread* thread, BuiltinFrame* frame) { 61 | CHECK(frame->arguments[0].isList()); 62 | CHECK(frame->arguments[1].isNumber()); 63 | 64 | auto list = RawList::cast(frame->arguments[0]); 65 | int64_t index = frame->arguments[1].int_value(); 66 | 67 | return list.insert_at(thread, index, frame->arguments[2]); 68 | } 69 | 70 | RawValue erase(Thread* thread, BuiltinFrame* frame) { 71 | CHECK(frame->arguments[0].isList()); 72 | CHECK(frame->arguments[1].isNumber()); 73 | CHECK(frame->arguments[2].isNumber()); 74 | 75 | auto list = RawList::cast(frame->arguments[0]); 76 | int64_t start = frame->arguments[1].int_value(); 77 | int64_t count = frame->arguments[2].int_value(); 78 | return list.erase_at(thread, start, count); 79 | } 80 | 81 | RawValue push(Thread* thread, BuiltinFrame* frame) { 82 | CHECK(frame->arguments[0].isList()); 83 | auto list = RawList::cast(frame->arguments[0]); 84 | return list.push_value(thread, frame->arguments[1]); 85 | } 86 | 87 | RawValue pop(Thread* thread, BuiltinFrame* frame) { 88 | CHECK(frame->arguments[0].isList()); 89 | auto list = RawList::cast(frame->arguments[0]); 90 | return list.pop_value(thread); 91 | } 92 | 93 | } // namespace charly::core::runtime::builtin::list 94 | -------------------------------------------------------------------------------- /src/charly/core/runtime/builtins/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/runtime/builtins/builtin.h" 28 | #include "charly/value.h" 29 | 30 | #pragma once 31 | 32 | namespace charly::core::runtime::builtin::list { 33 | 34 | void initialize(Thread* thread); 35 | 36 | #define DEF_BUILTIN_LIST(V) \ 37 | V(list, create, 2) \ 38 | V(list, insert, 3) \ 39 | V(list, erase, 3) \ 40 | V(list, push, 2) \ 41 | V(list, pop, 1) 42 | DEF_BUILTIN_LIST(DEFINE_BUILTIN_METHOD_DECLARATIONS) 43 | 44 | } // namespace charly::core::runtime::builtin::list 45 | -------------------------------------------------------------------------------- /src/charly/core/runtime/builtins/readline.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "charly/core/runtime/builtins/readline.h" 32 | #include "charly/core/runtime/interpreter.h" 33 | #include "charly/core/runtime/runtime.h" 34 | 35 | namespace charly::core::runtime::builtin::readline { 36 | 37 | void initialize(Thread* thread) { 38 | Runtime* runtime = thread->runtime(); 39 | HandleScope scope(thread); 40 | DEF_BUILTIN_READLINE(REGISTER_BUILTIN_FUNCTION) 41 | } 42 | 43 | RawValue prompt(Thread* thread, BuiltinFrame* frame) { 44 | DCHECK(frame->arguments[0].isString()); 45 | std::string prompt = RawString::cast(frame->arguments[0]).str(); 46 | 47 | char* raw_line = nullptr; 48 | thread->native_section([&] { 49 | raw_line = ::readline(prompt.c_str()); 50 | }); 51 | 52 | // EOF passed on empty line 53 | if (raw_line == nullptr) { 54 | return kNull; 55 | } 56 | 57 | size_t length = std::strlen(raw_line); 58 | SYMBOL hash = crc32::hash_block(raw_line, length); 59 | 60 | if (length > RawString::kMaxByteLength) { 61 | return thread->throw_message("String exceeds maximum allowed size"); 62 | } 63 | 64 | return RawString::acquire(thread, raw_line, length, hash); 65 | } 66 | 67 | RawValue add_history(Thread* thread, BuiltinFrame* frame) { 68 | DCHECK(frame->arguments[0].isString()); 69 | 70 | std::string name = RawString::cast(frame->arguments[0]).str(); 71 | thread->native_section([&] { 72 | ::add_history(name.c_str()); 73 | }); 74 | 75 | return kNull; 76 | } 77 | 78 | RawValue clear_history(Thread* thread, BuiltinFrame*) { 79 | thread->native_section([&] { 80 | ::clear_history(); 81 | }); 82 | 83 | return kNull; 84 | } 85 | 86 | } // namespace charly::core::runtime::builtin::readline 87 | -------------------------------------------------------------------------------- /src/charly/core/runtime/builtins/readline.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/runtime/builtins/builtin.h" 28 | #include "charly/value.h" 29 | 30 | #pragma once 31 | 32 | namespace charly::core::runtime::builtin::readline { 33 | 34 | void initialize(Thread* thread); 35 | 36 | #define DEF_BUILTIN_READLINE(V) \ 37 | V(readline, prompt, 1) \ 38 | V(readline, add_history, 1) \ 39 | V(readline, clear_history, 0) 40 | DEF_BUILTIN_READLINE(DEFINE_BUILTIN_METHOD_DECLARATIONS) 41 | 42 | } // namespace charly::core::runtime::builtin::readline 43 | -------------------------------------------------------------------------------- /src/charly/core/runtime/builtins/timer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/runtime/builtins/timer.h" 28 | #include "charly/core/runtime/runtime.h" 29 | 30 | namespace charly::core::runtime::builtin::timer { 31 | 32 | void initialize(Thread* thread) { 33 | Runtime* runtime = thread->runtime(); 34 | HandleScope scope(thread); 35 | DEF_BUILTIN_TIMER(REGISTER_BUILTIN_FUNCTION) 36 | } 37 | 38 | RawValue fibercreate(Thread* thread, BuiltinFrame* frame) { 39 | CHECK(frame->arguments[0].isNumber()); 40 | CHECK(frame->arguments[1].isFunction()); 41 | 42 | int64_t delay = frame->arguments[0].int_value(); 43 | 44 | HandleScope scope(thread); 45 | Function function(scope, frame->arguments[1]); 46 | Value context(scope, frame->arguments[2]); 47 | Value arguments(scope, frame->arguments[3]); 48 | 49 | if (delay <= 0) { 50 | RawFiber::create(thread, function, context, arguments); 51 | return kNull; 52 | } 53 | 54 | size_t now = get_steady_timestamp(); 55 | size_t timestamp = now + delay; 56 | 57 | Processor* proc = thread->worker()->processor(); 58 | TimerId id = proc->init_timer_fiber_create(timestamp, function, context, arguments); 59 | return RawInt::create(id); 60 | } 61 | 62 | RawValue sleep(Thread* thread, BuiltinFrame* frame) { 63 | CHECK(frame->arguments[0].isNumber()); 64 | int64_t delay = frame->arguments[0].int_value(); 65 | 66 | if (delay <= 0) { 67 | return kNull; 68 | } 69 | 70 | size_t now = get_steady_timestamp(); 71 | size_t timestamp = now + delay; 72 | thread->sleep_until(timestamp); 73 | return kNull; 74 | } 75 | 76 | RawValue cancel(Thread* thread, BuiltinFrame* frame) { 77 | CHECK(frame->arguments[0].isInt()); 78 | TimerId id = RawInt::cast(frame->arguments[0]).value(); 79 | Processor* proc = thread->worker()->processor(); 80 | 81 | if (!proc->cancel_timer(id)) { 82 | return thread->throw_message("Timer with id % either already expired or doesn't exist", id); 83 | } 84 | 85 | return kTrue; 86 | } 87 | 88 | } // namespace charly::core::runtime::builtin::list 89 | -------------------------------------------------------------------------------- /src/charly/core/runtime/builtins/timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/runtime/builtins/builtin.h" 28 | #include "charly/value.h" 29 | 30 | #pragma once 31 | 32 | namespace charly::core::runtime::builtin::timer { 33 | 34 | void initialize(Thread* thread); 35 | 36 | #define DEF_BUILTIN_TIMER(V) \ 37 | V(timer, fibercreate, 4) \ 38 | V(timer, sleep, 1) \ 39 | V(timer, cancel, 1) 40 | DEF_BUILTIN_TIMER(DEFINE_BUILTIN_METHOD_DECLARATIONS) 41 | 42 | } // namespace charly::core::runtime::builtin::timer 43 | -------------------------------------------------------------------------------- /src/charly/core/runtime/compiled_module.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/core/runtime/compiled_module.h" 28 | #include "charly/core/compiler/ir/bytecode.h" 29 | #include "charly/utils/colorwriter.h" 30 | 31 | namespace charly::core::runtime { 32 | 33 | using namespace utils; 34 | using namespace compiler::ir; 35 | 36 | void CompiledModule::dump(std::ostream& out) const { 37 | ColorWriter writer(out); 38 | writer.fg(Color::Grey, "; assembled module for file "); 39 | writer.fg(Color::Yellow, "'", this->filename, "'", "\n"); 40 | writer.fg(Color::Grey, "; bytecode buffer size = "); 41 | writer.fg(Color::Yellow, this->buffer.size(), "\n"); 42 | 43 | out << '\n'; 44 | 45 | // disassemble functions 46 | for (const SharedFunctionInfo* function : this->function_table) { 47 | function->dump(out); 48 | } 49 | } 50 | 51 | void SharedFunctionInfo::dump(std::ostream& out) const { 52 | ColorWriter writer(out); 53 | 54 | const uint8_t* function_bytecodes = (uint8_t*)this->bytecode_base_ptr; 55 | const uint8_t* function_end = (uint8_t*)this->end_ptr; 56 | size_t function_bytecodes_length = function_end - function_bytecodes; 57 | 58 | writer.fg(Color::Grey, "; function "); 59 | writer.fg(Color::Yellow, "'", this->name, "'", "\n"); 60 | 61 | writer.fg(Color::Grey, "; bytecodes ptr = "); 62 | writer.fg(Color::Yellow, std::hex, (uintptr_t)function_bytecodes, std::dec, "\n"); 63 | 64 | writer.fg(Color::Grey, "; bytecodes length = "); 65 | writer.fg(Color::Yellow, function_bytecodes_length, "\n"); 66 | 67 | writer.fg(Color::Grey, "; bytecode hash = "); 68 | writer.fg(Color::Yellow, std::hex, 69 | crc32::hash_block(bitcast(function_bytecodes), function_bytecodes_length), std::dec, "\n"); 70 | 71 | writer.fg(Color::Grey, "; ir_info = "); 72 | writer.fg(Color::Yellow, this->ir_info, "\n"); 73 | 74 | // decode individual bytecodes 75 | const uint8_t* next_opcode = function_bytecodes; 76 | while (next_opcode < function_end) { 77 | const Opcode opcode = *(Opcode*)next_opcode; 78 | DCHECK(opcode < Opcode::OpcodeCount); 79 | size_t opcode_length = kInstructionLength; 80 | const std::string& opcode_name = kOpcodeNames[opcode]; 81 | 82 | writer.fg(Color::Grey, "; ", std::setw(20), std::left, opcode_name, std::setw(1)); 83 | out << termcolor::yellow; 84 | Buffer::hexdump((const char*)next_opcode, opcode_length, out, true); 85 | out << termcolor::reset; 86 | 87 | next_opcode = next_opcode + opcode_length; 88 | } 89 | 90 | out << '\n'; 91 | } 92 | 93 | } // namespace charly::core::runtime 94 | -------------------------------------------------------------------------------- /src/charly/core/runtime/compiled_module.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "charly/value.h" 33 | 34 | #include "charly/core/compiler/ir/bytecode.h" 35 | #include "charly/core/compiler/ir/functioninfo.h" 36 | 37 | #include "charly/utils/buffer.h" 38 | 39 | #pragma once 40 | 41 | namespace charly::core::runtime { 42 | 43 | struct ExceptionTableEntry { 44 | ExceptionTableEntry(uint32_t b, uint32_t _end, uint32_t _handler) : 45 | begin_offset(b), end_offset(_end), handler_offset(_handler) {} 46 | 47 | uint32_t begin_offset; 48 | uint32_t end_offset; 49 | uint32_t handler_offset; 50 | uintptr_t begin_ptr = 0; 51 | uintptr_t end_ptr = 0; 52 | uintptr_t handler_ptr = 0; 53 | }; 54 | 55 | struct SourceMapEntry { 56 | SourceMapEntry(uint32_t offset, uint16_t row, uint16_t column, uint16_t end_row, uint16_t end_column) : 57 | instruction_offset(offset), row(row), column(column), end_row(end_row), end_column(end_column) {} 58 | 59 | uint32_t instruction_offset = 0; 60 | uintptr_t instruction_ptr; 61 | uint16_t row; 62 | uint16_t column; 63 | uint16_t end_row; 64 | uint16_t end_column; 65 | }; 66 | 67 | struct StringTableEntry { 68 | explicit StringTableEntry(const std::string& value) : hash(crc32::hash_string(value)), value(value) {} 69 | 70 | SYMBOL hash; 71 | std::string value; 72 | }; 73 | 74 | struct CompiledModule; 75 | struct SharedFunctionInfo { 76 | std::string name; 77 | SYMBOL name_symbol; 78 | compiler::ir::FunctionInfo ir_info; 79 | 80 | std::vector exception_table; 81 | std::vector sourcemap_table; 82 | std::vector string_table; 83 | std::vector constant_table; 84 | 85 | uintptr_t buffer_base_ptr; // pointer to the base of the containing modules buffer 86 | uintptr_t bytecode_base_ptr; // pointer to the functions first opcode 87 | uintptr_t end_ptr; // function end pointer 88 | 89 | uint32_t bytecode_offset; // offset into module buffer where the functions opcodes are located 90 | uint32_t end_offset; // function end offset 91 | 92 | void dump(std::ostream& out) const; 93 | }; 94 | 95 | struct CompiledModule { 96 | CompiledModule() : buffer(32) {} 97 | ~CompiledModule() { 98 | for (SharedFunctionInfo* func : function_table) { 99 | delete func; 100 | } 101 | } 102 | 103 | std::string filename; 104 | std::vector function_table; 105 | 106 | // buffer containing the bytecodes 107 | // the struct 'SharedFunctionInfo' contains offsets into this buffer 108 | utils::Buffer buffer; 109 | 110 | void dump(std::ostream& out) const; 111 | }; 112 | 113 | } // namespace charly::core::runtime 114 | -------------------------------------------------------------------------------- /src/charly/core/runtime/gc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "charly/charly.h" 34 | #include "charly/core/runtime/heap.h" 35 | #include "charly/value.h" 36 | 37 | #pragma once 38 | 39 | namespace charly::core::runtime { 40 | 41 | class Runtime; 42 | class Thread; 43 | 44 | constexpr size_t kGCObjectMaxSurvivorCount = 15; 45 | 46 | // if the minor GC cycle failed to free at least this ratio of free to mapped regions, trigger major GC 47 | constexpr float kGCFreeToMappedRatioMajorTrigger = 0.25f; 48 | 49 | // force a major GC cycle each nth cycle 50 | constexpr size_t kGCForceMajorGCEachNthCycle = 16; 51 | 52 | // if the time elapsed since the last collection is below this threshold, grow the heap 53 | constexpr size_t kGCHeapGrowTimeMajorThreshold = 1000 * 5; 54 | constexpr size_t kGCHeapGrowTimeMinorThreshold = 500; 55 | 56 | // if the time elapsed since the last collection is above this threshold, shrink the heap 57 | constexpr size_t kGCHeapShrinkTimeMajorThreshold = 1000 * 30; 58 | 59 | // if a thread fails to retrieve a free region, repeatedly invoke the garbage collector 60 | // if after this many attempts, there are still no free regions, crash with an out of memory error 61 | constexpr size_t kGCCollectionAttempts = 4; 62 | 63 | class GarbageCollector { 64 | friend class Heap; 65 | 66 | public: 67 | enum class CollectionMode { 68 | Minor, 69 | Major 70 | }; 71 | 72 | explicit GarbageCollector(Runtime* runtime); 73 | ~GarbageCollector(); 74 | 75 | void shutdown(); 76 | void join(); 77 | void perform_gc(); 78 | 79 | private: 80 | void main(); 81 | 82 | void collect(CollectionMode mode); 83 | 84 | void mark_live_objects(); 85 | void mark_runtime_roots(); 86 | void mark_dirty_span_roots(); 87 | void mark_queue_value(RawValue value, bool force_mark = false); 88 | 89 | void compact_object(RawObject object); 90 | HeapRegion* get_target_intermediate_region(size_t alloc_size); 91 | HeapRegion* get_target_old_region(size_t alloc_size); 92 | 93 | void update_old_references() const; 94 | 95 | // updates stale references to moved objects 96 | // returns true if any intermediate references remain 97 | bool update_object_references(RawObject object) const; 98 | 99 | // updates references stored in runtime roots 100 | void update_root_references() const; 101 | 102 | void deallocate_heap_ressources(); 103 | 104 | void queue_object_memory_for_deallocation(RawObject object); 105 | 106 | void recycle_collected_regions() const; 107 | 108 | void adjust_heap() const; 109 | 110 | void validate_heap_and_roots() const; 111 | 112 | private: 113 | Runtime* m_runtime; 114 | Heap* m_heap; 115 | 116 | CollectionMode m_collection_mode = CollectionMode::Minor; 117 | std::queue m_mark_queue; 118 | std::set m_target_intermediate_regions; 119 | std::set m_target_old_regions; 120 | 121 | std::vector m_deallocation_queue; 122 | 123 | size_t m_last_collection_time; 124 | 125 | atomic m_gc_cycle = 1; 126 | atomic m_has_initialized = false; 127 | atomic m_wants_collection = false; 128 | 129 | std::mutex m_mutex; 130 | std::condition_variable m_cv; 131 | std::thread m_thread; 132 | }; 133 | 134 | } // namespace charly::core::runtime 135 | -------------------------------------------------------------------------------- /src/charly/core/runtime/processor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "charly/core/runtime/heap.h" 33 | #include "charly/value.h" 34 | 35 | #pragma once 36 | 37 | namespace charly::core::runtime { 38 | 39 | class Runtime; 40 | class Worker; 41 | class Thread; 42 | class ThreadAllocationBuffer; 43 | class GarbageCollector; 44 | 45 | using TimerId = size_t; 46 | struct TimerEvent { 47 | struct FiberCreate { 48 | RawFunction function; 49 | RawValue context; 50 | RawValue arguments; 51 | }; 52 | 53 | struct ThreadWake { 54 | Thread* thread; 55 | }; 56 | 57 | TimerId id; 58 | size_t timestamp; 59 | std::variant action; 60 | 61 | struct Compare { 62 | constexpr bool operator()(const TimerEvent& left, const TimerEvent& right) const { 63 | return left.timestamp > right.timestamp; 64 | } 65 | }; 66 | }; 67 | 68 | // represents a virtual processor 69 | class Processor { 70 | friend class GarbageCollector; 71 | friend class Runtime; 72 | 73 | public: 74 | explicit Processor(Runtime* runtime); 75 | 76 | // getter / setter 77 | Runtime* runtime() const; 78 | size_t id() const; 79 | bool is_live() const; 80 | void set_live(bool value); 81 | Worker* worker() const; 82 | void set_worker(Worker* worker); 83 | ThreadAllocationBuffer* tab() const; 84 | 85 | // attempt to schedule a thread on this processor 86 | // returns false if the run queue is already at peak capacity 87 | bool schedule_thread(Thread* thread); 88 | 89 | // schedule a new timer at some timestamp in the future 90 | TimerId init_timer_fiber_create(size_t timestamp, RawFunction function, RawValue context, RawValue arguments); 91 | 92 | // puts thread asleep and schedules it to be run at some point in the future 93 | void suspend_thread_until(size_t timestamp, Thread* thread); 94 | 95 | // cancel a specific timer event 96 | // returns false if the timer already fired or doesn't exist 97 | bool cancel_timer(TimerId id); 98 | 99 | // acquire the next ready thread to execute 100 | Thread* get_ready_thread(); 101 | 102 | // look up a symbol in the processor symbol table, or global if not found 103 | // returns kNull if no such symbol exists 104 | // copies the symbol into the local symbol table if it doesn't already exist 105 | RawValue lookup_symbol(SYMBOL symbol); 106 | 107 | // Attempt to steal some threads from this processor 108 | // and put them into target_procs run queue 109 | bool steal_ready_threads(Processor* target_proc); 110 | 111 | void fire_timer_events(Thread* thread); 112 | size_t timestamp_of_next_timer_event(); 113 | 114 | private: 115 | static TimerId get_next_timer_id(); 116 | 117 | private: 118 | Runtime* m_runtime; 119 | size_t m_id; 120 | bool m_live = false; 121 | atomic m_worker = nullptr; 122 | std::unique_ptr m_tab; 123 | 124 | std::mutex m_run_queue_mutex; 125 | std::list m_run_queue; 126 | 127 | std::mutex m_timer_events_mutex; 128 | static atomic s_next_timer_id; 129 | std::vector m_timer_events; 130 | 131 | std::unordered_map m_symbol_table; 132 | }; 133 | 134 | } // namespace charly::core::runtime 135 | -------------------------------------------------------------------------------- /src/charly/core/runtime/watchdog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "charly/charly.h" 30 | #include "charly/core/runtime/runtime.h" 31 | #include "charly/core/runtime/watchdog.h" 32 | 33 | namespace charly::core::runtime { 34 | 35 | using namespace std::chrono_literals; 36 | 37 | WatchDog::WatchDog(Runtime* runtime) : 38 | m_runtime(runtime), m_thread(std::thread(&WatchDog::main, this)) { 39 | } 40 | 41 | WatchDog::~WatchDog() { 42 | DCHECK(!m_thread.joinable()); 43 | } 44 | 45 | void WatchDog::join() { 46 | m_thread.join(); 47 | } 48 | 49 | void WatchDog::main() { 50 | m_runtime->wait_for_initialization(); 51 | auto* scheduler = m_runtime->scheduler(); 52 | 53 | while (!m_runtime->wants_exit()) { 54 | m_clock = get_steady_timestamp(); 55 | 56 | for (Worker* worker : scheduler->m_workers) { 57 | if (worker->state() == Worker::State::Running) { 58 | if (auto* thread = worker->thread()) { 59 | 60 | // scheduler threads cannot be interrupted since there is no thread for them to yield to 61 | if (thread->is_scheduler()) { 62 | continue; 63 | } 64 | 65 | size_t last_scheduled_at = thread->last_scheduled_at(); 66 | if (last_scheduled_at >= Thread::kFirstValidScheduledAtTimestamp && last_scheduled_at < m_clock) { 67 | size_t execution_time = m_clock - last_scheduled_at; 68 | bool has_exceeded_timeslice = execution_time >= kThreadTimeslice; 69 | if (has_exceeded_timeslice) { 70 | thread->set_last_scheduled_at(last_scheduled_at, Thread::kShouldYieldToSchedulerTimestamp); 71 | } 72 | } 73 | } 74 | } 75 | } 76 | 77 | std::this_thread::sleep_for(std::chrono::milliseconds(kWatchDogWakeupInterval)); 78 | } 79 | } 80 | 81 | } // namespace charly::core::runtime 82 | -------------------------------------------------------------------------------- /src/charly/core/runtime/watchdog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "charly/atomic.h" 30 | 31 | #pragma once 32 | 33 | namespace charly::core::runtime { 34 | 35 | class Runtime; 36 | class WatchDog { 37 | public: 38 | static constexpr size_t kWatchDogWakeupInterval = 10; 39 | 40 | WatchDog(Runtime* runtime); 41 | ~WatchDog(); 42 | 43 | void join(); 44 | 45 | private: 46 | void main(); 47 | 48 | private: 49 | Runtime* m_runtime; 50 | std::thread m_thread; 51 | atomic m_clock; 52 | }; 53 | 54 | } // namespace charly::core::runtime 55 | -------------------------------------------------------------------------------- /src/charly/handle.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include "charly/handle.h" 28 | 29 | #include "charly/core/runtime/thread.h" 30 | 31 | namespace charly::core::runtime { 32 | 33 | template 34 | Handle::Handle(HandleScope& scope) : T(), m_thread(scope.thread()), m_next(m_thread->handles()->push(pointer())) {} 35 | 36 | template 37 | Handle::Handle(HandleScope& scope, RawValue value) : 38 | T(value.rawCast()), m_thread(scope.thread()), m_next(m_thread->handles()->push(pointer())) { 39 | DCHECK(is_valid_type()); 40 | } 41 | 42 | template 43 | Handle::~Handle() { 44 | DCHECK(m_thread->handles()->head() == pointer()); 45 | m_thread->handles()->pop(m_next); 46 | } 47 | 48 | #define HANDLE_DEF(T) template class Handle; 49 | TYPE_NAMES(HANDLE_DEF) 50 | #undef HANDLE_DEF 51 | 52 | } // namespace charly::core::runtime 53 | -------------------------------------------------------------------------------- /src/charly/stdlib/repl.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | let $$ 28 | loop { 29 | const input = prompt("> ") 30 | switch input { 31 | case "" { 32 | break 33 | } 34 | 35 | case ".exit" { 36 | return 37 | } 38 | 39 | case ".clear" { 40 | readline_clear_history() 41 | break 42 | } 43 | 44 | case ".help" { 45 | print(".exit Exit from the REPL") 46 | print(".clear Clear REPL history") 47 | print(".help Show this help message") 48 | break 49 | } 50 | 51 | default { 52 | try { 53 | const module = compile(input, "repl") 54 | $$ = module() 55 | print($$) 56 | } catch(e) { 57 | $$ = e 58 | print("Uncaught exception:") 59 | print($$) 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/charly/utils/argumentparser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #pragma once 35 | 36 | namespace charly::utils { 37 | 38 | class ArgumentParser { 39 | public: 40 | struct FlagDescriptor { 41 | std::string name; // e.g help 42 | std::vector selectors; // e.g --help, -h 43 | std::string description; // description of what the flag does 44 | std::optional argument = {}; // wether this flag requires an argument 45 | }; 46 | 47 | struct FlagGroup { 48 | std::string name; 49 | std::vector flags; 50 | }; 51 | 52 | static const std::string LICENSE; 53 | static const std::string VERSION; 54 | static const std::string ENVIRONMENT_STRING_DELIMITER; 55 | 56 | static std::optional USER_FILENAME; 57 | static std::unordered_map> CHARLY_FLAGS; 58 | static std::vector USER_FLAGS; 59 | static std::unordered_map ENVIRONMENT; 60 | 61 | // initialize arguments from C main function arguments and environment pointer 62 | static void init_argv(int argc, char** argv); 63 | static void init_env(char** environment); 64 | 65 | // set a flag 66 | static void set_flag(const std::string& name, std::optional argument = {}); 67 | 68 | // unset a flag 69 | static void unset_flag(const std::string& name); 70 | 71 | // toggle a flag 72 | // returns state after toggling 73 | static bool toggle_flag(const std::string& name); 74 | 75 | // check wether a specific flag is set, addressed by its full name 76 | static bool is_flag_set(const std::string& name); 77 | 78 | // check wether a specific environment variable exists 79 | static bool is_env_set(const std::string& name); 80 | 81 | // return all arguments for a specific flag 82 | static const std::vector& get_arguments_for_flag(const std::string& name); 83 | 84 | // returns the user argument at index 85 | static std::optional get_argument(uint32_t index); 86 | 87 | // check wether a flag has a specific argument set 88 | // 89 | // e.g: 90 | // CLIFlags::flag_has_argument("dump", current_filename, true) 91 | static bool flag_has_argument(const std::string& name, const std::string& argument, bool match_substring = false); 92 | 93 | // return the value of some environment variable 94 | static std::optional get_environment_for_key(const std::string& key); 95 | 96 | // print the help page 97 | static void print_help(std::ostream& out); 98 | }; 99 | 100 | } // namespace charly::utils 101 | -------------------------------------------------------------------------------- /src/charly/utils/colorwriter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include 30 | 31 | #pragma once 32 | 33 | namespace charly::utils { 34 | 35 | enum class Color : uint8_t { 36 | Grey, 37 | Red, 38 | Green, 39 | Yellow, 40 | Blue, 41 | Magenta, 42 | Cyan, 43 | White 44 | }; 45 | 46 | class ColorWriter { 47 | public: 48 | explicit ColorWriter(std::ostream& stream = std::cout) : m_stream(stream) {} 49 | 50 | void set_fg_color(Color color) { 51 | switch (color) { 52 | case Color::Grey: m_stream << termcolor::dark; break; 53 | case Color::Red: m_stream << termcolor::red; break; 54 | case Color::Green: m_stream << termcolor::green; break; 55 | case Color::Yellow: m_stream << termcolor::yellow; break; 56 | case Color::Blue: m_stream << termcolor::blue; break; 57 | case Color::Magenta: m_stream << termcolor::magenta; break; 58 | case Color::Cyan: m_stream << termcolor::cyan; break; 59 | case Color::White: m_stream << termcolor::white; break; 60 | } 61 | } 62 | 63 | void set_bg_color(Color color) { 64 | switch (color) { 65 | case Color::Grey: m_stream << termcolor::on_grey; break; 66 | case Color::Red: m_stream << termcolor::on_red; break; 67 | case Color::Green: m_stream << termcolor::on_green; break; 68 | case Color::Yellow: m_stream << termcolor::on_yellow << termcolor::grey; break; 69 | case Color::Blue: m_stream << termcolor::on_blue; break; 70 | case Color::Magenta: m_stream << termcolor::on_magenta; break; 71 | case Color::Cyan: m_stream << termcolor::on_cyan; break; 72 | case Color::White: m_stream << termcolor::on_white << termcolor::grey; break; 73 | } 74 | } 75 | 76 | void reset_color() { 77 | m_stream << termcolor::reset; 78 | } 79 | 80 | template 81 | ColorWriter& operator<<(T&& v) { 82 | m_stream << v; 83 | return *this; 84 | } 85 | 86 | template 87 | void fg(Color color, Args&&... params) { 88 | set_fg_color(color); 89 | ((m_stream << std::forward(params)), ...); 90 | reset_color(); 91 | } 92 | 93 | template 94 | void bg(Color color, Args&&... params) { 95 | set_bg_color(color); 96 | ((m_stream << std::forward(params)), ...); 97 | reset_color(); 98 | } 99 | 100 | private: 101 | std::ostream& m_stream; 102 | }; 103 | 104 | } // namespace charly::utils 105 | -------------------------------------------------------------------------------- /test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KCreate/charly-vm/b3dabc25954d5f34660281ca3f634aa7252b8b42/test/.gitkeep -------------------------------------------------------------------------------- /test/charly/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KCreate/charly-vm/b3dabc25954d5f34660281ca3f634aa7252b8b42/test/charly/.gitkeep -------------------------------------------------------------------------------- /test/charly/assertion.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | import { assert_throws, assert_no_exception } from unittest 28 | 29 | export class AssertionTest { 30 | static func test_assert { 31 | assert assert_throws(->{ 32 | let a = false 33 | assert a 34 | }).message == "Failed assertion" 35 | 36 | assert assert_throws(->{ 37 | let a = 0 38 | assert a 39 | }).message == "Failed assertion" 40 | 41 | assert assert_throws(->{ 42 | let a = null 43 | assert a 44 | }).message == "Failed assertion" 45 | } 46 | 47 | static func test_assert_comparison { 48 | assert assert_throws(->{ 49 | assert 100 == 200 50 | }).message == "Failed assertion (100 == 200)" 51 | 52 | assert assert_throws(->{ 53 | assert 100 > 150 54 | }).message == "Failed assertion (100 > 150)" 55 | 56 | assert assert_throws(->{ 57 | assert 100 != 100 58 | }).message == "Failed assertion (100 != 100)" 59 | } 60 | 61 | static func test_assert_message { 62 | assert assert_throws(->{ 63 | assert false : "some error" 64 | }).message == "some error" 65 | } 66 | 67 | static func test_assert_comparison_message { 68 | assert assert_throws(->{ 69 | assert 100 == 200 : "some error" 70 | }).message == "some error (100 == 200)" 71 | 72 | assert assert_throws(->{ 73 | assert 100 > 150 : "some error" 74 | }).message == "some error (100 > 150)" 75 | 76 | assert assert_throws(->{ 77 | assert 100 != 100 : "some error" 78 | }).message == "some error (100 != 100)" 79 | } 80 | 81 | static func test_assert_exception_components { 82 | const (value) = assert_throws(->assert null).components 83 | assert value == null 84 | } 85 | 86 | static func test_assert_comparison_exception_components { 87 | const (left, op, right) = assert_throws(->assert 100 == 200).components 88 | assert left == 100 89 | assert op == "==" 90 | assert right == 200 91 | } 92 | } 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /test/charly/fiber.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | import { assert_throws, assert_no_exception } from unittest 28 | 29 | export class FiberTest { 30 | static func test_fiber { 31 | const a = spawn { 32 | return 100 33 | } 34 | 35 | const b = spawn { 36 | return await a + 100 37 | } 38 | 39 | const c = spawn { 40 | return await b + 100 41 | } 42 | 43 | assert await c == 300 44 | } 45 | 46 | static func test_fiber_throw { 47 | const a = spawn { 48 | throw "some error" 49 | } 50 | 51 | const b = spawn { 52 | await a 53 | } 54 | 55 | const c = spawn { 56 | await b 57 | } 58 | 59 | assert assert_throws(->await a).message == "some error" 60 | assert assert_throws(->await b).message == "some error" 61 | assert assert_throws(->await c).message == "some error" 62 | 63 | assert assert_throws(->await a).message == "some error" 64 | assert assert_throws(->await b).message == "some error" 65 | assert assert_throws(->await c).message == "some error" 66 | } 67 | 68 | static func test_fiber_spawn_call { 69 | let mem = [] 70 | func add(x) = mem.push(x) 71 | 72 | class A { 73 | property mem = [] 74 | func add(value) = mem.push(value) 75 | } 76 | 77 | const a = A() 78 | 79 | const tasks = [ 80 | spawn add(2), 81 | spawn add(2), 82 | spawn add(2), 83 | spawn add(2), 84 | spawn a.add(8), 85 | spawn a.add(8), 86 | spawn a.add(8), 87 | spawn a.add(8) 88 | ] 89 | 90 | tasks.each(->(t) await t) 91 | 92 | mem = mem.reduce(0, ->(p, n) p + n) 93 | a.mem = a.mem.reduce(0, ->(p, n) p + n) 94 | 95 | assert mem == 8 96 | assert a.mem == 32 97 | } 98 | 99 | static func test_fiber_await_same_multiple_times { 100 | const fut = Future.create() 101 | 102 | const a = spawn await fut 103 | 104 | const tasks = [ 105 | spawn await a, 106 | spawn await a, 107 | spawn await a, 108 | spawn await a 109 | ] 110 | 111 | spawn { 112 | fut.resolve("done") 113 | } 114 | 115 | const r = tasks.map(->(t) await t) 116 | 117 | assert r.length == 4 118 | assert r == ["done", "done", "done", "done"] 119 | } 120 | 121 | static func test_fiber_current { 122 | const n = 1000 123 | func foo = Fiber.current() 124 | 125 | const tasks = List.create_with(n, ->(i) spawn foo()) 126 | const results = tasks.map(->(t) await t) 127 | 128 | assert tasks == results 129 | } 130 | } 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /test/charly/future.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | import { assert_throws, assert_no_exception } from unittest 28 | 29 | export class FutureTest { 30 | static func test_future_with_callback { 31 | const f = Future.create(->{ 32 | return 100 33 | }) 34 | 35 | assert await f == 100 36 | 37 | const g = Future.create(->{ 38 | throw "some error" 39 | }) 40 | 41 | assert assert_throws(->await g).message == "some error" 42 | } 43 | 44 | static func test_future_without_callback { 45 | const f = Future.create() 46 | const g = Future.create() 47 | const h = Future.create() 48 | 49 | const i = Future.create(->{ 50 | f.resolve("f done") 51 | g.resolve("g done") 52 | h.resolve("h done") 53 | 54 | throw "error" 55 | }) 56 | 57 | assert await f == "f done" 58 | assert await g == "g done" 59 | assert await h == "h done" 60 | 61 | assert assert_throws(->await i).message == "error" 62 | } 63 | 64 | static func test_future_reject { 65 | const a = Future.create() 66 | a.reject("hello world") 67 | assert assert_throws(->await a).message == "hello world" 68 | 69 | const b = Future.create() 70 | b.reject(Exception("other error")) 71 | assert assert_throws(->await b).message == "other error" 72 | 73 | const c = Future.create() 74 | c.reject(100) 75 | assert assert_throws(->await c).message == "Expected thrown value to be an exception or a string" 76 | } 77 | 78 | static func test_future_resolve_reject_again { 79 | const a = Future.create() 80 | a.resolve(100) 81 | assert await a == 100 82 | assert assert_throws(->a.resolve(200)).message == "Future has already completed" 83 | assert assert_throws(->a.reject("error")).message == "Future has already completed" 84 | assert await a == 100 85 | 86 | const b = Future.create() 87 | b.reject("error") 88 | assert assert_throws(->await b).message == "error" 89 | assert assert_throws(->b.resolve(200)).message == "Future has already completed" 90 | assert assert_throws(->b.reject("other error")).message == "Future has already completed" 91 | assert assert_throws(->await b).message == "error" 92 | } 93 | 94 | static func test_future_await_multiple_resolved { 95 | const a = Future.create() 96 | 97 | const tasks = Tuple.create_with(100, ->spawn await a) 98 | 99 | a.resolve(1) 100 | 101 | const sum = tasks.reduce(0, ->(p, n) p + await n) 102 | 103 | assert sum == 100 104 | } 105 | 106 | static func test_future_await_multiple_rejected { 107 | const a = Future.create() 108 | 109 | let n = 100 110 | 111 | const tasks = Tuple.create_with(n, ->spawn await a) 112 | 113 | a.reject("a") 114 | 115 | const exceptions = tasks.map(->(task) { 116 | try await task catch(e) { 117 | return e 118 | } 119 | }) 120 | 121 | assert exceptions.length == n 122 | assert exceptions[0].message = "a" 123 | assert exceptions[n / 2].message = "a" 124 | assert exceptions[n - 1].message = "a" 125 | } 126 | } 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /test/charly/globals.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | import { assert_throws } from unittest 28 | 29 | export class GlobalsTest { 30 | static func test_globals_argv { 31 | assert ARGV.length == 4 32 | assert ARGV[1] == "foo" 33 | assert ARGV[2] == "bar" 34 | assert ARGV[3] == "baz" 35 | } 36 | 37 | static func test_globals_charly_stdlib_path { 38 | assert CHARLY_STDLIB instanceof String 39 | assert CHARLY_STDLIB.begins_with("/") 40 | } 41 | 42 | static func test_builtin_types { 43 | assert Value instanceof Class 44 | assert Number instanceof Class 45 | assert Int instanceof Class 46 | assert Float instanceof Class 47 | assert Bool instanceof Class 48 | assert Symbol instanceof Class 49 | assert Null instanceof Class 50 | assert String instanceof Class 51 | assert Bytes instanceof Class 52 | assert Tuple instanceof Class 53 | assert List instanceof Class 54 | assert Instance instanceof Class 55 | assert Class instanceof Class 56 | assert Shape instanceof Class 57 | assert Function instanceof Class 58 | assert BuiltinFunction instanceof Class 59 | assert Fiber instanceof Class 60 | assert Future instanceof Class 61 | assert Exception instanceof Class 62 | assert ImportException instanceof Class 63 | assert AssertionException instanceof Class 64 | } 65 | 66 | static func test_builtin_functions { 67 | assert write instanceof Function 68 | assert print instanceof Function 69 | assert prompt instanceof Function 70 | assert exit instanceof Function 71 | assert sleep instanceof Function 72 | } 73 | } 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /test/charly/import-test/compiler-error.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | const a 28 | export a 29 | -------------------------------------------------------------------------------- /test/charly/import-test/import-test-throws.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | throw "some import error" 28 | -------------------------------------------------------------------------------- /test/charly/import-test/not-readable.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | export 100 28 | -------------------------------------------------------------------------------- /test/charly/import.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | import { assert_throws } from unittest 28 | 29 | export class ImportTest { 30 | static func test_import { 31 | import testlib 32 | assert testlib instanceof Class 33 | assert testlib.name == "TestLib" 34 | } 35 | 36 | static func test_import_as { 37 | import testlib as alias 38 | assert testlib instanceof Class 39 | assert testlib.name == "TestLib" 40 | assert alias instanceof Class 41 | assert alias.name == "TestLib" 42 | } 43 | 44 | static func test_import_extract_fields { 45 | import { foo, bar, baz } from testlib 46 | assert foo == 100 47 | assert bar == 200 48 | assert baz == 300 49 | assert testlib instanceof Class 50 | assert testlib.name == "TestLib" 51 | } 52 | 53 | static func test_import_declare_as_name { 54 | import { do_foo, do_bar, do_baz } from testlib as alias 55 | assert testlib instanceof Class 56 | assert testlib.name == "TestLib" 57 | assert alias instanceof Class 58 | assert alias.name == "TestLib" 59 | assert do_foo() == "foo" 60 | assert do_bar() == "bar" 61 | assert do_baz() == "baz" 62 | } 63 | 64 | static func test_import_multiple_times { 65 | import "testlib" as tlib1 66 | import "testlib" as tlib2 67 | import testlib as tlib3 68 | 69 | assert testlib instanceof Class 70 | assert testlib.name == "TestLib" 71 | 72 | assert tlib1 == testlib 73 | assert tlib2 == testlib 74 | assert tlib3 == testlib 75 | } 76 | 77 | static func test_import_file_not_found { 78 | const exc = assert_throws(->{ 79 | import "import-test/does-not-exist.ch" 80 | }) 81 | assert exc.message == "Could not resolve 'import-test/does-not-exist.ch' to a valid path" 82 | } 83 | 84 | static func test_import_exception_in_module { 85 | const exc = assert_throws(->{ 86 | import "import-test/import-test-throws.ch" 87 | }) 88 | assert exc.message == "some import error" 89 | } 90 | 91 | static func test_import_compilation_error { 92 | const exc = assert_throws(->{ 93 | import "import-test/compiler-error.ch" 94 | }) 95 | assert exc.message.begins_with("Encountered an error while importing") 96 | } 97 | } 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /test/charly/test.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | import unittest 28 | 29 | unittest.set_repeat_time(1) 30 | 31 | const status = unittest.run( 32 | import "./number.ch", 33 | import "./string.ch", 34 | import "./list.ch", 35 | import "./tuple.ch", 36 | import "./function.ch", 37 | import "./exception.ch", 38 | import "./truthyness.ch", 39 | import "./control-structures.ch", 40 | import "./typeof-instanceof.ch", 41 | import "./class.ch", 42 | import "./fiber.ch", 43 | import "./future.ch", 44 | import "./assertion.ch", 45 | import "./import.ch", 46 | import "./globals.ch" 47 | ) 48 | 49 | exit(status) 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /test/charly/testlib.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | export class TestLib { 28 | static property foo = 100 29 | static property bar = 200 30 | static property baz = 300 31 | 32 | static func do_foo = "foo" 33 | static func do_bar = "bar" 34 | static func do_baz = "baz" 35 | } 36 | -------------------------------------------------------------------------------- /test/charly/truthyness.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | export class TruthynessTest { 28 | static func test_truthyness { 29 | assert !!null == false 30 | assert !!false == false 31 | assert !!NaN == false 32 | assert !!0 == false 33 | assert !!0.0 == false 34 | 35 | assert !!true == true 36 | assert !!100 == true 37 | assert !!192.168 == true 38 | assert !!"" == true 39 | assert !!"hi" == true 40 | assert !!"hello world this is a test" == true 41 | assert !!() == true 42 | assert !!(100, 200) == true 43 | assert !![100, 200] == true 44 | assert !!(func foo {}) == true 45 | assert !!(->{}) == true 46 | assert !!(class Foo {}) == true 47 | assert !!(class Foo {})() == true 48 | assert !!(builtin_exit) == true 49 | assert !!(Exception("test exception")) == true 50 | } 51 | } 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /test/charly/typeof-instanceof.ch: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | import { assert_throws } from unittest 28 | 29 | export class TypeofInstanceofTest { 30 | static func test_type_builtin_types { 31 | assert typeof 25 == Int 32 | assert typeof 25.25 == Float 33 | assert typeof NaN == Float 34 | assert typeof Infinity == Float 35 | assert typeof true == Bool 36 | assert typeof false == Bool 37 | assert typeof null == Null 38 | assert typeof "" == String 39 | assert typeof "test" == String 40 | assert typeof "hello world" == String 41 | assert typeof print.name == String 42 | assert typeof builtin_exit.name == String 43 | assert typeof (class A {}).name == String 44 | assert typeof () == Tuple 45 | assert typeof (1,) == Tuple 46 | assert typeof (1, 2, 3) == Tuple 47 | assert typeof [] == List 48 | assert typeof [1] == List 49 | assert typeof [1, 2, 3] == List 50 | assert typeof Future.create() == Future 51 | assert typeof spawn {} == Fiber 52 | assert typeof ->{} == Function 53 | assert typeof builtin_exit == BuiltinFunction 54 | } 55 | 56 | static func test_type_user_types { 57 | assert typeof Exception("error") == Exception 58 | assert typeof assert_throws(->assert false : "test") == AssertionException 59 | 60 | class A {} 61 | class B extends A {} 62 | class C extends B {} 63 | 64 | const a = A() 65 | const b = B() 66 | const c = C() 67 | 68 | assert typeof a == A 69 | assert typeof b == B 70 | assert typeof c == C 71 | 72 | assert typeof a != B 73 | assert typeof a != C 74 | assert typeof b != A 75 | assert typeof b != C 76 | assert typeof c != A 77 | assert typeof c != B 78 | } 79 | 80 | static func test_type_instanceof { 81 | class A {} 82 | class B extends A {} 83 | class C extends B {} 84 | 85 | const a = A() 86 | const b = B() 87 | const c = C() 88 | 89 | assert a instanceof A 90 | assert b instanceof A 91 | assert c instanceof A 92 | 93 | assert a instanceof B == false 94 | assert b instanceof B 95 | assert c instanceof B 96 | 97 | assert a instanceof C == false 98 | assert b instanceof C == false 99 | assert c instanceof C 100 | 101 | assert 25 instanceof Number 102 | assert 25.25 instanceof Number 103 | assert "test" instanceof String 104 | assert null instanceof Null 105 | assert Exception instanceof Value 106 | } 107 | 108 | static func test_type_instanceof_not_a_class_exception { 109 | const exc1 = assert_throws(->100 instanceof 100) 110 | assert exc1.message == "Expected right hand side of instanceof to be a class, got 'Int'" 111 | 112 | class A {} 113 | const exc2 = assert_throws(->100 instanceof A()) 114 | assert exc2.message == "Expected right hand side of instanceof to be a class, got 'A'" 115 | } 116 | } 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /test/runtime/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KCreate/charly-vm/b3dabc25954d5f34660281ca3f634aa7252b8b42/test/runtime/.gitkeep -------------------------------------------------------------------------------- /test/runtime/core/compiler/diagnostic.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "charly/utils/buffer.h" 30 | 31 | #include "charly/core/compiler/compiler.h" 32 | 33 | using Catch::Matchers::Equals; 34 | 35 | using namespace charly; 36 | using namespace charly::core::compiler; 37 | 38 | CATCH_TEST_CASE("Diagnostic") { 39 | CATCH_SECTION("formats errors") { 40 | utils::Buffer buffer("foo,"); 41 | auto unit = Compiler::compile("test", buffer); 42 | 43 | CATCH_REQUIRE(unit->console.messages().size() == 1); 44 | 45 | utils::Buffer out; 46 | unit->console.dump_all(out); 47 | 48 | CATCH_CHECK_THAT(out.str(), Equals(("test:1:4: error: unexpected ',' token, expected an expression\n" 49 | " -> 1 | foo,\n"))); 50 | } 51 | 52 | CATCH_SECTION("formats messages without a location") { 53 | utils::Buffer buffer(""); 54 | DiagnosticConsole console("test", buffer); 55 | 56 | console.info(Location{ .valid = false }, "foo"); 57 | console.warning(Location{ .valid = false }, "bar"); 58 | console.error(Location{ .valid = false }, "baz"); 59 | 60 | CATCH_REQUIRE(console.messages().size() == 3); 61 | 62 | utils::Buffer out; 63 | console.dump_all(out); 64 | 65 | CATCH_CHECK_THAT(out.str(), Equals(("test: info: foo\n\n" 66 | "test: warning: bar\n\n" 67 | "test: error: baz\n"))); 68 | } 69 | 70 | CATCH_SECTION("formats multiple lines") { 71 | utils::Buffer buffer("\n\n(25 25)\n\n"); 72 | auto unit = Compiler::compile("test", buffer); 73 | 74 | CATCH_REQUIRE(unit->console.messages().size() == 1); 75 | 76 | utils::Buffer out; 77 | unit->console.dump_all(out); 78 | 79 | CATCH_CHECK_THAT(out.str(), Equals(("test:3:10: error: unexpected numerical constant, expected a ')' token\n" 80 | " 1 | \n" 81 | " 2 | \n" 82 | " -> 3 | (25 25)\n" 83 | " 4 | \n" 84 | " 5 | \n"))); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /test/runtime/core/compiler/module.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "charly/utils/buffer.h" 30 | 31 | #include "charly/core/compiler/compiler.h" 32 | 33 | using namespace charly; 34 | using namespace charly::utils; 35 | using namespace charly::core::compiler; 36 | 37 | CATCH_TEST_CASE("Compiled Module") { 38 | CATCH_SECTION("ir info") { 39 | auto source_string = "let a = 0 let b = a + 5 foo(->(a) a + b)"; 40 | utils::Buffer source_buffer(source_string); 41 | auto unit = Compiler::compile("test", source_buffer, CompilationUnit::Type::Module); 42 | auto module = unit->compiled_module; 43 | 44 | CATCH_CHECK(module); 45 | 46 | CATCH_CHECK(module->filename == "test"); 47 | 48 | CATCH_CHECK(module->function_table.size() == 2); 49 | auto main = module->function_table.at(0); 50 | CATCH_CHECK(main->name == "main"); 51 | CATCH_CHECK(main->ir_info.valid); 52 | CATCH_CHECK(main->ir_info.stacksize == 3); 53 | CATCH_CHECK(main->ir_info.local_variables == 1); 54 | CATCH_CHECK(main->ir_info.heap_variables == 1); 55 | CATCH_CHECK(main->ir_info.argc == 0); 56 | CATCH_CHECK(main->ir_info.minargc == 0); 57 | CATCH_CHECK(main->ir_info.spread_argument == false); 58 | CATCH_CHECK(main->ir_info.arrow_function == false); 59 | CATCH_CHECK(main->string_table.size() == 2); 60 | CATCH_CHECK(main->string_table.at(0).value == "main"); 61 | CATCH_CHECK(main->string_table.at(1).value == "foo"); 62 | 63 | auto anon = module->function_table.at(1); 64 | CATCH_CHECK(anon->name == "anonymous"); 65 | CATCH_CHECK(anon->ir_info.valid); 66 | CATCH_CHECK(anon->ir_info.stacksize == 2); 67 | CATCH_CHECK(anon->ir_info.local_variables == 1); 68 | CATCH_CHECK(anon->ir_info.heap_variables == 0); 69 | CATCH_CHECK(anon->ir_info.argc == 1); 70 | CATCH_CHECK(anon->ir_info.minargc == 1); 71 | CATCH_CHECK(anon->ir_info.spread_argument == false); 72 | CATCH_CHECK(anon->ir_info.arrow_function == true); 73 | CATCH_CHECK(anon->string_table.size() == 1); 74 | CATCH_CHECK(anon->string_table.at(0).value == "anonymous"); 75 | } 76 | 77 | CATCH_SECTION("exception tables") { 78 | auto source_string = "try { a } catch(e) { foo(e) } try { a } catch(e) { foo(e) }"; 79 | utils::Buffer source_buffer(source_string); 80 | auto unit = Compiler::compile("test", source_buffer, CompilationUnit::Type::Module); 81 | auto module = unit->compiled_module; 82 | 83 | CATCH_CHECK(module); 84 | CATCH_CHECK(module->function_table.size() == 1); 85 | auto func = module->function_table.at(0); 86 | CATCH_CHECK(func->exception_table.size() == 2); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /test/runtime/utils/cast.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "charly/utils/cast.h" 30 | 31 | using namespace charly::utils; 32 | 33 | CATCH_TEST_CASE("Cast") { 34 | CATCH_SECTION("string_to_int") { 35 | // decimals 36 | CATCH_CHECK(string_to_int("0") == 0); 37 | CATCH_CHECK(string_to_int("1") == 1); 38 | CATCH_CHECK(string_to_int("100") == 100); 39 | CATCH_CHECK(string_to_int("-250") == -250); 40 | 41 | // octal 42 | CATCH_CHECK(string_to_int("10", 8) == 8); 43 | CATCH_CHECK(string_to_int("20", 8) == 16); 44 | CATCH_CHECK(string_to_int("40", 8) == 32); 45 | CATCH_CHECK(string_to_int("-20", 8) == -16); 46 | CATCH_CHECK(string_to_int("777", 8) == 511); 47 | 48 | // binary 49 | CATCH_CHECK(string_to_int("0", 2) == 0); 50 | CATCH_CHECK(string_to_int("1", 2) == 1); 51 | CATCH_CHECK(string_to_int("10", 2) == 2); 52 | CATCH_CHECK(string_to_int("100", 2) == 4); 53 | CATCH_CHECK(string_to_int("1000", 2) == 8); 54 | CATCH_CHECK(string_to_int("11111111", 2) == 255); 55 | CATCH_CHECK(string_to_int("-10", 2) == -2); 56 | 57 | // hex 58 | CATCH_CHECK(string_to_int("0", 16) == 0); 59 | CATCH_CHECK(string_to_int("10", 16) == 16); 60 | CATCH_CHECK(string_to_int("20", 16) == 32); 61 | CATCH_CHECK(string_to_int("ff", 16) == 255); 62 | CATCH_CHECK(string_to_int("ffff", 16) == 65535); 63 | CATCH_CHECK(string_to_int("-ff", 16) == -255); 64 | } 65 | 66 | CATCH_SECTION("string_to_double") { 67 | CATCH_CHECK(string_to_double("0.0") == 0.0); 68 | CATCH_CHECK(string_to_double("1.0") == 1.0); 69 | CATCH_CHECK(string_to_double("1.5") == 1.5); 70 | CATCH_CHECK(string_to_double("25.25") == 25.25); 71 | CATCH_CHECK(string_to_double("-25.25") == -25.25); 72 | CATCH_CHECK(string_to_double("0.33333") == 0.33333); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /test/runtime/utils/random_device.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "charly/utils/random_device.h" 30 | 31 | using namespace charly::utils; 32 | 33 | CATCH_TEST_CASE("RandomDevice") { 34 | RandomDevice device; 35 | 36 | size_t a; 37 | size_t b; 38 | 39 | a = device.get(); 40 | b = device.get(); 41 | CATCH_CHECK(a != b); 42 | 43 | a = device.get(); 44 | b = device.get(); 45 | CATCH_CHECK(a != b); 46 | 47 | a = device.get(); 48 | b = device.get(); 49 | CATCH_CHECK(a != b); 50 | 51 | a = device.get(); 52 | b = device.get(); 53 | CATCH_CHECK(a != b); 54 | 55 | a = device.get(); 56 | b = device.get(); 57 | CATCH_CHECK(a != b); 58 | 59 | a = device.get(); 60 | b = device.get(); 61 | CATCH_CHECK(a != b); 62 | 63 | a = device.get(); 64 | b = device.get(); 65 | CATCH_CHECK(a != b); 66 | } 67 | -------------------------------------------------------------------------------- /test/runtime/utils/wait_flag.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Charly Virtual Machine (https://github.com/KCreate/charly-vm) 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 - 2022 Leonard Schütz 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "charly/utils/wait_flag.h" 30 | 31 | using namespace charly::utils; 32 | 33 | CATCH_TEST_CASE("WaitFlag") { 34 | std::mutex mutex; 35 | WaitFlag flag(mutex); 36 | 37 | std::thread other_thread([&] { 38 | CATCH_CHECK(flag.state() == false); 39 | flag.signal(); 40 | CATCH_CHECK(flag.state()); 41 | }); 42 | 43 | flag.wait(); 44 | 45 | other_thread.join(); 46 | 47 | CATCH_CHECK(flag.state()); 48 | 49 | flag.wait(); 50 | flag.wait(); 51 | flag.wait(); 52 | 53 | CATCH_CHECK(flag.state()); 54 | 55 | flag.reset(); 56 | 57 | CATCH_CHECK(flag.state() == false); 58 | } 59 | -------------------------------------------------------------------------------- /tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | red=$(tput setaf 1) 4 | green=$(tput setaf 2) 5 | reset=$(tput sgr0) 6 | 7 | echo_green () { 8 | echo "${green}$*${reset}" 9 | } 10 | 11 | echo_red () { 12 | echo "${red}$*${reset}" 13 | } 14 | 15 | mkdir -p cmake-build-debug 16 | 17 | # setup build files 18 | if ! test -f cmake-build-debug/Makefile; then 19 | cmake -DCMAKE_BUILD_TYPE=Debug -S . -B cmake-build-debug 20 | fi 21 | 22 | # build tests and charly executable in debug and release mode 23 | if ! cmake --build cmake-build-debug --target tests --target charly -j12; then 24 | echo_red "Test build failed!" 25 | exit 1 26 | fi 27 | if ! cmake --build cmake-build-debug --target charly -j12; then 28 | echo_red "Charly build failed!" 29 | exit 1 30 | fi 31 | 32 | # run c++ unit tests 33 | if ! cmake-build-debug/tests; then 34 | echo_red "C++ unit tests failed" 35 | exit 1 36 | fi 37 | 38 | # run charly unit tests in both multi- and single-threaded mode and with/without optimizations 39 | echo_green "Running charly unit tests" 40 | if ! cmake-build-debug/charly test/charly/test.ch foo bar baz; then 41 | echo_red "Charly unit tests failed" 42 | exit 1 43 | fi 44 | 45 | echo_green "Running charly (no optimizations) unit tests" 46 | if ! cmake-build-debug/charly test/charly/test.ch --no_ir_opt --no_ast_opt foo bar baz; then 47 | echo_red "Charly (no optimizations) unit tests failed" 48 | exit 1 49 | fi 50 | 51 | echo_green "Running charly (singlethreaded) unit tests" 52 | if ! cmake-build-debug/charly test/charly/test.ch --maxprocs 1 foo bar baz; then 53 | echo_red "Charly (singlethreaded) unit tests failed" 54 | exit 1 55 | fi 56 | -------------------------------------------------------------------------------- /todos.md: -------------------------------------------------------------------------------- 1 | # Todos --------------------------------------------------------------------------------