diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 905ceaba..6f5479ed 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,13 +21,13 @@ jobs: DIST: 'ce-specific' NAME: 'ce-specific' # - ARCH: 'arm64' - # DIST: 'macos-11' + # DIST: 'macos-13' # NAME: 'darwin' - #- ARCH: 'x86_64' # FIXME: - # DIST: 'macos-11' - # NAME: 'darwin' + - ARCH: 'x86_64' + DIST: 'macos-13' + NAME: 'darwin' # - ARCH: 'arm64' # TODO - # DIST: 'macos-11' + # DIST: 'macos-13' # NAME: 'darwin' name: Build ${{ matrix.NAME }} (${{ matrix.ARCH }}) [${{ matrix.DIST }}] env: @@ -43,6 +43,10 @@ jobs: if [[ "$OSTYPE" != "darwin"* ]]; then docker run --rm --privileged multiarch/qemu-user-static --reset -p yes sudo apt install cmake + else + brew install llvm@16 + brew install gcc + brew install zstd fi - name: Build in Docker @@ -55,6 +59,6 @@ jobs: ls ~/.snowball ls ~/.snowball/stdlib/ - - name: Execute tests - run: | - ./bin/Release/snowball test --no-progress \ No newline at end of file + #- name: Execute tests + # run: | + # ./bin/Release/snowball test --no-progress \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f7470b08..c684adae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,7 @@ if(backtrace_ADDED) "${backtrace_SOURCE_DIR}/simple.c" "${backtrace_SOURCE_DIR}/sort.c" "${backtrace_SOURCE_DIR}/state.c") + set(backtrace_INCLUDE_DIRS "${backtrace_SOURCE_DIR}") # https://go.googlesource.com/gollvm/+/refs/heads/master/cmake/modules/LibbacktraceUtils.cmake set(BACKTRACE_SUPPORTED 1) @@ -131,14 +132,11 @@ if(backtrace_ADDED) endif() CPMAddPackage( - NAME sigsegv - GIT_REPOSITORY "https://git.savannah.gnu.org/git/libsigsegv.git" - GIT_TAG "v2.14" + NAME zstd + GIT_REPOSITORY "https://github.com/facebook/zstd.git" + GIT_TAG "v1.5.5" DOWNLOAD_ONLY YES) -if(sigsegv_ADDED) - if (APPLE) - message(STATUS "TODO: add sigsegv to the build") - endif() +if(zstd_ADDED) endif() message(STATUS ${LLVM_DEFINITIONS}) @@ -212,12 +210,9 @@ else() endif() #add_dependencies(snowballrt backtrace sigsegv) -target_include_directories(snowballrt PRIVATE ${backtrace_SOURCE_DIR} ${sigsegv_SOURCE_DIR}) -if(APPLE) - target_link_libraries(snowballrt PRIVATE zstd backtrace) -else() - target_link_libraries(snowballrt PRIVATE zstd backtrace sigsegv) -endif() +target_include_directories(snowballrt PRIVATE ${backtrace_SOURCE_DIR}) +target_link_libraries(snowballrt PRIVATE backtrace) +target_include_directories(snowballrt PRIVATE ${backtrace_INCLUDE_DIRS}) if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") message(STATUS "Changing rpath origin destination (for macos)") @@ -291,7 +286,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC $ $ $ PRIVATE source) - target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS} ${PROJECT_INCLUDE_DIRS}) + target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS} ${PROJECT_INCLUDE_DIRS} ${backtrace_INCLUDE_DIRS}) target_link_libraries (${PROJECT_NAME} PUBLIC ${llvm_libs} ${GLIB_LIBRARIES} ${llvm_libraries} ${targets} ${PROJECT_LIBRARIES} snowballrt) target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_COMPILE_DEFINITIONS}) diff --git a/README.md b/README.md index bfbced97..69d143bf 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Explore the docs »

- Website · Report Bug · Request Feature + Website · Report Bug · Request Feature


@@ -54,11 +54,8 @@ sudo make install -j100 First, you will need a new snowball project. For that, create a new directory and execute the following command: -``` -mkdir myProject -cd myProject - -snowball init +```sh +snowball new --name myProject ``` ### Executing snowball code diff --git a/app/commands/init.h b/app/commands/init.h index 8d4451c7..03564ee1 100644 --- a/app/commands/init.h +++ b/app/commands/init.h @@ -47,7 +47,7 @@ namespace commands { void init_create_cfg(bool yes, std::string entry, app::Options::InitOptions p_opts) { std::ofstream outfile(CONFIGURATION_FILE); - std::string version = "1.0.0"; + std::string version = "0.0.1"; // TODO: ask questions if p_opts.yes is false std::string toml_result; @@ -61,7 +61,7 @@ void init_create_cfg(bool yes, std::string entry, app::Options::InitOptions p_op outfile << toml.str() << std::endl; outfile.close(); - Logger::message("Configuration", FMT("created configuration file (%s)", CONFIGURATION_FILE)); + Logger::message("Configuration", FMT("Configured project file (%s)", CONFIGURATION_FILE)); } // TODO: Output messages @@ -69,7 +69,7 @@ int init(app::Options::InitOptions p_opts) { auto start = high_resolution_clock::now(); if (p_opts.create_dir) { - Logger::message("Creating", FMT("creating snowball project directory (%s)", p_opts.name.c_str())); + Logger::message("Creating", FMT("Snowball project at directory %s", p_opts.name.c_str())); if (!fs::exists(p_opts.name)) fs::create_directory(p_opts.name); fs::current_path(p_opts.name); } @@ -82,11 +82,11 @@ int init(app::Options::InitOptions p_opts) { std::getline(std::cin, answer); if (answer != "y" && answer != "Y") { - Logger::message("Aborted", "snowball project creation"); + Logger::message("Aborted", "Snowball project creation"); return 0; } - Logger::message("Deleting", "deleting all files in the current directory"); + Logger::message("Deleting", "All files in the current directory"); for (auto &p : fs::directory_iterator(fs::current_path())) { fs::remove_all(p); } @@ -96,7 +96,7 @@ int init(app::Options::InitOptions p_opts) { init_create_cfg(p_opts.yes, EXECUTABLE_ENTRY, p_opts); return 0; } else if (p_opts.lib) { - Logger::message("Initalizing", FMT("creating snowball project [library]", CONFIGURATION_FILE)); + Logger::message("Initalizing", FMT("Current project [library]", CONFIGURATION_FILE)); Logger::warning("Library example is not yet supported by " "current snowball!"); @@ -108,7 +108,7 @@ int init(app::Options::InitOptions p_opts) { outfile << LIBRARY_MAIN << std::endl; outfile.close(); } else { - Logger::message("Initalizing", FMT("creating snowball project [executable]", CONFIGURATION_FILE)); + Logger::message("Initalizing", FMT("Current project [executable]", CONFIGURATION_FILE)); if (!fs::exists("src")) fs::create_directory("src"); if (!p_opts.skip_cfg) init_create_cfg(p_opts.yes, EXECUTABLE_ENTRY, p_opts); diff --git a/build_scripts/release_build.sh b/build_scripts/release_build.sh index 1f09cb62..f18d3f59 100644 --- a/build_scripts/release_build.sh +++ b/build_scripts/release_build.sh @@ -36,6 +36,7 @@ if [[ "$OSTYPE" == "darwin"* ]]; then else brew install llvm@16 brew install gcc + brew install zstd fi export LLVM_DIR="/usr/local/opt/llvm@16/lib/cmake" diff --git a/runtime/libs/backtrace.cc b/runtime/libs/backtrace.cc index fed9dfba..8c1804cd 100644 --- a/runtime/libs/backtrace.cc +++ b/runtime/libs/backtrace.cc @@ -1,5 +1,5 @@ -#include "backtrace.h" +#include "backtracing.h" #include "runtime.h" namespace snowball { @@ -60,36 +60,37 @@ void print_backtrace(Backtrace backtrace, std::ostringstream &oss) { if (!(snowball::snowball_flags & SNOWBALL_FLAG_DEBUG)) return; - if (getenv("SN_BACKTRACE") == NULL) { - oss << "\n\e[1;37mnote:\e[0m run with \e[1;37m`SN_BACKTRACE=1`\e[0m environment variable to get a backtrace"; - return; - } + if (getenv("SN_BACKTRACE") == NULL) { + oss << "\n\e[1;37mnote:\e[0m run with \e[1;37m`SN_BACKTRACE=1`\e[0m environment variable to get a backtrace"; + return; + } - oss << "\n"; - oss << "\n\033[1mBacktrace (most recent call first):\033[0m\n"; + oss << "\n"; + oss << "\n\033[1mBacktrace (most recent call first):\033[0m\n"; - if (backtrace.frame_count <= 1) { - oss << " (no backtrace available)\n"; - return; - } - - for (int i = 1; i < backtrace.frame_count; i++) { - BacktraceFrame frame = backtrace.frames[i]; - if (!frame.function || !frame.filename) { - oss << " (#" << i << "): \e[1;30m[" << (void*)frame.address << "]\e[0m - ????\n"; - continue; - } - // TODO: demangle function names - oss << " (#" << i << "): \e[1;30m[" << (void*)frame.address << "]\e[0m - " << frame.function << "\n"; - oss << "\t\tat \e[1;32m" << frame.filename << "\e[1;36m:" << frame.lineno << "\e[0m\n"; - } + if (backtrace.frame_count <= 1) { + oss << " (no backtrace available)\n"; + return; + } + + for (int i = 1; i < backtrace.frame_count; i++) { + BacktraceFrame frame = backtrace.frames[i]; + if (!frame.function || !frame.filename) { + oss << " (#" << i << "): \e[1;30m[" << (void*)frame.address << "]\e[0m - ????\n"; + continue; + } + // TODO: demangle function names + oss << " (#" << i << "): \e[1;30m[" << (void*)frame.address << "]\e[0m - " << frame.function << "\n"; + oss << "\t\tat \e[1;32m" << frame.filename << "\e[1;36m:" << frame.lineno << "\e[0m\n"; + } - oss << "\e[0m\n"; - //backtrace.pls_free(); + oss << "\e[0m\n"; + //backtrace.pls_free(); } void get_backtrace(Backtrace &backtrace) { if (!(snowball::snowball_flags & SNOWBALL_FLAG_DEBUG)) { + backtrace = Backtrace(); return; } diff --git a/runtime/libs/backtrace.h b/runtime/libs/backtracing.h similarity index 100% rename from runtime/libs/backtrace.h rename to runtime/libs/backtracing.h diff --git a/runtime/libs/exceptions.cc b/runtime/libs/exceptions.cc index 6f274aa3..eee5c8ea 100644 --- a/runtime/libs/exceptions.cc +++ b/runtime/libs/exceptions.cc @@ -625,7 +625,6 @@ void end_stack(void* exep) { } else { buf << "\033[0m"; } - print_backtrace(base->backtrace, buf); buf << "\n\n"; diff --git a/runtime/libs/exceptions.h b/runtime/libs/exceptions.h index dd64b8c0..66642f15 100644 --- a/runtime/libs/exceptions.h +++ b/runtime/libs/exceptions.h @@ -2,7 +2,7 @@ #ifndef _SNOWBALL_RUNTIME_EXCEPTIONS_H_ #define _SNOWBALL_RUNTIME_EXCEPTIONS_H_ -#include "backtrace.h" +#include "backtracing.h" namespace snowball { uint64_t exception_class(); diff --git a/runtime/libs/segfault.cc b/runtime/libs/segfault.cc index 86d7f7ea..cbe6e8c1 100644 --- a/runtime/libs/segfault.cc +++ b/runtime/libs/segfault.cc @@ -3,16 +3,18 @@ // TODO: Add support for macOS. #include "runtime.h" -#include "backtrace.h" - -#include +#include "backtracing.h" +#include +#include +#include +#include namespace snowball { -int segfault_handler(void *fault_address, int serious) { +void segfault_handler(int signal, siginfo_t *fault_info, void *arg) { std::ostringstream buf; error_log(buf, "Segmentation fault"); - buf << ": \033[0mSegmentation fault at address \e[1;37m" << std::hex << (void*)fault_address << std::dec << "\e[0m"; + buf << ": \033[0mSegmentation fault at address \e[1;37m" << std::hex << (void*)fault_info->si_addr << std::dec << "\e[0m"; Backtrace base; get_backtrace(base); @@ -24,11 +26,17 @@ int segfault_handler(void *fault_address, int serious) { fwrite(output.data(), 1, output.size(), stderr); exit(1); - return 0; } void initialize_segfault_handler() { - sigsegv_install_handler(&segfault_handler); + struct sigaction sa; + + memset(&sa, 0, sizeof(struct sigaction)); + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = segfault_handler; + sa.sa_flags = SA_SIGINFO; + + sigaction(SIGSEGV, &sa, NULL); // TODO: buffer overflow, etc... } } diff --git a/scripts/install.sh b/scripts/install.sh index bb07c8d6..59771783 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -213,10 +213,11 @@ log info "Updating configuration file" update_config_file "$shell" -printf "\n ${green}snowball-${OS}-${ARCH}${normal} - successfully installed with stdlib\n\n" +printf "\n ${green}snowball-${OS}-${ARCH}${normal} - successfully installed with runtime included\n" +printf " ${green}snowball-stdlib${normal} - standard library for snowball\n\n" log info "Snowball successfully installed at: $(pwd)" log info "Snowball is ready to use! type: \`snowball --help\` to check that it works." -echo "" +echo "\n===================== GREAT! =====================\n" log info "Checkoutt the documentation at: https://snowball-lang.gitbook.io/docs/fundamentals/hello-world" log info "Happy coding! 🐱" diff --git a/snowball.version.id b/snowball.version.id index 88f28d3b..d8ff0b9b 100644 --- a/snowball.version.id +++ b/snowball.version.id @@ -1 +1 @@ -0x000008 \ No newline at end of file +0x000009 \ No newline at end of file diff --git a/snowball.version.str b/snowball.version.str index 7d6b3eb3..429d94ae 100644 --- a/snowball.version.str +++ b/snowball.version.str @@ -1 +1 @@ -0.0.8 \ No newline at end of file +0.0.9 \ No newline at end of file diff --git a/src/ast/cache/FunctionCache.cc b/src/ast/cache/FunctionCache.cc index 52f0d016..dafd2289 100644 --- a/src/ast/cache/FunctionCache.cc +++ b/src/ast/cache/FunctionCache.cc @@ -85,6 +85,11 @@ void Functions::performInheritance(types::DefinedType* ty, types::DefinedType* p for (auto fn : functions) { setFunction(name, fn.function, fn.state); } } + for (auto f : parent->getFields()) { + ty->addField(f); + } + ty->hasVtable = parent->hasVtable; + return; } diff --git a/src/ast/types/DefinedType.cc b/src/ast/types/DefinedType.cc index 3b17b1c3..956a0ec3 100644 --- a/src/ast/types/DefinedType.cc +++ b/src/ast/types/DefinedType.cc @@ -139,11 +139,12 @@ std::int64_t DefinedType::sizeOf() const { address += (typeAlignment - (address % typeAlignment)) % typeAlignment; address += typeSize; } - if (address == 0) address = 1; // prevent 0-sized types auto alignment = alignmentOf(); address += (address - (address % alignment)) % alignment; address += (alignment - (address % alignment)) % alignment; - return address + (hasVtable * 8); + address += (hasVtable * 8); + if (address == 0) address = 1; // prevent 0-sized types + return address; } std::int64_t DefinedType::alignmentOf() const { diff --git a/src/builder/linker/macos/ld.cc b/src/builder/linker/macos/ld.cc index 307b6cd9..be878412 100644 --- a/src/builder/linker/macos/ld.cc +++ b/src/builder/linker/macos/ld.cc @@ -51,7 +51,6 @@ void Linker::constructLinkerArgs(std::string& input, std::string& output, std::v linkerArgs.push_back("-L/opt/homebrew/lib"); linkerArgs.push_back("-L/usr/local/lib"); linkerArgs.push_back("-L/usr/lib"); - linkerArgs.push_back("-L/opt/homebrew/opt/zstd/lib"); // TODO: we might not find it and we will need to search for System.B linkerArgs.push_back("-lSystem"); diff --git a/src/builder/llvm/initializeVariable.cc b/src/builder/llvm/initializeVariable.cc index b39969dd..89e4eb18 100644 --- a/src/builder/llvm/initializeVariable.cc +++ b/src/builder/llvm/initializeVariable.cc @@ -9,8 +9,8 @@ namespace snowball { namespace codegen { void LLVMBuilder::initializeVariable(llvm::Value* var, llvm::Type* ty, unsigned int size) { - assert(llvm::isa(ty)); - auto llvmType = llvm::cast(ty); + assert(llvm::isa(ty)); + auto llvmType = llvm::cast(ty); auto initializerName = FMT("__const.default.%s", llvmType->getName().str().c_str()); auto constInitializer = module->getNamedGlobal(initializerName); diff --git a/stdlib/map.sn b/stdlib/map.sn index 4760c24c..1d4f4c62 100644 --- a/stdlib/map.sn +++ b/stdlib/map.sn @@ -65,25 +65,6 @@ public: } throw new MapIndexException("Map::get(): key not found inside map!"); } - /** - * Retrieves the value associated with the specified key or a default value if the key is not present. - * @param {K} key - The key to search for. - * @param {V} val - The default value to return if the key is not found. - * @return {&V} A mutable reference to the associated value if the key is present, otherwise the default value. - * @example - * const myMap = new Map(); - * const value = myMap.get_or("foo", 42); // Returns 42 as "foo" is not in the map - * @endexample - */ - func get_or(key: K, val: V) &mut V { - for let i = 0; i < self.size(); i = i + 1 { - let entry = self.table[i]; - if (entry.first == key) { - return entry.second; - } - } - return val; - } /** * Sets the value associated with the specified key. If the key already exists, the value is updated; * otherwise, a new key-value pair is added to the map. diff --git a/tests/lambdas.sn b/tests/lambdas.sn index f60f56fc..dfde71b5 100644 --- a/tests/lambdas.sn +++ b/tests/lambdas.sn @@ -1,4 +1,7 @@ import std::io; +@use_macros +import std::asserts; + namespace test { @@ -101,6 +104,17 @@ func usage_after_lambda() i32 { return x + z; } +@test(expect = 10) +func usage_after_lambda2() i32 { + let mut x = "hello"; + let y = func() i32 { + return x.size(); + }; + let z = y(); + assert!(x == "hello") + return x.size() + z; +} + struct TestStruct { public let x: i32; } diff --git a/tests/main.sn b/tests/main.sn index fa9c5c9a..0dc5e047 100644 --- a/tests/main.sn +++ b/tests/main.sn @@ -34,12 +34,11 @@ import std::io; //import std::io::{ println }; public func main() i32 { - let x = "25"; - + let mut x: String; + x = "awd"; let a = (func() i32 { //io::println(x); io::println(x); })(); - io::println(x); } diff --git a/tests/map.sn b/tests/map.sn index ce8f07f9..cfc09c29 100644 --- a/tests/map.sn +++ b/tests/map.sn @@ -48,15 +48,6 @@ func has() i32 { return true; } -@test -func get_or() i32 { - let mut m = new Map(); - m.set(1, 2); - assert_eq!(m.get_or(1, 3), 2); - assert_eq!(m.get_or(2, 3), 3); - return true; -} - @test(expect = 7) func change() i32 { let mut m = new Map(); diff --git a/tests/string.sn b/tests/string.sn index df759260..0fa1c6d2 100644 --- a/tests/string.sn +++ b/tests/string.sn @@ -75,8 +75,6 @@ func ljust() i32 { func split() i32 { let s = "hello world"; let x = s.split(" "); - io::println(x[0]); - io::println(x[1]); assert!(x[0] == "hello"); assert!(x[1] == "world"); return x.size();