From: Brendan Hansen Date: Mon, 26 Sep 2022 01:32:28 +0000 (-0500) Subject: added '#with' clause to interfaces X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=76dc572c60e0ff099b0643dbc54cdfdd35d0add9;p=onyx.git added '#with' clause to interfaces --- diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index 6c48a770..66f0a2b7 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -1097,12 +1097,18 @@ typedef struct InterfaceConstraint { b32 invert_condition: 1; } InterfaceConstraint; +typedef struct InterfaceVariable { + OnyxToken *symbol; + AstType *type; +} InterfaceVariable; + struct AstInterface { AstTyped_base; char *name; bh_arr(InterfaceParam) params; bh_arr(InterfaceConstraint) exprs; + bh_arr(InterfaceVariable) vars; }; typedef enum ConstraintPhase { diff --git a/compiler/src/checker.c b/compiler/src/checker.c index 64f79440..b574ff8c 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -1985,6 +1985,10 @@ CheckStatus check_expression(AstTyped** pexpr) { CHECK(directive_first, (AstDirectiveFirst *) expr); break; + case Ast_Kind_Constraint_Sentinel: + if (expr->type == NULL) YIELD(expr->token->pos, "Waiting to know constraint sentinel's type."); + break; + case Ast_Kind_StrLit: break; case Ast_Kind_File_Contents: break; case Ast_Kind_Overloaded_Function: break; @@ -1993,7 +1997,6 @@ CheckStatus check_expression(AstTyped** pexpr) { case Ast_Kind_Package: break; case Ast_Kind_Error: break; case Ast_Kind_Unary_Field_Access: break; - case Ast_Kind_Constraint_Sentinel: break; case Ast_Kind_Switch_Case: break; case Ast_Kind_Foreign_Block: break; case Ast_Kind_Zero_Value: break; @@ -2846,6 +2849,16 @@ CheckStatus check_constraint(AstConstraint *constraint) { symbol_introduce(constraint->scope, ip->type_token, (AstNode *) type_alias); } + fori (i, 0, bh_arr_length(constraint->interface->vars)) { + InterfaceVariable *iv = &constraint->interface->vars[i]; + + AstTyped *sentinel = onyx_ast_node_new(context.ast_alloc, sizeof(AstTyped), Ast_Kind_Constraint_Sentinel); + sentinel->token = iv->symbol; + sentinel->type_node = iv->type; + + symbol_introduce(constraint->scope, iv->symbol, (AstNode *) sentinel); + } + assert(constraint->entity); constraint->entity->scope = constraint->scope; diff --git a/compiler/src/parser.c b/compiler/src/parser.c index ea4ef81d..7ffd0912 100644 --- a/compiler/src/parser.c +++ b/compiler/src/parser.c @@ -2168,11 +2168,24 @@ static AstInterface* parse_interface(OnyxParser* parser) { } bh_arr_new(global_heap_allocator, interface->exprs, 2); + bh_arr_new(global_heap_allocator, interface->vars, 2); expect_token(parser, '{'); while (!consume_token_if_next(parser, '}')) { if (parser->hit_unexpected_token) return interface; + if (parse_possible_directive(parser, "with")) { + InterfaceVariable v; + v.symbol = expect_token(parser, Token_Type_Symbol); + expect_token(parser, ':'); + + v.type = parse_type(parser); + expect_token(parser, ';'); + + bh_arr_push(interface->vars, v); + continue; + } + InterfaceConstraint ic = {0}; if (parse_possible_directive(parser, "not")) { ic.invert_condition = 1; diff --git a/compiler/src/symres.c b/compiler/src/symres.c index b5044fac..7042740f 100644 --- a/compiler/src/symres.c +++ b/compiler/src/symres.c @@ -519,7 +519,21 @@ static SymresStatus symres_expression(AstTyped** expr) { } switch ((*expr)->kind) { - case Ast_Kind_Symbol: SYMRES(symbol, (AstNode **) expr); break; + case Ast_Kind_Symbol: + SYMRES(symbol, (AstNode **) expr); + + // HACK? + // I don't know how I never ran into this problem before, + // but when a symbol is resolved, there is never a "double + // check" that its type node is symbol resolved as well. + // This only proved to be an issue when using constraint + // sentinels, so I only added that case here. This should + // maybe be considered in the future because I think this + // lack of double checking could be causing other bugs. + if ((*expr)->kind == Ast_Kind_Constraint_Sentinel) { + SYMRES(type, &(*expr)->type_node); + } + break; case Ast_Kind_Binary_Op: SYMRES(expression, &((AstBinaryOp *)(*expr))->left); @@ -623,6 +637,12 @@ static SymresStatus symres_expression(AstTyped** expr) { } break; + case Ast_Kind_Constraint_Sentinel: { + AstTyped *sentinel = (AstTyped *) *expr; + SYMRES(type, &sentinel->type_node); + break; + } + default: break; }