Merge remote-tracking branch 'origin/main' into 6-add-mechanism-to-read-and-globally-save-options

# Conflicts:
#	CMakeLists.txt
#	src/main.c
This commit is contained in:
Sven Vogel 2024-05-31 16:21:25 +02:00
commit 0c722f3635
28 changed files with 1152 additions and 301 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
SDK=0.2.4-alpine-3.19.1

View File

@ -1,14 +1,14 @@
name: "Build check gemstone in SDK" name: "Build check gemstone in SDK"
run-name: SDK build check to ${{ inputs.deploy_target }} by @${{ github.actor }} run-name: SDK build check to ${{ inputs.deploy_target }} by @${{ github.actor }}
on: [push, pull_request] on: [push, pull_request]
env:
SDK: 0.2.3-alpine-3.19.1
jobs: jobs:
build-check-sdk: build-check-sdk:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup repository
run: git submodule init && git submodule update
- name: Setup SDK - name: Setup SDK
run: docker pull servostar/gemstone:sdk-"$SDK" && docker build --tag gemstone:devkit-"$SDK" . run: source ./.env && docker pull servostar/gemstone:sdk-"$SDK"
- name: Compile - name: Compile
run: docker run gemstone:devkit-"$SDK" sh run-check-test.sh run: set -a && source ./.env && sh run-docker-build.sh

View File

@ -61,11 +61,18 @@ set(YACC_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.y)
set(YACC_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c) set(YACC_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c)
add_custom_command(OUTPUT ${YACC_GENERATED_SOURCE_FILE} add_custom_command(OUTPUT ${YACC_GENERATED_SOURCE_FILE}
COMMAND yacc COMMAND bison
ARGS -Wno-yacc -Wcounterexamples -d -o ${YACC_GENERATED_SOURCE_FILE} ${YACC_SOURCE_FILE} ARGS -Wno-yacc -Wcounterexamples -d -o ${YACC_GENERATED_SOURCE_FILE} ${YACC_SOURCE_FILE}
COMMENT "generate C source file for parser" COMMENT "generate C source file for parser"
VERBATIM) VERBATIM)
# ------------------------------------------------ #
# Setup Glib 2.0 #
# ------------------------------------------------ #
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
# ------------------------------------------------ # # ------------------------------------------------ #
# TOML-C99 # # TOML-C99 #
# ------------------------------------------------ # # ------------------------------------------------ #
@ -84,17 +91,21 @@ set_target_properties(tomlc99
include_directories(${PROJECT_SOURCE_DIR}/dep/tomlc99) include_directories(${PROJECT_SOURCE_DIR}/dep/tomlc99)
# ------------------------------------------------ # # ------------------------------------------------ #
# Source # # Source #
# ------------------------------------------------ # # ------------------------------------------------ #
include_directories(${PROJECT_SOURCE_DIR}/src)
include_directories(PRIVATE ${GLIB_INCLUDE_DIRS})
file(GLOB_RECURSE SOURCE_FILES src/*.c) file(GLOB_RECURSE SOURCE_FILES src/*.c)
# define default compile flags # define default compile flags
if (MSVC) if (MSVC)
set(FLAGS /Wall /W3 /permissive) set(FLAGS /Wall /W3 /permissive)
else() else()
set(FLAGS -Wall -Wextra -Wconversion -Wpedantic) set(FLAGS -Wall -Wextra -Wpedantic)
endif() endif()
# ------------------------------------------------ # # ------------------------------------------------ #
@ -111,6 +122,8 @@ set_target_properties(release
OUTPUT_NAME "gsc" OUTPUT_NAME "gsc"
RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/release) RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/release)
target_link_libraries(release PkgConfig::GLIB)
target_link_libraries(release tomlc99) target_link_libraries(release tomlc99)
# FIXME: cannot compile with /O2 because of /RTC1 flag # FIXME: cannot compile with /O2 because of /RTC1 flag
@ -145,6 +158,8 @@ set_target_properties(debug
OUTPUT_NAME "gsc" OUTPUT_NAME "gsc"
RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/debug) RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/debug)
target_link_libraries(debug PkgConfig::GLIB)
target_link_libraries(debug tomlc99) target_link_libraries(debug tomlc99)
if (MSVC) if (MSVC)
@ -176,6 +191,8 @@ set_target_properties(check
OUTPUT_NAME "gsc" OUTPUT_NAME "gsc"
RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/check) RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/check)
target_link_libraries(check PkgConfig::GLIB)
target_link_libraries(check tomlc99) target_link_libraries(check tomlc99)
if (MSVC) if (MSVC)

View File

@ -1,6 +1,6 @@
FROM servostar/gemstone:sdk-0.2.3-alpine-3.19.1 FROM servostar/gemstone:sdk-0.2.4-alpine-3.19.1
LABEL authors="servostar" LABEL authors="servostar"
LABEL version="0.2.3" LABEL version="0.2.4"
LABEL description="docker image for setting up the build pipeline on SDK" LABEL description="docker image for setting up the build pipeline on SDK"
LABEL website="https://github.com/Servostar/gemstone" LABEL website="https://github.com/Servostar/gemstone"
@ -8,5 +8,7 @@ COPY --chown=lorang src /home/lorang/src
COPY --chown=lorang tests /home/lorang/tests COPY --chown=lorang tests /home/lorang/tests
COPY --chown=lorang CMakeLists.txt /home/lorang/ COPY --chown=lorang CMakeLists.txt /home/lorang/
COPY --chown=lorang run-check-test.sh /home/lorang/ COPY --chown=lorang run-check-test.sh /home/lorang/
COPY --chown=lorang .env /home/lorang/
COPY --chown=lorang run-docker-build.sh /home/lorang/
RUN cmake . RUN cmake .

View File

@ -9,6 +9,8 @@ echo "+--------------------------------------+"
echo "| BUILDING all TARGETS |" echo "| BUILDING all TARGETS |"
echo "+--------------------------------------+" echo "+--------------------------------------+"
cmake .
make -B make -B
if [ ! $? -eq 0 ]; then if [ ! $? -eq 0 ]; then
echo "===> failed to build targets" echo "===> failed to build targets"

58
run-docker-build.sh Executable file
View File

@ -0,0 +1,58 @@
#!/usr/bin/env sh
# Author: Sven Vogel
# Created: 17.05.2024
# Description: Builds the Dockerfile for SDK and DEVKIT
echo "+--------------------------------------+"
echo "| CHECKING prelude |"
echo "+--------------------------------------+"
if [ -z "$SDK" ]; then
echo "no SDK specified, sourcing .env"
source ./.env
if [ -z "$SDK" ]; then
echo "no SDK specified"
exit 1
else
echo "using SDK $SDK"
fi
else
echo "using SDK $SDK"
fi
echo "+--------------------------------------+"
echo "| BUILDING SDK |"
echo "+--------------------------------------+"
docker build --tag servostar/gemstone:sdk-"$SDK" sdk/.
if [ ! $? -eq 0 ]; then
echo "===> failed to build sdk"
exit 1
fi
echo "+--------------------------------------+"
echo "| BUILDING DEVKIT |"
echo "+--------------------------------------+"
docker build --tag servostar/gemstone:devkit-"$SDK" .
if [ ! $? -eq 0 ]; then
echo "===> failed to build devkit"
exit 1
fi
echo "+--------------------------------------+"
echo "| RUNNING check test |"
echo "+--------------------------------------+"
docker run servostar/gemstone:devkit-"$SDK" sh run-check-test.sh
if [ ! $? -eq 0 ]; then
echo "===> failed to run build or checks"
exit 1
fi
echo "+--------------------------------------+"
echo "| DONE |"
echo "+--------------------------------------+"

View File

@ -1,11 +1,11 @@
FROM alpine:3.19.1 FROM alpine:3.19.1
LABEL authors="servostar" LABEL authors="servostar"
LABEL version="0.2.3" LABEL version="0.2.4"
LABEL description="base image for building the gemstone programming language compiler" LABEL description="base image for building the gemstone programming language compiler"
LABEL website="https://github.com/Servostar/gemstone" LABEL website="https://github.com/Servostar/gemstone"
# install dependencies # install dependencies
RUN apk add build-base gcc make cmake bison flex git python3 graphviz RUN apk add build-base gcc make cmake bison flex git python3 graphviz glib glib-dev
# create user for build # create user for build
RUN adduser --disabled-password lorang RUN adduser --disabled-password lorang

View File

@ -5,7 +5,7 @@
#include <sys/log.h> #include <sys/log.h>
#include <assert.h> #include <assert.h>
struct AST_Node_t *AST_new_node(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);
@ -23,6 +23,7 @@ struct AST_Node_t *AST_new_node(enum AST_SyntaxElement_t kind, const char* value
node->child_count = 0; node->child_count = 0;
node->kind = kind; node->kind = kind;
node->value = value; node->value = value;
node->location = location;
return node; return node;
} }
@ -33,8 +34,8 @@ void AST_init() {
DEBUG("initializing global syntax tree..."); DEBUG("initializing global syntax tree...");
INFO("filling lookup table..."); INFO("filling lookup table...");
lookup_table[AST_Stmt] = "stmt"; lookup_table[AST_Stmt] = "stmt";
lookup_table[AST_Module] = "module";
lookup_table[AST_Expr] = "expr"; lookup_table[AST_Expr] = "expr";
lookup_table[AST_Add] = "+"; lookup_table[AST_Add] = "+";
@ -69,9 +70,20 @@ void AST_init() {
lookup_table[AST_Box] = "box"; lookup_table[AST_Box] = "box";
lookup_table[AST_Fun] = "fun"; lookup_table[AST_Fun] = "fun";
lookup_table[AST_Typecast] = "cast"; lookup_table[AST_Call] = "funcall";
lookup_table[AST_Transmute] = "as"; lookup_table[AST_Typecast] = "typecast";
lookup_table[AST_Transmute] = "transmute";
lookup_table[AST_Condition] = "condition"; lookup_table[AST_Condition] = "condition";
lookup_table[AST_List] = "list";
lookup_table[AST_ExprList] = "expr list";
lookup_table[AST_ArgList] = "arg list";
lookup_table[AST_ParamList] = "param list";
lookup_table[AST_StmtList] = "stmt list";
lookup_table[AST_IdentList] = "ident list";
lookup_table[AST_Type] = "type";
lookup_table[AST_Negate] = "-";
lookup_table[AST_Parameter] = "parameter";
lookup_table[AST_ParamDecl] = "parameter-declaration";
} }
const char* AST_node_to_string(const struct AST_Node_t* node) { const char* AST_node_to_string(const struct AST_Node_t* node) {
@ -87,7 +99,11 @@ const char* AST_node_to_string(const struct AST_Node_t* node) {
case AST_Ident: case AST_Ident:
case AST_Macro: case AST_Macro:
case AST_Import: case AST_Import:
case AST_Call: case AST_Storage:
case AST_Typekind:
case AST_Sign:
case AST_Scale:
case AST_Qualifyier:
string = node->value; string = node->value;
break; break;
default: default:
@ -99,6 +115,14 @@ const char* AST_node_to_string(const struct AST_Node_t* node) {
return string; return string;
} }
static inline unsigned long int min(unsigned long int a, unsigned long int b) {
return a > b ? b : a;
}
static inline unsigned long int max(unsigned long int a, unsigned long int b) {
return a > b ? a : b;
}
void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) { void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) {
DEBUG("Adding new node %p to %p", child, owner); DEBUG("Adding new node %p to %p", child, owner);
assert(owner != NULL); assert(owner != NULL);
@ -119,6 +143,12 @@ void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) {
PANIC("failed to allocate children array of AST node"); PANIC("failed to allocate children array of AST node");
} }
owner->location.col_end = max(owner->location.col_end, child->location.col_end);
owner->location.line_end = max(owner->location.line_end, child->location.line_end);
owner->location.col_start = min(owner->location.col_start, child->location.col_start);
owner->location.line_start = min(owner->location.line_start, child->location.line_start);
assert(owner->children != NULL); assert(owner->children != NULL);
owner->children[owner->child_count++] = child; owner->children[owner->child_count++] = child;

View File

@ -3,6 +3,7 @@
#define _AST_H_ #define _AST_H_
#include <stdio.h> #include <stdio.h>
#include <io/files.h>
/** /**
* @brief The type of a AST node * @brief The type of a AST node
@ -12,6 +13,7 @@
*/ */
enum AST_SyntaxElement_t { enum AST_SyntaxElement_t {
AST_Stmt = 0, AST_Stmt = 0,
AST_Module,
AST_Expr, AST_Expr,
// Literals // Literals
AST_Int, AST_Int,
@ -58,7 +60,22 @@ enum AST_SyntaxElement_t {
AST_Fun, AST_Fun,
AST_Import, AST_Import,
// amount of variants // amount of variants
// in this enum // in this enums
AST_List,
AST_ExprList,
AST_ArgList,
AST_ParamList,
AST_StmtList,
AST_IdentList,
AST_Storage,
AST_Type,
AST_Typekind,
AST_Sign,
AST_Scale,
AST_Negate,
AST_Parameter,
AST_Qualifyier,
AST_ParamDecl,
AST_ELEMENT_COUNT AST_ELEMENT_COUNT
}; };
@ -78,6 +95,8 @@ struct AST_Node_t {
// optional value: integer literal, string literal, ... // optional value: integer literal, string literal, ...
const char* value; const char* value;
TokenLocation location;
// number of child nodes ownd by this node // number of child nodes ownd by this node
// length of children array // length of children array
size_t child_count; size_t child_count;
@ -117,7 +136,7 @@ const char* AST_node_to_string(const struct AST_Node_t* node);
[[maybe_unused]] [[maybe_unused]]
[[nodiscard("pointer must be freed")]] [[nodiscard("pointer must be freed")]]
[[gnu::returns_nonnull]] [[gnu::returns_nonnull]]
struct AST_Node_t *AST_new_node(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);
/** /**
* @brief Deallocate this node and all of its children. * @brief Deallocate this node and all of its children.

235
src/io/files.c Normal file
View File

@ -0,0 +1,235 @@
//
// Created by servostar on 5/30/24.
//
#include <io/files.h>
#include <sys/log.h>
#include <assert.h>
#include <sys/col.h>
ModuleFile *push_file(ModuleFileStack *stack, const char *path) {
assert(stack != NULL);
// lazy init of heap stack
if (stack->files == NULL) {
stack->files = g_array_new(FALSE, FALSE, sizeof(ModuleFile));
}
ModuleFile new_file = {
.path = path,
.handle = NULL
};
g_array_append_val(stack->files, new_file);
return ((ModuleFile *) stack->files->data) + stack->files->len - 1;
}
void delete_files(ModuleFileStack *stack) {
for (size_t i = 0; i < stack->files->len; i++) {
ModuleFile *file = ((ModuleFile *) stack->files->data) + i;
if (file->handle != NULL) {
DEBUG("closing file: %s", file->path);
fclose(file->handle);
}
}
g_array_free(stack->files, TRUE);
DEBUG("deleted module file stack");
}
#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
static void custom_fgets(char *buffer, size_t n, FILE *stream) {
if (n == 1) {
buffer[0] = (char) fgetc(stream);
buffer[1] = 0;
} else {
fgets(buffer, (int) n, stream);
}
}
void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, const char *message) {
assert(file->handle != NULL);
assert(location != NULL);
assert(message != NULL);
// reset to start
rewind(file->handle);
char *buffer = alloca(SEEK_BUF_BYTES);
unsigned long int line_count = 1;
// seek to first line
while (line_count < location->line_start && fgets(buffer, SEEK_BUF_BYTES, file->handle) != NULL) {
line_count += strchr(buffer, '\n') != NULL;
}
const char *accent_color = RESET;
const char *kind_text = "unknown";
switch (kind) {
case Info:
kind_text = "info";
accent_color = CYAN;
file->statistics.info_count++;
break;
case Warning:
kind_text = "warning";
accent_color = YELLOW;
file->statistics.warning_count++;
break;
case Error:
kind_text = "error";
accent_color = RED;
file->statistics.error_count++;
break;
}
char absolute_path[PATH_MAX];
realpath(file->path, absolute_path);
printf("%s%s:%ld:%s %s%s:%s %s\n", BOLD, absolute_path, location->line_start, RESET, accent_color, kind_text, RESET,
message);
size_t lines = location->line_end - location->line_start + 1;
for (size_t l = 0; l < lines; l++) {
printf(" %4ld | ", location->line_start + l);
size_t limit;
size_t chars = 0;
// print line before token group start
limit = min(location->col_start, SEEK_BUF_BYTES);
while (limit > 1) {
custom_fgets(buffer, (int) limit, file->handle);
chars += printf("%s", buffer);
limit = min(location->col_start - chars, SEEK_BUF_BYTES);
if (strchr(buffer, '\n') != NULL) {
goto cont;
}
}
printf("%s", accent_color);
chars = 0;
limit = min(location->col_end - location->col_start + 1, SEEK_BUF_BYTES);
while (limit > 0) {
custom_fgets(buffer, (int) limit, file->handle);
chars += printf("%s", buffer);
limit = min(location->col_end - location->col_start + 1 - chars, SEEK_BUF_BYTES);
if (strchr(buffer, '\n') != NULL) {
goto cont;
}
}
printf("%s", RESET);
// print rest of the line
do {
custom_fgets(buffer, SEEK_BUF_BYTES, file->handle);
printf("%s", buffer);
} while (strchr(buffer, '\n') == NULL);
cont:
printf("%s", RESET);
}
printf(" | ");
for (size_t i = 1; i < location->col_start; i++) {
printf(" ");
}
printf("%s", accent_color);
printf("^");
for (size_t i = 0; i < location->col_end - location->col_start; i++) {
printf("~");
}
printf("%s\n\n", RESET);
}
TokenLocation new_location(unsigned long int line_start, unsigned long int col_start, unsigned long int line_end,
unsigned long int col_end) {
TokenLocation location;
location.line_start = line_start;
location.line_end = line_end;
location.col_start = col_start;
location.col_end = col_end;
return location;
}
TokenLocation empty_location(void) {
TokenLocation location;
location.line_start = 0;
location.line_end = 0;
location.col_start = 0;
location.col_end = 0;
return location;
}
void print_file_statistics(ModuleFile *file) {
if (file->statistics.info_count + file->statistics.warning_count + file->statistics.error_count < 1) {
return;
}
printf("File %s generated ", file->path);
if (file->statistics.info_count > 0) {
printf("%ld notice(s) ", file->statistics.info_count);
}
if (file->statistics.warning_count > 0) {
printf("%ld warning(s) ", file->statistics.warning_count);
}
if (file->statistics.error_count > 0) {
printf("%ld error(s) ", file->statistics.error_count);
}
printf("\n\n");
}
void print_unit_statistics(ModuleFileStack *file_stack) {
FileDiagnosticStatistics stats;
stats.info_count = 0;
stats.warning_count = 0;
stats.error_count = 0;
for (size_t i = 0; i < file_stack->files->len; i++) {
ModuleFile *file = (ModuleFile *) file_stack->files->data;
stats.info_count += file->statistics.warning_count;
stats.warning_count += file->statistics.warning_count;
stats.error_count += file->statistics.error_count;
}
printf("%d files generated ", file_stack->files->len);
if (stats.info_count > 0) {
printf("%ld notice(s) ", stats.info_count);
}
if (stats.warning_count > 0) {
printf("%ld warning(s) ", stats.warning_count);
}
if (stats.error_count > 0) {
printf("%ld error(s) ", stats.error_count);
}
printf("\n\n");
}

79
src/io/files.h Normal file
View File

@ -0,0 +1,79 @@
//
// Created by servostar on 5/30/24.
//
#ifndef GEMSTONE_FILES_H
#define GEMSTONE_FILES_H
#include <stdio.h>
#include <glib.h>
typedef struct FileDiagnosticStatistics_t {
size_t error_count;
size_t warning_count;
size_t info_count;
} FileDiagnosticStatistics;
typedef struct ModuleFile_t {
const char *path;
FILE *handle;
FileDiagnosticStatistics statistics;
} ModuleFile;
typedef struct ModuleFileStack_t {
GArray *files;
} ModuleFileStack;
typedef enum Message_t {
Info,
Warning,
Error
} Message;
typedef struct TokenLocation_t {
unsigned long int line_start;
unsigned long int col_start;
unsigned long int line_end;
unsigned long int col_end;
} TokenLocation;
/**
* @brief Add a new file to the file stack.
* @attention The file handle returned will be invalid
* @param stack
* @param path
* @return A new file module
*/
[[gnu::nonnull(1), gnu::nonnull(2)]]
ModuleFile *push_file(ModuleFileStack *stack, const char *path);
/**
* @brief Delete all files in the stack and the stack itself
* @param stack
*/
[[gnu::nonnull(1)]]
void delete_files(ModuleFileStack *stack);
/**
* Create a new token location
* @param line_start
* @param col_start
* @param line_end
* @param col_end
* @return
*/
TokenLocation new_location(unsigned long int line_start, unsigned long int col_start, unsigned long int line_end,
unsigned long int col_end);
TokenLocation empty_location(void);
[[gnu::nonnull(1), gnu::nonnull(2)]]
void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, const char *message);
[[gnu::nonnull(1)]]
void print_file_statistics(ModuleFile *file);
[[gnu::nonnull(1)]]
void print_unit_statistics(ModuleFileStack *file_stack);
#endif //GEMSTONE_FILES_H

View File

@ -52,6 +52,7 @@
"float" {DEBUG("\"%s\" tokenized with \'KeyFloat\'", yytext); return(KeyFloat);}; "float" {DEBUG("\"%s\" tokenized with \'KeyFloat\'", yytext); return(KeyFloat);};
"self" {DEBUG("\"%s\" tokenized with \'KeySelf\'", yytext); return(KeySelf);}; "self" {DEBUG("\"%s\" tokenized with \'KeySelf\'", yytext); return(KeySelf);};
"as" {DEBUG("\"%s\" tokenized with \'KeyAs'", yytext); return (KeyAs);}; "as" {DEBUG("\"%s\" tokenized with \'KeyAs'", yytext); return (KeyAs);};
"to" {DEBUG("\"%s\" tokenized with \'KeyTo'", yytext); return (KeyTo);};
"short" {DEBUG("\"%s\" tokenized with \'KeyShort\'", yytext); return(KeyShort);}; "short" {DEBUG("\"%s\" tokenized with \'KeyShort\'", yytext); return(KeyShort);};
"long" {DEBUG("\"%s\" tokenized with \'KeyLong\'", yytext); return(KeyLong);}; "long" {DEBUG("\"%s\" tokenized with \'KeyLong\'", yytext); return(KeyLong);};
"half" {DEBUG("\"%s\" tokenized with \'KeyHalf\'", yytext); return(KeyHalf);}; "half" {DEBUG("\"%s\" tokenized with \'KeyHalf\'", yytext); return(KeyHalf);};
@ -91,8 +92,17 @@
[0-9]+ {DEBUG("\"%s\" tokenized with \'ValInt\'", yytext); yylval.string = strdup(yytext); return(ValInt); }; [0-9]+ {DEBUG("\"%s\" tokenized with \'ValInt\'", yytext); yylval.string = strdup(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 = strdup(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 = strdup(yytext); return(Ident); };
\"([^\"\n])*\" {DEBUG("\"%s\" tokenized with \'ValStr\'", yytext); yylval.string = strdup(yytext); return(ValStr);};
\"\"\"([^\"\n]|\\\n)*\"\"\" {DEBUG("\"%s\" tokenized with \'ValMultistr\'", yytext); yylval.string = strdup(yytext); return(ValMultistr);}; \"([^\"\n])*\" {
yytext = yytext +1;
yytext[yyleng - 2] = 0;
DEBUG("\"%s\" tokenized with \'ValStr\'", yytext); yylval.string = strdup(yytext); return(ValStr);};
\"\"\"([^\"\n]|\\\n)*\"\"\" {
yytext = yytext +3;
yytext[yyleng - 4] = 0;
DEBUG("\"%s\" tokenized with \'ValMultistr\'", yytext); yylval.string = strdup(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 */ };
%% %%

View File

@ -25,6 +25,16 @@ void lex_init(void) {
atexit(lex_deinit); atexit(lex_deinit);
} }
void lex_reset(void) {
eof = 0;
nRow = 0;
nBuffer = 0;
lBuffer = 0;
nTokenStart = 0;
nTokenLength = 0;
nTokenNextStart = 0;
}
void beginToken(char *t) { void beginToken(char *t) {
nTokenStart = nTokenNextStart; nTokenStart = nTokenNextStart;
nTokenLength = (int) strlen(t); nTokenLength = (int) strlen(t);

View File

@ -16,6 +16,8 @@ extern char* buffer;
*/ */
void lex_init(void); void lex_init(void);
void lex_reset(void);
/** /**
* @brief Begin counting a new token. This will fill the global struct yylloc. * @brief Begin counting a new token. This will fill the global struct yylloc.
* @param t the text of the token. Must be null terminated * @param t the text of the token. Must be null terminated

View File

@ -4,10 +4,52 @@
#include <yacc/parser.tab.h> #include <yacc/parser.tab.h>
#include <sys/col.h> #include <sys/col.h>
#include <lex/util.h> #include <lex/util.h>
#include <io/files.h>
#include <assert.h>
#define LOG_LEVEL LOG_LEVEL_DEBUG extern void yyrestart(FILE *);
extern FILE *yyin; [[maybe_unused]]
AST_NODE_PTR root;
[[maybe_unused]]
ModuleFile *current_file;
/**
* @brief Compile the specified file into AST
* @param ast
* @param file
* @return EXIT_SUCCESS in case the parsing was success full anything lese if not
*/
[[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);
file->handle = fopen(file->path, "r");
if (file->handle == NULL) {
INFO("unable to open file: %s", file->path);
return 1;
}
DEBUG("parsing file: %s", file->path);
// setup global state
root = ast;
current_file = file;
yyin = file->handle;
yyrestart(yyin);
lex_reset();
yyparse();
// clean up global state
// current_file = NULL;
root = NULL;
yyin = NULL;
return 0;
}
/** /**
* @brief Log a debug message to inform about beginning exit procedures * @brief Log a debug message to inform about beginning exit procedures
@ -15,16 +57,15 @@ extern FILE *yyin;
*/ */
void notify_exit(void) { DEBUG("Exiting gemstone..."); } void notify_exit(void) { DEBUG("Exiting gemstone..."); }
/** /**
* @brief Closes File after compiling. * @brief Closes File after compiling.
* *
*/ */
void close_file(void) { void close_file(void) {
if (NULL != yyin) { if (NULL != yyin) {
fclose(yyin); fclose(yyin);
} }
} }
/** /**
@ -32,46 +73,62 @@ void close_file(void) {
* *
*/ */
void setup(void) { void setup(void) {
// setup preample // setup preample
log_init();
DEBUG("starting gemstone..."); log_init();
DEBUG("starting gemstone...");
#if LOG_LEVEL <= LOG_LEVEL_DEBUG #if LOG_LEVEL <= LOG_LEVEL_DEBUG
atexit(&notify_exit); atexit(&notify_exit);
#endif #endif
// actual setup // actual setup
AST_init(); AST_init();
col_init(); col_init();
lex_init(); lex_init();
DEBUG("finished starting up gemstone..."); DEBUG("finished starting up gemstone...");
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
setup(); setup();
atexit(close_file); atexit(close_file);
// Check for file input as argument ModuleFileStack files;
if (2 != argc) { files.files = NULL;
INFO("Usage: %s <filename>\n", argv[0]);
PANIC("No File could be found");
}
// filename as first argument for (int i = 1; i < argc; i++) {
char *filename = argv[1]; printf("Compiling file: %s\n\n", argv[i]);
FILE *file = fopen(filename, "r"); TokenLocation location = {
.line_start = 0,
.line_end = 0,
.col_start = 0,
.col_end = 0
};
AST_NODE_PTR ast = AST_new_node(location, AST_Module, NULL);
ModuleFile *file = push_file(&files, argv[i]);
if (NULL == file) { if (compile_file_to_ast(ast, file) == EXIT_SUCCESS) {
PANIC("File couldn't be opened!"); // TODO: parse AST to semantic values
} // TODO: backend codegen
yyin = file; }
yyparse(); AST_delete_node(ast);
return 0; print_file_statistics(file);
}
if (files.files == NULL) {
printf("No input files, nothing to do.\n\n");
exit(1);
}
print_unit_statistics(&files);
delete_files(&files);
return 0;
} }

View File

@ -1,9 +1,13 @@
%locations %locations
%define parse.error verbose %define parse.error verbose
%{ %code requires {
#include <sys/log.h> #include <sys/log.h>
#include <ast/ast.h>
#include <sys/col.h> #include <sys/col.h>
#include <io/files.h>
extern int yylineno;
extern ModuleFile* current_file;
int yyerror(const char*); int yyerror(const char*);
@ -11,16 +15,66 @@
extern int yylineno; extern int yylineno;
extern int yylex(); extern int yylex();
%} extern AST_NODE_PTR root;
#define new_loc() new_location(yylloc.first_line, yylloc.first_column, yylloc.last_line, yylloc.last_column)
}
%union { %union {
char *string; char *string;
AST_NODE_PTR node_ptr;
} }
%type <node_ptr> operation
%type <node_ptr> boxaccess
%type <node_ptr> boxselfaccess
%type <node_ptr> statement
%type <node_ptr> statementlist
%type <node_ptr> assign
%type <node_ptr> oparith
%type <node_ptr> decl
%type <node_ptr> definition
%type <node_ptr> while
%type <node_ptr> funcall
%type <node_ptr> boxcall
%type <node_ptr> branchhalf
%type <node_ptr> branchfull
%type <node_ptr> branchelse
%type <node_ptr> branchelseif
%type <node_ptr> branchif
%type <node_ptr> type
%type <node_ptr> identlist
%type <node_ptr> storagequalifier
%type <node_ptr> typekind
%type <node_ptr> scale
%type <node_ptr> sign
%type <node_ptr> expr
%type <node_ptr> oplogic
%type <node_ptr> opbool
%type <node_ptr> opbit
%type <node_ptr> moduleimport
%type <node_ptr> programbody
%type <node_ptr> fundef
%type <node_ptr> box
%type <node_ptr> typedef
%type <node_ptr> exprlist
%type <node_ptr> argumentlist
%type <node_ptr> paramlist
%type <node_ptr> params
%type <node_ptr> IOqualifyier
%type <node_ptr> paramdecl
%type <node_ptr> boxbody
%type <node_ptr> boxcontent
%type <node_ptr> typecast
%type <node_ptr> reinterpretcast
%type <node_ptr> program
%token KeyInt %token KeyInt
%token KeyFloat %token KeyFloat
%token KeySelf %token KeySelf
%token KeyAs %token KeyAs
%token KeyTo
%token <string> ValInt %token <string> ValInt
%token <string> Ident %token <string> Ident
%token <string> ValFloat %token <string> ValFloat
@ -64,235 +118,412 @@
%token Invalid %token Invalid
/* Operator associativity */ /* Operator associativity */
/* Operators at lower line number have lower precedence */
/* Operators in same line have same precedence */
%right '=' %right '='
%left '+' '-' '*' '/' %left OpOr
%left OpEquals OpNot '<' '>' %left OpXor
%left OpAnd OpOr OpXor %left OpAnd
%left OpBitand OpBitor OpBitxor OpBitnot %left OpBitor
%left OpBitxor
%left OpBitand
%left OpEquals '<' '>'
%left '+' '-'
%left '*' '/'
%left OpNot OpBitnot
%left KeyAs KeyTo
%left '(' ')'
%% %%
program: program programbody program: program programbody {AST_push_node(root, $2);}
| programbody; | programbody {AST_push_node(root, $1);};
programbody: moduleimport programbody: moduleimport {$$ = $1;}
| fundef | fundef{$$ = $1;}
| box | box{$$ = $1;}
| definition | definition{$$ = $1;}
| decl | decl{$$ = $1;}
| typedef; | typedef{$$ = $1;};
expr: ValFloat expr: ValFloat {$$ = AST_new_node(new_loc(), AST_Float, $1);}
| ValInt | ValInt {$$ = AST_new_node(new_loc(), AST_Int, $1);}
| ValMultistr | ValMultistr {$$ = AST_new_node(new_loc(), AST_String, $1);}
| ValStr | ValStr {$$ = AST_new_node(new_loc(), AST_String, $1);}
| Ident | Ident {$$ = AST_new_node(new_loc(), AST_Ident, $1);}
| operation | operation {$$ = $1;}
| boxaccess | boxaccess {$$ = $1;}
| boxselfaccess; | boxselfaccess{$$ = $1;}
| typecast{$$ = $1;}
| reinterpretcast{$$ = $1;}
| '(' expr ')' {$$=$2;}
exprlist: expr ',' exprlist exprlist: expr ',' exprlist {AST_push_node($3, $1);
| expr; $$ = $3;}
| expr {AST_NODE_PTR list = AST_new_node(new_loc(), AST_ExprList, NULL);
AST_push_node(list, $1);
$$ = list;};
argumentlist: argumentlist '(' exprlist ')' argumentlist: argumentlist '(' exprlist ')' {AST_push_node($1, $3);
| ; $$ = $1;}
| '(' exprlist ')'{AST_NODE_PTR list = AST_new_node(new_loc(), AST_ArgList, NULL);
AST_push_node(list, $2);
$$ = list;}
| argumentlist '(' ')'
| '(' ')'{AST_NODE_PTR list = AST_new_node(new_loc(), AST_ArgList, NULL);
$$ = list;};
fundef: KeyFun Ident paramlist '{' statementlist'}' { DEBUG("Function");}; fundef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_Fun, NULL);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $2);
AST_push_node(fun, ident);
AST_push_node(fun, $3);
AST_push_node(fun, $5);
$$ = fun;
DEBUG("Function");};
paramlist: paramlist '(' params ')' paramlist: paramlist '(' params ')' {AST_push_node($1, $3);
| paramlist '(' ')' $$ = $1;}
| '(' params ')' | paramlist '(' ')'{$$ = $1;}
| '(' ')'; | '(' params ')' {AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
AST_push_node(list, $2);
$$ = list;}
| '(' ')' {$$ = AST_new_node(new_loc(), AST_List, NULL);};
params: IOqualifyier paramdecl ',' params params: IOqualifyier paramdecl ',' params {AST_NODE_PTR parameter = AST_new_node(new_loc(), AST_Parameter, NULL);
| IOqualifyier paramdecl; AST_push_node(parameter, $1);
AST_push_node(parameter, $2);
AST_push_node($4, parameter);
$$ = $4;}
| IOqualifyier paramdecl {AST_NODE_PTR list = AST_new_node(new_loc(), AST_ParamList, NULL);
AST_NODE_PTR parameter = AST_new_node(new_loc(), AST_Parameter, NULL);
AST_push_node(parameter, $1);
AST_push_node(parameter, $2);
AST_push_node(list, parameter);
$$ = list;};
IOqualifyier: KeyIn IOqualifyier: KeyIn { AST_NODE_PTR in = AST_new_node(new_loc(), AST_Qualifyier, "in");
| KeyOut AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
| KeyIn KeyOut AST_push_node(list, in);
| KeyOut KeyIn $$ = list;}
| ; | KeyOut{ AST_NODE_PTR out = AST_new_node(new_loc(), AST_Qualifyier, "out");
AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
AST_push_node(list, out);
$$ = list;}
| KeyIn KeyOut{ AST_NODE_PTR in = AST_new_node(new_loc(), AST_Qualifyier, "in");
AST_NODE_PTR out = AST_new_node(new_loc(), AST_Qualifyier, "out");
AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
AST_push_node(list, in);
AST_push_node(list, out);
$$ = list;}
| KeyOut KeyIn{ AST_NODE_PTR in = AST_new_node(new_loc(), AST_Qualifyier, "in");
AST_NODE_PTR out = AST_new_node(new_loc(), AST_Qualifyier, "out");
AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
AST_push_node(list, in);
AST_push_node(list, out);
$$ = list;}
| {$$ = AST_new_node(new_loc(), AST_List, NULL);};
paramdecl: type ':' Ident { DEBUG("Param-Declaration"); }; paramdecl: type ':' Ident { AST_NODE_PTR paramdecl = AST_new_node(new_loc(), AST_ParamDecl, NULL);
AST_push_node(paramdecl, $1);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $3);
AST_push_node(paramdecl, ident);
$$ = paramdecl;
DEBUG("Param-Declaration"); };
box: KeyType KeyBox ':' Ident '{' boxbody '}' { DEBUG("Box"); } box: KeyType KeyBox ':' Ident '{' boxbody '}' {AST_NODE_PTR box = AST_new_node(new_loc(), AST_Box, NULL);
| KeyType KeyBox ':' Ident '{' '}'; AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $4);
AST_push_node(box, ident);
AST_push_node(box, $6);
$$ = box;
DEBUG("Box"); }
| KeyType KeyBox ':' Ident '{' '}' {AST_NODE_PTR box = AST_new_node(new_loc(), AST_Box, NULL);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $4);
AST_push_node(box, ident);
$$ = box;};
boxbody: boxbody boxcontent boxbody: boxbody boxcontent {AST_push_node($1, $2);
| boxcontent; $$ = $1;}
| boxcontent {AST_NODE_PTR list = AST_new_node(new_loc(), AST_List, NULL);
AST_push_node(list, $1);
$$ = list;};
boxcontent: decl { DEBUG("Box decl Content"); } boxcontent: decl { $$ = $1;DEBUG("Box decl Content"); }
| definition { DEBUG("Box def Content"); } | definition { $$ = $1;DEBUG("Box def Content"); }
| fundef { DEBUG("Box fun Content"); }; | fundef { $$ = $1;DEBUG("Box fun Content"); };
boxselfaccess: KeySelf '.' Ident boxselfaccess: KeySelf '.' Ident {AST_NODE_PTR boxselfaccess = AST_new_node(new_loc(), AST_List, NULL);
| KeySelf '.' boxaccess; AST_NODE_PTR self = AST_new_node(new_loc(), AST_Ident, "self");
AST_push_node(boxselfaccess, self);
AST_NODE_PTR identlist = AST_new_node(new_loc(), AST_IdentList, NULL);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $3);
AST_push_node(identlist,ident);
AST_push_node(boxselfaccess, identlist);
$$ = boxselfaccess;}
| KeySelf '.' boxaccess {AST_NODE_PTR boxselfaccess = AST_new_node(new_loc(), AST_List, NULL);
AST_NODE_PTR self = AST_new_node(new_loc(), AST_Ident, "self");
AST_push_node(boxselfaccess, self);
AST_push_node(boxselfaccess, $3);
$$ = boxselfaccess;};
boxaccess: Ident '.' Ident boxaccess: Ident '.' Ident {AST_NODE_PTR identlist = AST_new_node(new_loc(), AST_IdentList, NULL);
| Ident '.' boxaccess; AST_NODE_PTR ident1 = AST_new_node(new_loc(), AST_Ident, $1);
AST_NODE_PTR ident2 = AST_new_node(new_loc(), AST_Ident, $3);
AST_push_node(identlist,ident1);
AST_push_node(identlist,ident2);
$$ = identlist;}
| Ident '.' boxaccess {AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1);
AST_push_node($3,ident);
$$ = $3;};
boxcall: boxaccess argumentlist boxcall: boxaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(new_loc(), AST_Call, NULL);
| boxselfaccess argumentlist; AST_push_node(boxcall, $1);
AST_push_node(boxcall, $2);
funcall: Ident argumentlist { DEBUG("Function call"); }; $$ = boxcall;}
| boxselfaccess argumentlist {AST_NODE_PTR boxcall = AST_new_node(new_loc(), AST_Call, NULL);
moduleimport: KeyImport ValStr { DEBUG("Module-Import"); }; AST_push_node(boxcall, $1);
AST_push_node(boxcall, $2);
statementlist: statement statementlist $$ = boxcall;};
| statement;
statement: assign
| decl
| definition
| while
| branch
| funcall
| boxcall;
branchif: KeyIf expr '{' statementlist '}' { DEBUG("if"); };
branchelse: KeyElse '{' statementlist '}' { DEBUG("if-else"); };
branchelseif: KeyElse KeyIf expr '{' statementlist '}' { DEBUG("else-if"); };
branchelseifs: branchelseifs branchelseif
| branchelseif;
branch: branchif branchelseifs
| branchif branchelseifs branchelse;
while: KeyWhile expr '{' statementlist '}' { DEBUG("while"); };
identlist: Ident ',' identlist
| Ident;
decl: type ':' identlist
| storagequalifier type ':' identlist
definition: decl '=' expr { DEBUG("Definition"); }; typecast: expr KeyAs type %prec KeyAs {AST_NODE_PTR cast = AST_new_node(new_loc(), AST_Typecast, NULL);
AST_push_node(cast, $1);
AST_push_node(cast, $3);
$$ = cast;
DEBUG("Type-Cast"); };
storagequalifier: KeyGlobal reinterpretcast: expr KeyTo type %prec KeyTo { AST_NODE_PTR cast = AST_new_node(new_loc(), AST_Transmute, NULL);
| KeyStatic AST_push_node(cast, $1);
| KeyLocal; AST_push_node(cast, $3);
$$ = cast;
DEBUG("Reinterpret-Cast"); };
funcall: Ident argumentlist {AST_NODE_PTR funcall = AST_new_node(new_loc(), AST_Call, NULL);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1);
AST_push_node(funcall, ident);
AST_push_node(funcall, $2);
$$ = funcall;
DEBUG("Function call"); };
moduleimport: KeyImport ValStr {$$ = AST_new_node(new_loc(), AST_Import, $2);
DEBUG("Module-Import"); };
statementlist: statementlist statement {AST_push_node($1, $2);
$$ = $1;}
| statement {AST_NODE_PTR list = AST_new_node(new_loc(), AST_StmtList, NULL);
AST_push_node(list, $1);
$$ = list;};
statement: assign {$$ = $1;}
| decl {$$ = $1;}
| definition {$$ = $1;}
| while {$$ = $1;}
| branchfull {$$ = $1;}
| funcall {$$ = $1;}
| boxcall{$$ = $1;};
branchif: KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_If, NULL);
AST_push_node(branch, $2);
AST_push_node(branch, $4);
$$ = branch; };
branchelse: KeyElse '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_Else, NULL);
AST_push_node(branch, $3);
$$ = branch; };
branchelseif: KeyElse KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_IfElse, NULL);
AST_push_node(branch, $3);
AST_push_node(branch, $5);
$$ = branch; };
branchfull: branchhalf { $$ = $1;};
|branchhalf branchelse { AST_push_node($1 , $2);
$$ = $1; }
branchhalf: branchif { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_Stmt, NULL);
AST_push_node(branch, $1);
$$ = branch; }
| branchhalf branchelseif { AST_push_node($1 , $2);
$$ = $1; };
while: KeyWhile expr '{' statementlist '}' {AST_NODE_PTR whilenode = AST_new_node(new_loc(), AST_While, NULL);
AST_push_node(whilenode, $2);
AST_push_node(whilenode, $4);
$$ = whilenode;};
identlist: Ident ',' identlist {AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1);
AST_push_node($3, ident);
$$ = $3;}
| Ident {AST_NODE_PTR list = AST_new_node(new_loc(), AST_IdentList, NULL);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1);
AST_push_node(list, ident);
$$ = list;};
decl: type ':' identlist {AST_NODE_PTR decl = AST_new_node(new_loc(), AST_Decl, NULL);
AST_push_node(decl, $1);
AST_push_node(decl, $3);
$$ = decl;}
| storagequalifier type ':' identlist {AST_NODE_PTR decl = AST_new_node(new_loc(), AST_Decl, NULL);
AST_push_node(decl, $1);
AST_push_node(decl, $2);
AST_push_node(decl, $4);
$$ = decl;}
definition: decl '=' expr { AST_NODE_PTR def = AST_new_node(new_loc(), AST_Def, NULL);
AST_push_node(def, $1);
AST_push_node(def, $3);
$$ = def;
DEBUG("Definition"); };
storagequalifier: KeyGlobal {$$ = AST_new_node(new_loc(), AST_Storage, "global");}
| KeyStatic {$$ = AST_new_node(new_loc(), AST_Storage, "static");}
| KeyLocal {$$ = AST_new_node(new_loc(), AST_Storage, "local");};
assign: Ident '=' expr { AST_NODE_PTR assign = AST_new_node(new_loc(), AST_Assign, NULL);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $1);
AST_push_node(assign, ident);
AST_push_node(assign, $3);
$$ = assign;
DEBUG("Assignment"); }
assign: Ident '=' expr { DEBUG("Assignment"); }
| boxaccess '=' expr | boxaccess '=' expr
| boxselfaccess '=' expr ; | boxselfaccess '=' expr ;
sign: KeySigned sign: KeySigned {$$ = AST_new_node(new_loc(), AST_Sign, "signed");}
| KeyUnsigned; | KeyUnsigned{$$ = AST_new_node(new_loc(), AST_Sign, "unsigned");};
typedef: KeyType type':' Ident; typedef: KeyType type':' Ident {AST_NODE_PTR typeDef = AST_new_node(new_loc(), AST_Typedef, NULL);
AST_push_node(typeDef, $2);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $4);
AST_push_node(typeDef, ident);
$$ = typeDef;};
scale: scale KeyShort scale: scale KeyShort {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "short");
| scale KeyHalf AST_push_node($1, shortnode);
| scale KeyLong $$ = $1;}
| scale KeyDouble | scale KeyHalf {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "half");
| KeyShort AST_push_node($1, shortnode);
| KeyHalf $$ = $1;}
| KeyLong | scale KeyLong {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "long");
| KeyDouble; AST_push_node($1, shortnode);
$$ = $1;}
| scale KeyDouble {AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "double");
AST_push_node($1, shortnode);
$$ = $1;}
| KeyShort {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL);
AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "short");
AST_push_node(scale, shortnode);
$$ = scale;}
| KeyHalf {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL);
AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "half");
AST_push_node(scale, shortnode);
$$ = scale;}
| KeyLong {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL);
AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "long");
AST_push_node(scale, shortnode);
$$ = scale;}
| KeyDouble {AST_NODE_PTR scale = AST_new_node(new_loc(), AST_List, NULL);
AST_NODE_PTR shortnode = AST_new_node(new_loc(), AST_Scale, "double");
AST_push_node(scale, shortnode);
$$ = scale;};
typekind: Ident typekind: Ident {$$ = AST_new_node(new_loc(), AST_Typekind, $1);}
| KeyInt | KeyInt {$$ = AST_new_node(new_loc(), AST_Typekind, "int");}
| KeyFloat; | KeyFloat {$$ = AST_new_node(new_loc(), AST_Typekind, "float");};
type: typekind type: typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL);
| scale typekind AST_push_node(type, $1);
| sign typekind $$ = type;}
| sign scale typekind; | scale typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL);
AST_push_node(type, $1);
AST_push_node(type, $2);
$$ = type;}
| sign typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL);
AST_push_node(type, $1);
AST_push_node(type, $2);
$$ = type;}
| sign scale typekind {AST_NODE_PTR type = AST_new_node(new_loc(), AST_Type, NULL);
AST_push_node(type, $1);
AST_push_node(type, $2);
AST_push_node(type, $3);
$$ = type;};
operation: oparith operation: oparith {$$ = $1;}
| oplogic | oplogic {$$ = $1;}
| opbool | opbool {$$ = $1;}
| opbit; | opbit {$$ = $1;};
oparith: expr '+' expr oparith: expr '+' expr {AST_NODE_PTR add = AST_new_node(new_loc(), AST_Add, NULL);
| expr '-' expr AST_push_node(add, $1);
| expr '*' expr AST_push_node(add, $3);
| expr '/' expr $$ = add;}
| '-' expr %prec '*'; | expr '-' expr {AST_NODE_PTR subtract = AST_new_node(new_loc(), AST_Sub, NULL);
AST_push_node(subtract, $1);
AST_push_node(subtract, $3);
$$ = subtract;}
| expr '*' expr {AST_NODE_PTR mul = AST_new_node(new_loc(), AST_Mul, NULL);
AST_push_node(mul, $1);
AST_push_node(mul, $3);
$$ = mul;}
| expr '/' expr {AST_NODE_PTR div = AST_new_node(new_loc(), AST_Div, NULL);
AST_push_node(div, $1);
AST_push_node(div, $3);
$$ = div;}
| '-' expr %prec '*'{AST_NODE_PTR negator = AST_new_node(new_loc(), AST_Negate, NULL);
AST_push_node(negator, $2);
$$ = negator;};
oplogic: expr OpEquals expr oplogic: expr OpEquals expr {AST_NODE_PTR equals = AST_new_node(new_loc(), AST_Eq, NULL);
| expr '<' expr AST_push_node(equals, $1);
| expr '>' expr; AST_push_node(equals, $3);
$$ = equals;}
| expr '<' expr {AST_NODE_PTR less = AST_new_node(new_loc(), AST_Less, NULL);
AST_push_node(less, $1);
AST_push_node(less, $3);
$$ = less;}
| expr '>' expr{AST_NODE_PTR greater = AST_new_node(new_loc(), AST_Greater, NULL);
AST_push_node(greater, $1);
AST_push_node(greater, $3);
$$ = greater;};
opbool: expr OpAnd expr opbool: expr OpAnd expr {AST_NODE_PTR and = AST_new_node(new_loc(), AST_BoolAnd, NULL);
| expr OpOr expr AST_push_node(and, $1);
| expr OpXor expr AST_push_node(and, $3);
| OpNot expr %prec OpAnd; $$ = and;}
| expr OpOr expr{AST_NODE_PTR or = AST_new_node(new_loc(), AST_BoolOr, NULL);
AST_push_node(or, $1);
AST_push_node(or, $3);
$$ = or;}
| expr OpXor expr{AST_NODE_PTR xor = AST_new_node(new_loc(), AST_BoolXor, NULL);
AST_push_node(xor, $1);
AST_push_node(xor, $3);
$$ = xor;}
| OpNot expr %prec OpAnd{AST_NODE_PTR not = AST_new_node(new_loc(), AST_BoolNot, NULL);
AST_push_node(not, $2);
$$ = not;};
opbit: expr OpBitand expr opbit: expr OpBitand expr {AST_NODE_PTR and = AST_new_node(new_loc(), AST_BitAnd, NULL);
| expr OpBitor expr AST_push_node(and, $1);
| expr OpBitxor expr AST_push_node(and, $3);
| OpBitnot expr %prec OpBitand; $$ = and;}
| expr OpBitor expr{AST_NODE_PTR or = AST_new_node(new_loc(), AST_BitOr, NULL);
AST_push_node(or, $1);
AST_push_node(or, $3);
$$ = or;}
| expr OpBitxor expr{AST_NODE_PTR xor = AST_new_node(new_loc(), AST_BitXor, NULL);
AST_push_node(xor, $1);
AST_push_node(xor, $3);
$$ = xor;}
| OpBitnot expr %prec OpBitand{AST_NODE_PTR not = AST_new_node(new_loc(), AST_BitNot, NULL);
AST_push_node(not, $2);
$$ = not;};
%% %%
const char* ERROR = "error";
const char* WARNING = "warning";
const char* NOTE = "note";
int print_message(const char* kind, const char* message) {
// number of characters written
int char_count = 0;
// highlight to use
char* HIGHLIGHT = CYAN;
// convert message kind into color
if (kind == ERROR) {
HIGHLIGHT = RED;
} else if (kind == WARNING) {
HIGHLIGHT = YELLOW;
}
// print message
char_count += printf("%sfilename:%d:%d%s:%s%s %s: %s%s\n", BOLD, yylloc.first_line, yylloc.first_column, RESET, HIGHLIGHT, BOLD, kind, RESET, message);
// print line in which error occurred
char_count += printf(" %4d | ", yylloc.first_line);
for (int i = 0; i < yylloc.first_column - 1; i++) {
if (buffer[i] == '\n') {
break;
}
printf("%c", buffer[i]);
}
char_count += printf("%s%s", BOLD, HIGHLIGHT);
for (int i = yylloc.first_column - 1; i < yylloc.last_column; i++) {
if (buffer[i] == '\n') {
break;
}
char_count += printf("%c", buffer[i]);
}
char_count += printf("%s", RESET);
for (int i = yylloc.last_column; buffer[i] != '\0' && buffer[i] != '\n'; i++) {
printf("%c", buffer[i]);
}
char_count += printf("\n | ");
for (int i = 0; i < yylloc.first_column - 1; i++) {
char_count += printf(" ");
}
char_count += printf("%s^", HIGHLIGHT);
for (int i = 0; i < yylloc.last_column - yylloc.first_column; i++) {
printf("~");
}
char_count += printf("%s\n\n", RESET);
return char_count;
}
int yyerror(const char *s) { int yyerror(const char *s) {
return print_message(ERROR, s); TokenLocation location = new_loc();
print_diagnostic(current_file, &location, Error, s);
return 0;
} }

View File

@ -9,3 +9,4 @@ set(CTEST_BINARY_DIRECTORY ${PROJECT_BINARY_DIR}/tests)
add_subdirectory(logging) add_subdirectory(logging)
add_subdirectory(input_file) add_subdirectory(input_file)
add_subdirectory(ast) add_subdirectory(ast)
add_subdirectory(glib)

View File

@ -2,6 +2,14 @@ include(CTest)
include_directories(${PROJECT_SOURCE_DIR}/src) 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})
# ------------------------------------------------------- # # ------------------------------------------------------- #
# CTEST 1 # CTEST 1
# test building the syntax tree # test building the syntax tree
@ -9,11 +17,14 @@ include_directories(${PROJECT_SOURCE_DIR}/src)
add_executable(ast_build_tree add_executable(ast_build_tree
${PROJECT_SOURCE_DIR}/src/ast/ast.c ${PROJECT_SOURCE_DIR}/src/ast/ast.c
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/io/files.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
build_tree.c) build_tree.c)
set_target_properties(ast_build_tree set_target_properties(ast_build_tree
PROPERTIES PROPERTIES
OUTPUT_NAME "build_tree" OUTPUT_NAME "build_tree"
RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast) RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast)
target_link_libraries(ast_build_tree PkgConfig::GLIB)
add_test(NAME ast_build_tree add_test(NAME ast_build_tree
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_build_tree) COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_build_tree)
@ -25,11 +36,14 @@ add_test(NAME ast_build_tree
add_executable(ast_print_node add_executable(ast_print_node
${PROJECT_SOURCE_DIR}/src/ast/ast.c ${PROJECT_SOURCE_DIR}/src/ast/ast.c
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/io/files.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
print_node.c) print_node.c)
set_target_properties(ast_print_node set_target_properties(ast_print_node
PROPERTIES PROPERTIES
OUTPUT_NAME "print_node" OUTPUT_NAME "print_node"
RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast) RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast)
target_link_libraries(ast_print_node PkgConfig::GLIB)
add_test(NAME ast_print_node add_test(NAME ast_print_node
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_print_node) COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_print_node)
@ -41,11 +55,14 @@ add_test(NAME ast_print_node
add_executable(ast_graphviz add_executable(ast_graphviz
${PROJECT_SOURCE_DIR}/src/ast/ast.c ${PROJECT_SOURCE_DIR}/src/ast/ast.c
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/io/files.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
print_graphviz.c) print_graphviz.c)
set_target_properties(ast_graphviz set_target_properties(ast_graphviz
PROPERTIES PROPERTIES
OUTPUT_NAME "print_graphviz" OUTPUT_NAME "print_graphviz"
RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast) RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/ast)
target_link_libraries(ast_graphviz PkgConfig::GLIB)
add_test(NAME ast_graphviz add_test(NAME ast_graphviz
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_print_graphviz) COMMAND python ${GEMSTONE_TEST_DIR}/ast/test_ast.py check_print_graphviz)

View File

@ -6,22 +6,22 @@
#include <sys/log.h> #include <sys/log.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(AST_Add, NULL); const AST_NODE_PTR add = AST_new_node(empty_location(), AST_Add, NULL);
AST_push_node(add, AST_new_node(AST_Int, "3")); AST_push_node(add, AST_new_node(empty_location(), AST_Int, "3"));
AST_push_node(add, AST_new_node(AST_Int, "6")); AST_push_node(add, AST_new_node(empty_location(), AST_Int, "6"));
AST_push_node(stmt, add); AST_push_node(stmt, add);
} }
void generate_branch(const AST_NODE_PTR stmt) { void generate_branch(const AST_NODE_PTR stmt) {
const AST_NODE_PTR branch = AST_new_node(AST_If, NULL); const AST_NODE_PTR branch = AST_new_node(empty_location(), AST_If, NULL);
const AST_NODE_PTR gt = AST_new_node(AST_Greater, NULL); const AST_NODE_PTR gt = AST_new_node(empty_location(), AST_Greater, NULL);
AST_push_node(branch, gt); AST_push_node(branch, gt);
AST_push_node(gt, AST_new_node(AST_Float, "2.3")); AST_push_node(gt, AST_new_node(empty_location(), AST_Float, "2.3"));
AST_push_node(gt, AST_new_node(AST_Float, "0.79")); AST_push_node(gt, AST_new_node(empty_location(), AST_Float, "0.79"));
AST_push_node(stmt, branch); AST_push_node(stmt, branch);
@ -30,7 +30,7 @@ void generate_branch(const AST_NODE_PTR stmt) {
int main(void) { int main(void) {
const AST_NODE_PTR root = AST_new_node(AST_Stmt, NULL); const AST_NODE_PTR root = AST_new_node(empty_location(), AST_Stmt, NULL);
generate_branch(root); generate_branch(root);

View File

@ -7,15 +7,15 @@
int main(void) { int main(void) {
struct AST_Node_t* node = AST_new_node(AST_If, NULL); struct AST_Node_t* node = AST_new_node(empty_location(), AST_If, NULL);
struct AST_Node_t* child = AST_new_node(AST_Add, NULL); struct AST_Node_t* child = AST_new_node(empty_location(), AST_Add, NULL);
AST_push_node(child, AST_new_node(AST_Int, "43")); AST_push_node(child, AST_new_node(empty_location(), AST_Int, "43"));
AST_push_node(child, AST_new_node(AST_Int, "9")); AST_push_node(child, AST_new_node(empty_location(), AST_Int, "9"));
AST_push_node(node, child); AST_push_node(node, child);
AST_push_node(node, AST_new_node(AST_Expr, NULL)); AST_push_node(node, AST_new_node(empty_location(), AST_Expr, NULL));
AST_push_node(node, AST_new_node(AST_Expr, NULL)); AST_push_node(node, AST_new_node(empty_location(), AST_Expr, NULL));
FILE* out = fopen("ast.gv", "w+"); FILE* out = fopen("ast.gv", "w+");
// convert this file ^^^^^^ // convert this file ^^^^^^

View File

@ -6,22 +6,22 @@
#include <sys/log.h> #include <sys/log.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(AST_Add, NULL); const AST_NODE_PTR add = AST_new_node(empty_location(), AST_Add, NULL);
AST_push_node(add, AST_new_node(AST_Int, "3")); AST_push_node(add, AST_new_node(empty_location(), AST_Int, "3"));
AST_push_node(add, AST_new_node(AST_Int, "6")); AST_push_node(add, AST_new_node(empty_location(), AST_Int, "6"));
AST_push_node(stmt, add); AST_push_node(stmt, add);
} }
void generate_branch(const AST_NODE_PTR stmt) { void generate_branch(const AST_NODE_PTR stmt) {
const AST_NODE_PTR branch = AST_new_node(AST_If, NULL); const AST_NODE_PTR branch = AST_new_node(empty_location(), AST_If, NULL);
const AST_NODE_PTR gt = AST_new_node(AST_Greater, NULL); const AST_NODE_PTR gt = AST_new_node(empty_location(), AST_Greater, NULL);
AST_push_node(branch, gt); AST_push_node(branch, gt);
AST_push_node(gt, AST_new_node(AST_Float, "2.3")); AST_push_node(gt, AST_new_node(empty_location(), AST_Float, "2.3"));
AST_push_node(gt, AST_new_node(AST_Float, "0.79")); AST_push_node(gt, AST_new_node(empty_location(), AST_Float, "0.79"));
AST_push_node(stmt, branch); AST_push_node(stmt, branch);
@ -32,7 +32,7 @@ int main(void) {
AST_init(); AST_init();
const AST_NODE_PTR root = AST_new_node(AST_Stmt, NULL); const AST_NODE_PTR root = AST_new_node(empty_location(), AST_Stmt, NULL);
generate_branch(root); generate_branch(root);

View File

@ -8,7 +8,7 @@ int main(void) {
AST_init(); AST_init();
const AST_NODE_PTR node = AST_new_node(0, "value"); const AST_NODE_PTR node = AST_new_node(empty_location(), 0, "value");
for (size_t i = 0; i < AST_ELEMENT_COUNT; i++) { for (size_t i = 0; i < AST_ELEMENT_COUNT; i++) {
// set kind // set kind

View File

@ -29,42 +29,58 @@ def run_check_print_node():
assert p.returncode == 0 assert p.returncode == 0
assert """0 stmt assert """0 stmt
1 expr 1 module
2 value 2 expr
3 value 3 value
4 value 4 value
5 while 5 value
6 if 6 while
7 else if 7 if
8 else 8 else if
9 condition 9 else
10 decl 10 condition
11 assign 11 decl
12 def 12 assign
13 value 13 def
14 + 14 value
15 - 15 +
16 * 16 -
17 / 17 *
18 & 18 /
19 | 19 &
20 ^ 20 |
21 ! 21 ^
22 && 22 !
23 || 23 &&
24 ^^ 24 ||
25 !! 25 ^^
26 == 26 !!
27 > 27 ==
28 < 28 >
29 cast 29 <
30 as 30 typecast
31 value 31 transmute
32 value 32 funcall
33 typedef 33 value
34 box 34 typedef
35 fun 35 box
36 value 36 fun
37 value
38 list
39 expr list
40 arg list
41 param list
42 stmt list
43 ident list
44 value
45 type
46 value
47 value
48 value
49 -
50 parameter
51 value
52 parameter-declaration
""" == p.stdout """ == p.stdout

22
tests/glib/CMakeLists.txt Normal file
View File

@ -0,0 +1,22 @@
include(CTest)
include_directories(${PROJECT_SOURCE_DIR}/src)
include_directories(PRIVATE ${GLIB_INCLUDE_DIRS})
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
# ------------------------------------------------------- #
# CTEST 1
# test Glib's hashmap
add_executable(glib_hashmap
glib_hashmap.c)
set_target_properties(glib_hashmap
PROPERTIES
OUTPUT_NAME "glib_hashmap"
RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/glib)
target_link_libraries(glib_hashmap PkgConfig::GLIB)
add_test(NAME glib_hashmap
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMAND ${GEMSTONE_BINARY_DIR}/tests/glib/glib_hashmap)

27
tests/glib/glib_hashmap.c Normal file
View File

@ -0,0 +1,27 @@
#include <glib.h>
int main(int argc, char* argv[]) {
GHashTable* map = g_hash_table_new(g_str_hash, g_str_equal);
for (int i = 0; i < argc; i++) {
int* index = malloc(sizeof(int));
*index = i;
g_hash_table_insert(map, argv[i], index);
}
for (int i = 0; i < argc; i++) {
int* index = (int*) g_hash_table_lookup(map, argv[i]);
g_hash_table_remove(map, argv[i]);
free(index);
}
g_hash_table_destroy(map);
return 0;
}

View File

@ -2,12 +2,20 @@ include(CTest)
include_directories(${PROJECT_SOURCE_DIR}/src) include_directories(${PROJECT_SOURCE_DIR}/src)
# ------------------------------------------------ #
# Setup Glib 2.0 #
# ------------------------------------------------ #
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
# ------------------------------------------------------- # # ------------------------------------------------------- #
# CTEST 1 # CTEST 1
# test the default output of the logger # test the default output of the logger
add_executable(logging_output add_executable(logging_output
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
output.c) output.c)
set_target_properties(logging_output set_target_properties(logging_output
PROPERTIES PROPERTIES
@ -23,6 +31,7 @@ add_test(NAME logging_output
add_executable(logging_panic add_executable(logging_panic
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
panic.c) panic.c)
set_target_properties(logging_panic set_target_properties(logging_panic
PROPERTIES PROPERTIES
@ -38,6 +47,7 @@ add_test(NAME logging_panic
add_executable(logging_streams add_executable(logging_streams
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
streams.c) streams.c)
set_target_properties(logging_streams set_target_properties(logging_streams
PROPERTIES PROPERTIES
@ -53,6 +63,7 @@ add_test(NAME logging_streams
add_executable(logging_level add_executable(logging_level
${PROJECT_SOURCE_DIR}/src/sys/log.c ${PROJECT_SOURCE_DIR}/src/sys/log.c
${PROJECT_SOURCE_DIR}/src/sys/col.c
level.c) level.c)
set_target_properties(logging_level set_target_properties(logging_level
PROPERTIES PROPERTIES

View File

@ -3,11 +3,13 @@
// //
#include "sys/log.h" #include "sys/log.h"
#include <sys/col.h>
#define LOG_LEVEL LOG_LEVEL_WARNING #define LOG_LEVEL LOG_LEVEL_WARNING
int main(void) { int main(void) {
log_init(); log_init();
col_init();
DEBUG("logging some debug..."); DEBUG("logging some debug...");
INFO("logging some info..."); INFO("logging some info...");

View File

@ -3,9 +3,11 @@
// //
#include "sys/log.h" #include "sys/log.h"
#include <sys/col.h>
int main(void) { int main(void) {
log_init(); log_init();
col_init();
DEBUG("logging some debug..."); DEBUG("logging some debug...");
INFO("logging some info..."); INFO("logging some info...");