diff --git a/cpp/src/build.cpp b/cpp/src/build.cpp index fbe9f57..9f6c6ec 100644 --- a/cpp/src/build.cpp +++ b/cpp/src/build.cpp @@ -14,6 +14,10 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/TargetParser/Host.h" +#ifdef _WIN32 +#include +#endif + build::info* cur_build_info = nullptr; void set_linkage_type(std::int64_t link_type_value) @@ -43,6 +47,11 @@ void add_link_library(const char* link_library) cur_build_info->link_libraries.push_back(link_library); } +void use_stdlib(std::uint8_t use) +{ + cur_build_info->using_stdlib = use; +} + void install_functions(llvm::ExecutionEngine& exe) { exe.addGlobalMapping("set_linkage_type", reinterpret_cast(&set_linkage_type)); @@ -50,6 +59,35 @@ void install_functions(llvm::ExecutionEngine& exe) exe.addGlobalMapping("set_output_name", reinterpret_cast(&set_output_name)); exe.addGlobalMapping("add_source", reinterpret_cast(&add_source)); exe.addGlobalMapping("add_link_library", reinterpret_cast(&add_link_library)); + exe.addGlobalMapping("use_stdlib", reinterpret_cast(&use_stdlib)); +} + +const char* get_output_extension(build::linkage_type link) +{ + const char* extension = ""; + switch(link) + { + case build::linkage_type::executable: + #ifdef _WIN32 + extension = ".exe"; + #elif defined(__linux__) + extension = ".out"; + #else + static_assert("unknown platform"); + #endif + break; + case build::linkage_type::library: + #ifdef _WIN32 + extension = ".lib"; + #elif defined(__linux__) + extension = ".a"; + #else + static_assert("unknown platform"); + #endif + break; + default: break; + } + return extension; } namespace build @@ -114,13 +152,19 @@ namespace build metaprogram_handle->dropAllReferences(); code::cleanup(); } - #ifdef _WIN32 - ret.link_name += ".exe"; - #elif defined(__linux__) - ret.link_name += ".out"; - #else - static_assert("unknown platform"); - #endif + ret.link_name += get_output_extension(ret.link); + if(ret.using_stdlib) + { + std::string psyc_path; + #ifdef _WIN32 + psyc_path.resize(MAX_PATH); + GetModuleFileNameA(nullptr, psyc_path.data(), psyc_path.size()); + #endif + std::filesystem::path psyc_dir = std::filesystem::path{psyc_path}.parent_path(); + std::filesystem::path stdlib_path = psyc_dir / "stdlib.psy"; + diag::assert_that(std::filesystem::exists(stdlib_path), error_code::buildmeta, "could not find stdlib implementation. expected to find: \"{}\"", stdlib_path.string()); + ret.extra_input_files.push_back(stdlib_path); + } return ret; } @@ -276,6 +320,24 @@ namespace build .is_extern = true } }); + ret.root.children.push_back(ast::node + { + .payload = ast::function_definition + { + .func_name = "use_stdlib", + .params = + { + ast::variable_declaration + { + .var_name = "use", + .type_name = "bool", + .initialiser = ast::expression{.expr = ast::bool_literal{.val = true}} + }, + }, + .ret_type = "u0", + .is_extern = true + } + }); // same with some globals. diff --git a/cpp/src/build.hpp b/cpp/src/build.hpp index ba33229..5fa44b5 100644 --- a/cpp/src/build.hpp +++ b/cpp/src/build.hpp @@ -39,6 +39,7 @@ namespace build linkage_type link = linkage_type::none; config_type config = config_type::debug; std::string link_name = "a"; + bool using_stdlib = true; std::vector extra_input_files = {}; std::vector link_libraries = {}; std::string target_triple; diff --git a/cpp/src/link.cpp b/cpp/src/link.cpp index 1ceffeb..cc98d23 100644 --- a/cpp/src/link.cpp +++ b/cpp/src/link.cpp @@ -160,7 +160,7 @@ namespace linkage } for(std::filesystem::path link_library : binfo.link_libraries) { - cmd += std::format(" {}", link_library.string()); + cmd += std::format(" \"{}\"", link_library.string()); } auto lt = divine_linker_type(binfo.compiler_args.linker_name); @@ -209,7 +209,7 @@ namespace linkage for(std::filesystem::path link_library : binfo.link_libraries) { - cmd += std::format(" {}", link_library.string()); + cmd += std::format(" \"{}\"", link_library.string()); } int ret = std::system(cmd.c_str()); diff --git a/samples/scratchpad.psy b/samples/scratchpad.psy index 471ad35..df3499b 100644 --- a/samples/scratchpad.psy +++ b/samples/scratchpad.psy @@ -1,64 +1,18 @@ -puts :: (str : i8& const) -> u0 := extern; main :: () -> i64 { - puts("hello world!"); + puts("hello world! ;)"); greeting : string; defer greeting.cleanup(); greeting.resize(5); - greeting.print(); + puts(greeting.str); greeting.set("hey!"); - greeting.print(); + puts(greeting.str); print(); return 0; } -strlen :: (str : i8& const) -> i64 := extern; -strcpy :: (dst : i8& const, src : i8& const) -> i8& const := extern; -string :: struct -{ - str : i8& := null; - resize :: (sz : i64) -> u0 - { - if this.str != null - { - // free it first. - __builtin_free(this.str); - } - this.str = __builtin_malloc(sz); - i : i64; - for i = 0, (i != sz), i = (i + 1) - { - this.str[i] = '\0'; - } - } - cleanup :: () -> u0 - { - if this.str != null - { - __builtin_free(this.str); - } - this.str = null; - } - size :: () -> i64 - { - if this.str == null - { - return 0; - } - return strlen(this.str); - } - set :: (literal : i8& const) -> u0 - { - strcpy(this.str, literal); - } - print :: () -> u0 - { - puts(this.str); - } -} - print :: () -> u0 { puts("free-function print!"); diff --git a/stdlib/stdlib.psy b/stdlib/stdlib.psy new file mode 100644 index 0000000..2ee808d --- /dev/null +++ b/stdlib/stdlib.psy @@ -0,0 +1,47 @@ +puts :: (str : i8& const) -> u0 := extern; +strlen :: (str : i8& const) -> i64 := extern; +strcpy :: (dst : i8& const, src : i8& const) -> i8& const := extern; + +string :: struct +{ + str : i8& := null; + resize :: (sz : i64) -> u0 + { + if this.str != null + { + // free it first. + __builtin_free(this.str); + } + this.str = __builtin_malloc(sz); + i : i64; + for i = 0, (i != sz), i = (i + 1) + { + this.str[i] = '\0'; + } + } + cleanup :: () -> u0 + { + if this.str != null + { + __builtin_free(this.str); + } + this.str = null; + } + size :: () -> i64 + { + if this.str == null + { + return 0; + } + return strlen(this.str); + } + set :: (literal : i8& const) -> u0 + { + strcpy(this.str, literal); + } + + //print :: () -> u0 + //{ + // puts(this.str); + //} +}