From a57691cace54926c8533de26e3cac401eee03df0 Mon Sep 17 00:00:00 2001 From: servostar Date: Sun, 21 Jul 2024 01:36:44 +0200 Subject: [PATCH] added driver test fixed memory leaks added hello world test --- .env | 2 +- Dockerfile | 4 +- sdk/Dockerfile | 4 +- src/cfg/opt.c | 76 +++++++++------ src/cfg/opt.h | 2 + src/compiler.c | 25 +++-- src/io/files.c | 12 ++- src/llvm/backend.c | 7 +- src/llvm/link/lld.c | 26 +++-- src/llvm/llvm-ir/func.c | 4 +- src/llvm/parser.c | 9 +- src/main.c | 2 + src/mem/cache.h | 1 + src/set/set.c | 124 +++++++++++++----------- tests/CMakeLists.txt | 2 + tests/driver/CMakeLists.txt | 13 +++ tests/driver/clang/build.toml | 19 ++++ tests/driver/clang/main.gsc | 28 ++++++ tests/driver/clang/test_driver_clang.py | 29 ++++++ tests/driver/gcc/build.toml | 19 ++++ tests/driver/gcc/main.gsc | 28 ++++++ tests/driver/gcc/test_driver_gcc.py | 29 ++++++ tests/hello_world/CMakeLists.txt | 9 ++ tests/hello_world/build.toml | 19 ++++ tests/hello_world/main.gsc | 28 ++++++ tests/hello_world/test_hello_world.py | 29 ++++++ tests/input_file/CMakeLists.txt | 2 +- tests/input_file/{test.gem => test.gsc} | 0 28 files changed, 430 insertions(+), 122 deletions(-) create mode 100644 tests/driver/CMakeLists.txt create mode 100644 tests/driver/clang/build.toml create mode 100644 tests/driver/clang/main.gsc create mode 100644 tests/driver/clang/test_driver_clang.py create mode 100644 tests/driver/gcc/build.toml create mode 100644 tests/driver/gcc/main.gsc create mode 100644 tests/driver/gcc/test_driver_gcc.py create mode 100644 tests/hello_world/CMakeLists.txt create mode 100644 tests/hello_world/build.toml create mode 100644 tests/hello_world/main.gsc create mode 100644 tests/hello_world/test_hello_world.py rename tests/input_file/{test.gem => test.gsc} (100%) diff --git a/.env b/.env index 6eb74fb..b31e782 100644 --- a/.env +++ b/.env @@ -1 +1 @@ -SDK=0.2.5-alpine-3.19.1 +SDK=0.2.6-alpine-3.19.1 diff --git a/Dockerfile b/Dockerfile index a68c334..6674f53 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM servostar/gemstone:sdk-0.2.5-alpine-3.19.1 +FROM servostar/gemstone:sdk-0.2.6-alpine-3.19.1 LABEL authors="servostar" -LABEL version="0.2.5" +LABEL version="0.2.6" LABEL description="docker image for setting up the build pipeline on SDK" LABEL website="https://github.com/Servostar/gemstone" diff --git a/sdk/Dockerfile b/sdk/Dockerfile index 1cba1d3..5bfaf89 100644 --- a/sdk/Dockerfile +++ b/sdk/Dockerfile @@ -1,11 +1,11 @@ FROM alpine:3.19.1 LABEL authors="servostar" -LABEL version="0.2.5" +LABEL version="0.2.6" LABEL description="base image for building the gemstone programming language compiler" LABEL website="https://github.com/Servostar/gemstone" # install dependencies -RUN apk add build-base gcc make cmake bison flex git python3 graphviz glib glib-dev llvm17-libs llvm17-dev +RUN apk add build-base gcc clang make cmake bison flex git python3 graphviz glib glib-dev llvm17-libs llvm17-dev # create user for build RUN adduser --disabled-password lorang diff --git a/src/cfg/opt.c b/src/cfg/opt.c index 5853082..8a946b6 100644 --- a/src/cfg/opt.c +++ b/src/cfg/opt.c @@ -98,7 +98,7 @@ TargetConfig* default_target_config() { config->print_ast = false; config->print_asm = false; config->print_ir = false; - config->driver = DEFAULT_DRIVER; + config->driver = mem_strdup(MemoryNamespaceOpt, DEFAULT_DRIVER); config->mode = Application; config->archive_directory = mem_strdup(MemoryNamespaceOpt, "archive"); config->output_directory = mem_strdup(MemoryNamespaceOpt, "bin"); @@ -169,9 +169,10 @@ TargetConfig* default_target_config_from_args() { } } - // TODO: free vvvvvvvvvvvvv char* cwd = g_get_current_dir(); - g_array_append_val(config->link_search_paths, cwd); + char* cached_cwd = mem_strdup(MemoryNamespaceOpt, cwd); + g_array_append_val(config->link_search_paths, cached_cwd); + free(cwd); if (is_option_set("link-paths")) { const Option* opt = get_option("link-paths"); @@ -183,7 +184,7 @@ TargetConfig* default_target_config_from_args() { while((end = strchr(start, ',')) != NULL) { const int len = end - start; - char* link_path = malloc(len + 1); + char* link_path = mem_alloc(MemoryNamespaceOpt, len + 1); memcpy(link_path, start, len); link_path[len] = 0; @@ -194,7 +195,7 @@ TargetConfig* default_target_config_from_args() { const int len = strlen(start); if (len > 0) { - char* link_path = malloc(len + 1); + char* link_path = mem_alloc(MemoryNamespaceOpt, len + 1); memcpy(link_path, start, len); link_path[len] = 0; @@ -213,7 +214,7 @@ TargetConfig* default_target_config_from_args() { print_message(Warning, "Got more than one file to compile, using first, ignoring others."); } - config->root_module = mem_strdup(MemoryNamespaceOpt, ((char**) files->data) [0]); + config->root_module = mem_strdup(MemoryNamespaceOpt, g_array_index(files, char*, 0)); } char* default_import_path = mem_strdup(MemoryNamespaceOpt, "."); @@ -229,7 +230,7 @@ TargetConfig* default_target_config_from_args() { while((end = strchr(start, ',')) != NULL) { const int len = end - start; - char* import_path = malloc(len + 1); + char* import_path = mem_alloc(MemoryNamespaceOpt, len + 1); memcpy(import_path, start, len); import_path[len] = 0; @@ -240,7 +241,7 @@ TargetConfig* default_target_config_from_args() { const int len = strlen(start); if (len > 0) { - char* import_path = malloc(len + 1); + char* import_path = mem_alloc(MemoryNamespaceOpt, len + 1); memcpy(import_path, start, len); import_path[len] = 0; @@ -382,7 +383,7 @@ static int get_mode_from_str(TargetCompilationMode* mode, const char* name) { *mode = Library; return PROJECT_OK; } - printf("Invalid project configuration, mode is invalid: %s\n\n", name); + print_message(Error, "Invalid project configuration, mode is invalid: %s", name); return PROJECT_SEMANTIC_ERR; } @@ -413,11 +414,13 @@ static int parse_target(const ProjectConfig *config, const toml_table_t *target_ return err; } char* cwd = g_get_current_dir(); + char* cached_cwd = mem_strdup(MemoryNamespaceOpt, cwd); + free(cwd); - g_array_append_val(target_config->link_search_paths, cwd); + g_array_append_val(target_config->link_search_paths, cached_cwd); get_array(target_config->link_search_paths, target_table, "link-paths"); - g_array_append_val(target_config->import_paths, cwd); + g_array_append_val(target_config->import_paths, cached_cwd); get_array(target_config->import_paths, target_table, "import-paths"); g_hash_table_insert(config->targets, target_config->name, target_config); @@ -436,14 +439,14 @@ static int parse_targets(ProjectConfig *config, const toml_table_t *root) { config->targets = mem_new_g_hash_table(MemoryNamespaceOpt, g_str_hash, g_str_equal); - for (int i = 0; i < MAX_TARGETS_PER_PROJECT; i++) { + for (int i = 0; i < toml_table_ntab(targets); i++) { const char *key = toml_key_in(targets, i); if (key == NULL) break; toml_table_t *target = toml_table_in(targets, key); - parse_target(config, target, key); + parse_target(config, target, mem_strdup(MemoryNamespaceOpt, (char*) key)); } return PROJECT_OK; @@ -455,8 +458,7 @@ int load_project_config(ProjectConfig *config) { FILE *config_file = fopen(PROJECT_CONFIG_FILE, "r"); if (config_file == NULL) { print_message(Error, "Cannot open file %s: %s", PROJECT_CONFIG_FILE, strerror(errno)); - INFO("project file not found"); - return PROJECT_TOML_ERR; + return PROJECT_SEMANTIC_ERR; } char err_buf[TOML_ERROR_MSG_BUF]; @@ -464,21 +466,24 @@ int load_project_config(ProjectConfig *config) { toml_table_t *conf = toml_parse_file(config_file, err_buf, sizeof(err_buf)); fclose(config_file); - if (conf == NULL) { + if (conf != NULL) { + int status = PROJECT_SEMANTIC_ERR; + toml_table_t *project = toml_table_in(conf, "project"); + + if (project != NULL) { + if (parse_project_table(config, project) == PROJECT_OK) { + status = parse_targets(config, conf); + } + } else { + print_message(Error, "Invalid project configuration: missing project table."); + } + + toml_free(conf); + return status; + } else { print_message(Error, "Invalid project configuration: %s", err_buf); - return PROJECT_SEMANTIC_ERR; } - toml_table_t *project = toml_table_in(conf, "project"); - if (project == NULL) { - print_message(Error, "Invalid project configuration: missing project table."); - } - - if (parse_project_table(config, project) == PROJECT_OK) { - return parse_targets(config, conf); - } - - toml_free(conf); return PROJECT_SEMANTIC_ERR; } @@ -497,7 +502,7 @@ void delete_target_config(TargetConfig* config) { } if (config->link_search_paths) { for (guint i = 0; i < config->link_search_paths->len; i++) { - free(g_array_index(config->link_search_paths, char*, i)); + mem_free(g_array_index(config->link_search_paths, char*, i)); } } mem_free(config); @@ -527,7 +532,7 @@ void delete_project_config(ProjectConfig* config) { delete_target_config(val); } - g_hash_table_destroy(config->targets); + mem_free(config->targets); } mem_free_from(MemoryNamespaceOpt, config); @@ -545,3 +550,16 @@ ProjectConfig* default_project_config() { return config; } + +static void* toml_cached_malloc(size_t bytes) { + return mem_alloc(MemoryNamespaceTOML, bytes); +} + +static void toml_cached_free(void* ptr) { + mem_free(ptr); +} + +void init_toml() { + INFO("setting up cached memory for TOML C99..."); + toml_set_memutil(toml_cached_malloc, toml_cached_free); +} diff --git a/src/cfg/opt.h b/src/cfg/opt.h index 5699145..06e6f1d 100644 --- a/src/cfg/opt.h +++ b/src/cfg/opt.h @@ -186,4 +186,6 @@ const Option* get_option(const char* option); [[nodiscard("must be freed")]] GArray* get_non_options_after(const char* command); +void init_toml(); + #endif //GEMSTONE_OPT_H diff --git a/src/compiler.c b/src/compiler.c index 103f07d..a515009 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -15,7 +15,6 @@ #include #include #include -#include #define GRAPHVIZ_FILE_EXTENSION "gv" @@ -166,13 +165,18 @@ static void run_backend_codegen(const Module* module, const TargetConfig* target print_message(Info, "Compilation finished successfully"); err = deinit_backend(); + if (err.kind != Success) { + ERROR("Unable to deinit backend: %s", err.impl.message); + } } const char* get_absolute_import_path(const TargetConfig* config, const char* import_target_name) { INFO("resolving absolute path for import target: %s", import_target_name); if (!g_str_has_suffix(import_target_name, ".gsc")) { - import_target_name = g_strjoin("", import_target_name, ".gsc", NULL); + char* full_filename = g_strjoin("", import_target_name, ".gsc", NULL); + import_target_name = mem_strdup(MemoryNamespaceLld, full_filename); + g_free(full_filename); } for (guint i = 0; i < config->import_paths->len; i++) { @@ -185,15 +189,16 @@ const char* get_absolute_import_path(const TargetConfig* config, const char* imp const gboolean exists = g_file_test(canonical, G_FILE_TEST_EXISTS); const gboolean is_dir = g_file_test(canonical, G_FILE_TEST_IS_DIR); + char* cached_canonical = mem_strdup(MemoryNamespaceLld, canonical); + g_free(path); g_free(cwd); + g_free(canonical); if (exists && !is_dir) { - INFO("import target found at: %s", canonical); - return canonical; + INFO("import target found at: %s", cached_canonical); + return cached_canonical; } - - g_free(canonical); } // file not found @@ -233,7 +238,9 @@ static int compile_module_with_dependencies(ModuleFileStack *unit, ModuleFile* f g_hash_table_insert(imports, (gpointer) path, NULL); gchar* directory = g_path_get_dirname(path); - g_array_append_val(target->import_paths, directory); + gchar* cached_directory = mem_strdup(MemoryNamespaceLld, directory); + g_free(directory); + g_array_append_val(target->import_paths, cached_directory); } } } else { @@ -323,7 +330,7 @@ static void build_project_targets(ModuleFileStack *unit, const ProjectConfig *co if (targets != NULL) { for (guint i = 0; i < targets->len; i++) { - const char *target_name = (((Option*) targets->data) + i)->string; + const char *target_name = g_array_index(targets, const char*, i); if (g_hash_table_contains(config->targets, target_name)) { build_target(unit, g_hash_table_lookup(config->targets, target_name)); @@ -332,7 +339,7 @@ static void build_project_targets(ModuleFileStack *unit, const ProjectConfig *co } } - g_array_free(targets, FALSE); + mem_free(targets); } else { print_message(Error, "No targets specified."); } diff --git a/src/io/files.c b/src/io/files.c index dc4d044..ddd018c 100644 --- a/src/io/files.c +++ b/src/io/files.c @@ -42,7 +42,7 @@ ModuleFile *push_file(ModuleFileStack *stack, const char *path) { // lazy init of heap stack if (stack->files == NULL) { - stack->files = g_array_new(FALSE, FALSE, sizeof(ModuleFile*)); + stack->files = mem_new_g_array(MemoryNamespaceStatic, sizeof(ModuleFile*)); } ModuleFile* new_file = mem_alloc(MemoryNamespaceStatic, sizeof(ModuleFile)); @@ -66,9 +66,10 @@ void delete_files(ModuleFileStack *stack) { fclose(file->handle); } + mem_free((void*) file); } - g_array_free(stack->files, TRUE); + mem_free(stack->files); DEBUG("deleted module file stack"); } @@ -330,8 +331,11 @@ const char *get_absolute_path(const char *path) { DEBUG("resolving absolute path of: %s", path); char* cwd = g_get_current_dir(); - char* canoical = g_canonicalize_filename(path, cwd); + char* canonical = g_canonicalize_filename(path, cwd); g_free(cwd); - return canoical; + char* cached_canonical = mem_strdup(MemoryNamespaceStatic, canonical); + g_free(canonical); + + return cached_canonical; } diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 870987d..07f4954 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -7,6 +7,7 @@ #include #include #include +#include Target create_native_target() { DEBUG("creating native target..."); @@ -54,7 +55,11 @@ static char* create_target_output_name(const TargetConfig* config) { prefix = "lib"; } - return g_strjoin("", prefix, config->name, NULL); + char* name = g_strjoin("", prefix, config->name, NULL); + char* cached_name = mem_strdup(MemoryNamespaceLlvm, name); + g_free(name); + + return cached_name; } Target create_target_from_config(const TargetConfig* config) { diff --git a/src/llvm/link/lld.c b/src/llvm/link/lld.c index cb0fb2b..79eec2a 100644 --- a/src/llvm/link/lld.c +++ b/src/llvm/link/lld.c @@ -19,19 +19,19 @@ const char* get_absolute_link_path(const TargetConfig* config, const char* link_ char* path = g_build_filename(link_directory_path, link_target_name, NULL); char* cwd = g_get_current_dir(); char* canonical = g_canonicalize_filename(path, cwd); + char* cached_canonical = mem_strdup(MemoryNamespaceLld, canonical); const gboolean exists = g_file_test(canonical, G_FILE_TEST_EXISTS); const gboolean is_dir = g_file_test(canonical, G_FILE_TEST_IS_DIR); g_free(path); g_free(cwd); + g_free(canonical); if (exists && !is_dir) { - INFO("link target found at: %s", canonical); - return canonical; + INFO("link target found at: %s", cached_canonical); + return cached_canonical; } - - g_free(canonical); } // file not found @@ -44,26 +44,33 @@ TargetLinkConfig* lld_create_link_config(__attribute__((unused)) const Target* t TargetLinkConfig* config = mem_alloc(MemoryNamespaceLld, sizeof(TargetLinkConfig)); config->fatal_warnings = target_config->lld_fatal_warnings; - config->object_file_names = g_array_new(FALSE, FALSE, sizeof(char*)); + config->object_file_names = mem_new_g_array(MemoryNamespaceLld, sizeof(char*)); config->colorize = stdout_supports_ansi_esc(); config->driver = target_config->driver; // append build object file char* basename = g_strjoin(".", target_config->name, "o", NULL); char* filename = g_build_filename(target_config->archive_directory, basename, NULL); + g_free(basename); const char* target_object = get_absolute_link_path(target_config, (const char*) filename); if (target_object == NULL) { ERROR("failed to resolve path to target object: %s", filename); + g_free(filename); lld_delete_link_config(config); + g_free(filename); return NULL; } + g_free(filename); { // output file after linking basename = g_strjoin(".", target_config->name, "out", NULL); filename = g_build_filename(target_config->output_directory, basename, NULL); - config->output_file = filename; + config->output_file = mem_strdup(MemoryNamespaceLld, filename); + + g_free(basename); + g_free(filename); } g_array_append_val(config->object_file_names, target_object); @@ -81,8 +88,10 @@ TargetLinkConfig* lld_create_link_config(__attribute__((unused)) const Target* t ERROR("failed to resolve path to dependency object: %s", library); print_message(Warning, "failed to resolve path to dependency object: %s", dependency); lld_delete_link_config(config); lld_delete_link_config(config); + g_free((void*) library); return NULL; } + g_free((void*) library); g_array_append_val(config->object_file_names, dependency_object); INFO("resolved path of target object: %s", dependency_object); } @@ -102,9 +111,6 @@ BackendError lld_link_target(TargetLinkConfig* config) { } void lld_delete_link_config(TargetLinkConfig* config) { - for (guint i = 0; i < config->object_file_names->len; i++) { - free((void*) g_array_index(config->object_file_names, const char*, i)); - } - g_array_free(config->object_file_names, TRUE); + mem_free(config->object_file_names); mem_free(config); } diff --git a/src/llvm/llvm-ir/func.c b/src/llvm/llvm-ir/func.c index 63d9b39..032aa3b 100644 --- a/src/llvm/llvm-ir/func.c +++ b/src/llvm/llvm-ir/func.c @@ -103,7 +103,7 @@ BackendError impl_func_type(LLVMBackendCompileUnit* unit, DEBUG("implementing function declaration: %s()", func->name); BackendError err = SUCCESS; - GArray* llvm_params = g_array_new(FALSE, FALSE, sizeof(LLVMTypeRef)); + GArray* llvm_params = mem_new_g_array(MemoryNamespaceLlvm, sizeof(LLVMTypeRef)); GArray* func_params = NULL; if (func->kind == FunctionDeclarationKind) { @@ -135,8 +135,6 @@ BackendError impl_func_type(LLVMBackendCompileUnit* unit, g_hash_table_insert(scope->functions, (char*) func->name, llvm_fun_type); - g_array_free(llvm_params, FALSE); - return err; } diff --git a/src/llvm/parser.c b/src/llvm/parser.c index ac009f5..be7ae7c 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -90,10 +90,11 @@ BackendError emit_module_to_file(LLVMBackendCompileUnit* unit, ERROR("failed to emit code: %s", error); err = new_backend_impl_error(Implementation, NULL, "failed to emit code"); - LLVMDisposeMessage(error); + } else { print_message(Info, "Generated code was written to: %s", filename); } + LLVMDisposeMessage(error); g_free((void*) filename); g_free((void*) basename); @@ -124,9 +125,9 @@ BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target, ERROR("failed to create target machine: %s", error); err = new_backend_impl_error(Implementation, NULL, "unable to create target machine"); - LLVMDisposeMessage(error); return err; } + LLVMDisposeMessage(error); DEBUG("Creating target machine..."); LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine( @@ -147,6 +148,8 @@ BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target, err = emit_module_to_file(unit, target_machine, LLVMObjectFile, error, config); + LLVMDisposeTargetMachine(target_machine); + return err; } @@ -223,9 +226,9 @@ static BackendError build_module(LLVMBackendCompileUnit* unit, char* error = NULL; if (LLVMVerifyModule(unit->module, LLVMReturnStatusAction, &error)) { print_message(Error, "Unable to compile due to: %s", error); - LLVMDisposeMessage(error); err = new_backend_impl_error(Implementation, NULL, "LLVM backend verification error, see stdout"); } + LLVMDisposeMessage(error); return err; } diff --git a/src/main.c b/src/main.c index ea6aef9..0367f8b 100644 --- a/src/main.c +++ b/src/main.c @@ -41,6 +41,8 @@ void setup(int argc, char *argv[]) { link_init(); + init_toml(); + DEBUG("finished starting up gemstone..."); } diff --git a/src/mem/cache.h b/src/mem/cache.h index 486e84c..cb47d06 100644 --- a/src/mem/cache.h +++ b/src/mem/cache.h @@ -15,6 +15,7 @@ typedef char* MemoryNamespaceName; #define MemoryNamespaceLex "Lexer" #define MemoryNamespaceLog "Logging" #define MemoryNamespaceOpt "Options" +#define MemoryNamespaceTOML "TOML" #define MemoryNamespaceSet "SET" #define MemoryNamespaceLlvm "LLVM" #define MemoryNamespaceLld "LLD" diff --git a/src/set/set.c b/src/set/set.c index 66f8f71..0d41b2e 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -20,7 +19,7 @@ int createTypeCastFromExpression(Expression *expression, Type *resultType, Expre bool compareTypes(Type *leftType, Type *rightType); -char* type_to_string(Type* type); +char *type_to_string(Type *type); const Type ShortShortUnsingedIntType = { .kind = TypeKindComposite, @@ -335,8 +334,8 @@ int createRef(AST_NODE_PTR currentNode, Type **reftype) { assert(currentNode->children->len == 1); assert(AST_get_node(currentNode, 0)->kind == AST_Type); - Type *type = malloc(sizeof(Type)); - Type *referenceType = malloc(sizeof(Type)); + Type *type = mem_alloc(MemoryNamespaceSet, sizeof(Type)); + Type *referenceType = mem_alloc(MemoryNamespaceSet, sizeof(Type)); referenceType->kind = TypeKindReference; referenceType->nodePtr = currentNode; @@ -459,8 +458,8 @@ int createDef(AST_NODE_PTR currentNode, GArray **variables) { } if (!compareTypes(def.declaration.type, name->result)) { - char* expected_type = type_to_string(def.declaration.type); - char* gotten_type = type_to_string(name->result); + char *expected_type = type_to_string(def.declaration.type); + char *gotten_type = type_to_string(name->result); print_diagnostic(&name->nodePtr->location, Warning, "expected `%s` got `%s`", expected_type, gotten_type); @@ -490,8 +489,8 @@ int createDef(AST_NODE_PTR currentNode, GArray **variables) { return status; } -char* type_to_string(Type* type) { - char* string = NULL; +char *type_to_string(Type *type) { + char *string = NULL; switch (type->kind) { case TypeKindPrimitive: @@ -510,27 +509,32 @@ char* type_to_string(Type* type) { if (type->impl.composite.scale < 1.0) { for (int i = 0; i < (int) (type->impl.composite.scale * 4); i++) { - char* concat = g_strconcat("half ", string, NULL); - string = concat; + char *concat = g_strconcat("half ", string, NULL); + string = mem_strdup(MemoryNamespaceSet, concat); + g_free(concat); } } else if (type->impl.composite.scale > 1.0) { for (int i = 0; i < (int) type->impl.composite.scale; i++) { - char* concat = g_strconcat("long ", string, NULL); - string = concat; + char *concat = g_strconcat("long ", string, NULL); + string = mem_strdup(MemoryNamespaceSet, concat); + g_free(concat); } } if (type->impl.composite.sign == Unsigned) { - char* concat = g_strconcat("unsigned ", string, NULL); - string = concat; + char *concat = g_strconcat("unsigned ", string, NULL); + string = mem_strdup(MemoryNamespaceSet, concat); + g_free(concat); } break; } case TypeKindReference: { - char* type_string = type_to_string(type->impl.reference); - char* concat = g_strconcat("ref ", type_string, NULL); - string = concat; + char *type_string = type_to_string(type->impl.reference); + char *concat = g_strconcat("ref ", type_string, NULL); + mem_free(type_string); + string = mem_strdup(MemoryNamespaceSet, concat); + g_free(concat); break; } case TypeKindBox: @@ -617,6 +621,7 @@ int fillTablesWithVars(GHashTable *variableTable, const GArray *variables) { } [[nodiscard("type must be freed")]] + TypeValue createTypeValue(AST_NODE_PTR currentNode) { DEBUG("create TypeValue"); TypeValue value; @@ -731,7 +736,7 @@ int createArithOperation(Expression *ParentExpression, AST_NODE_PTR currentNode, DEBUG("create arithmetic operation"); ParentExpression->impl.operation.kind = Arithmetic; ParentExpression->impl.operation.nodePtr = currentNode; - ParentExpression->impl.operation.operands = g_array_new(FALSE, FALSE, sizeof(Expression *)); + ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); assert(expectedChildCount == currentNode->children->len); @@ -809,7 +814,7 @@ int createRelationalOperation(Expression *ParentExpression, AST_NODE_PTR current // fill kind and Nodeptr ParentExpression->impl.operation.kind = Relational; ParentExpression->impl.operation.nodePtr = currentNode; - ParentExpression->impl.operation.operands = g_array_new(FALSE, FALSE, sizeof(Expression *)); + ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); // fill Operands for (size_t i = 0; i < currentNode->children->len; i++) { @@ -868,7 +873,7 @@ int createBoolOperation(Expression *ParentExpression, AST_NODE_PTR currentNode) // fill kind and Nodeptr ParentExpression->impl.operation.kind = Boolean; ParentExpression->impl.operation.nodePtr = currentNode; - ParentExpression->impl.operation.operands = g_array_new(FALSE, FALSE, sizeof(Expression *)); + ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); // fill Operands for (size_t i = 0; i < currentNode->children->len; i++) { @@ -952,7 +957,7 @@ int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNod //fill kind and Nodeptr ParentExpression->impl.operation.kind = Boolean; ParentExpression->impl.operation.nodePtr = currentNode; - ParentExpression->impl.operation.operands = g_array_new(FALSE, FALSE, sizeof(Expression *)); + ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); //fill Operand Expression *expression = createExpression(AST_get_node(currentNode, 0)); @@ -1020,7 +1025,7 @@ int createBitOperation(Expression *ParentExpression, AST_NODE_PTR currentNode) { // fill kind and Nodeptr ParentExpression->impl.operation.kind = Boolean; ParentExpression->impl.operation.nodePtr = currentNode; - ParentExpression->impl.operation.operands = g_array_new(FALSE, FALSE, sizeof(Expression *)); + ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); // fill Operands for (size_t i = 0; i < currentNode->children->len; i++) { @@ -1157,7 +1162,7 @@ int createBitNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNode //fill kind and Nodeptr ParentExpression->impl.operation.kind = Bitwise; ParentExpression->impl.operation.nodePtr = currentNode; - ParentExpression->impl.operation.operands = g_array_new(FALSE, FALSE, sizeof(Expression *)); + ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); //fill Operand Expression *expression = createExpression(AST_get_node(currentNode, 0)); @@ -1430,7 +1435,7 @@ int createAddressOf(Expression *ParentExpression, AST_NODE_PTR currentNode) { return SEMANTIC_ERROR; } - Type *resultType = malloc(sizeof(Type)); + Type *resultType = mem_alloc(MemoryNamespaceSet, sizeof(Type)); resultType->nodePtr = currentNode; resultType->kind = TypeKindReference; resultType->impl.reference = address_of.variable->result; @@ -1440,7 +1445,7 @@ int createAddressOf(Expression *ParentExpression, AST_NODE_PTR currentNode) { return SEMANTIC_OK; } -IO_Qualifier getParameterQualifier(Parameter* parameter) { +IO_Qualifier getParameterQualifier(Parameter *parameter) { if (parameter->kind == ParameterDeclarationKind) { return parameter->impl.declaration.qualifier; } else { @@ -1479,7 +1484,8 @@ Expression *createExpression(AST_NODE_PTR currentNode) { } if (getParameterQualifier(expression->impl.parameter) == Out) { - print_diagnostic(¤tNode->location, Error, "Parameter is write-only: `%s`", currentNode->value); + print_diagnostic(¤tNode->location, Error, "Parameter is write-only: `%s`", + currentNode->value); return NULL; } @@ -1625,7 +1631,7 @@ bool compareTypes(Type *leftType, Type *rightType) { return FALSE; } -Type* getVariableType(Variable* variable) { +Type *getVariableType(Variable *variable) { if (variable->kind == VariableKindDeclaration) { return variable->impl.declaration.type; } else { @@ -1633,7 +1639,7 @@ Type* getVariableType(Variable* variable) { } } -Type* getParameterType(Parameter* parameter) { +Type *getParameterType(Parameter *parameter) { if (parameter->kind == ParameterDeclarationKind) { return parameter->impl.declaration.type; } else { @@ -1641,7 +1647,7 @@ Type* getParameterType(Parameter* parameter) { } } -int createStorageExpr(StorageExpr* expr, AST_NODE_PTR node) { +int createStorageExpr(StorageExpr *expr, AST_NODE_PTR node) { switch (node->kind) { case AST_Ident: expr->kind = StorageExprKindVariable; @@ -1669,7 +1675,7 @@ int createStorageExpr(StorageExpr* expr, AST_NODE_PTR node) { expr->impl.dereference.index = createExpression(index_node); expr->impl.dereference.array = mem_alloc(MemoryNamespaceSet, sizeof(StorageExpr)); - if (createStorageExpr(expr->impl.dereference.array, array_node) == SEMANTIC_ERROR){ + if (createStorageExpr(expr->impl.dereference.array, array_node) == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } @@ -1704,7 +1710,8 @@ int createAssign(Statement *ParentStatement, AST_NODE_PTR currentNode) { if (strg_expr->kind == AST_Parameter) { if (getParameterQualifier(assign.destination->impl.parameter) == In) { - print_diagnostic(¤tNode->location, Error, "Parameter is read-only: `%s`", assign.destination->impl.parameter->name); + print_diagnostic(¤tNode->location, Error, "Parameter is read-only: `%s`", + assign.destination->impl.parameter->name); return SEMANTIC_ERROR; } } @@ -1730,8 +1737,8 @@ int createStatement(Block *block, AST_NODE_PTR currentNode); int fillBlock(Block *block, AST_NODE_PTR currentNode) { DEBUG("start filling Block"); block->nodePtr = currentNode; - block->statemnts = g_array_new(FALSE, FALSE, sizeof(Statement *)); - GHashTable *lowerScope = g_hash_table_new(g_str_hash, g_str_equal); + block->statemnts = mem_new_g_array(MemoryNamespaceSet, sizeof(Statement *)); + GHashTable *lowerScope = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); g_array_append_val(Scope, lowerScope); for (size_t i = 0; i < currentNode->children->len; i++) { @@ -1742,7 +1749,7 @@ int fillBlock(Block *block, AST_NODE_PTR currentNode) { } } - g_hash_table_destroy(lowerScope); + mem_free(lowerScope); g_array_remove_index(Scope, Scope->len - 1); DEBUG("created Block successfully"); @@ -1921,7 +1928,7 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) { for (size_t i = 0; i < argsListNode->children->len; i++) { AST_NODE_PTR currentExprList = AST_get_node(argsListNode, i); - for (int j = ((int) currentExprList->children->len) -1; j >= 0; j--) { + for (int j = ((int) currentExprList->children->len) - 1; j >= 0; j--) { AST_NODE_PTR expr_node = AST_get_node(currentExprList, j); Expression *expr = createExpression(expr_node); if (expr == NULL) { @@ -1943,7 +1950,7 @@ int createStatement(Block *Parentblock, AST_NODE_PTR currentNode) { switch (currentNode->kind) { case AST_Decl: { - GArray *variable = g_array_new(FALSE, FALSE, sizeof(Variable *)); + GArray *variable = mem_new_g_array(MemoryNamespaceSet, sizeof(Variable *)); int status = createDecl(currentNode, &variable); if (status) { @@ -1962,7 +1969,7 @@ int createStatement(Block *Parentblock, AST_NODE_PTR currentNode) { break; case AST_Def: { - GArray *variable = g_array_new(FALSE, FALSE, sizeof(Variable *)); + GArray *variable = mem_new_g_array(MemoryNamespaceSet, sizeof(Variable *)); if (createDef(currentNode, &variable)) { return SEMANTIC_ERROR; @@ -2057,7 +2064,7 @@ int createParam(GArray *Paramlist, AST_NODE_PTR currentNode) { if (set_get_type_impl(AST_get_node(paramdecl, 0), &(decl.type))) { return SEMANTIC_ERROR; } - Parameter* param = mem_alloc(MemoryNamespaceSet, sizeof(Parameter)); + Parameter *param = mem_alloc(MemoryNamespaceSet, sizeof(Parameter)); param->nodePtr = currentNode; param->kind = ParameterDeclarationKind; param->impl.declaration = decl; @@ -2067,7 +2074,8 @@ int createParam(GArray *Paramlist, AST_NODE_PTR currentNode) { g_array_append_val(Paramlist, *param); if (g_hash_table_contains(functionParameter, param->name)) { - print_diagnostic(¶m->nodePtr->location, Error, "Names of function parameters must be unique: %s", param->name); + print_diagnostic(¶m->nodePtr->location, Error, "Names of function parameters must be unique: %s", + param->name); return SEMANTIC_ERROR; } g_hash_table_insert(functionParameter, (gpointer) param->name, param); @@ -2087,7 +2095,7 @@ int createFunDef(Function *Parentfunction, AST_NODE_PTR currentNode) { fundef.nodePtr = currentNode; fundef.name = nameNode->value; fundef.body = mem_alloc(MemoryNamespaceSet, sizeof(Block)); - fundef.parameter = g_array_new(FALSE, FALSE, sizeof(Parameter)); + fundef.parameter = mem_new_g_array(MemoryNamespaceSet, sizeof(Parameter)); DEBUG("paramlistlist child count: %i", paramlistlist->children->len); for (size_t i = 0; i < paramlistlist->children->len; i++) { @@ -2150,7 +2158,8 @@ bool compareParameter(GArray *leftParameter, GArray *rightParameter) { int addFunction(const char *name, Function *function) { if (function->kind == FunctionDefinitionKind) { if (g_hash_table_contains(definedFunctions, name)) { - print_diagnostic(&function->nodePtr->location, Error, "Multiple definition of function: `%s`", function->name); + print_diagnostic(&function->nodePtr->location, Error, "Multiple definition of function: `%s`", + function->name); return SEMANTIC_ERROR; } g_hash_table_insert(declaredFunctions, (gpointer) name, function); @@ -2161,7 +2170,8 @@ int addFunction(const char *name, Function *function) { function->impl.declaration.parameter); // a function can have multiple declartations but all have to be identical if (result == FALSE) { - print_diagnostic(&function->nodePtr->location, Error, "Divergent declaration of function: `%s`", function->name); + print_diagnostic(&function->nodePtr->location, Error, "Divergent declaration of function: `%s`", + function->name); return SEMANTIC_ERROR; } } @@ -2219,7 +2229,7 @@ int createFunDecl(Function *Parentfunction, AST_NODE_PTR currentNode) { int createFunction(Function *function, AST_NODE_PTR currentNode) { assert(currentNode->kind == AST_Fun); - functionParameter = g_hash_table_new(g_str_hash, g_str_equal); + functionParameter = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); if (currentNode->children->len == 2) { int signal = createFunDecl(function, currentNode); @@ -2235,7 +2245,7 @@ int createFunction(Function *function, AST_NODE_PTR currentNode) { PANIC("function should have 2 or 3 children"); } - g_hash_table_destroy(functionParameter); + mem_free(functionParameter); functionParameter = NULL; int result = addFunction(function->name, function); @@ -2403,27 +2413,27 @@ int createTypeDef(GHashTable *types, AST_NODE_PTR currentNode) { Module *create_set(AST_NODE_PTR currentNode) { DEBUG("create root Module"); //create tables for types - declaredComposites = g_hash_table_new(g_str_hash, g_str_equal); - declaredBoxes = g_hash_table_new(g_str_hash, g_str_equal); - declaredFunctions = g_hash_table_new(g_str_hash, g_str_equal); - definedFunctions = g_hash_table_new(g_str_hash, g_str_equal); + declaredComposites = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); + declaredBoxes = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); + declaredFunctions = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); + definedFunctions = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); //create scope - Scope = g_array_new(FALSE, FALSE, sizeof(GHashTable *)); + Scope = mem_new_g_array(MemoryNamespaceSet, sizeof(GHashTable *)); //building current scope for module - GHashTable *globalscope = g_hash_table_new(g_str_hash, g_str_equal); - globalscope = g_hash_table_new(g_str_hash, g_str_equal); + GHashTable *globalscope = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); + globalscope = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); g_array_append_val(Scope, globalscope); Module *rootModule = mem_alloc(MemoryNamespaceSet, sizeof(Module)); - GHashTable *boxes = g_hash_table_new(g_str_hash, g_str_equal); - GHashTable *types = g_hash_table_new(g_str_hash, g_str_equal); - GHashTable *functions = g_hash_table_new(g_str_hash, g_str_equal); - GHashTable *variables = g_hash_table_new(g_str_hash, g_str_equal); - GArray *imports = g_array_new(FALSE, FALSE, sizeof(const char *)); - GArray *includes = g_array_new(FALSE, FALSE, sizeof(const char *)); + GHashTable *boxes = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); + GHashTable *types = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); + GHashTable *functions = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); + GHashTable *variables = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); + GArray *imports = mem_new_g_array(MemoryNamespaceSet, sizeof(const char *)); + GArray *includes = mem_new_g_array(MemoryNamespaceSet, sizeof(const char *)); rootModule->boxes = boxes; rootModule->types = types; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3ce0770..456af55 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -13,3 +13,5 @@ add_subdirectory(glib) add_subdirectory(llvm) add_subdirectory(project) add_subdirectory(cache) +add_subdirectory(hello_world) +add_subdirectory(driver) diff --git a/tests/driver/CMakeLists.txt b/tests/driver/CMakeLists.txt new file mode 100644 index 0000000..85fd68c --- /dev/null +++ b/tests/driver/CMakeLists.txt @@ -0,0 +1,13 @@ +include(CTest) + +# ------------------------------------------------------- # +# CTEST 1 +# test compilation and execution with GCC driver + +add_test(NAME driver_gcc + WORKING_DIRECTORY ${GEMSTONE_TEST_DIR}/driver/gcc + COMMAND python ${GEMSTONE_TEST_DIR}/driver/gcc/test_driver_gcc.py) + +add_test(NAME driver_clang + WORKING_DIRECTORY ${GEMSTONE_TEST_DIR}/driver/clang + COMMAND python ${GEMSTONE_TEST_DIR}/driver/clang/test_driver_clang.py) diff --git a/tests/driver/clang/build.toml b/tests/driver/clang/build.toml new file mode 100644 index 0000000..f200572 --- /dev/null +++ b/tests/driver/clang/build.toml @@ -0,0 +1,19 @@ +[project] +name = "driver compilation test" +version = "0.1.0" +description = "Print a string to stdout" +license = "GPL-2.0" +authors = [ "Sven Vogel " ] + +[target.release] +link-paths = [ "../../../bin/std" ] +import-paths = [ "../../../lib/src" ] +driver = "clang" +root = "main.gsc" +mode = "application" +output = "bin" +archive = "archive" +print_ast = false +print_asm = false +print_ir = false +opt = 3 diff --git a/tests/driver/clang/main.gsc b/tests/driver/clang/main.gsc new file mode 100644 index 0000000..70314a2 --- /dev/null +++ b/tests/driver/clang/main.gsc @@ -0,0 +1,28 @@ + +import "std" + +fun cstrlen(in cstr: str)(out u32: len) { + u32: idx = 0 as u32 + + while !(str[idx] == 0) { + idx = idx + 1 + } + + len = idx +} + +fun printcstr(in cstr: msg) { + u32: len = 0 + cstrlen(msg)(len) + + handle: stdout = 0 + getStdoutHandle()(stdout) + + u32: written = 0 + writeBytes(stdout, msg, len)(written) +} + +fun main() { + cstr: msg = "Hello, world!\n" + printcstr(msg) +} diff --git a/tests/driver/clang/test_driver_clang.py b/tests/driver/clang/test_driver_clang.py new file mode 100644 index 0000000..ae8f2b1 --- /dev/null +++ b/tests/driver/clang/test_driver_clang.py @@ -0,0 +1,29 @@ +import os.path +import subprocess +import logging +from logging import info + + +def check_clang(): + info("testing Clang driver...") + + logging.basicConfig(level=logging.INFO) + + p = subprocess.run(["../../../bin/check/gsc", "build", "release", "--verbose", "--driver=clang"], capture_output=True, text=True) + + print(p.stdout) + + assert p.returncode == 0 + + p = subprocess.run(["bin/release.out"], capture_output=True, text=True) + + print(p.stdout) + + assert "Hello, world!" in p.stdout + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + info("check if binary exists...") + assert os.path.exists("../../../bin/check/gsc") + + check_clang() diff --git a/tests/driver/gcc/build.toml b/tests/driver/gcc/build.toml new file mode 100644 index 0000000..85e76d9 --- /dev/null +++ b/tests/driver/gcc/build.toml @@ -0,0 +1,19 @@ +[project] +name = "driver compilation test" +version = "0.1.0" +description = "Print a string to stdout" +license = "GPL-2.0" +authors = [ "Sven Vogel " ] + +[target.release] +link-paths = [ "../../../bin/std" ] +import-paths = [ "../../../lib/src" ] +driver = "gcc" +root = "main.gsc" +mode = "application" +output = "bin" +archive = "archive" +print_ast = false +print_asm = false +print_ir = false +opt = 3 diff --git a/tests/driver/gcc/main.gsc b/tests/driver/gcc/main.gsc new file mode 100644 index 0000000..70314a2 --- /dev/null +++ b/tests/driver/gcc/main.gsc @@ -0,0 +1,28 @@ + +import "std" + +fun cstrlen(in cstr: str)(out u32: len) { + u32: idx = 0 as u32 + + while !(str[idx] == 0) { + idx = idx + 1 + } + + len = idx +} + +fun printcstr(in cstr: msg) { + u32: len = 0 + cstrlen(msg)(len) + + handle: stdout = 0 + getStdoutHandle()(stdout) + + u32: written = 0 + writeBytes(stdout, msg, len)(written) +} + +fun main() { + cstr: msg = "Hello, world!\n" + printcstr(msg) +} diff --git a/tests/driver/gcc/test_driver_gcc.py b/tests/driver/gcc/test_driver_gcc.py new file mode 100644 index 0000000..a081961 --- /dev/null +++ b/tests/driver/gcc/test_driver_gcc.py @@ -0,0 +1,29 @@ +import os.path +import subprocess +import logging +from logging import info + + +def check_gcc(): + info("testing GCC driver...") + + logging.basicConfig(level=logging.INFO) + + p = subprocess.run(["../../../bin/check/gsc", "build", "release", "--verbose", "--driver=gcc"], capture_output=True, text=True) + + print(p.stdout) + + assert p.returncode == 0 + + p = subprocess.run(["bin/release.out"], capture_output=True, text=True) + + print(p.stdout) + + assert "Hello, world!" in p.stdout + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + info("check if binary exists...") + assert os.path.exists("../../../bin/check/gsc") + + check_gcc() diff --git a/tests/hello_world/CMakeLists.txt b/tests/hello_world/CMakeLists.txt new file mode 100644 index 0000000..6ca46a7 --- /dev/null +++ b/tests/hello_world/CMakeLists.txt @@ -0,0 +1,9 @@ +include(CTest) + +# ------------------------------------------------------- # +# CTEST 1 +# test a simple project + +add_test(NAME hello_world + WORKING_DIRECTORY ${GEMSTONE_TEST_DIR}/hello_world + COMMAND python ${GEMSTONE_TEST_DIR}/hello_world/test_hello_world.py) diff --git a/tests/hello_world/build.toml b/tests/hello_world/build.toml new file mode 100644 index 0000000..71fbfd3 --- /dev/null +++ b/tests/hello_world/build.toml @@ -0,0 +1,19 @@ +[project] +name = "print C string test" +version = "0.1.0" +description = "Print a string to stdout" +license = "GPL-2.0" +authors = [ "Sven Vogel " ] + +[target.release] +link-paths = [ "../../bin/std" ] +import-paths = [ "../../lib/src" ] +driver = "gcc" +root = "main.gsc" +mode = "application" +output = "bin" +archive = "archive" +print_ast = false +print_asm = false +print_ir = false +opt = 3 diff --git a/tests/hello_world/main.gsc b/tests/hello_world/main.gsc new file mode 100644 index 0000000..70314a2 --- /dev/null +++ b/tests/hello_world/main.gsc @@ -0,0 +1,28 @@ + +import "std" + +fun cstrlen(in cstr: str)(out u32: len) { + u32: idx = 0 as u32 + + while !(str[idx] == 0) { + idx = idx + 1 + } + + len = idx +} + +fun printcstr(in cstr: msg) { + u32: len = 0 + cstrlen(msg)(len) + + handle: stdout = 0 + getStdoutHandle()(stdout) + + u32: written = 0 + writeBytes(stdout, msg, len)(written) +} + +fun main() { + cstr: msg = "Hello, world!\n" + printcstr(msg) +} diff --git a/tests/hello_world/test_hello_world.py b/tests/hello_world/test_hello_world.py new file mode 100644 index 0000000..a9f801d --- /dev/null +++ b/tests/hello_world/test_hello_world.py @@ -0,0 +1,29 @@ +import os.path +import subprocess +import logging +from logging import info + + +def check_build_and_run(): + info("testing compilation of hello world...") + + logging.basicConfig(level=logging.INFO) + + p = subprocess.run(["../../bin/check/gsc", "build", "release", "--verbose"], capture_output=True, text=True) + + print(p.stdout) + + assert p.returncode == 0 + + p = subprocess.run(["bin/release.out"], capture_output=True, text=True) + + print(p.stdout) + + assert "Hello, world!" in p.stdout + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + info("check if binary exists...") + assert os.path.exists("../../bin/check/gsc") + + check_build_and_run() diff --git a/tests/input_file/CMakeLists.txt b/tests/input_file/CMakeLists.txt index 263e769..23244fb 100644 --- a/tests/input_file/CMakeLists.txt +++ b/tests/input_file/CMakeLists.txt @@ -6,4 +6,4 @@ include(CTest) add_test(NAME input_file_check WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/bin/check - COMMAND python ${GEMSTONE_TEST_DIR}/input_file/test_input_file.py ${GEMSTONE_TEST_DIR}/input_file/test.gem) + COMMAND python ${GEMSTONE_TEST_DIR}/input_file/test_input_file.py ${GEMSTONE_TEST_DIR}/input_file/test.gsc) diff --git a/tests/input_file/test.gem b/tests/input_file/test.gsc similarity index 100% rename from tests/input_file/test.gem rename to tests/input_file/test.gsc