From: Brendan Hansen Date: Sun, 4 Feb 2024 21:31:24 +0000 (-0600) Subject: changed: interface syntax X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=aaac5f1c8ae3348a7506199e1d5e5210bf72f6c7;p=onyx.git changed: interface syntax Interfaces now look more like procedures, with sentinels being specified using `t as T` in the body. --- diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index 6ac93721..1968cd2b 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -1207,9 +1207,15 @@ struct AstOverloadedFunction { // @CLEANUP: Is this really necessary? typedef struct InterfaceParam { OnyxToken *value_token; - OnyxToken *type_token; + AstType *value_type; + Type *type; } InterfaceParam; +typedef struct InterfaceSentinel { + OnyxToken *name; + AstType *type; +} InterfaceSentinel; + typedef struct InterfaceConstraint { AstTyped *expr; AstType *expected_type_expr; @@ -1225,6 +1231,7 @@ struct AstInterface { char *name; bh_arr(InterfaceParam) params; + bh_arr(InterfaceSentinel) sentinels; bh_arr(InterfaceConstraint) exprs; Scope *scope; @@ -1248,7 +1255,7 @@ struct AstConstraint { union { struct { AstInterface * interface; - bh_arr(AstType *) type_args; + bh_arr(AstTyped *) args; Scope* scope; bh_arr(InterfaceConstraint) exprs; u32 expr_idx; diff --git a/compiler/src/astnodes.c b/compiler/src/astnodes.c index ea6ed878..0a3381bd 100644 --- a/compiler/src/astnodes.c +++ b/compiler/src/astnodes.c @@ -929,7 +929,8 @@ TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) { // an instance of a type generic polymorphic structure. // For example, converting to an iterator can be tested with: // - // IsIterable :: interface (t: $T) { + // IsIterable :: interface (T: type_expr) { + // t as T; // { t->AsIterator() } -> Iterator; // } // @@ -1841,7 +1842,7 @@ AstPolyCallType* convert_call_to_polycall(AstCall* call) { b32 resolve_intrinsic_interface_constraint(AstConstraint *constraint) { AstInterface *interface = constraint->interface; - Type* type = type_build_from_ast(context.ast_alloc, constraint->type_args[0]); + Type* type = type_build_from_ast(context.ast_alloc, (AstType *) constraint->args[0]); if (!type) return 0; if (!strcmp(interface->name, "type_is_bool")) return type_is_bool(type); diff --git a/compiler/src/checker.c b/compiler/src/checker.c index 8fed0610..fd3d9206 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -1,3 +1,5 @@ +#include "astnodes.h" +#include "types.h" #define BH_INTERNAL_ALLOCATOR (global_heap_allocator) #define BH_DEBUG #include "parser.h" @@ -3655,6 +3657,19 @@ CheckStatus check_macro(AstMacro* macro) { return Check_Success; } +CheckStatus check_interface(AstInterface *interface) { + bh_arr_each(InterfaceParam, param, interface->params) { + CHECK(type, ¶m->value_type); + + param->type = type_build_from_ast(context.ast_alloc, param->value_type); + if (!param->type) { + YIELD(param->value_type->token->pos, "Waiting for interface parameter's type to be constructed."); + } + } + + return Check_Success; +} + CheckStatus check_interface_constraint(AstConstraint *constraint) { if (constraint->interface->kind != Ast_Kind_Interface) { // CLEANUP: This error message might not look totally right in some cases. @@ -3690,25 +3705,35 @@ CheckStatus check_interface_constraint(AstConstraint *constraint) { constraint->scope = scope_create(context.ast_alloc, constraint->interface->scope, constraint->token->pos); - if (bh_arr_length(constraint->type_args) != bh_arr_length(constraint->interface->params)) { + if (bh_arr_length(constraint->args) != bh_arr_length(constraint->interface->params)) { ERROR_(constraint->token->pos, "Wrong number of arguments given to interface. Expected %d, got %d.", bh_arr_length(constraint->interface->params), - bh_arr_length(constraint->type_args)); + bh_arr_length(constraint->args)); } fori (i, 0, bh_arr_length(constraint->interface->params)) { InterfaceParam *ip = &constraint->interface->params[i]; - AstTyped *sentinel = onyx_ast_node_new(context.ast_alloc, sizeof(AstTyped), Ast_Kind_Constraint_Sentinel); - sentinel->token = ip->value_token; - sentinel->type_node = constraint->type_args[i]; + AstTyped *arg = constraint->args[i]; + TYPE_CHECK(&arg, ip->type) { + ERROR_(arg->token->pos, "Mismatched type in interface construction. Expected something of type '%s', but got something of type '%s'.", type_get_name(ip->type), type_get_name(arg->type)); + } AstAlias *type_alias = onyx_ast_node_new(context.ast_alloc, sizeof(AstAlias), Ast_Kind_Alias); - type_alias->token = ip->type_token; - type_alias->alias = (AstTyped *) constraint->type_args[i]; + type_alias->token = ip->value_token; + type_alias->alias = arg; + + symbol_introduce(constraint->scope, ip->value_token, (AstNode *) type_alias); + } + + fori (i, 0, bh_arr_length(constraint->interface->sentinels)) { + InterfaceSentinel *is = &constraint->interface->sentinels[i]; - symbol_introduce(constraint->scope, ip->value_token, (AstNode *) sentinel); - symbol_introduce(constraint->scope, ip->type_token, (AstNode *) type_alias); + AstTyped *sentinel = onyx_ast_node_new(context.ast_alloc, sizeof(AstTyped), Ast_Kind_Constraint_Sentinel); + sentinel->token = is->name; + sentinel->type_node = is->type; + + symbol_introduce(constraint->scope, is->name, (AstNode *) sentinel); } assert(constraint->entity); @@ -3858,7 +3883,11 @@ CheckStatus check_constraint_context(ConstraintContext *cc, Scope *scope, OnyxFi if (cc->produce_errors) { AstConstraint *constraint = cc->constraints[i]; char constraint_map[512] = {0}; - fori (i, 0, bh_arr_length(constraint->type_args)) { + fori (i, 0, bh_arr_length(constraint->args)) { + if (!node_is_type((AstNode *) constraint->args[i])) { + continue; + } + if (i != 0) strncat(constraint_map, ", ", 511); OnyxToken* symbol = constraint->interface->params[i].value_token; @@ -3867,7 +3896,7 @@ CheckStatus check_constraint_context(ConstraintContext *cc, Scope *scope, OnyxFi token_toggle_end(symbol); strncat(constraint_map, " is of type '", 511); - strncat(constraint_map, type_get_name(type_build_from_ast(context.ast_alloc, constraint->type_args[i])), 511); + strncat(constraint_map, type_get_name(type_build_from_ast(context.ast_alloc, (AstType *) constraint->args[i])), 511); strncat(constraint_map, "'", 511); } @@ -4040,6 +4069,7 @@ void check_entity(Entity* ent) { case Entity_Type_Polymorph_Query: cs = check_polyquery(ent->poly_query); break; case Entity_Type_Enum_Value: cs = check_expression(&ent->enum_value->value); break; case Entity_Type_Process_Directive: cs = check_process_directive((AstNode *) ent->expr); break; + case Entity_Type_Interface: cs = check_interface(ent->interface); break; case Entity_Type_String_Literal: case Entity_Type_Expression: diff --git a/compiler/src/clone.c b/compiler/src/clone.c index d9639938..c457bb35 100644 --- a/compiler/src/clone.c +++ b/compiler/src/clone.c @@ -591,11 +591,11 @@ AstNode* ast_clone(bh_allocator a, void* n) { AstConstraint* dc = (AstConstraint *) nn; AstConstraint* sc = (AstConstraint *) node; - dc->type_args = NULL; - bh_arr_new(global_heap_allocator, dc->type_args, bh_arr_length(sc->type_args)); + dc->args = NULL; + bh_arr_new(global_heap_allocator, dc->args, bh_arr_length(sc->args)); - bh_arr_each(AstType *, type_arg, sc->type_args) { - bh_arr_push(dc->type_args, (AstType *) ast_clone(a, (AstNode *) *type_arg)); + bh_arr_each(AstTyped *, arg, sc->args) { + bh_arr_push(dc->args, (AstTyped *) ast_clone(a, (AstNode *) *arg)); } dc->phase = Constraint_Phase_Waiting_To_Be_Queued; diff --git a/compiler/src/doc.c b/compiler/src/doc.c index 003e91c4..84f4539b 100644 --- a/compiler/src/doc.c +++ b/compiler/src/doc.c @@ -471,12 +471,12 @@ static void write_doc_constraints(bh_buffer *buffer, ConstraintContext *constrai write_type_node(&tmp_buffer, constraint->interface); bh_buffer_write_string(&tmp_buffer, "("); - bh_arr_each(AstType *, ptype_arg, constraint->type_args) { - if (ptype_arg != constraint->type_args) { + bh_arr_each(AstTyped *, ptype_arg, constraint->args) { + if (ptype_arg != constraint->args) { bh_buffer_write_string(&tmp_buffer, ", "); } - AstType *type_arg = *ptype_arg; + AstTyped *type_arg = *ptype_arg; write_type_node(&tmp_buffer, type_arg); } diff --git a/compiler/src/parser.c b/compiler/src/parser.c index 75739546..922003c0 100644 --- a/compiler/src/parser.c +++ b/compiler/src/parser.c @@ -3,6 +3,7 @@ // such as procedure definitions, string literals, struct definitions // and declarations to be introduced into scopes. +#include "astnodes.h" #define BH_INTERNAL_ALLOCATOR (global_heap_allocator) #include "parser.h" @@ -2524,8 +2525,7 @@ static AstInterface* parse_interface(OnyxParser* parser) { InterfaceParam ip; ip.value_token = expect_token(parser, Token_Type_Symbol); expect_token(parser, ':'); - expect_token(parser, '$'); - ip.type_token = expect_token(parser, Token_Type_Symbol); + ip.value_type = parse_type(parser); bh_arr_push(interface->params, ip); @@ -2539,6 +2539,7 @@ static AstInterface* parse_interface(OnyxParser* parser) { } bh_arr_new(global_heap_allocator, interface->exprs, 2); + bh_arr_new(global_heap_allocator, interface->sentinels, 2); type_create_scope(parser, &interface->scope, interface->token); parser->current_scope = interface->scope; @@ -2558,6 +2559,18 @@ static AstInterface* parse_interface(OnyxParser* parser) { continue; } + if (next_tokens_are(parser, 2, Token_Type_Symbol, Token_Type_Keyword_As)) { + InterfaceSentinel sentinel; + sentinel.name = expect_token(parser, Token_Type_Symbol); + consume_token(parser); + + sentinel.type = parse_type(parser); + bh_arr_push(interface->sentinels, sentinel); + + consume_token_if_next(parser, ';'); + continue; + } + InterfaceConstraint ic = {0}; if (parse_possible_directive(parser, "not")) { ic.invert_condition = 1; @@ -2620,14 +2633,14 @@ static AstConstraint* parse_constraint(OnyxParser* parser) { constraint->token = constraint->interface->token; - bh_arr_new(global_heap_allocator, constraint->type_args, 2); + bh_arr_new(global_heap_allocator, constraint->args, 2); expect_token(parser, '('); while (!consume_token_if_next(parser, ')')) { if (parser->hit_unexpected_token) return constraint; - AstType* type_node = parse_type(parser); - bh_arr_push(constraint->type_args, type_node); + AstTyped* type_node = parse_expression(parser, 0); + bh_arr_push(constraint->args, type_node); if (parser->curr->type != ')') expect_token(parser, ','); diff --git a/compiler/src/polymorph.h b/compiler/src/polymorph.h index ee3742c9..953a15d9 100644 --- a/compiler/src/polymorph.h +++ b/compiler/src/polymorph.h @@ -182,8 +182,8 @@ static AstSolidifiedFunction generate_solidified_function( constraint->interface = (AstInterface *) param->implicit_interface; constraint->token = constraint->interface->token; - bh_arr_new(global_heap_allocator, constraint->type_args, 1); - bh_arr_push(constraint->type_args, (AstType *) ast_clone(context.ast_alloc, param->poly_sym)); + bh_arr_new(global_heap_allocator, constraint->args, 1); + bh_arr_push(constraint->args, (AstTyped *) ast_clone(context.ast_alloc, param->poly_sym)); bh_arr_push(solidified_func.func->constraints.constraints, constraint); } diff --git a/compiler/src/symres.c b/compiler/src/symres.c index d112cf06..c7844b58 100644 --- a/compiler/src/symres.c +++ b/compiler/src/symres.c @@ -1658,14 +1658,22 @@ static SymresStatus symres_macro(AstMacro* macro) { return Symres_Success; } +static SymresStatus symres_interface(AstInterface* interface) { + bh_arr_each(InterfaceParam, param, interface->params) { + SYMRES(type, ¶m->value_type); + } + + return Symres_Success; +} + static SymresStatus symres_constraint(AstConstraint* constraint) { switch (constraint->phase) { case Constraint_Phase_Cloning_Expressions: case Constraint_Phase_Waiting_To_Be_Queued: { SYMRES(expression, (AstTyped **) &constraint->interface); - bh_arr_each(AstType *, type_arg, constraint->type_args) { - SYMRES(type, type_arg); + bh_arr_each(AstTyped *, arg, constraint->args) { + SYMRES(expression, arg); } return Symres_Success; @@ -1943,6 +1951,8 @@ void symres_entity(Entity* ent) { next_state = Entity_State_Finalized; break; + case Entity_Type_Interface: ss = symres_interface(ent->interface); break; + case Entity_Type_Overloaded_Function: ss = symres_overloaded_function(ent->overloaded_function); break; case Entity_Type_Expression: ss = symres_expression(&ent->expr); break; case Entity_Type_Type_Alias: ss = symres_type(&ent->type_alias); break; diff --git a/core/builtin.onyx b/core/builtin.onyx index 4f166a45..9bc40c2e 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -377,7 +377,9 @@ cfree :: (ptr: rawptr) => raw_free(context.allocator, ptr); delete :: #match {} #local - Destroyable :: interface (t: $T) { + Destroyable :: interface (T: type_expr) { + t as T; + { T.destroy(&t) } -> void; } diff --git a/core/container/iter.onyx b/core/container/iter.onyx index c14dbefa..0212b6e3 100644 --- a/core/container/iter.onyx +++ b/core/container/iter.onyx @@ -53,7 +53,8 @@ as_iter :: #match -> Iterator {} Helper interface to test if something can be passed to as_iter successfully. """ -Iterable :: interface (t: $T) { +Iterable :: interface (T: type_expr) { + t as T; { as_iter(t) } -> Iterator; } @@ -129,7 +130,9 @@ as_iter :: (x: &$T/ImplicitIterator) => { } #local -ImplicitIterator :: interface (t: $T) { +ImplicitIterator :: interface (T: type_expr) { + t as T; + { t->iter_open() } -> void; t->iter_next(); { t->iter_close() } -> void; @@ -147,7 +150,9 @@ ImplicitIterator :: interface (t: $T) { as_iter :: macro (x: $T/HasAsIter) => x->as_iter(); #local -HasAsIter :: interface (t: $T) { +HasAsIter :: interface (T: type_expr) { + t as T; + { t->as_iter() } -> Iterator; } diff --git a/core/container/map.onyx b/core/container/map.onyx index 93f11c47..4459fd66 100644 --- a/core/container/map.onyx +++ b/core/container/map.onyx @@ -30,11 +30,13 @@ Map :: struct (Key_Type: type_expr, Value_Type: type_expr) where ValidKey(Key_Ty } } -#local ValidKey :: interface (t: $T) { +#local 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.hash() for that type, // and you must provide an operator overload for ==. + t as T; + { hash.hash(t) } -> u32; { t == t } -> bool; } diff --git a/core/container/pair.onyx b/core/container/pair.onyx index 9f02bc2d..e79402d8 100644 --- a/core/container/pair.onyx +++ b/core/container/pair.onyx @@ -40,6 +40,7 @@ hash.hash :: (p: Pair($First_Type/hash.Hashable, $Second_Type/hash.Hashable)) => return !(p1.first == p2.first) || !(p1.second == p2.second); } -#local Equatable :: interface (t: $T) { +#local Equatable :: interface (T: type_expr) { + t as T; { t == t } -> bool; } diff --git a/core/container/set.onyx b/core/container/set.onyx index 83a4a1b0..9a28755f 100644 --- a/core/container/set.onyx +++ b/core/container/set.onyx @@ -8,7 +8,9 @@ use core.math use core {Optional} -#local SetValue :: interface (t: $T) { +#local SetValue :: interface (T: type_expr) { + t as T; + { hash.hash(t) } -> u32; { t == t } -> bool; } diff --git a/core/container/slice.onyx b/core/container/slice.onyx index 45c5a712..f0a5d094 100644 --- a/core/container/slice.onyx +++ b/core/container/slice.onyx @@ -654,7 +654,8 @@ group_by :: macro (arr_: [] $T, comp: Code, allocator := context.allocator) -> [ -#local HasEquals :: interface (t: $T) { +#local HasEquals :: interface (T: type_expr) { + t as T; { t == t } -> bool; } diff --git a/core/hash/hash.onyx b/core/hash/hash.onyx index 08fab5bf..4e08791c 100644 --- a/core/hash/hash.onyx +++ b/core/hash/hash.onyx @@ -55,12 +55,14 @@ hash :: #match -> u32 { // Interface that holds true when the type has a hash() overload defined. // Useful in datastructure when the ability to hash is dependent on whether // the stored type is hashable. See core/container/pair.onyx for an example. -Hashable :: interface (t: $T) { +Hashable :: interface (T: type_expr) { + t as T; { hash(t) } -> u32; } #local -HasHashMethod :: interface (t: $T) { +HasHashMethod :: interface (T: type_expr) { + t as T; { t->hash() } -> u32; } diff --git a/core/intrinsics/type_interfaces.onyx b/core/intrinsics/type_interfaces.onyx index 2b78c73d..04fd8b77 100644 --- a/core/intrinsics/type_interfaces.onyx +++ b/core/intrinsics/type_interfaces.onyx @@ -12,17 +12,17 @@ package core.intrinsics.types // Slice: [] $T // Function: () -> void -type_is_bool :: interface (t: $T) #intrinsic -type_is_int :: interface (t: $T) #intrinsic -type_is_float :: interface (t: $T) #intrinsic -type_is_number :: interface (t: $T) #intrinsic -type_is_simd :: interface (t: $T) #intrinsic -type_is_pointer :: interface (t: $T) #intrinsic -type_is_enum :: interface (t: $T) #intrinsic -type_is_simple :: interface (t: $T) #intrinsic -type_is_array :: interface (t: $T) #intrinsic -type_is_slice :: interface (t: $T) #intrinsic -type_is_struct :: interface (t: $T) #intrinsic -type_is_compound :: interface (t: $T) #intrinsic -type_is_function :: interface (t: $T) #intrinsic +type_is_bool :: interface (T: type_expr) #intrinsic +type_is_int :: interface (T: type_expr) #intrinsic +type_is_float :: interface (T: type_expr) #intrinsic +type_is_number :: interface (T: type_expr) #intrinsic +type_is_simd :: interface (T: type_expr) #intrinsic +type_is_pointer :: interface (T: type_expr) #intrinsic +type_is_enum :: interface (T: type_expr) #intrinsic +type_is_simple :: interface (T: type_expr) #intrinsic +type_is_array :: interface (T: type_expr) #intrinsic +type_is_slice :: interface (T: type_expr) #intrinsic +type_is_struct :: interface (T: type_expr) #intrinsic +type_is_compound :: interface (T: type_expr) #intrinsic +type_is_function :: interface (T: type_expr) #intrinsic diff --git a/core/misc/method_ops.onyx b/core/misc/method_ops.onyx index 48e2fd53..926a8b18 100644 --- a/core/misc/method_ops.onyx +++ b/core/misc/method_ops.onyx @@ -22,26 +22,26 @@ use runtime // #local { - __HasEqMethod :: interface (t: $T, r: $R) { T.__eq(t, r); } - __HasNeMethod :: interface (t: $T, r: $R) { T.__ne(t, r); } - __HasLtMethod :: interface (t: $T, r: $R) { T.__lt(t, r); } - __HasLeMethod :: interface (t: $T, r: $R) { T.__le(t, r); } - __HasGtMethod :: interface (t: $T, r: $R) { T.__gt(t, r); } - __HasGeMethod :: interface (t: $T, r: $R) { T.__ge(t, r); } - __HasAddMethod :: interface (t: $T, r: $R) { T.__add(t, r); } - __HasMinusMethod :: interface (t: $T, r: $R) { T.__minus(t, r); } - __HasMulMethod :: interface (t: $T, r: $R) { T.__mul(t, r); } - __HasDivMethod :: interface (t: $T, r: $R) { T.__div(t, r); } - __HasModMethod :: interface (t: $T, r: $R) { T.__mod(t, r); } - __HasAndMethod :: interface (t: $T, r: $R) { T.__and(t, r); } - __HasOrMethod :: interface (t: $T, r: $R) { T.__or(t, r); } - __HasShlMethod :: interface (t: $T, r: $R) { T.__shl(t, r); } - __HasShrMethod :: interface (t: $T, r: $R) { T.__shr(t, r); } - __HasSarMethod :: interface (t: $T, r: $R) { T.__sar(t, r); } - __HasXorMethod :: interface (t: $T, r: $R) { T.__xor(t, r); } - __HasBandMethod :: interface (t: $T, r: $R) { T.__band(t, r); } - __HasBorMethod :: interface (t: $T, r: $R) { T.__bor(t, r); } - __HasSubMethod :: interface (t: $T, r: $R) { T.__sub(t, r); } + __HasEqMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__eq(t, r); } + __HasNeMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__ne(t, r); } + __HasLtMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__lt(t, r); } + __HasLeMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__le(t, r); } + __HasGtMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__gt(t, r); } + __HasGeMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__ge(t, r); } + __HasAddMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__add(t, r); } + __HasMinusMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__minus(t, r); } + __HasMulMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__mul(t, r); } + __HasDivMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__div(t, r); } + __HasModMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__mod(t, r); } + __HasAndMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__and(t, r); } + __HasOrMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__or(t, r); } + __HasShlMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__shl(t, r); } + __HasShrMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__shr(t, r); } + __HasSarMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__sar(t, r); } + __HasXorMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__xor(t, r); } + __HasBandMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__band(t, r); } + __HasBorMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__bor(t, r); } + __HasSubMethod :: interface (T: type_expr, R: type_expr) { t as T; r as R; T.__sub(t, r); } } #if #defined(runtime.vars.Onyx_Enable_Operator_Methods) { diff --git a/core/string/string.onyx b/core/string/string.onyx index 86cca236..034a4aa2 100644 --- a/core/string/string.onyx +++ b/core/string/string.onyx @@ -5,7 +5,9 @@ use core {package, *} #doc "Generic procedure for turning something into a string." as_str :: #match -> str {} -#local HasAsStrMethod :: interface (t: $T) { +#local HasAsStrMethod :: interface (T: type_expr) { + t as T; + { T.as_str(t) } -> str; } diff --git a/examples/22_interfaces.onyx b/examples/22_interfaces.onyx index da875cd5..ca83830b 100644 --- a/examples/22_interfaces.onyx +++ b/examples/22_interfaces.onyx @@ -32,7 +32,9 @@ add_example :: () { // expressions do not type check correctly, then the set of parameters does not // satisfy the interface. - CanAdd :: interface (t: $T) { + CanAdd :: interface (T: type_expr) { + t as T; + t + t; } @@ -59,7 +61,9 @@ add_example :: () { // These have to be defined out here because #operator and #match are only allowed // as top level expressions currently. -NumberLike :: interface (t: $T) { +NumberLike :: interface (T: type_expr) { + t as T; + // The constraints here are a little stricter than before. This syntax // allows you to specify the expected type of the expression. If the type // of the expression and the type after the arrow do not match, then the @@ -101,7 +105,9 @@ overloaded_procedure_example :: () { // when the are combined with overloaded procedures. // Take this example. Here is the same CanAdd interface from before. - CanAdd :: interface (t: $T) { + CanAdd :: interface (T: type_expr) { + t as T; + t + t; } diff --git a/tests/aoc-2020/day17.onyx b/tests/aoc-2020/day17.onyx index a859448b..575060dc 100644 --- a/tests/aoc-2020/day17.onyx +++ b/tests/aoc-2020/day17.onyx @@ -2,7 +2,8 @@ use core {package, *} -OverloadsEqual :: interface (t: $T) { +OverloadsEqual :: interface (T: type_expr) { + t as T; { T.equals(t, t) } -> bool; } diff --git a/tests/aoc-2020/day20.onyx b/tests/aoc-2020/day20.onyx index 9267d083..979f2785 100644 --- a/tests/aoc-2020/day20.onyx +++ b/tests/aoc-2020/day20.onyx @@ -254,7 +254,7 @@ main :: (args: [] cstr) { // allocating memory that isn't technically free, but there // should be more than enough space in the allocator to not // run into that problem... Hopefully. - tile_data_ring := alloc.ring.make(tile_data); + tile_data_ring := alloc.ring.make(.{ ~~tile_data.data, 200 * sizeof TileData }); tile_allocator := alloc.ring.make_allocator(&tile_data_ring); while !string.empty(file) { diff --git a/tests/aoc-2021/day21.onyx b/tests/aoc-2021/day21.onyx index e3ad6317..8956121d 100644 --- a/tests/aoc-2021/day21.onyx +++ b/tests/aoc-2021/day21.onyx @@ -111,7 +111,9 @@ Player :: struct { } -#local __HasEqMethod :: interface (t: $T) { +#local __HasEqMethod :: interface (T: type_expr) { + t as T; + { T.__eq(t, t) } -> bool; } diff --git a/tests/complicated_polymorph.onyx b/tests/complicated_polymorph.onyx index 80162f03..db0833fc 100644 --- a/tests/complicated_polymorph.onyx +++ b/tests/complicated_polymorph.onyx @@ -14,7 +14,9 @@ main :: (args: [] cstr) { return g(f(a)); } - Number :: interface (t: $T) { + Number :: interface (T: type_expr) { + t as T; + { t * t } -> T; } diff --git a/tests/interface_scopes.onyx b/tests/interface_scopes.onyx index b63bfb33..eeec1c16 100644 --- a/tests/interface_scopes.onyx +++ b/tests/interface_scopes.onyx @@ -1,6 +1,8 @@ use core {*} -Speak :: interface (t: $T) { +Speak :: interface (T: type_expr) { + t as T; + { speak(t, str.{}) } -> void; { yell(t, str.{}) } -> void; @@ -51,4 +53,4 @@ main :: () { speak_things(dog); speak_things(cat); -} \ No newline at end of file +} diff --git a/tests/interfaces b/tests/interfaces index af3069fe..beece68b 100644 --- a/tests/interfaces +++ b/tests/interfaces @@ -11,3 +11,4 @@ false true false true +[ 1, 2, 3, 4, 5 ] diff --git a/tests/interfaces.onyx b/tests/interfaces.onyx index dcec9b54..cd3f236e 100644 --- a/tests/interfaces.onyx +++ b/tests/interfaces.onyx @@ -8,7 +8,9 @@ use core.iter use core {println, printf} -Hashable :: interface (t :$T) { +Hashable :: interface (T: type_expr) { + t as T; + { hash.to_u32(t) } -> u32; } @@ -16,13 +18,14 @@ try_hash :: #match { macro (x: $T) where Hashable(T) { println(hash.to_u32(x)); }, - (x: any) { printf("{} is not hashable!\n", x.type); }, } -CanCastTo :: interface (t: $T, d: $D) { +CanCastTo :: interface (T: type_expr, D: type_expr) { + t as T; + { cast(D) t } -> D; } @@ -43,7 +46,9 @@ do_math :: macro (x, y: $T) -> T where SemiRing(T) { return x + y + x * y; } -SemiRing :: interface (t: $T) { +SemiRing :: interface (T: type_expr) { + t as T; + {t + t} -> T; {t * t} -> T; } @@ -52,7 +57,9 @@ bit_math :: (x, y: $T) -> T where BitField(T) { return (x & y) | (x ^ y); } -BitField :: interface (t: $T) { +BitField :: interface (T: type_expr) { + t as T; + { ~t } -> T; { t & t } -> T; { t | t } -> T; @@ -99,6 +106,25 @@ consume :: macro (x: $T/iter.Iterable) => { return consume_inner(iterator); } + +ReturnsArray :: interface (T: type_expr, N: i32) { + t as T; + + { t->make_an_array() } -> [N] i32; +} + +MakeArray :: struct { + member: i32; + + make_an_array :: (self: &MakeArray) -> [5] i32 { + return .[ 1, 2, 3, 4, 5 ]; + } +} + +run_make_array :: (x: $T) where ReturnsArray(T, 5) { + x->make_an_array() |> println(); +} + main :: (args: [] cstr) { try_hash("This is a test"); try_hash(context); @@ -124,4 +150,6 @@ main :: (args: [] cstr) { b: [10] i32; println(cast_able(b, [] i32)); + + run_make_array(&MakeArray.{}); } diff --git a/tests/where_clauses.onyx b/tests/where_clauses.onyx index 2d8f56c9..dd4aa8c8 100644 --- a/tests/where_clauses.onyx +++ b/tests/where_clauses.onyx @@ -12,8 +12,10 @@ main :: () { d.values = c; } -Adder :: interface(t: $T) { - { t + t } -> T; +Adder :: interface(T: type_expr) { + t as T; + + { t + t } -> T; } add :: (a, b: [$N]$T) -> [N]T @@ -22,8 +24,10 @@ add :: (a, b: [$N]$T) -> [N]T return a + b; } -CanBeIndexed :: interface(t: $T) { - t[0]; +CanBeIndexed :: interface(T: type_expr) { + t as T; + + t[0]; } Foo :: struct (T: type_expr) where CanBeIndexed(T) {