From b22dd5b4e4d34b642e3637eb1e5e182822bd0312 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Fri, 12 Nov 2021 12:12:44 -0600 Subject: [PATCH] made type constraints nicer to use --- core/container/map.onyx | 4 ++++ include/astnodes.h | 9 ++++++--- include/bh.h | 2 +- src/checker.c | 10 +++++++--- src/parser.c | 1 + src/polymorph.c | 6 ++++-- src/utils.c | 7 +++---- 7 files changed, 26 insertions(+), 13 deletions(-) diff --git a/core/container/map.onyx b/core/container/map.onyx index 02ad2799..f99b5dd8 100644 --- a/core/container/map.onyx +++ b/core/container/map.onyx @@ -11,6 +11,10 @@ package core.map #private_file { ValidKey :: interface (T: type_expr) { + // In order to use a certain type as a key in a Map, you must + // provide an implementation of core.hash.to_u32() for that type, + // and you must provide an operator overload for ==. + hash.to_u32(T); T == T; } diff --git a/include/astnodes.h b/include/astnodes.h index 4545ce9c..6c9e8d5c 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -251,6 +251,8 @@ typedef enum AstFlags { Ast_Flag_Static_If_Resolved = BH_BIT(17), Ast_Flag_Symbol_Invisible = BH_BIT(18), + + Ast_Flag_Header_Check_No_Error = BH_BIT(19), } AstFlags; typedef enum UnaryOp { @@ -1500,7 +1502,7 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lo AstFunction* polymorphic_proc_solidify(AstPolyProc* pp, bh_arr(AstPolySolution) slns, OnyxToken* tkn); AstNode* polymorphic_proc_try_solidify(AstPolyProc* pp, bh_arr(AstPolySolution) slns, OnyxToken* tkn); AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual); -AstFunction* polymorphic_proc_build_only_header_with_slns(AstPolyProc* pp, bh_arr(AstPolySolution) slns); +AstFunction* polymorphic_proc_build_only_header_with_slns(AstPolyProc* pp, bh_arr(AstPolySolution) slns, b32 error_if_failed); void add_overload_option(bh_arr(OverloadOption)* poverloads, u64 precedence, AstTyped* overload); AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads, Arguments* args); @@ -1508,7 +1510,7 @@ AstTyped* find_matching_overload_by_type(bh_arr(OverloadOption) overloads, Type* void report_unable_to_match_overload(AstCall* call); void expand_macro(AstCall** pcall, AstFunction* template); -AstFunction* macro_resolve_header(AstMacro* macro, Arguments* args, OnyxToken* callsite); +AstFunction* macro_resolve_header(AstMacro* macro, Arguments* args, OnyxToken* callsite, b32 error_if_failed); Type* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstPolySolution) slns, OnyxFilePos pos); @@ -1520,7 +1522,8 @@ static inline b32 is_lval(AstNode* node) { || (node->kind == Ast_Kind_Dereference) || (node->kind == Ast_Kind_Subscript) || (node->kind == Ast_Kind_Field_Access) - || (node->kind == Ast_Kind_Memres)) + || (node->kind == Ast_Kind_Memres) + || (node->kind == Ast_Kind_Constraint_Sentinel)) // Bit of a hack, but this makes constraints like 'T->foo()' work. return 1; if (node->kind == Ast_Kind_Compound) { diff --git a/include/bh.h b/include/bh.h index a3a56f19..dd33f3e9 100644 --- a/include/bh.h +++ b/include/bh.h @@ -180,7 +180,7 @@ u8* double_to_ieee754(f64 f, b32 reverse); #define bh_pointer_add(ptr, amm) ((void *)((u8 *) ptr + amm)) #define BH_BIT(x) (1 << (x)) -#define BH_MASK_SET(var, set, mask) ((set) ? (var) |= (mask) : (var) &= ~(mask)) +#define BH_MASK_SET(var, set, mask) ((set) ? ((var) |= (mask)) : ((var) &= ~(mask))) #define fori(var, lo, hi) for (i64 var = (lo); var < (hi); var++) #define forir(var, hi, lo) for (i64 var = (hi); var >= (lo); var--) diff --git a/src/checker.c b/src/checker.c index 70395c35..253f4db7 100644 --- a/src/checker.c +++ b/src/checker.c @@ -433,7 +433,7 @@ static CheckStatus check_resolve_callee(AstCall* call, AstTyped** effective_call calling_a_macro = 1; call->callee = callee; - AstTyped* new_callee = (AstTyped *) macro_resolve_header((AstMacro *) callee, &call->args, call->token); + AstTyped* new_callee = (AstTyped *) macro_resolve_header((AstMacro *) callee, &call->args, call->token, 1); if (new_callee == NULL) return Check_Error; if (new_callee == (AstTyped *) &node_that_signals_a_yield) { YIELD(call->token->pos, "Waiting for macro header to pass type-checking."); @@ -1336,7 +1336,8 @@ CheckStatus check_address_of(AstAddressOf** paof) { && expr->kind != Ast_Kind_Dereference && expr->kind != Ast_Kind_Field_Access && expr->kind != Ast_Kind_Memres - && expr->kind != Ast_Kind_Local) + && expr->kind != Ast_Kind_Local + && expr->kind != Ast_Kind_Constraint_Sentinel) || (expr->flags & Ast_Flag_Cannot_Take_Addr) != 0) { ERROR_(aof->token->pos, "Cannot take the address of something that is not an l-value. %s", onyx_ast_node_kind_string(expr->kind)); } @@ -2028,7 +2029,10 @@ CheckStatus check_struct_defaults(AstStructType* s_node) { CheckStatus check_temp_function_header(AstFunction* func) { CheckStatus cs = check_function_header(func); if (cs == Check_Error) { - onyx_clear_errors(); + if (func->flags & Ast_Flag_Header_Check_No_Error) { + onyx_clear_errors(); + } + return Check_Failed; } diff --git a/src/parser.c b/src/parser.c index 50b57a7b..263fd460 100644 --- a/src/parser.c +++ b/src/parser.c @@ -2373,6 +2373,7 @@ static b32 parse_possible_function_definition_no_consume(OnyxParser* parser) { && token_after_paren->type != '{' && token_after_paren->type != Token_Type_Keyword_Do && token_after_paren->type != Token_Type_Empty_Block + && token_after_paren->type != Token_Type_Keyword_Where && (token_after_paren->type != '=' || (token_after_paren + 1)->type != '>')) return 0; diff --git a/src/polymorph.c b/src/polymorph.c index 7af1daaf..dda7b615 100644 --- a/src/polymorph.c +++ b/src/polymorph.c @@ -708,10 +708,10 @@ AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupM ensure_polyproc_cache_is_created(pp); - return polymorphic_proc_build_only_header_with_slns(pp, slns); + return polymorphic_proc_build_only_header_with_slns(pp, slns, 0); } -AstFunction* polymorphic_proc_build_only_header_with_slns(AstPolyProc* pp, bh_arr(AstPolySolution) slns) { +AstFunction* polymorphic_proc_build_only_header_with_slns(AstPolyProc* pp, bh_arr(AstPolySolution) slns, b32 error_if_failed) { AstSolidifiedFunction solidified_func; char* unique_key = build_poly_slns_unique_key(slns); @@ -732,6 +732,8 @@ AstFunction* polymorphic_proc_build_only_header_with_slns(AstPolyProc* pp, bh_ar return (AstFunction *) &node_that_signals_a_yield; } + BH_MASK_SET(solidified_func.func->flags, !error_if_failed, Ast_Flag_Header_Check_No_Error); + Entity func_header_entity = { .state = Entity_State_Resolve_Symbols, .type = Entity_Type_Temp_Function_Header, diff --git a/src/utils.c b/src/utils.c index a4b3642e..ddd436a5 100644 --- a/src/utils.c +++ b/src/utils.c @@ -358,7 +358,7 @@ AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads, AstFunction* overload = NULL; switch (node->kind) { case Ast_Kind_Function: overload = (AstFunction *) node; break; - case Ast_Kind_Macro: overload = macro_resolve_header((AstMacro *) node, param_args, NULL); break; + case Ast_Kind_Macro: overload = macro_resolve_header((AstMacro *) node, param_args, NULL, 0); break; case Ast_Kind_Polymorphic_Proc: overload = polymorphic_proc_build_only_header((AstPolyProc *) node, PPLM_By_Arguments, param_args); break; } @@ -514,7 +514,7 @@ void expand_macro(AstCall** pcall, AstFunction* template) { return; } -AstFunction* macro_resolve_header(AstMacro* macro, Arguments* args, OnyxToken* callsite) { +AstFunction* macro_resolve_header(AstMacro* macro, Arguments* args, OnyxToken* callsite, b32 error_if_failed) { switch (macro->body->kind) { case Ast_Kind_Function: return (AstFunction *) macro->body; @@ -536,8 +536,7 @@ AstFunction* macro_resolve_header(AstMacro* macro, Arguments* args, OnyxToken* c return NULL; } - // CLEANUP Copy'n'pasted from polymorphic_proc_build_only_header - return polymorphic_proc_build_only_header_with_slns(pp, slns); + return polymorphic_proc_build_only_header_with_slns(pp, slns, error_if_failed); } default: assert(("Bad macro body type.", 0)); -- 2.25.1