From: Brendan Hansen Date: Thu, 7 Oct 2021 04:15:31 +0000 (-0500) Subject: changec tag syntax for struct members; added top-level #tag X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=03e541e647a18c2a16b9fd67a47cd36607211551;p=onyx.git changec tag syntax for struct members; added top-level #tag --- diff --git a/include/astnodes.h b/include/astnodes.h index 02f0c1be..1e975011 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -38,6 +38,7 @@ NODE(DirectiveOperator) \ NODE(DirectiveExport) \ NODE(DirectiveDefined) \ + NODE(DirectiveTag) \ \ NODE(Return) \ NODE(Jump) \ @@ -192,6 +193,7 @@ typedef enum AstKind { Ast_Kind_Directive_Operator, Ast_Kind_Directive_Export, Ast_Kind_Directive_Defined, + Ast_Kind_Directive_Tag, Ast_Kind_Call_Site, Ast_Kind_Code_Block, @@ -1049,6 +1051,13 @@ struct AstDirectiveDefined { b32 is_defined: 1; }; +struct AstDirectiveTag { + AstNode_base; + + AstTyped* expr; + AstTyped* tag; +}; + struct AstNote { AstNode_base; }; diff --git a/src/astnodes.c b/src/astnodes.c index 1563aee2..991bd3dd 100644 --- a/src/astnodes.c +++ b/src/astnodes.c @@ -86,6 +86,7 @@ static const char* ast_node_names[] = { "OPERATOR OVERLOAD", "EXPORT", "DEFINED", + "TAG", "CALL SITE", "CODE BLOCK", diff --git a/src/checker.c b/src/checker.c index 57586d73..215a1c51 100644 --- a/src/checker.c +++ b/src/checker.c @@ -2197,6 +2197,62 @@ CheckStatus check_process_directive(AstNode* directive) { YIELD(directive->token->pos, "Waiting for export type to be known."); } + if (directive->kind == Ast_Kind_Directive_Tag) { + AstDirectiveTag *tag = (AstDirectiveTag *) directive; + + CHECK(expression, &tag->tag); + + switch (tag->expr->kind) { + case Ast_Kind_Struct_Type: { + AstStructType* st = (AstStructType *) tag->expr; + + if (st->meta_tags == NULL) bh_arr_new(global_heap_allocator, st->meta_tags, 1); + bh_arr_push(st->meta_tags, tag->tag); + + return Check_Complete; + } + + case Ast_Kind_Field_Access: { + AstFieldAccess* fa = (AstFieldAccess *) tag->expr; + + if (fa->expr->kind == Ast_Kind_Struct_Type) { + AstStructType* st = (AstStructType *) fa->expr; + Type* s_type = type_build_from_ast(context.ast_alloc, (AstType *) st); + + bh_arr_each(AstStructMember *, smem, st->members) { + if (token_equals((*smem)->token, fa->token)) { + bh_arr(AstTyped *) tags = (*smem)->meta_tags; + + if (tags == NULL) bh_arr_new(global_heap_allocator, tags, 1); + bh_arr_push(tags, tag->tag); + + (*smem)->meta_tags = tags; + + bh_arr_each(StructMember *, smem_type, s_type->Struct.memarr) { + if (token_text_equals((*smem)->token, (*smem_type)->name)) { + (*smem_type)->meta_tags = tags; + break; + } + } + + return Check_Complete; + } + } + + onyx_report_error(fa->token->pos, "'%b' is not a member of '%s'.", + fa->token->text, fa->token->length, + st->name); + return Check_Error; + } + } + + default: { + onyx_report_error(tag->token->pos, "Cannot tag this."); + return Check_Error; + } + } + } + return Check_Success; } diff --git a/src/entities.c b/src/entities.c index ed209a28..6d4569a8 100644 --- a/src/entities.c +++ b/src/entities.c @@ -327,6 +327,7 @@ void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* s case Ast_Kind_Directive_Export: case Ast_Kind_Directive_Add_Overload: + case Ast_Kind_Directive_Tag: case Ast_Kind_Directive_Operator: { ent.type = Entity_Type_Process_Directive; ent.expr = (AstTyped *) node; diff --git a/src/parser.c b/src/parser.c index 38762521..0f776f3d 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1947,15 +1947,15 @@ static AstStructType* parse_struct(OnyxParser* parser) { } else { bh_arr(AstTyped *) meta_tags=NULL; - while (parse_possible_directive(parser, "tag")) { - expect_token(parser, '('); + while (parser->curr->type == '[') { + expect_token(parser, '['); AstTyped* expr = parse_expression(parser, 0); if (meta_tags == NULL) bh_arr_new(global_heap_allocator, meta_tags, 1); bh_arr_push(meta_tags, expr); - expect_token(parser, ')'); + expect_token(parser, ']'); } bh_arr_clear(member_list_temp); @@ -2827,6 +2827,17 @@ static void parse_top_level_statement(OnyxParser* parser) { ENTITY_SUBMIT(export); return; } + else if (parse_possible_directive(parser, "tag")) { + AstDirectiveTag *tag = make_node(AstDirectiveTag, Ast_Kind_Directive_Tag); + tag->token = dir_token; + + tag->expr = parse_expression(parser, 0); + expect_token(parser, ','); + tag->tag = parse_expression(parser, 0); + + ENTITY_SUBMIT(tag); + return; + } else { OnyxToken* directive_token = expect_token(parser, '#'); OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol); diff --git a/src/symres.c b/src/symres.c index 97c7702c..e2c630dd 100644 --- a/src/symres.c +++ b/src/symres.c @@ -1184,6 +1184,13 @@ static SymresStatus symres_process_directive(AstNode* directive) { break; } + + case Ast_Kind_Directive_Tag: { + AstDirectiveTag *tag = (AstDirectiveTag *) directive; + SYMRES(expression, &tag->tag); + SYMRES(expression, &tag->expr); + break; + } } return Symres_Success;