From: Brendan Hansen Date: Fri, 30 Sep 2022 22:42:14 +0000 (-0500) Subject: added '#export_name' X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=6f5416a4ae0ab92749119f69431e5e4bc25ea496;p=onyx.git added '#export_name' --- diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index 5246f114..246d4dc1 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -43,6 +43,7 @@ NODE(DirectiveLibrary) \ NODE(DirectiveRemove) \ NODE(DirectiveFirst) \ + NODE(DirectiveExportName) \ \ NODE(Return) \ NODE(Jump) \ @@ -219,6 +220,7 @@ typedef enum AstKind { Ast_Kind_Directive_Library, Ast_Kind_Directive_Remove, Ast_Kind_Directive_First, + Ast_Kind_Directive_Export_Name, Ast_Kind_Call_Site, Ast_Kind_Code_Block, @@ -1337,6 +1339,13 @@ struct AstDirectiveFirst { AstFor *for_node; }; +struct AstDirectiveExportName { + AstTyped_base; + AstFunction *func; + AstStrLit *name; + b32 created_export_entity : 1; +}; + struct AstNote { AstNode_base; }; diff --git a/compiler/src/astnodes.c b/compiler/src/astnodes.c index 7c9d7924..54837f9d 100644 --- a/compiler/src/astnodes.c +++ b/compiler/src/astnodes.c @@ -99,6 +99,7 @@ static const char* ast_node_names[] = { "LIBRARY", "REMOVE", "FIRST", + "EXPORT NAME", "CALL SITE", "CODE BLOCK", diff --git a/compiler/src/checker.c b/compiler/src/checker.c index ed8674a7..f3e4d268 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -109,6 +109,7 @@ CheckStatus check_constraint(AstConstraint *constraint); CheckStatus check_constraint_context(ConstraintContext *cc, Scope *scope, OnyxFilePos pos); CheckStatus check_polyquery(AstPolyQuery *query); CheckStatus check_directive_first(AstDirectiveFirst *first); +CheckStatus check_directive_export_name(AstDirectiveExportName *ename); // HACK HACK HACK b32 expression_types_must_be_known = 0; @@ -2017,6 +2018,10 @@ CheckStatus check_expression(AstTyped** pexpr) { if (expr->type == NULL) YIELD(expr->token->pos, "Waiting to know constraint sentinel's type."); break; + case Ast_Kind_Directive_Export_Name: + retval = check_directive_export_name((AstDirectiveExportName *) expr); + break; + case Ast_Kind_StrLit: break; case Ast_Kind_File_Contents: break; case Ast_Kind_Overloaded_Function: break; @@ -2131,6 +2136,69 @@ CheckStatus check_directive_first(AstDirectiveFirst *first) { return Check_Success; } +CheckStatus check_directive_export_name(AstDirectiveExportName *ename) { + if (ename->func->kind != Ast_Kind_Function) { + ERROR(ename->token->pos, "#export_name can only be used on functions."); + } + + if (ename->type == NULL) YIELD(ename->token->pos, "This should never yield here..."); + + ename->flags |= Ast_Flag_Comptime; + + // + // TODO: Cleanup this code. I feel like there should be some convenience functions + // to make string literals, tokens, exports, etc... + if (ename->func->exported_name == NULL) { + if (ename->created_export_entity) { + return Check_Yield_Macro; + } + + // In this case, we know the function is not exported. + assert(ename->func->is_exported == 0); + + char *random_name = bh_alloc_array(context.ast_alloc, char, 16); + random_name[15] = 0; + fori (i, 0, 15) random_name[i] = (rand() % 26) + 'a'; + + OnyxToken *name_token = bh_alloc_item(context.ast_alloc, OnyxToken); + memset(name_token, 0, sizeof(*name_token)); + name_token->type = Token_Type_Literal_String; + name_token->length = 15; + name_token->text = random_name; + + AstStrLit* name = bh_alloc_item(context.ast_alloc, AstStrLit); + memset(name, 0, sizeof(AstStrLit)); + name->kind = Ast_Kind_StrLit; + name->token = name_token; + name->type_node = builtin_string_type; + + add_entities_for_node(NULL, (AstNode *) name, NULL, NULL); + ename->name = name; + + AstDirectiveExport *export = onyx_ast_node_new(context.ast_alloc, sizeof(AstDirectiveExport), Ast_Kind_Directive_Export); + export->token = ename->token; + export->export_name_expr = (AstTyped *) name; + export->export = (AstTyped *) ename->func; + + add_entities_for_node(NULL, (AstNode *) export, NULL, NULL); + + ename->created_export_entity = 1; + return Check_Yield_Macro; + + } else { + AstStrLit* name = bh_alloc_item(context.ast_alloc, AstStrLit); + memset(name, 0, sizeof(AstStrLit)); + name->kind = Ast_Kind_StrLit; + name->token = ename->func->exported_name; + name->type_node = builtin_string_type; + + add_entities_for_node(NULL, (AstNode *) name, NULL, NULL); + ename->name = name; + } + + return Check_Success; +} + CheckStatus check_statement(AstNode** pstmt) { AstNode* stmt = *pstmt; @@ -2773,6 +2841,11 @@ CheckStatus check_process_directive(AstNode* directive) { } export->export_name = export->export_name_expr->token; + + AstFunction *exported_func = (AstFunction *) export->export; + if (exported_func->exported_name == NULL) { + exported_func->exported_name = export->export_name; + } } if (directive->kind == Ast_Kind_Directive_Init) { diff --git a/compiler/src/clone.c b/compiler/src/clone.c index 2c3a49fc..6b708f8e 100644 --- a/compiler/src/clone.c +++ b/compiler/src/clone.c @@ -114,6 +114,7 @@ static inline i32 ast_kind_to_size(AstNode* node) { case Ast_Kind_Constraint: return sizeof(AstConstraint); case Ast_Kind_Directive_Remove: return sizeof(AstDirectiveRemove); case Ast_Kind_Directive_First: return sizeof(AstDirectiveFirst); + case Ast_Kind_Directive_Export_Name: return sizeof(AstDirectiveExportName); case Ast_Kind_Count: return 0; } @@ -577,6 +578,10 @@ AstNode* ast_clone(bh_allocator a, void* n) { C(AstFileContents, filename_expr); E(nn); break; + + case Ast_Kind_Directive_Export_Name: + C(AstDirectiveExportName, func); + break; } clone_depth--; diff --git a/compiler/src/parser.c b/compiler/src/parser.c index 6e6f3b0e..912312e9 100644 --- a/compiler/src/parser.c +++ b/compiler/src/parser.c @@ -764,6 +764,15 @@ static AstTyped* parse_factor(OnyxParser* parser) { retval = (AstTyped *) first; break; } + else if (parse_possible_directive(parser, "export_name")) { + AstDirectiveExportName *export_name = make_node(AstDirectiveExportName, Ast_Kind_Directive_Export_Name); + export_name->token = parser->curr - 1; + export_name->func = (AstFunction *) parse_factor(parser); + export_name->type_node = builtin_string_type; + + retval = (AstTyped *) export_name; + break; + } onyx_report_error(parser->curr->pos, Error_Critical, "Invalid directive in expression."); return NULL; diff --git a/compiler/src/symres.c b/compiler/src/symres.c index e8433bd1..1fc9c4e5 100644 --- a/compiler/src/symres.c +++ b/compiler/src/symres.c @@ -646,6 +646,12 @@ static SymresStatus symres_expression(AstTyped** expr) { break; } + case Ast_Kind_Directive_Export_Name: { + AstDirectiveExportName *ename = (AstDirectiveExportName *) *expr; + SYMRES(expression, (AstTyped **) &ename->func); + break; + } + default: break; } @@ -1412,19 +1418,16 @@ static SymresStatus symres_process_directive(AstNode* directive) { if (export->export->kind == Ast_Kind_Function) { AstFunction *func = (AstFunction *) export->export; - func->exported_name = export->export_name; func->is_exported = 1; - if (func->is_exported) { - if (func->is_foreign) { - onyx_report_error(export->token->pos, Error_Critical, "Cannot export a foreign function."); - return Symres_Error; - } + if (func->is_foreign) { + onyx_report_error(export->token->pos, Error_Critical, "Cannot export a foreign function."); + return Symres_Error; + } - if (func->is_intrinsic) { - onyx_report_error(export->token->pos, Error_Critical, "Cannot export an intrinsic function."); - return Symres_Error; - } + if (func->is_intrinsic) { + onyx_report_error(export->token->pos, Error_Critical, "Cannot export an intrinsic function."); + return Symres_Error; } } diff --git a/compiler/src/wasm_emit.c b/compiler/src/wasm_emit.c index 17e981a5..db467362 100644 --- a/compiler/src/wasm_emit.c +++ b/compiler/src/wasm_emit.c @@ -3463,6 +3463,12 @@ EMIT_FUNC(expression, AstTyped* expr) { break; } + case Ast_Kind_Directive_Export_Name: { + AstDirectiveExportName *ename = (AstDirectiveExportName *) expr; + emit_expression(mod, &code, (AstTyped *) ename->name); + break; + } + default: bh_printf("Unhandled case: %d\n", expr->kind); DEBUG_HERE; @@ -4114,6 +4120,15 @@ static b32 emit_constexpr_(ConstExprContext *ctx, AstTyped *node, u32 offset) { break; } + case Ast_Kind_Directive_Export_Name: { + AstDirectiveExportName *ename = (AstDirectiveExportName *) node; + node = (AstTyped *) ename->name; + + // This fallthrough is very intentional. This replaces the value of "node" + // so the case below thinks it is just generating the constexpr of a string. + // fallthrough + } + case Ast_Kind_StrLit: { AstStrLit* sl = (AstStrLit *) node; diff --git a/core/alloc/arena.onyx b/core/alloc/arena.onyx index 729b2125..e92c430e 100644 --- a/core/alloc/arena.onyx +++ b/core/alloc/arena.onyx @@ -126,6 +126,21 @@ clear :: (arena: ^ArenaState) { arena.size = sizeof rawptr; } +get_allocated_arenas :: (arena: ^ArenaState) -> u32 { + arenas := 0; + walker := arena.first_arena; + while walker != null { + arenas += 1; + walker = walker.next; + } + + return arenas; +} + +get_allocated_bytes :: (arena: ^ArenaState) -> u32 { + return get_allocated_arenas(arena) * (arena.arena_size - 1) + arena.size; +} + auto :: #match { macro (size := 32 * 1024, $dest: Code = #(context.allocator)) { alloc :: package core.alloc diff --git a/tests/aoc-2021/day18.onyx b/tests/aoc-2021/day18.onyx index 09f08a02..afd60668 100644 --- a/tests/aoc-2021/day18.onyx +++ b/tests/aoc-2021/day18.onyx @@ -62,25 +62,31 @@ SnailNum :: struct { reduce_explodes :: (use n: ^SnailNum, depth := 0) -> (reduced_something: bool, zero_node: bool) { if depth <= 3 { - did_reduce, zero_node := false, false; - if left != null { - if did_reduce, zero_node = left->reduce_explodes(depth + 1); zero_node { + if did_reduce, zero_node := left->reduce_explodes(depth + 1); zero_node { left = null; + return true, false; + + } elseif did_reduce { + return true, false; } } - if right != null && !did_reduce { - if did_reduce, zero_node = right->reduce_explodes(depth + 1); zero_node { + if right != null { + if did_reduce, zero_node := right->reduce_explodes(depth + 1); zero_node { right = null; + return true, false; + + } elseif did_reduce { + return true, false; } } - return did_reduce, false; + return false, false; } - pleft := n->pair_to_left(); - pright := n->pair_to_right(); + pleft := n->number_to_left(); + pright := n->number_to_right(); if pleft != null do *pleft += left_val; if pright != null do *pright += right_val; @@ -135,7 +141,7 @@ SnailNum :: struct { if new_right != null do new_right.parent = parent; } - pair_to_left :: (n: ^SnailNum) -> ^u32 { + number_to_left :: (n: ^SnailNum) -> ^u32 { while n.parent != null && n.parent.left == n { n = n.parent; } @@ -153,7 +159,7 @@ SnailNum :: struct { return ^n.right_val; } - pair_to_right :: (n: ^SnailNum) -> ^u32 { + number_to_right :: (n: ^SnailNum) -> ^u32 { while n.parent != null && n.parent.right == n { n = n.parent; } @@ -222,7 +228,7 @@ SnailNum :: struct { main :: () { - num_arena := arena.make(context.allocator, 64 * 1024); + num_arena := arena.make(context.allocator, 256 * 1024); SnailNum.allocator = alloc.as_allocator(^num_arena); conv.register_custom_formatter(SnailNum.format);