Merge remote-tracking branch 'origin/main' into 90-implement-the-struct-tree-for-the-parser
# Conflicts: # src/compiler.c # src/main.c
This commit is contained in:
commit
af07d82d94
|
@ -0,0 +1,20 @@
|
||||||
|
name: MSYS2
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
msys2-mingw64:
|
||||||
|
runs-on: windows-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: msys2 {0}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: MINGW64
|
||||||
|
update: true
|
||||||
|
install: mingw-w64-x86_64-gcc mingw-w64-x86_64-glib2 bison flex mingw-w64-x86_64-llvm cmake git make
|
||||||
|
- name: CI-Build
|
||||||
|
run: |
|
||||||
|
echo 'Running in MSYS2!'
|
||||||
|
./ci-build.sh
|
30
README.md
30
README.md
|
@ -1,17 +1,31 @@
|
||||||
# Gemstone
|
|
||||||
|
|
||||||
Gemstone is a programming language compiler written in C with lex and yacc.
|
<div align="center">
|
||||||
|
<picture>
|
||||||
|
<img alt="gemstone logo" src="https://github.com/Servostar/gemstone/assets/72654954/fdb37c1b-81ca-4e6a-a9e9-c46effb12dae" width="75%">
|
||||||
|
</picture>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## Gemstone
|
||||||
|
|
||||||
|
Gemstone is a programming language compiler (short: GSC) written in C based on flex and GNU bison.
|
||||||
|
It uses LLVM to produce optimized native binaries for many platforms and uses its own builtin build system for more complex project management.
|
||||||
|
|
||||||
## Dependencies (build)
|
## Dependencies (build)
|
||||||
|
|
||||||
### Windows 11
|
### Windows 11
|
||||||
|
|
||||||
For setup instruction see issue #30
|
#### MSYS2
|
||||||
|
|
||||||
Requires:
|
|
||||||
- Microsoft Build Tools 2022 (includes: CMake, MSVC)
|
|
||||||
- WinFlexBison [find it here](https://github.com/lexxmark/winflexbison) (needs to be in PATH)
|
|
||||||
|
|
||||||
|
Install MSYS2 under Windows 11. Open the MingGW64 environment.
|
||||||
|
Install the following packages:
|
||||||
|
```
|
||||||
|
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-glib2 bison flex mingw-w64-x86_64-llvm cmake git make
|
||||||
|
```
|
||||||
|
Clone the repository and build the gemstone compiler:
|
||||||
|
```
|
||||||
|
cmake . && make release
|
||||||
|
```
|
||||||
### GNU/Linux
|
### GNU/Linux
|
||||||
|
|
||||||
Requires:
|
Requires:
|
||||||
|
@ -20,6 +34,8 @@ Requires:
|
||||||
- Make
|
- Make
|
||||||
- bison
|
- bison
|
||||||
- flex
|
- flex
|
||||||
|
- LLVM
|
||||||
|
- Glib 2.0
|
||||||
|
|
||||||
## Writing Tests
|
## Writing Tests
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cmake .
|
||||||
|
make release
|
|
@ -1,15 +1,15 @@
|
||||||
|
|
||||||
#include <ast/ast.h>
|
#include <ast/ast.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char* value) {
|
struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char* value) {
|
||||||
DEBUG("creating new AST node: %d \"%s\"", kind, value);
|
DEBUG("creating new AST node: %d \"%s\"", kind, value);
|
||||||
assert(kind < AST_ELEMENT_COUNT);
|
assert(kind < AST_ELEMENT_COUNT);
|
||||||
|
|
||||||
struct AST_Node_t *node = malloc(sizeof(struct AST_Node_t));
|
struct AST_Node_t *node = mem_alloc(MemoryNamespaceAst, sizeof(struct AST_Node_t));
|
||||||
|
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
PANIC("failed to allocate AST node");
|
PANIC("failed to allocate AST node");
|
||||||
|
@ -134,12 +134,12 @@ void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) {
|
||||||
// if there are no children for now
|
// if there are no children for now
|
||||||
if (owner->child_count == 0) {
|
if (owner->child_count == 0) {
|
||||||
DEBUG("Allocating new children array");
|
DEBUG("Allocating new children array");
|
||||||
owner->children = malloc(sizeof(struct AST_Node_t *));
|
owner->children = mem_alloc(MemoryNamespaceAst, sizeof(struct AST_Node_t *));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG("Rellocating old children array");
|
DEBUG("Rellocating old children array");
|
||||||
const size_t size = sizeof(struct AST_Node_t *) * (owner->child_count + 1);
|
const size_t size = sizeof(struct AST_Node_t *) * (owner->child_count + 1);
|
||||||
owner->children = realloc(owner->children, size);
|
owner->children = mem_realloc(MemoryNamespaceAst, owner->children, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (owner->children == NULL) {
|
if (owner->children == NULL) {
|
||||||
|
@ -214,23 +214,22 @@ void AST_delete_node(struct AST_Node_t *node) {
|
||||||
|
|
||||||
DEBUG("Deleting AST node: %p", node);
|
DEBUG("Deleting AST node: %p", node);
|
||||||
|
|
||||||
if (node->children == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->parent != NULL) {
|
if (node->parent != NULL) {
|
||||||
|
[[maybe_unused]]
|
||||||
const struct AST_Node_t* child = AST_detach_child(node->parent, node);
|
const struct AST_Node_t* child = AST_detach_child(node->parent, node);
|
||||||
assert(child == node);
|
assert(child == node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->children != NULL) {
|
||||||
for (size_t i = 0; i < node->child_count; i++) {
|
for (size_t i = 0; i < node->child_count; i++) {
|
||||||
// prevent detach of children node
|
// prevent detach of children node
|
||||||
node->children[i]->parent = NULL;
|
node->children[i]->parent = NULL;
|
||||||
AST_delete_node(node->children[i]);
|
AST_delete_node(node->children[i]);
|
||||||
}
|
}
|
||||||
|
mem_free(node->children);
|
||||||
|
}
|
||||||
|
|
||||||
free(node->children);
|
mem_free(node);
|
||||||
free(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AST_visit_nodes_recurse2(struct AST_Node_t *root,
|
static void AST_visit_nodes_recurse2(struct AST_Node_t *root,
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <io/files.h>
|
#include <io/files.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <toml.h>
|
#include <toml.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
static GHashTable* args = NULL;
|
static GHashTable* args = NULL;
|
||||||
|
|
||||||
|
@ -17,8 +18,8 @@ static void clean(void) {
|
||||||
g_hash_table_iter_init(&iter, args);
|
g_hash_table_iter_init(&iter, args);
|
||||||
|
|
||||||
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
||||||
free(value);
|
mem_free(value);
|
||||||
free(key);
|
mem_free(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_hash_table_destroy(args);
|
g_hash_table_destroy(args);
|
||||||
|
@ -30,9 +31,9 @@ void parse_options(int argc, char* argv[]) {
|
||||||
atexit(clean);
|
atexit(clean);
|
||||||
|
|
||||||
for (int i = 0; i < argc; i++) {
|
for (int i = 0; i < argc; i++) {
|
||||||
Option* option = malloc(sizeof(Option));
|
Option* option = mem_alloc(MemoryNamespaceOpt, sizeof(Option));
|
||||||
option->is_opt = g_str_has_prefix(argv[i], "--");
|
option->is_opt = g_str_has_prefix(argv[i], "--");
|
||||||
option->string = strdup(argv[i] + (option->is_opt ? 2 : 0));
|
option->string = mem_strdup(MemoryNamespaceOpt, argv[i] + (option->is_opt ? 2 : 0));
|
||||||
option->index = i;
|
option->index = i;
|
||||||
option->value = NULL;
|
option->value = NULL;
|
||||||
|
|
||||||
|
@ -91,15 +92,15 @@ GArray* get_non_options_after(const char* command) {
|
||||||
TargetConfig* default_target_config() {
|
TargetConfig* default_target_config() {
|
||||||
DEBUG("generating default target config...");
|
DEBUG("generating default target config...");
|
||||||
|
|
||||||
TargetConfig* config = malloc(sizeof(TargetConfig));
|
TargetConfig* config = mem_alloc(MemoryNamespaceOpt, sizeof(TargetConfig));
|
||||||
|
|
||||||
config->name = strdup("out");
|
config->name = mem_strdup(MemoryNamespaceOpt, "out");
|
||||||
config->print_ast = false;
|
config->print_ast = false;
|
||||||
config->print_asm = false;
|
config->print_asm = false;
|
||||||
config->print_ir = false;
|
config->print_ir = false;
|
||||||
config->mode = Application;
|
config->mode = Application;
|
||||||
config->archive_directory = strdup("archive");
|
config->archive_directory = mem_strdup(MemoryNamespaceOpt, "archive");
|
||||||
config->output_directory = strdup("bin");
|
config->output_directory = mem_strdup(MemoryNamespaceOpt, "bin");
|
||||||
config->optimization_level = 1;
|
config->optimization_level = 1;
|
||||||
config->root_module = NULL;
|
config->root_module = NULL;
|
||||||
|
|
||||||
|
@ -141,7 +142,7 @@ TargetConfig* default_target_config_from_args() {
|
||||||
const Option* opt = get_option("output");
|
const Option* opt = get_option("output");
|
||||||
|
|
||||||
if (opt->value != NULL) {
|
if (opt->value != NULL) {
|
||||||
config->name = strdup(opt->value);
|
config->name = mem_strdup(MemoryNamespaceOpt, (char*) opt->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +156,7 @@ TargetConfig* default_target_config_from_args() {
|
||||||
print_message(Warning, "Got more than one file to compile, using first, ignoring others.");
|
print_message(Warning, "Got more than one file to compile, using first, ignoring others.");
|
||||||
}
|
}
|
||||||
|
|
||||||
config->root_module = strdup( ((char**) files->data) [0]);
|
config->root_module = mem_strdup(MemoryNamespaceOpt, ((char**) files->data) [0]);
|
||||||
|
|
||||||
g_array_free(files, TRUE);
|
g_array_free(files, TRUE);
|
||||||
}
|
}
|
||||||
|
@ -182,6 +183,7 @@ void print_help(void) {
|
||||||
" --debug print debug logs (if not disabled at compile time)",
|
" --debug print debug logs (if not disabled at compile time)",
|
||||||
" --version print the version",
|
" --version print the version",
|
||||||
" --help print this hel dialog",
|
" --help print this hel dialog",
|
||||||
|
" --print-memory-stats print statistics of the garbage collector"
|
||||||
};
|
};
|
||||||
|
|
||||||
for (unsigned int i = 0; i < sizeof(lines) / sizeof(const char *); i++) {
|
for (unsigned int i = 0; i < sizeof(lines) / sizeof(const char *); i++) {
|
||||||
|
@ -361,32 +363,32 @@ int load_project_config(ProjectConfig *config) {
|
||||||
|
|
||||||
void delete_target_config(TargetConfig* config) {
|
void delete_target_config(TargetConfig* config) {
|
||||||
if (config->root_module != NULL) {
|
if (config->root_module != NULL) {
|
||||||
free(config->root_module);
|
mem_free(config->root_module);
|
||||||
}
|
}
|
||||||
if (config->archive_directory != NULL) {
|
if (config->archive_directory != NULL) {
|
||||||
free(config->archive_directory);
|
mem_free(config->archive_directory);
|
||||||
}
|
}
|
||||||
if (config->name != NULL) {
|
if (config->name != NULL) {
|
||||||
free(config->name);
|
mem_free(config->name);
|
||||||
}
|
}
|
||||||
if (config->output_directory != NULL) {
|
if (config->output_directory != NULL) {
|
||||||
free(config->output_directory);
|
mem_free(config->output_directory);
|
||||||
}
|
}
|
||||||
free(config);
|
mem_free(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_project_config(ProjectConfig* config) {
|
void delete_project_config(ProjectConfig* config) {
|
||||||
if (config->name != NULL) {
|
if (config->name != NULL) {
|
||||||
free(config->name);
|
mem_free(config->name);
|
||||||
}
|
}
|
||||||
if (config->authors != NULL) {
|
if (config->authors != NULL) {
|
||||||
g_array_free(config->authors, TRUE);
|
g_array_free(config->authors, TRUE);
|
||||||
}
|
}
|
||||||
if (config->desc != NULL) {
|
if (config->desc != NULL) {
|
||||||
free(config->desc);
|
mem_free(config->desc);
|
||||||
}
|
}
|
||||||
if (config->license != NULL) {
|
if (config->license != NULL) {
|
||||||
free(config->license);
|
mem_free(config->license);
|
||||||
}
|
}
|
||||||
if (config->targets != NULL) {
|
if (config->targets != NULL) {
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
|
@ -402,11 +404,11 @@ void delete_project_config(ProjectConfig* config) {
|
||||||
g_hash_table_destroy(config->targets);
|
g_hash_table_destroy(config->targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(config);
|
mem_free_from(MemoryNamespaceOpt, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectConfig* default_project_config() {
|
ProjectConfig* default_project_config() {
|
||||||
ProjectConfig* config = malloc(sizeof(ProjectConfig));
|
ProjectConfig* config = mem_alloc(MemoryNamespaceOpt, sizeof(ProjectConfig));
|
||||||
|
|
||||||
config->authors = NULL;
|
config->authors = NULL;
|
||||||
config->name = NULL;
|
config->name = NULL;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <io/files.h>
|
#include <io/files.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <cfg/opt.h>
|
#include <cfg/opt.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
#include <set/set.h>
|
#include <set/set.h>
|
||||||
|
|
||||||
extern void yyrestart(FILE *);
|
extern void yyrestart(FILE *);
|
||||||
|
@ -150,6 +151,9 @@ static void build_target(ModuleFileStack *unit, const TargetConfig *target) {
|
||||||
|
|
||||||
AST_delete_node(ast);
|
AST_delete_node(ast);
|
||||||
|
|
||||||
|
mem_purge_namespace(MemoryNamespaceLex);
|
||||||
|
mem_purge_namespace(MemoryNamespaceAst);
|
||||||
|
|
||||||
print_file_statistics(file);
|
print_file_statistics(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/col.h>
|
#include <sys/col.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
#ifdef __unix__
|
#ifdef __unix__
|
||||||
|
|
||||||
|
@ -15,9 +16,15 @@
|
||||||
|
|
||||||
#define MAX_PATH_BYTES PATH_MAX
|
#define MAX_PATH_BYTES PATH_MAX
|
||||||
|
|
||||||
|
#define min(a, b) ((a) > (b) ? (b) : (a))
|
||||||
|
|
||||||
#elif defined(_WIN32) || defined(WIN32)
|
#elif defined(_WIN32) || defined(WIN32)
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
// for _fullpath
|
||||||
|
#include <stdlib.h>
|
||||||
|
// for _mkdir
|
||||||
|
#include <direct.h>
|
||||||
|
|
||||||
#define MAX_PATH_BYTES _MAX_PATH
|
#define MAX_PATH_BYTES _MAX_PATH
|
||||||
|
|
||||||
|
@ -67,10 +74,6 @@ void delete_files(ModuleFileStack *stack) {
|
||||||
// seeking the current line in print_diagnostic()
|
// seeking the current line in print_diagnostic()
|
||||||
#define SEEK_BUF_BYTES 256
|
#define SEEK_BUF_BYTES 256
|
||||||
|
|
||||||
static inline unsigned long int min(unsigned long int a, unsigned long int b) {
|
|
||||||
return a > b ? b : a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// behaves like fgets except that it has defined behavior when n == 1
|
// behaves like fgets except that it has defined behavior when n == 1
|
||||||
static void custom_fgets(char *buffer, size_t n, FILE *stream) {
|
static void custom_fgets(char *buffer, size_t n, FILE *stream) {
|
||||||
if (n == 1) {
|
if (n == 1) {
|
||||||
|
@ -130,17 +133,17 @@ void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, c
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
free((void *) absolute_path);
|
mem_free((void *) absolute_path);
|
||||||
|
|
||||||
const size_t lines = location->line_end - location->line_start + 1;
|
const unsigned long int lines = location->line_end - location->line_start + 1;
|
||||||
|
|
||||||
for (size_t l = 0; l < lines; l++) {
|
for (unsigned long int l = 0; l < lines; l++) {
|
||||||
printf(" %4ld | ", location->line_start + l);
|
printf(" %4ld | ", location->line_start + l);
|
||||||
|
|
||||||
size_t chars = 0;
|
unsigned long int chars = 0;
|
||||||
|
|
||||||
// print line before token group start
|
// print line before token group start
|
||||||
size_t limit = min(location->col_start, SEEK_BUF_BYTES);
|
unsigned long int limit = min(location->col_start, SEEK_BUF_BYTES);
|
||||||
while (limit > 1) {
|
while (limit > 1) {
|
||||||
custom_fgets(buffer, (int) limit, file->handle);
|
custom_fgets(buffer, (int) limit, file->handle);
|
||||||
chars += printf("%s", buffer);
|
chars += printf("%s", buffer);
|
||||||
|
@ -178,13 +181,13 @@ void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, c
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" | ");
|
printf(" | ");
|
||||||
for (size_t i = 1; i < location->col_start; i++) {
|
for (unsigned long int i = 1; i < location->col_start; i++) {
|
||||||
printf(" ");
|
printf(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s", accent_color);
|
printf("%s", accent_color);
|
||||||
printf("^");
|
printf("^");
|
||||||
for (size_t i = 0; i < location->col_end - location->col_start; i++) {
|
for (unsigned long int i = 0; i < location->col_end - location->col_start; i++) {
|
||||||
printf("~");
|
printf("~");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +318,7 @@ int create_directory(const char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *get_last_error() {
|
const char *get_last_error() {
|
||||||
return strdup(strerror(errno));
|
return mem_strdup(MemoryNamespaceIo, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *get_absolute_path(const char *path) {
|
const char *get_absolute_path(const char *path) {
|
||||||
|
@ -330,10 +333,10 @@ const char *get_absolute_path(const char *path) {
|
||||||
#elif defined(_WIN32) || defined(WIN32)
|
#elif defined(_WIN32) || defined(WIN32)
|
||||||
// use Windows CRT specific function
|
// use Windows CRT specific function
|
||||||
char absolute_path[MAX_PATH_BYTES];
|
char absolute_path[MAX_PATH_BYTES];
|
||||||
_fullpath(path, absolute_path, _MAX_PATH);
|
_fullpath((char*) path, absolute_path, _MAX_PATH);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return strdup(absolute_path);
|
return mem_strdup(MemoryNamespaceIo, absolute_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* make_file_path(const char* name, const char* ext, int count, ...) {
|
const char* make_file_path(const char* name, const char* ext, int count, ...) {
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct FileDiagnosticStatistics_t {
|
typedef struct FileDiagnosticStatistics_t {
|
||||||
size_t error_count;
|
unsigned long int error_count;
|
||||||
size_t warning_count;
|
unsigned long int warning_count;
|
||||||
size_t info_count;
|
unsigned long int info_count;
|
||||||
} FileDiagnosticStatistics;
|
} FileDiagnosticStatistics;
|
||||||
|
|
||||||
typedef struct ModuleFile_t {
|
typedef struct ModuleFile_t {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <yacc/parser.tab.h>
|
#include <yacc/parser.tab.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
#include <lex/util.h>
|
#include <lex/util.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
int yyLineNumber = 1;
|
int yyLineNumber = 1;
|
||||||
|
|
||||||
|
@ -89,20 +90,20 @@
|
||||||
"lineno" {DEBUG("\"%s\" tokenized with \'FunLineno\'", yytext); return(FunLineno);};
|
"lineno" {DEBUG("\"%s\" tokenized with \'FunLineno\'", yytext); return(FunLineno);};
|
||||||
"extsupport" {DEBUG("\"%s\" tokenized with \'FunExtsupport\'", yytext); return(FunExtsupport);};
|
"extsupport" {DEBUG("\"%s\" tokenized with \'FunExtsupport\'", yytext); return(FunExtsupport);};
|
||||||
|
|
||||||
[0-9]+ {DEBUG("\"%s\" tokenized with \'ValInt\'", yytext); yylval.string = strdup(yytext); return(ValInt); };
|
[0-9]+ {DEBUG("\"%s\" tokenized with \'ValInt\'", yytext); yylval.string = mem_strdup(MemoryNamespaceLex, yytext); return(ValInt); };
|
||||||
[0-9]*\.[0-9]+ {DEBUG("\"%s\" tokenized with \'ValFloat\'", yytext); yylval.string = strdup(yytext); return(ValFloat);};
|
[0-9]*\.[0-9]+ {DEBUG("\"%s\" tokenized with \'ValFloat\'", yytext); yylval.string = mem_strdup(MemoryNamespaceLex, yytext); return(ValFloat);};
|
||||||
[a-zA-Z_0-9]+ {DEBUG("\"%s\" tokenized with \'Ident\'", yytext); yylval.string = strdup(yytext); return(Ident); };
|
[a-zA-Z_0-9]+ {DEBUG("\"%s\" tokenized with \'Ident\'", yytext); yylval.string = mem_strdup(MemoryNamespaceLex, yytext); return(Ident); };
|
||||||
|
|
||||||
\"([^\"\n])*\" {
|
\"([^\"\n])*\" {
|
||||||
yytext = yytext +1;
|
yytext = yytext +1;
|
||||||
yytext[yyleng - 2] = 0;
|
yytext[yyleng - 2] = 0;
|
||||||
|
|
||||||
DEBUG("\"%s\" tokenized with \'ValStr\'", yytext); yylval.string = strdup(yytext); return(ValStr);};
|
DEBUG("\"%s\" tokenized with \'ValStr\'", yytext); yylval.string = mem_strdup(MemoryNamespaceLex, yytext); return(ValStr);};
|
||||||
\"\"\"[^\"]*\"\"\" {
|
\"\"\"[^\"]*\"\"\" {
|
||||||
yytext = yytext +3;
|
yytext = yytext +3;
|
||||||
yytext[yyleng - 6] = 0;
|
yytext[yyleng - 6] = 0;
|
||||||
|
|
||||||
DEBUG("\"%s\" tokenized with \'ValMultistr\'", yytext); yylval.string = strdup(yytext); return(ValMultistr);};
|
DEBUG("\"%s\" tokenized with \'ValMultistr\'", yytext); yylval.string = mem_strdup(MemoryNamespaceLex, yytext); return(ValMultistr);};
|
||||||
[ \r\t] { /* ignore whitespace */ };
|
[ \r\t] { /* ignore whitespace */ };
|
||||||
. { return yytext[0]; /* passthrough unknown token, let parser handle the error */ };
|
. { return yytext[0]; /* passthrough unknown token, let parser handle the error */ };
|
||||||
%%
|
%%
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include <lex/util.h>
|
#include <lex/util.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
// implementation based on:
|
// implementation based on:
|
||||||
// https://github.com/sunxfancy/flex-bison-examples/blob/master/error-handling/ccalc.c
|
// https://github.com/sunxfancy/flex-bison-examples/blob/master/error-handling/ccalc.c
|
||||||
|
@ -16,13 +18,8 @@ static int nTokenStart = 0;
|
||||||
static int nTokenLength = 0;
|
static int nTokenLength = 0;
|
||||||
static int nTokenNextStart = 0;
|
static int nTokenNextStart = 0;
|
||||||
|
|
||||||
static void lex_deinit(void) {
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lex_init(void) {
|
void lex_init(void) {
|
||||||
buffer = malloc(MAX_READ_BUFFER_SIZE);
|
buffer = mem_alloc(MemoryNamespaceStatic, MAX_READ_BUFFER_SIZE);
|
||||||
atexit(lex_deinit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lex_reset(void) {
|
void lex_reset(void) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <lex/util.h>
|
#include <lex/util.h>
|
||||||
#include <cfg/opt.h>
|
#include <cfg/opt.h>
|
||||||
#include <compiler.h>
|
#include <compiler.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Log a debug message to inform about beginning exit procedures
|
* @brief Log a debug message to inform about beginning exit procedures
|
||||||
|
@ -17,6 +18,8 @@ void notify_exit(void) { DEBUG("Exiting gemstone..."); }
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void setup(int argc, char *argv[]) {
|
void setup(int argc, char *argv[]) {
|
||||||
|
mem_init();
|
||||||
|
|
||||||
// setup preample
|
// setup preample
|
||||||
parse_options(argc, argv);
|
parse_options(argc, argv);
|
||||||
|
|
||||||
|
@ -57,5 +60,9 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
run_compiler();
|
run_compiler();
|
||||||
|
|
||||||
|
if (is_option_set("print-memory-stats")) {
|
||||||
|
print_memory_statistics();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,271 @@
|
||||||
|
//
|
||||||
|
// Created by servostar on 6/5/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <mem/cache.h>
|
||||||
|
#include <sys/log.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
static GHashTable* namespaces = NULL;
|
||||||
|
|
||||||
|
typedef struct MemoryNamespaceStatistic_t {
|
||||||
|
size_t bytes_allocated;
|
||||||
|
size_t allocation_count;
|
||||||
|
size_t reallocation_count;
|
||||||
|
size_t manual_free_count;
|
||||||
|
size_t faulty_reallocations;
|
||||||
|
size_t faulty_allocations;
|
||||||
|
size_t purged_free_count;
|
||||||
|
} MemoryNamespaceStatistic;
|
||||||
|
|
||||||
|
typedef struct MemoryNamespace_t {
|
||||||
|
MemoryNamespaceStatistic statistic;
|
||||||
|
GArray* blocks;
|
||||||
|
} MemoryNamespace;
|
||||||
|
|
||||||
|
typedef MemoryNamespace* MemoryNamespaceRef;
|
||||||
|
|
||||||
|
static void namespace_statistics_print(MemoryNamespaceStatistic* memoryNamespaceStatistic, char* name) {
|
||||||
|
printf("Memory namespace statistics: `%s`\n", name);
|
||||||
|
printf("------------------------------\n");
|
||||||
|
printf(" allocated bytes: %ld\n", memoryNamespaceStatistic->bytes_allocated);
|
||||||
|
printf(" allocations: %ld\n", memoryNamespaceStatistic->allocation_count);
|
||||||
|
printf(" reallocations: %ld\n", memoryNamespaceStatistic->reallocation_count);
|
||||||
|
printf(" frees: %ld\n", memoryNamespaceStatistic->manual_free_count);
|
||||||
|
printf(" faulty allocations: %ld\n", memoryNamespaceStatistic->faulty_allocations);
|
||||||
|
printf(" faulty reallocations: %ld\n", memoryNamespaceStatistic->faulty_reallocations);
|
||||||
|
printf(" purged allocations: %ld\n", memoryNamespaceStatistic->purged_free_count);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* namespace_malloc(MemoryNamespaceRef memoryNamespace, size_t size) {
|
||||||
|
assert(memoryNamespace != NULL);
|
||||||
|
assert(size != 0);
|
||||||
|
|
||||||
|
void* block = malloc(size);
|
||||||
|
|
||||||
|
if (block == NULL) {
|
||||||
|
memoryNamespace->statistic.faulty_allocations ++;
|
||||||
|
} else {
|
||||||
|
g_array_append_val(memoryNamespace->blocks, block);
|
||||||
|
|
||||||
|
memoryNamespace->statistic.allocation_count ++;
|
||||||
|
memoryNamespace->statistic.bytes_allocated += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean namespace_free(MemoryNamespaceRef memoryNamespace, void* block) {
|
||||||
|
for (guint i = 0; i < memoryNamespace->blocks->len; i++) {
|
||||||
|
void* current_block = g_array_index(memoryNamespace->blocks, void*, i);
|
||||||
|
|
||||||
|
if (current_block == block) {
|
||||||
|
assert(block != NULL);
|
||||||
|
|
||||||
|
free(block);
|
||||||
|
g_array_remove_index(memoryNamespace->blocks, i);
|
||||||
|
|
||||||
|
memoryNamespace->statistic.manual_free_count++;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* namespace_realloc(MemoryNamespaceRef memoryNamespace, void* block, size_t size) {
|
||||||
|
void* reallocated_block = NULL;
|
||||||
|
|
||||||
|
for (guint i = 0; i < memoryNamespace->blocks->len; i++) {
|
||||||
|
void* current_block = g_array_index(memoryNamespace->blocks, void*, i);
|
||||||
|
|
||||||
|
if (current_block == block) {
|
||||||
|
reallocated_block = realloc(block, size);
|
||||||
|
|
||||||
|
if (reallocated_block != NULL) {
|
||||||
|
g_array_index(memoryNamespace->blocks, void*, i) = reallocated_block;
|
||||||
|
memoryNamespace->statistic.bytes_allocated += size;
|
||||||
|
memoryNamespace->statistic.reallocation_count ++;
|
||||||
|
} else {
|
||||||
|
memoryNamespace->statistic.faulty_reallocations++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reallocated_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void namespace_delete(MemoryNamespaceRef memoryNamespace) {
|
||||||
|
g_array_free(memoryNamespace->blocks, TRUE);
|
||||||
|
free(memoryNamespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void namespace_purge(MemoryNamespaceRef memoryNamespace) {
|
||||||
|
|
||||||
|
for (guint i = 0; i < memoryNamespace->blocks->len; i++) {
|
||||||
|
void* current_block = g_array_index(memoryNamespace->blocks, void*, i);
|
||||||
|
|
||||||
|
free(current_block);
|
||||||
|
|
||||||
|
memoryNamespace->statistic.purged_free_count ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_array_remove_range(memoryNamespace->blocks, 0, memoryNamespace->blocks->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MemoryNamespaceRef namespace_new() {
|
||||||
|
MemoryNamespaceRef memoryNamespace = malloc(sizeof(MemoryNamespace));
|
||||||
|
|
||||||
|
memoryNamespace->blocks = g_array_new(FALSE, FALSE, sizeof(void*));
|
||||||
|
memoryNamespace->statistic.bytes_allocated = 0;
|
||||||
|
memoryNamespace->statistic.allocation_count = 0;
|
||||||
|
memoryNamespace->statistic.manual_free_count = 0;
|
||||||
|
memoryNamespace->statistic.faulty_reallocations = 0;
|
||||||
|
memoryNamespace->statistic.faulty_allocations = 0;
|
||||||
|
memoryNamespace->statistic.purged_free_count = 0;
|
||||||
|
memoryNamespace->statistic.reallocation_count = 0;
|
||||||
|
|
||||||
|
return memoryNamespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cleanup() {
|
||||||
|
if (namespaces == NULL) {
|
||||||
|
printf("==> Memory cache was unused <==\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHashTableIter iter;
|
||||||
|
char* name = NULL;
|
||||||
|
MemoryNamespaceRef memoryNamespace = NULL;
|
||||||
|
|
||||||
|
g_hash_table_iter_init(&iter, namespaces);
|
||||||
|
|
||||||
|
while (g_hash_table_iter_next(&iter, (gpointer) &name, (gpointer) &memoryNamespace)) {
|
||||||
|
assert(name != NULL);
|
||||||
|
assert(memoryNamespace != NULL);
|
||||||
|
|
||||||
|
namespace_purge(memoryNamespace);
|
||||||
|
namespace_delete(memoryNamespace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_init() {
|
||||||
|
atexit(cleanup);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MemoryNamespaceRef check_namespace(MemoryNamespaceName name) {
|
||||||
|
if (namespaces == NULL) {
|
||||||
|
namespaces = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_hash_table_contains(namespaces, name)) {
|
||||||
|
|
||||||
|
return g_hash_table_lookup(namespaces, name);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
MemoryNamespaceRef namespace = namespace_new();
|
||||||
|
|
||||||
|
g_hash_table_insert(namespaces, name, namespace);
|
||||||
|
|
||||||
|
return namespace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mem_alloc(MemoryNamespaceName name, size_t size) {
|
||||||
|
MemoryNamespaceRef cache = check_namespace(name);
|
||||||
|
|
||||||
|
if (cache == NULL) {
|
||||||
|
PANIC("memory namespace not created");
|
||||||
|
}
|
||||||
|
|
||||||
|
return namespace_malloc(cache, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mem_realloc(MemoryNamespaceName name, void *ptr, size_t size) {
|
||||||
|
MemoryNamespaceRef cache = check_namespace(name);
|
||||||
|
|
||||||
|
if (cache == NULL) {
|
||||||
|
PANIC("memory namespace not created");
|
||||||
|
}
|
||||||
|
|
||||||
|
return namespace_realloc(cache, ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_free_from(MemoryNamespaceName name, void *memory) {
|
||||||
|
MemoryNamespaceRef cache = check_namespace(name);
|
||||||
|
|
||||||
|
namespace_free(cache, memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_free(void* memory) {
|
||||||
|
GHashTableIter iter;
|
||||||
|
char* name;
|
||||||
|
MemoryNamespaceRef memoryNamespace;
|
||||||
|
|
||||||
|
g_hash_table_iter_init(&iter, namespaces);
|
||||||
|
while (g_hash_table_iter_next(&iter, (gpointer) &name, (gpointer) &memoryNamespace)) {
|
||||||
|
|
||||||
|
if (namespace_free(memoryNamespace, memory)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_purge_namespace(MemoryNamespaceName name) {
|
||||||
|
if (g_hash_table_contains(namespaces, name)) {
|
||||||
|
MemoryNamespaceRef cache = g_hash_table_lookup(namespaces, name);
|
||||||
|
|
||||||
|
namespace_purge(cache);
|
||||||
|
} else {
|
||||||
|
PANIC("purging invalid namespace: %s", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char* mem_strdup(MemoryNamespaceName name, char* string) {
|
||||||
|
return mem_clone(name, string, strlen(string) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mem_clone(MemoryNamespaceName name, void* data, size_t size) {
|
||||||
|
void *clone = mem_alloc(name, size);
|
||||||
|
|
||||||
|
memcpy(clone, data, size);
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_memory_statistics() {
|
||||||
|
GHashTableIter iter;
|
||||||
|
char* name;
|
||||||
|
MemoryNamespaceRef memoryNamespace;
|
||||||
|
|
||||||
|
MemoryNamespaceStatistic total;
|
||||||
|
total.bytes_allocated = 0;
|
||||||
|
total.faulty_reallocations = 0;
|
||||||
|
total.faulty_allocations = 0;
|
||||||
|
total.manual_free_count = 0;
|
||||||
|
total.allocation_count = 0;
|
||||||
|
total.purged_free_count = 0;
|
||||||
|
total.reallocation_count = 0;
|
||||||
|
|
||||||
|
g_hash_table_iter_init(&iter, namespaces);
|
||||||
|
while (g_hash_table_iter_next(&iter, (gpointer) &name, (gpointer) &memoryNamespace)) {
|
||||||
|
|
||||||
|
namespace_statistics_print(&memoryNamespace->statistic, name);
|
||||||
|
|
||||||
|
total.bytes_allocated += memoryNamespace->statistic.bytes_allocated;
|
||||||
|
total.faulty_reallocations += memoryNamespace->statistic.faulty_reallocations;
|
||||||
|
total.faulty_allocations += memoryNamespace->statistic.faulty_allocations;
|
||||||
|
total.manual_free_count += memoryNamespace->statistic.manual_free_count;
|
||||||
|
total.allocation_count += memoryNamespace->statistic.allocation_count;
|
||||||
|
total.purged_free_count += memoryNamespace->statistic.purged_free_count;
|
||||||
|
total.reallocation_count += memoryNamespace->statistic.reallocation_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace_statistics_print(&total, "summary");
|
||||||
|
|
||||||
|
printf("Note: untracked are memory allocations from external libraries.\n");
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
//
|
||||||
|
// Created by servostar on 6/5/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GEMSTONE_CACHE_H
|
||||||
|
#define GEMSTONE_CACHE_H
|
||||||
|
|
||||||
|
#include <mem/cache.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef char* MemoryNamespaceName;
|
||||||
|
|
||||||
|
#define MemoryNamespaceAst "AST"
|
||||||
|
#define MemoryNamespaceLex "Lexer"
|
||||||
|
#define MemoryNamespaceLog "Logging"
|
||||||
|
#define MemoryNamespaceOpt "Options"
|
||||||
|
#define MemoryNamespaceSet "SET"
|
||||||
|
#define MemoryNamespaceLlvm "LLVM"
|
||||||
|
#define MemoryNamespaceIo "I/O"
|
||||||
|
#define MemoryNamespaceStatic "Static"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize the garbage collector.
|
||||||
|
* Must be done to ensure cleanup of memory.
|
||||||
|
*/
|
||||||
|
void mem_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate a block of memory in the specified namespace.
|
||||||
|
* @attention Must only be freed with mem_free() or mem_free_from()
|
||||||
|
* @param name
|
||||||
|
* @param size
|
||||||
|
* @return pointer to the block
|
||||||
|
*/
|
||||||
|
void* mem_alloc(MemoryNamespaceName name, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reallocate a block of memory in the specified namespace.
|
||||||
|
* @attention Must only be freed with mem_free() or mem_free_from()
|
||||||
|
* @param name
|
||||||
|
* @param size
|
||||||
|
* @return pointer to the block
|
||||||
|
*/
|
||||||
|
void* mem_realloc(MemoryNamespaceName name, void *ptr, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free a block of memory from a specified namespace.
|
||||||
|
* Invoking multiple times on the same pointer will do nothing.
|
||||||
|
* @param name
|
||||||
|
* @param memory
|
||||||
|
*/
|
||||||
|
void mem_free_from(MemoryNamespaceName name, void* memory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free a block of memory.
|
||||||
|
* Invoking multiple times on the same pointer will do nothing.
|
||||||
|
* @attention In case the namespace of the block is known, consider using mem_free_from()
|
||||||
|
* to avoid unnecessary overhead.
|
||||||
|
* @param name
|
||||||
|
* @param memory
|
||||||
|
*/
|
||||||
|
void mem_free(void* memory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delete all memory from the given namespace.
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
void mem_purge_namespace(MemoryNamespaceName name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Duplicate the given string with memory in the given namespace.
|
||||||
|
* @param name
|
||||||
|
* @param string
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
char* mem_strdup(MemoryNamespaceName name, char* string);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Duplicate the given block of data with memory in the given namespace.
|
||||||
|
* @param name
|
||||||
|
* @param data
|
||||||
|
* @param size
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
void* mem_clone(MemoryNamespaceName name, void* data, size_t size);
|
||||||
|
|
||||||
|
void print_memory_statistics();
|
||||||
|
|
||||||
|
#endif //GEMSTONE_CACHE_H
|
|
@ -71,8 +71,7 @@ int stdout_supports_ansi_esc() {
|
||||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
if (!GetConsoleMode(hConsole, &mode)) {
|
if (!GetConsoleMode(hConsole, &mode)) {
|
||||||
ERROR("failed to get console mode");
|
return ASNI_DISABLED;
|
||||||
return ANSI_ENABLED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mode & ENABLE_VIRTUAL_TERMINAL_INPUT) |
|
if ((mode & ENABLE_VIRTUAL_TERMINAL_INPUT) |
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <cfg/opt.h>
|
#include <cfg/opt.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
static struct Logger_t {
|
static struct Logger_t {
|
||||||
FILE** streams;
|
FILE** streams;
|
||||||
|
@ -39,7 +40,7 @@ void log_register_stream(FILE* restrict stream)
|
||||||
|
|
||||||
if (GlobalLogger.stream_count == 0)
|
if (GlobalLogger.stream_count == 0)
|
||||||
{
|
{
|
||||||
GlobalLogger.streams = (FILE**) malloc(sizeof(FILE*));
|
GlobalLogger.streams = (FILE**) mem_alloc(MemoryNamespaceLog, sizeof(FILE*));
|
||||||
GlobalLogger.stream_count = 1;
|
GlobalLogger.stream_count = 1;
|
||||||
|
|
||||||
if (GlobalLogger.streams == NULL)
|
if (GlobalLogger.streams == NULL)
|
||||||
|
@ -51,7 +52,7 @@ void log_register_stream(FILE* restrict stream)
|
||||||
{
|
{
|
||||||
GlobalLogger.stream_count++;
|
GlobalLogger.stream_count++;
|
||||||
size_t bytes = GlobalLogger.stream_count * sizeof(FILE*);
|
size_t bytes = GlobalLogger.stream_count * sizeof(FILE*);
|
||||||
GlobalLogger.streams = (FILE**) realloc(GlobalLogger.streams, bytes);
|
GlobalLogger.streams = (FILE**) mem_realloc(MemoryNamespaceLog, GlobalLogger.streams, bytes);
|
||||||
|
|
||||||
if (GlobalLogger.streams == NULL)
|
if (GlobalLogger.streams == NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,3 +11,4 @@ add_subdirectory(input_file)
|
||||||
add_subdirectory(ast)
|
add_subdirectory(ast)
|
||||||
add_subdirectory(glib)
|
add_subdirectory(glib)
|
||||||
add_subdirectory(project)
|
add_subdirectory(project)
|
||||||
|
add_subdirectory(cache)
|
||||||
|
|
|
@ -26,6 +26,7 @@ add_executable(ast_build_tree
|
||||||
${PROJECT_SOURCE_DIR}/src/io/files.c
|
${PROJECT_SOURCE_DIR}/src/io/files.c
|
||||||
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
||||||
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mem/cache.c
|
||||||
${PROJECT_SOURCE_DIR}/dep/tomlc99/toml.c
|
${PROJECT_SOURCE_DIR}/dep/tomlc99/toml.c
|
||||||
build_tree.c)
|
build_tree.c)
|
||||||
set_target_properties(ast_build_tree
|
set_target_properties(ast_build_tree
|
||||||
|
@ -47,6 +48,7 @@ add_executable(ast_print_node
|
||||||
${PROJECT_SOURCE_DIR}/src/io/files.c
|
${PROJECT_SOURCE_DIR}/src/io/files.c
|
||||||
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
||||||
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mem/cache.c
|
||||||
${PROJECT_SOURCE_DIR}/dep/tomlc99/toml.c
|
${PROJECT_SOURCE_DIR}/dep/tomlc99/toml.c
|
||||||
print_node.c)
|
print_node.c)
|
||||||
set_target_properties(ast_print_node
|
set_target_properties(ast_print_node
|
||||||
|
@ -68,6 +70,7 @@ add_executable(ast_graphviz
|
||||||
${PROJECT_SOURCE_DIR}/src/io/files.c
|
${PROJECT_SOURCE_DIR}/src/io/files.c
|
||||||
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
||||||
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mem/cache.c
|
||||||
${PROJECT_SOURCE_DIR}/dep/tomlc99/toml.c
|
${PROJECT_SOURCE_DIR}/dep/tomlc99/toml.c
|
||||||
print_graphviz.c)
|
print_graphviz.c)
|
||||||
set_target_properties(ast_graphviz
|
set_target_properties(ast_graphviz
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <ast/ast.h>
|
#include <ast/ast.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
void generate_statement(const AST_NODE_PTR stmt) {
|
void generate_statement(const AST_NODE_PTR stmt) {
|
||||||
const AST_NODE_PTR add = AST_new_node(empty_location(), AST_Add, NULL);
|
const AST_NODE_PTR add = AST_new_node(empty_location(), AST_Add, NULL);
|
||||||
|
@ -29,6 +30,7 @@ void generate_branch(const AST_NODE_PTR stmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
mem_init();
|
||||||
|
|
||||||
const AST_NODE_PTR root = AST_new_node(empty_location(), AST_Stmt, NULL);
|
const AST_NODE_PTR root = AST_new_node(empty_location(), AST_Stmt, NULL);
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
|
|
||||||
#include <ast/ast.h>
|
#include <ast/ast.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
mem_init();
|
||||||
|
|
||||||
struct AST_Node_t* node = AST_new_node(empty_location(), AST_If, NULL);
|
struct AST_Node_t* node = AST_new_node(empty_location(), AST_If, NULL);
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <ast/ast.h>
|
#include <ast/ast.h>
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
void generate_statement(const AST_NODE_PTR stmt) {
|
void generate_statement(const AST_NODE_PTR stmt) {
|
||||||
const AST_NODE_PTR add = AST_new_node(empty_location(), AST_Add, NULL);
|
const AST_NODE_PTR add = AST_new_node(empty_location(), AST_Add, NULL);
|
||||||
|
@ -29,7 +30,7 @@ void generate_branch(const AST_NODE_PTR stmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
mem_init();
|
||||||
AST_init();
|
AST_init();
|
||||||
|
|
||||||
const AST_NODE_PTR root = AST_new_node(empty_location(), AST_Stmt, NULL);
|
const AST_NODE_PTR root = AST_new_node(empty_location(), AST_Stmt, NULL);
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <ast/ast.h>
|
#include <ast/ast.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
mem_init();
|
||||||
AST_init();
|
AST_init();
|
||||||
|
|
||||||
const AST_NODE_PTR node = AST_new_node(empty_location(), 0, "value");
|
const AST_NODE_PTR node = AST_new_node(empty_location(), 0, "value");
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
include(CTest)
|
||||||
|
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||||
|
|
||||||
|
# ------------------------------------------------ #
|
||||||
|
# Setup Glib 2.0 #
|
||||||
|
# ------------------------------------------------ #
|
||||||
|
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
|
||||||
|
include_directories(PRIVATE ${GLIB_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
# ------------------------------------------------ #
|
||||||
|
# Setup TOML-C99 #
|
||||||
|
# ------------------------------------------------ #
|
||||||
|
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/dep/tomlc99)
|
||||||
|
|
||||||
|
# ------------------------------------------------------- #
|
||||||
|
# CTEST 1
|
||||||
|
# test the memory cache
|
||||||
|
|
||||||
|
add_executable(cache
|
||||||
|
${PROJECT_SOURCE_DIR}/src/sys/log.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/io/files.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mem/cache.c
|
||||||
|
cache_test.c)
|
||||||
|
set_target_properties(cache
|
||||||
|
PROPERTIES
|
||||||
|
OUTPUT_NAME "cache"
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/cache)
|
||||||
|
target_link_libraries(cache PkgConfig::GLIB)
|
||||||
|
target_link_libraries(cache tomlc99)
|
||||||
|
add_test(NAME cache
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
|
COMMAND ${GEMSTONE_BINARY_DIR}/tests/cache/cache)
|
|
@ -0,0 +1,28 @@
|
||||||
|
//
|
||||||
|
// Created by servostar on 6/5/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <sys/log.h>
|
||||||
|
#include <sys/col.h>
|
||||||
|
#include <cfg/opt.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
mem_init();
|
||||||
|
parse_options(argc, argv);
|
||||||
|
log_init();
|
||||||
|
set_log_level(LOG_LEVEL_DEBUG);
|
||||||
|
col_init();
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
void* data = mem_alloc(MemoryNamespaceAst, 457);
|
||||||
|
mem_realloc(MemoryNamespaceAst, data, 200);
|
||||||
|
mem_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
mem_purge_namespace(MemoryNamespaceOpt);
|
||||||
|
|
||||||
|
print_memory_statistics();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ add_executable(logging_output
|
||||||
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
||||||
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
||||||
${PROJECT_SOURCE_DIR}/src/io/files.c
|
${PROJECT_SOURCE_DIR}/src/io/files.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mem/cache.c
|
||||||
output.c)
|
output.c)
|
||||||
set_target_properties(logging_output
|
set_target_properties(logging_output
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
@ -45,6 +46,7 @@ add_executable(logging_panic
|
||||||
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
||||||
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
||||||
${PROJECT_SOURCE_DIR}/src/io/files.c
|
${PROJECT_SOURCE_DIR}/src/io/files.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mem/cache.c
|
||||||
panic.c)
|
panic.c)
|
||||||
set_target_properties(logging_panic
|
set_target_properties(logging_panic
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
@ -65,6 +67,7 @@ add_executable(logging_streams
|
||||||
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
||||||
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
||||||
${PROJECT_SOURCE_DIR}/src/io/files.c
|
${PROJECT_SOURCE_DIR}/src/io/files.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mem/cache.c
|
||||||
streams.c)
|
streams.c)
|
||||||
set_target_properties(logging_streams
|
set_target_properties(logging_streams
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
@ -85,6 +88,7 @@ add_executable(logging_level
|
||||||
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
${PROJECT_SOURCE_DIR}/src/sys/col.c
|
||||||
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
${PROJECT_SOURCE_DIR}/src/cfg/opt.c
|
||||||
${PROJECT_SOURCE_DIR}/src/io/files.c
|
${PROJECT_SOURCE_DIR}/src/io/files.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mem/cache.c
|
||||||
level.c)
|
level.c)
|
||||||
set_target_properties(logging_level
|
set_target_properties(logging_level
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
|
|
@ -5,10 +5,12 @@
|
||||||
#include "sys/log.h"
|
#include "sys/log.h"
|
||||||
#include <sys/col.h>
|
#include <sys/col.h>
|
||||||
#include <cfg/opt.h>
|
#include <cfg/opt.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
#define LOG_LEVEL LOG_LEVEL_WARNING
|
#define LOG_LEVEL LOG_LEVEL_WARNING
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
mem_init();
|
||||||
parse_options(argc, argv);
|
parse_options(argc, argv);
|
||||||
log_init();
|
log_init();
|
||||||
set_log_level(LOG_LEVEL_DEBUG);
|
set_log_level(LOG_LEVEL_DEBUG);
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
#include "sys/log.h"
|
#include "sys/log.h"
|
||||||
#include <sys/col.h>
|
#include <sys/col.h>
|
||||||
#include <cfg/opt.h>
|
#include <cfg/opt.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
mem_init();
|
||||||
parse_options(argc, argv);
|
parse_options(argc, argv);
|
||||||
log_init();
|
log_init();
|
||||||
set_log_level(LOG_LEVEL_DEBUG);
|
set_log_level(LOG_LEVEL_DEBUG);
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
|
|
||||||
#include "sys/log.h"
|
#include "sys/log.h"
|
||||||
#include <cfg/opt.h>
|
#include <cfg/opt.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
mem_init();
|
||||||
parse_options(argc, argv);
|
parse_options(argc, argv);
|
||||||
log_init();
|
log_init();
|
||||||
set_log_level(LOG_LEVEL_DEBUG);
|
set_log_level(LOG_LEVEL_DEBUG);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "sys/log.h"
|
#include "sys/log.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cfg/opt.h>
|
#include <cfg/opt.h>
|
||||||
|
#include <mem/cache.h>
|
||||||
|
|
||||||
static FILE* file;
|
static FILE* file;
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ void close_file(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
mem_init();
|
||||||
parse_options(argc, argv);
|
parse_options(argc, argv);
|
||||||
log_init();
|
log_init();
|
||||||
set_log_level(LOG_LEVEL_DEBUG);
|
set_log_level(LOG_LEVEL_DEBUG);
|
||||||
|
|
Loading…
Reference in New Issue