added driver test
fixed memory leaks added hello world test
This commit is contained in:
parent
ee8809a393
commit
a57691cace
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include <llvm/backend.h>
|
||||
#include <mem/cache.h>
|
||||
#include <set/set.h>
|
||||
#include <link/lib.h>
|
||||
|
||||
#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.");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <llvm/backend.h>
|
||||
#include <llvm/parser.h>
|
||||
#include <sys/log.h>
|
||||
#include <mem/cache.h>
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ void setup(int argc, char *argv[]) {
|
|||
|
||||
link_init();
|
||||
|
||||
init_toml();
|
||||
|
||||
DEBUG("finished starting up gemstone...");
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
124
src/set/set.c
124
src/set/set.c
|
@ -1,7 +1,6 @@
|
|||
#include <io/files.h>
|
||||
#include <ast/ast.h>
|
||||
#include <set/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/log.h>
|
||||
#include <glib.h>
|
||||
|
@ -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;
|
||||
|
|
|
@ -13,3 +13,5 @@ add_subdirectory(glib)
|
|||
add_subdirectory(llvm)
|
||||
add_subdirectory(project)
|
||||
add_subdirectory(cache)
|
||||
add_subdirectory(hello_world)
|
||||
add_subdirectory(driver)
|
||||
|
|
|
@ -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)
|
|
@ -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 <sven.vogel123@web.de>" ]
|
||||
|
||||
[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
|
|
@ -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)
|
||||
}
|
|
@ -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()
|
|
@ -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 <sven.vogel123@web.de>" ]
|
||||
|
||||
[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
|
|
@ -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)
|
||||
}
|
|
@ -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()
|
|
@ -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)
|
|
@ -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 <sven.vogel123@web.de>" ]
|
||||
|
||||
[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
|
|
@ -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)
|
||||
}
|
|
@ -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()
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue