fixed implementation vaults
This commit is contained in:
parent
76b011511a
commit
8f24596779
|
@ -27,6 +27,8 @@ set(CMAKE_C_STANDARD_REQUIRED TRUE)
|
|||
set(GEMSTONE_TEST_DIR ${PROJECT_SOURCE_DIR}/tests)
|
||||
set(GEMSTONE_BINARY_DIR ${PROJECT_SOURCE_DIR}/bin)
|
||||
|
||||
add_compile_definitions(GSC_VERSION="${PROJECT_VERSION}")
|
||||
|
||||
include(CTest)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
|
@ -144,6 +146,9 @@ target_compile_options(release PUBLIC ${FLAGS} ${RELEASE_FLAGS})
|
|||
# add src directory as include path
|
||||
target_include_directories(release PUBLIC src)
|
||||
|
||||
# disable assertions
|
||||
target_compile_definitions(release PUBLIC NDEBUG="1")
|
||||
|
||||
# ------------------------------------------------ #
|
||||
# Target DEBUG #
|
||||
# ------------------------------------------------ #
|
||||
|
|
169
src/cfg/opt.c
169
src/cfg/opt.c
|
@ -4,41 +4,47 @@
|
|||
|
||||
#include <cfg/opt.h>
|
||||
#include <string.h>
|
||||
#include <sys/log.h>
|
||||
|
||||
#define MAX_TARGETS_PER_PROJECT 100
|
||||
TargetConfig* default_target_config() {
|
||||
DEBUG("generating default target config...");
|
||||
|
||||
TargetConfig default_target_config() {
|
||||
TargetConfig config;
|
||||
TargetConfig* config = malloc(sizeof(TargetConfig));
|
||||
|
||||
config.name = "debug";
|
||||
config.print_ast = false;
|
||||
config.print_asm = false;
|
||||
config.print_ir = false;
|
||||
config.mode = Application;
|
||||
config.archive_directory = "archive";
|
||||
config.archive_directory = "bin";
|
||||
config.optimization_level = 1;
|
||||
config.root_module = NULL;
|
||||
config->name = NULL;
|
||||
config->print_ast = false;
|
||||
config->print_asm = false;
|
||||
config->print_ir = false;
|
||||
config->mode = Application;
|
||||
config->archive_directory = NULL;
|
||||
config->archive_directory = NULL;
|
||||
config->optimization_level = 1;
|
||||
config->root_module = NULL;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
TargetConfig default_target_config_from_args(int argc, char *argv[]) {
|
||||
TargetConfig config = default_target_config();
|
||||
TargetConfig* default_target_config_from_args(int argc, char *argv[]) {
|
||||
DEBUG("generating default target from command line...");
|
||||
|
||||
TargetConfig* config = default_target_config();
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
DEBUG("processing argument: %ld %s", i, argv[i]);
|
||||
char *option = argv[i];
|
||||
|
||||
if (strcmp(option, "--print-ast") == 0) {
|
||||
config.print_ast = true;
|
||||
config->print_ast = true;
|
||||
} else if (strcmp(option, "--print-asm") == 0) {
|
||||
config.print_asm = true;
|
||||
config->print_asm = true;
|
||||
} else if (strcmp(option, "--print-ir") == 0) {
|
||||
config.print_ir = true;
|
||||
config->print_ir = true;
|
||||
} else if (strcmp(option, "--mode=app") == 0) {
|
||||
config.mode = Application;
|
||||
config->mode = Application;
|
||||
} else if (strcmp(option, "--mode=lib") == 0) {
|
||||
config.mode = Library;
|
||||
config->mode = Library;
|
||||
} else {
|
||||
config->root_module = option;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,11 +52,14 @@ TargetConfig default_target_config_from_args(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
void print_help(void) {
|
||||
DEBUG("printing help dialog...");
|
||||
|
||||
const char *lines[] = {
|
||||
"Gemstone Compiler (C) GPL-2.0\n",
|
||||
"Compile file(s): gsc <options> [files]",
|
||||
"Build project (build.toml): gsc [directory] [target]|all",
|
||||
"Gemstone Compiler (C) GPL-2.0",
|
||||
"Build a project target: gsc build [target]|all",
|
||||
"Compile non-project file: gsc compile <options> [file]",
|
||||
"Options:",
|
||||
" --version print the version",
|
||||
" --print-ast print resulting abstract syntax tree to a file",
|
||||
" --print-asm print resulting assembly language to a file",
|
||||
" --print-ir print resulting LLVM-IR to a file",
|
||||
|
@ -62,35 +71,42 @@ void print_help(void) {
|
|||
}
|
||||
}
|
||||
|
||||
#define PROJECT_OK 0
|
||||
#define PROJECT_TOML_ERR 1
|
||||
#define PROJECT_SEMANTIC_ERR 2
|
||||
|
||||
static void get_bool(bool* boolean, toml_table_t *table, const char* name) {
|
||||
DEBUG("retrieving boolean %s", name);
|
||||
|
||||
toml_datum_t datum = toml_bool_in(table, name);
|
||||
|
||||
if (datum.ok) {
|
||||
*boolean = datum.u.b;
|
||||
DEBUG("boolean has value: %d", datum.u.b);
|
||||
}
|
||||
}
|
||||
|
||||
static void get_str(char** string, toml_table_t *table, const char* name) {
|
||||
DEBUG("retrieving string %s", name);
|
||||
|
||||
toml_datum_t datum = toml_string_in(table, name);
|
||||
|
||||
if (datum.ok) {
|
||||
*string = datum.u.s;
|
||||
DEBUG("string has value: %s", datum.u.s);
|
||||
}
|
||||
}
|
||||
|
||||
static void get_int(int* integer, toml_table_t *table, const char* name) {
|
||||
DEBUG("retrieving integer %s", name);
|
||||
|
||||
toml_datum_t datum = toml_int_in(table, name);
|
||||
|
||||
if (datum.ok) {
|
||||
*integer = (int) datum.u.i;
|
||||
DEBUG("integer has value: %ld", datum.u.i);
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_project_table(ProjectConfig *config, toml_table_t *project_table) {
|
||||
DEBUG("parsing project table...");
|
||||
|
||||
// project name
|
||||
get_str(&config->name, project_table, "version");
|
||||
if (config->name == NULL) {
|
||||
|
@ -99,7 +115,7 @@ static int parse_project_table(ProjectConfig *config, toml_table_t *project_tabl
|
|||
}
|
||||
|
||||
// project version
|
||||
get_str(&config->name, project_table, "version");
|
||||
get_str(&config->name, project_table, "name");
|
||||
|
||||
// author names
|
||||
toml_array_t *authors = toml_array_in(project_table, "authors");
|
||||
|
@ -136,34 +152,44 @@ static int get_mode_from_str(TargetCompilationMode* mode, const char* name) {
|
|||
}
|
||||
|
||||
static int parse_target(ProjectConfig *config, toml_table_t *target_table, const char* name) {
|
||||
TargetConfig target_config = default_target_config();
|
||||
DEBUG("parsing target table...");
|
||||
|
||||
target_config.name = (char*) name;
|
||||
TargetConfig* target_config = default_target_config();
|
||||
|
||||
get_bool(&target_config.print_ast, target_table, "print_ast");
|
||||
get_bool(&target_config.print_asm, target_table, "print_asm");
|
||||
get_bool(&target_config.print_ir, target_table, "print_ir");
|
||||
target_config->name = (char*) name;
|
||||
|
||||
get_str(&target_config.root_module, target_table, "root");
|
||||
get_str(&target_config.output_directory, target_table, "output");
|
||||
get_str(&target_config.archive_directory, target_table, "archive");
|
||||
get_bool(&target_config->print_ast, target_table, "print_ast");
|
||||
get_bool(&target_config->print_asm, target_table, "print_asm");
|
||||
get_bool(&target_config->print_ir, target_table, "print_ir");
|
||||
|
||||
get_int(&target_config.optimization_level, target_table, "opt");
|
||||
get_str(&target_config->root_module, target_table, "root");
|
||||
get_str(&target_config->output_directory, target_table, "output");
|
||||
get_str(&target_config->archive_directory, target_table, "archive");
|
||||
|
||||
get_int(&target_config->optimization_level, target_table, "opt");
|
||||
|
||||
char* mode = NULL;
|
||||
get_str(&mode, target_table, "mode");
|
||||
int err = get_mode_from_str(&target_config.mode, mode);
|
||||
int err = get_mode_from_str(&target_config->mode, mode);
|
||||
if (err != PROJECT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
g_array_append_val(config->targets, target_config);
|
||||
g_hash_table_insert(config->targets, target_config->name, target_config);
|
||||
|
||||
return PROJECT_OK;
|
||||
}
|
||||
|
||||
static int parse_targets(ProjectConfig *config, toml_table_t *root) {
|
||||
DEBUG("parsing targets of project \"%s\"", config->name);
|
||||
|
||||
toml_table_t *targets = toml_table_in(root, "target");
|
||||
if (targets == NULL) {
|
||||
printf("Project has no targets\n");
|
||||
return PROJECT_SEMANTIC_ERR;
|
||||
}
|
||||
|
||||
config->targets = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
|
||||
for (int i = 0; i < MAX_TARGETS_PER_PROJECT; i++) {
|
||||
const char *key = toml_key_in(targets, i);
|
||||
|
@ -179,8 +205,12 @@ static int parse_targets(ProjectConfig *config, toml_table_t *root) {
|
|||
}
|
||||
|
||||
int load_project_config(ProjectConfig *config) {
|
||||
FILE *config_file = fopen("build.toml", "r");
|
||||
DEBUG("loading project config...");
|
||||
|
||||
FILE *config_file = fopen(PROJECT_CONFIG_FILE, "r");
|
||||
if (config_file == NULL) {
|
||||
printf("Cannot open file %s: %s\n", PROJECT_CONFIG_FILE, strerror(errno));
|
||||
ERROR("project file not found");
|
||||
return PROJECT_TOML_ERR;
|
||||
}
|
||||
|
||||
|
@ -197,7 +227,7 @@ int load_project_config(ProjectConfig *config) {
|
|||
toml_table_t *project = toml_table_in(conf, "project");
|
||||
if (project) {
|
||||
if (parse_project_table(config, project) == PROJECT_OK) {
|
||||
return parse_targets(config, project);
|
||||
return parse_targets(config, conf);
|
||||
}
|
||||
} else {
|
||||
printf("Invalid project configuration: missing project table\n\n");
|
||||
|
@ -206,3 +236,62 @@ int load_project_config(ProjectConfig *config) {
|
|||
toml_free(conf);
|
||||
return PROJECT_SEMANTIC_ERR;
|
||||
}
|
||||
|
||||
void delete_target_config(TargetConfig* config) {
|
||||
if (config->root_module != NULL) {
|
||||
free(config->root_module);
|
||||
}
|
||||
if (config->archive_directory != NULL) {
|
||||
free(config->archive_directory);
|
||||
}
|
||||
if (config->name != NULL) {
|
||||
free(config->name);
|
||||
}
|
||||
if (config->output_directory != NULL) {
|
||||
free(config->output_directory);
|
||||
}
|
||||
free(config);
|
||||
}
|
||||
|
||||
void delete_project_config(ProjectConfig* config) {
|
||||
if (config->name != NULL) {
|
||||
free(config->name);
|
||||
}
|
||||
if (config->authors != NULL) {
|
||||
g_array_free(config->authors, TRUE);
|
||||
}
|
||||
if (config->desc != NULL) {
|
||||
free(config->desc);
|
||||
}
|
||||
if (config->license != NULL) {
|
||||
free(config->license);
|
||||
}
|
||||
if (config->targets != NULL) {
|
||||
GHashTableIter iter;
|
||||
|
||||
g_hash_table_iter_init(&iter, config->targets);
|
||||
|
||||
char* key;
|
||||
TargetConfig* val;
|
||||
while (g_hash_table_iter_next(&iter, (gpointer) &key, (gpointer) &val)) {
|
||||
delete_target_config(val);
|
||||
}
|
||||
|
||||
g_hash_table_destroy(config->targets);
|
||||
}
|
||||
|
||||
free(config);
|
||||
}
|
||||
|
||||
ProjectConfig* default_project_config() {
|
||||
ProjectConfig* config = malloc(sizeof(ProjectConfig));
|
||||
|
||||
config->authors = NULL;
|
||||
config->name = NULL;
|
||||
config->targets = NULL;
|
||||
config->license = NULL;
|
||||
config->version = NULL;
|
||||
config->desc = NULL;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,13 @@
|
|||
#include <toml.h>
|
||||
#include <glib.h>
|
||||
|
||||
#define MAX_TARGETS_PER_PROJECT 100
|
||||
#define PROJECT_CONFIG_FILE "build.toml"
|
||||
|
||||
#define PROJECT_OK 0
|
||||
#define PROJECT_TOML_ERR 1
|
||||
#define PROJECT_SEMANTIC_ERR 2
|
||||
|
||||
typedef enum TargetCompilationMode_t {
|
||||
Application,
|
||||
Library
|
||||
|
@ -42,13 +49,21 @@ typedef struct ProjectConfig_t {
|
|||
char* license;
|
||||
// list of authors
|
||||
GArray* authors;
|
||||
GArray* targets;
|
||||
GHashTable* targets;
|
||||
} ProjectConfig;
|
||||
|
||||
TargetConfig default_target_config();
|
||||
TargetConfig* default_target_config();
|
||||
|
||||
TargetConfig default_target_config_from_args(int argc, char* argv[]);
|
||||
ProjectConfig* default_project_config();
|
||||
|
||||
TargetConfig* default_target_config_from_args(int argc, char* argv[]);
|
||||
|
||||
int load_project_config(ProjectConfig *config);
|
||||
|
||||
void print_help(void);
|
||||
|
||||
void delete_project_config(ProjectConfig* config);
|
||||
|
||||
void delete_target_config(TargetConfig*);
|
||||
|
||||
#endif //GEMSTONE_OPT_H
|
||||
|
|
101
src/main.c
101
src/main.c
|
@ -6,6 +6,7 @@
|
|||
#include <lex/util.h>
|
||||
#include <io/files.h>
|
||||
#include <assert.h>
|
||||
#include <cfg/opt.h>
|
||||
|
||||
extern void yyrestart(FILE *);
|
||||
|
||||
|
@ -22,6 +23,7 @@ ModuleFile *current_file;
|
|||
*/
|
||||
[[nodiscard("AST may be in invalid state")]]
|
||||
[[gnu::nonnull(1), gnu::nonnull(1)]]
|
||||
|
||||
static size_t compile_file_to_ast(AST_NODE_PTR ast, ModuleFile *file) {
|
||||
assert(file->path != NULL);
|
||||
assert(ast != NULL);
|
||||
|
@ -30,6 +32,7 @@ static size_t compile_file_to_ast(AST_NODE_PTR ast, ModuleFile *file) {
|
|||
|
||||
if (file->handle == NULL) {
|
||||
INFO("unable to open file: %s", file->path);
|
||||
printf("Cannot open file %s: %s\n", file->path, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -92,16 +95,8 @@ void setup(void) {
|
|||
DEBUG("finished starting up gemstone...");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
setup();
|
||||
atexit(close_file);
|
||||
|
||||
ModuleFileStack files;
|
||||
files.files = NULL;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
printf("Compiling file: %s\n\n", argv[i]);
|
||||
void build_target(ModuleFileStack *unit, TargetConfig *target) {
|
||||
printf("Compiling file: %s\n\n", target->root_module);
|
||||
|
||||
TokenLocation location = {
|
||||
.line_start = 0,
|
||||
|
@ -110,7 +105,7 @@ int main(int argc, char *argv[]) {
|
|||
.col_end = 0
|
||||
};
|
||||
AST_NODE_PTR ast = AST_new_node(location, AST_Module, NULL);
|
||||
ModuleFile *file = push_file(&files, argv[i]);
|
||||
ModuleFile *file = push_file(unit, target->root_module);
|
||||
|
||||
if (compile_file_to_ast(ast, file) == EXIT_SUCCESS) {
|
||||
// TODO: parse AST to semantic values
|
||||
|
@ -120,6 +115,72 @@ int main(int argc, char *argv[]) {
|
|||
AST_delete_node(ast);
|
||||
|
||||
print_file_statistics(file);
|
||||
}
|
||||
|
||||
void compile_file(ModuleFileStack *unit, int argc, char *argv[]) {
|
||||
INFO("compiling basic files...");
|
||||
|
||||
TargetConfig *target = default_target_config_from_args(argc, argv);
|
||||
|
||||
if (target->root_module == NULL) {
|
||||
printf("No input file specified\n");
|
||||
delete_target_config(target);
|
||||
return;
|
||||
}
|
||||
|
||||
build_target(unit, target);
|
||||
|
||||
delete_target_config(target);
|
||||
}
|
||||
|
||||
void build_project_targets(ModuleFileStack *unit, ProjectConfig *config, const char *filter) {
|
||||
if (strcmp(filter, "all") == 0) {
|
||||
GHashTableIter iter;
|
||||
|
||||
g_hash_table_iter_init(&iter, config->targets);
|
||||
|
||||
char* key;
|
||||
TargetConfig* val;
|
||||
while (g_hash_table_iter_next(&iter, (gpointer) &key, (gpointer) &val)) {
|
||||
build_target(unit, val);
|
||||
}
|
||||
} else if (g_hash_table_contains(config->targets, filter)) {
|
||||
build_target(unit, g_hash_table_lookup(config->targets, filter));
|
||||
}
|
||||
}
|
||||
|
||||
void build_project(ModuleFileStack *unit, int argc, char *argv[]) {
|
||||
if (argc >= 1) {
|
||||
ProjectConfig* config = default_project_config();
|
||||
int err = load_project_config(config);
|
||||
|
||||
if (err == PROJECT_OK) {
|
||||
if (argc == 1) {
|
||||
build_project_targets(unit, config, "all");
|
||||
} else {
|
||||
build_project_targets(unit, config, argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
delete_project_config(config);
|
||||
|
||||
} else {
|
||||
printf("Expected 1 target to run\n");
|
||||
}
|
||||
}
|
||||
|
||||
void configure_run_mode(int argc, char *argv[]) {
|
||||
if (argc > 1) {
|
||||
|
||||
ModuleFileStack files;
|
||||
files.files = NULL;
|
||||
|
||||
if (strcmp(argv[1], "build") == 0) {
|
||||
build_project(&files, argc - 2, &argv[2]);
|
||||
} else if (strcmp(argv[1], "compile") == 0) {
|
||||
compile_file(&files, argc - 2, &argv[2]);
|
||||
} else {
|
||||
printf("invalid mode of operation\n");
|
||||
}
|
||||
|
||||
if (files.files == NULL) {
|
||||
|
@ -128,7 +189,23 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
print_unit_statistics(&files);
|
||||
|
||||
delete_files(&files);
|
||||
|
||||
return;
|
||||
}
|
||||
INFO("no arguments provided");
|
||||
|
||||
print_help();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
setup();
|
||||
atexit(close_file);
|
||||
|
||||
printf("running GSC version %s\n", GSC_VERSION);
|
||||
|
||||
configure_run_mode(argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue