From 56cebd574214c9e1d209c40f9cb7ca444b5d4cf8 Mon Sep 17 00:00:00 2001 From: servostar Date: Thu, 10 Oct 2024 20:11:42 +0200 Subject: [PATCH] feat: implemented function annotations --- lib/src/libc/bootstrap.gsc | 2 +- lib/src/libc/os.gsc | 2 +- src/ast/ast.c | 15 ++++++++++ src/ast/ast.h | 41 +++++++++++++++++++++++++++ src/cfg/opt.c | 4 ++- src/io/files.c | 5 +++- src/lex/lexer.l | 4 ++- src/set/set.c | 16 +++++++---- src/yacc/parser.y | 58 ++++++++++++++++++++++++++++++++++---- tests/box/main.gsc | 1 + 10 files changed, 133 insertions(+), 15 deletions(-) diff --git a/lib/src/libc/bootstrap.gsc b/lib/src/libc/bootstrap.gsc index 2580d08..1caad01 100644 --- a/lib/src/libc/bootstrap.gsc +++ b/lib/src/libc/bootstrap.gsc @@ -12,5 +12,5 @@ fun main() #[nomangle,noreturn,entry] fun _start() { main() - os::exit(0 as i32) + std::os::exit(0 as i32) } diff --git a/lib/src/libc/os.gsc b/lib/src/libc/os.gsc index d4225ee..c7801a4 100644 --- a/lib/src/libc/os.gsc +++ b/lib/src/libc/os.gsc @@ -7,5 +7,5 @@ fun _exit(in i32: code) #[noreturn] fun exit(in i32: code) { - os::_exit(code) + _exit(code) } diff --git a/src/ast/ast.c b/src/ast/ast.c index 012581f..1306318 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -5,6 +5,20 @@ #include #include +bool AST_annotation_array_contains_flag(AST_Annotation* haystack, const char* needle) { + if (haystack->kind == AnnotationKindArray) { + for (guint i = 0; i < haystack->impl.array->len; i++) { + AST_Annotation child = g_array_index(haystack->impl.array, AST_Annotation, i); + + if (child.kind == AnnotationKindFlag && strcmp(child.impl.flag, needle) == 0) { + return true; + } + } + } + + return false; +} + struct AST_Node_t* AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char* value) { @@ -26,6 +40,7 @@ struct AST_Node_t* AST_new_node(TokenLocation location, node->kind = kind; node->value = value; node->location = location; + node->annotation.kind = AnnotationKindNone; return node; } diff --git a/src/ast/ast.h b/src/ast/ast.h index adb71a5..e120cfd 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -89,6 +89,45 @@ enum AST_SyntaxElement_t { AST_ELEMENT_COUNT }; +typedef enum AST_AnnotationKind_t { + AnnotationKindFlag, + AnnotationKindVariable, + AnnotationKindArray, + AnnotationKindNone +} AST_AnnotationKind; + +struct AST_Annotation_t; + +typedef enum AST_AnnotationValueKind_t { + AnnotationValueKindAnnotation, + AnnotationValueKindString, + AnnotationValueKindInteger +} AST_AnnotationValueKind; + +typedef struct AST_AnnotationValue_t { + AST_AnnotationValueKind kind; + union { + struct AST_Annotation_t* annotation; + char* string; + int64_t integer; + } impl; +} AST_AnnotationValue; + +typedef struct AST_Annotation_t { + AST_AnnotationKind kind; + union { + // array of annotation values + GArray* array; + struct { + char* name; + AST_AnnotationValue value; + } variable; + char* flag; + } impl; +} AST_Annotation; + +bool AST_annotation_array_contains_flag(AST_Annotation*, const char*); + /** * @brief A single node which can be joined with other nodes like a graph. * Every node can have one ancestor (parent) but multiple (also none) children. @@ -108,6 +147,8 @@ typedef struct AST_Node_t { TokenLocation location; + AST_Annotation annotation; + // children array GArray* children; } AST_Node; diff --git a/src/cfg/opt.c b/src/cfg/opt.c index 97c837a..6a101a6 100644 --- a/src/cfg/opt.c +++ b/src/cfg/opt.c @@ -167,7 +167,9 @@ void module_ref_push(ModuleRef* ref, char* name) { } void module_ref_pop(ModuleRef* ref) { - g_array_remove_index(ref->module_path, ref->module_path->len - 1); + if (ref->module_path->len > 0) { + g_array_remove_index(ref->module_path, ref->module_path->len - 1); + } } char* module_ref_to_str(ModuleRef* ref) { diff --git a/src/io/files.c b/src/io/files.c index aabaef0..12d8478 100644 --- a/src/io/files.c +++ b/src/io/files.c @@ -66,7 +66,10 @@ char* module_from_basename(char* path) { *dot = '\0'; } - return basename; + char* cached_module_name = mem_strdup(MemoryNamespaceOpt, basename); + g_free(basename); + + return cached_module_name; } void delete_files(ModuleFileStack* stack) { diff --git a/src/lex/lexer.l b/src/lex/lexer.l index 8762224..7eaff0b 100644 --- a/src/lex/lexer.l +++ b/src/lex/lexer.l @@ -28,7 +28,9 @@ %% "\n" yyLineNumber++; -//.* ; +\/\/.* ; + +"#" {DEBUG("\"%s\" tokenized with \'#\'", yytext); return('#');}; "::" {return(ModSep);}; ":" {DEBUG("\"%s\" tokenized with \':\'", yytext); return(':');}; diff --git a/src/set/set.c b/src/set/set.c index 8cf746c..74cd9e8 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -2648,11 +2648,17 @@ int createFunction(Function* function, AST_NODE_PTR currentNode) { return SEMANTIC_ERROR; } - // compose function name by appending parent modules - char* modules = module_ref_to_str(currentNode->location.module_ref); - char* composed_name = g_strjoin("", modules, "::", function->name, NULL); - g_free(modules); - function->name = composed_name; + if (!(currentNode->annotation.kind == AnnotationKindArray + && AST_annotation_array_contains_flag(¤tNode->annotation, "nomangle"))) { + + // compose function name by appending parent modules + char* modules = module_ref_to_str(currentNode->location.module_ref); + char* composed_name = g_strjoin("", modules, "::", function->name, NULL); + char* cached_composed_name = mem_strdup(MemoryNamespaceSet, composed_name); + g_free(modules); + g_free(composed_name); + function->name = cached_composed_name; + } mem_free(functionParameter); functionParameter = NULL; diff --git a/src/yacc/parser.y b/src/yacc/parser.y index cf83f51..434852e 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -6,6 +6,7 @@ #include #include #include + #include #include extern int yylineno; extern ModuleFile* current_file; @@ -26,6 +27,9 @@ %union { char *string; AST_NODE_PTR node_ptr; + AST_Annotation annotation; + AST_AnnotationValue annotationvalue; + GArray* array; } %type operation @@ -78,7 +82,11 @@ %type storage_expr %type returnstmt %type moduleref - +%type callable +%type annotationlist +%type annotationvalue +%type annotation +%type annotationbind %token KeyInt %token KeyFloat @@ -155,15 +163,55 @@ program: program programbody {AST_push_node(root, $2); programbody: moduleimport {$$ = $1;} | moduleinclude {$$ = $1;} - | fundef{$$ = $1;} - | fundecl{$$ = $1;} - | procdecl{$$ = $1;} - | procdef{$$ = $1;} + | callable {$$ = $1;} | box{$$ = $1;} | definition{$$ = $1;} | decl{$$ = $1;} | typedef{$$ = $1;}; +callable: fundef {$$=$1;} + | fundecl {$$=$1;} + | procdef {$$=$1;} + | procdecl {$$=$1;} + | annotationbind callable { + $2->annotation = $1; + $$ = $2; + }; + +annotationvalue: ValStr { AST_AnnotationValue value; + value.impl.string = $1; + value.kind = AnnotationValueKindString; + $$ = value; } + | ValInt { AST_AnnotationValue value; + value.impl.integer = atol($1); + value.kind = AnnotationValueKindInteger; + $$ = value; } + | annotation { AST_AnnotationValue value; + value.impl.annotation = mem_clone(MemoryNamespaceAst, &($1), sizeof(AST_Annotation)); + value.kind = AnnotationValueKindAnnotation; + $$ = value; }; + +annotationlist: annotation ',' annotationlist { g_array_append_val($3, $1); $$ = $3; } + | annotation { GArray* list = mem_new_g_array(MemoryNamespaceSet, sizeof(AST_Annotation)); + g_array_append_val(list, $1); + $$ = list; }; + +annotation: Ident { AST_Annotation annotation; + annotation.kind = AnnotationKindFlag; + annotation.impl.flag = $1; + $$ = annotation; } + | '[' annotationlist ']' { AST_Annotation annotation; + annotation.kind = AnnotationKindArray; + annotation.impl.array = $2; + $$ = annotation; } + | Ident '(' annotationvalue ')' { AST_Annotation annotation; + annotation.kind = AnnotationKindVariable; + annotation.impl.variable.name = $1; + annotation.impl.variable.value = $3; + $$ = annotation; }; + +annotationbind: '#' annotation { $$ = $2; }; + moduleref: Ident {$$ = AST_new_node(new_loc(), AST_Ident, $1);} | Ident ModSep moduleref {AST_NODE_PTR modref = AST_new_node(new_loc(), AST_ModuleRef, NULL); AST_push_node(modref, AST_new_node(new_loc(), AST_Ident, $1)); diff --git a/tests/box/main.gsc b/tests/box/main.gsc index 9231fa7..07f113a 100644 --- a/tests/box/main.gsc +++ b/tests/box/main.gsc @@ -1,6 +1,7 @@ import "std" +#[nomangle] fun main() { i32: u = 0 as i32 }