From: Brendan Hansen Date: Tue, 8 Sep 2020 01:11:18 +0000 (-0500) Subject: added polymorphic varargs of a single type X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=ad1c1d173f428476561f5c59cd1726ced974c9d7;p=onyx.git added polymorphic varargs of a single type --- diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 66da4b2b..c0bda210 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -41,6 +41,7 @@ typedef struct AstFunctionType AstFunctionType; typedef struct AstArrayType AstArrayType; typedef struct AstSliceType AstSliceType; typedef struct AstDynArrType AstDynArrType; +typedef struct AstVarArgType AstVarArgType; typedef struct AstStructType AstStructType; typedef struct AstStructMember AstStructMember; typedef struct AstEnumType AstEnumType; @@ -103,6 +104,7 @@ typedef enum AstKind { Ast_Kind_Array_Type, Ast_Kind_Slice_Type, Ast_Kind_DynArr_Type, + Ast_Kind_VarArg_Type, Ast_Kind_Struct_Type, Ast_Kind_Enum_Type, Ast_Kind_Type_Alias, @@ -179,7 +181,7 @@ typedef enum AstFlags { Ast_Flag_No_Clone = BH_BIT(18), Ast_Flag_Cannot_Take_Addr = BH_BIT(19), - + Ast_Flag_Arg_Is_VarArg = BH_BIT(20), } AstFlags; @@ -409,6 +411,7 @@ struct AstFunctionType { AstType_base; AstType* return_type; u64 param_count; A struct AstArrayType { AstType_base; AstType* elem; AstTyped *count_expr; }; struct AstSliceType { AstType_base; AstType* elem; }; struct AstDynArrType { AstType_base; AstType* elem; }; +struct AstVarArgType { AstType_base; AstType* elem; }; struct AstStructType { AstType_base; @@ -474,6 +477,11 @@ struct AstParam { AstLocal *local; AstTyped *default_value; + // HACK: There is a little too much complexity here. If a parameter is + // a vararg, not only is the flag below set, but the type_node of the + // local is also a AstVarArgType. I think this redudancy should be able + // to be cleaned up. -brendanfh 2020/09/07 + b32 is_vararg : 1; }; struct AstFunction { diff --git a/onyx b/onyx index ff1a0ff8..4f86f2c1 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/poly_test.onyx b/progs/poly_test.onyx index 212d7a94..eff90783 100644 --- a/progs/poly_test.onyx +++ b/progs/poly_test.onyx @@ -133,9 +133,20 @@ print_strings :: proc (ss: ..string) { for s: ss do print_string(s); } +multi_max :: proc (nums: ..$T) -> T { + max := nums[0]; + for num: nums do if num > max do max = num; + return max; +} + +weird_sum :: proc (n1: $T, others: ..T) -> T { + s := n1; + for n: others do s += n; + return s; +} + // At some point, it would be nice to have the ability to say something like: // complex_varargs :: proc (nums: ..i32, names: ..string) { -// ... // } main :: proc (args: [] cstring) { @@ -146,6 +157,15 @@ main :: proc (args: [] cstring) { vararg_test("Here are some numbers:\n", 1, 2, 3, 4, 5); print("\n\n"); + multi_max(4, 2, 76, 3, 1203, 2, 4) |> print(); + print("\n"); + + multi_max(4l, 2l, 76l, 3l, 1203l, 2l, 4l) |> print(); + print("\n"); + + weird_sum(4, 1) |> print(); + print("\n"); + ni := get_num_info(1, 2, 3, 4, 5); print("Some information about those numbers:\n"); print("Min: "); diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 32a92b3e..42781cd1 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -894,7 +894,9 @@ b32 check_array_access(AstArrayAccess* aa) { if (check_expression(&aa->expr)) return 1; if (!type_is_array_accessible(aa->addr->type)) { - onyx_report_error(aa->token->pos, "Expected pointer or array type for left of array access."); + onyx_report_error(aa->token->pos, + "Expected pointer or array type for left of array access, got '%s'.", + type_get_name(aa->addr->type)); return 1; } @@ -1299,11 +1301,7 @@ b32 check_function_header(AstFunction* func) { return 1; } - if (param->is_vararg) { - has_had_varargs = 1; - - local->type = type_make_varargs(semstate.node_allocator, local->type); - } + if (param->is_vararg) has_had_varargs = 1; if (local->type->kind != Type_Kind_Array && type_size_of(local->type) == 0) { diff --git a/src/onyxclone.c b/src/onyxclone.c index 78100a00..87a43792 100644 --- a/src/onyxclone.c +++ b/src/onyxclone.c @@ -52,6 +52,7 @@ static inline i32 ast_kind_to_size(AstNode* node) { case Ast_Kind_Array_Type: return sizeof(AstArrayType); case Ast_Kind_Slice_Type: return sizeof(AstSliceType); case Ast_Kind_DynArr_Type: return sizeof(AstDynArrType); + case Ast_Kind_VarArg_Type: return sizeof(AstVarArgType); case Ast_Kind_Struct_Type: return sizeof(AstStructType); case Ast_Kind_Enum_Type: return sizeof(AstEnumType); case Ast_Kind_Type_Alias: return sizeof(AstTypeAlias); @@ -264,6 +265,10 @@ AstNode* ast_clone(bh_allocator a, void* n) { ((AstDynArrType *) nn)->elem = (AstType *) ast_clone(a, ((AstDynArrType *) node)->elem); break; + case Ast_Kind_VarArg_Type: + ((AstVarArgType *) nn)->elem = (AstType *) ast_clone(a, ((AstVarArgType *) node)->elem); + break; + case Ast_Kind_Type_Alias: ((AstTypeAlias *) nn)->to = (AstType *) ast_clone(a, ((AstTypeAlias *) node)->to); break; @@ -301,6 +306,7 @@ AstNode* ast_clone(bh_allocator a, void* n) { AstParam new_param; new_param.local = (AstLocal *) ast_clone(a, param->local); new_param.default_value = (AstTyped *) ast_clone(a, param->default_value); + new_param.is_vararg = param->is_vararg; bh_arr_push(df->params, new_param); } diff --git a/src/onyxlex.c b/src/onyxlex.c index d5a0a0fe..82167bfc 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -93,7 +93,7 @@ static inline b32 token_lit(OnyxTokenizer* tokenizer, OnyxToken* tk, char* lit, while (*ptr2 != '\0' && *ptr1 == *ptr2) ptr1++, ptr2++, len++; if (*ptr2 != '\0') return 0; - if (is_word && char_is_alphanum(*ptr1) || *ptr1 == '_' || *ptr1 == '$') + if (is_word && char_is_alphanum(*ptr1) || *ptr1 == '_') return 0; tk->type = type; diff --git a/src/onyxparser.c b/src/onyxparser.c index f31bb666..1bfd8aa2 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -1430,6 +1430,13 @@ static void parse_function_params(OnyxParser* parser, AstFunction* func) { i32 new_len = bh_arr_length(*parser->polymorph_context.poly_params); i32 new_poly_params = new_len - old_len; + if (curr_param.is_vararg) { + AstVarArgType* va_type = make_node(AstVarArgType, Ast_Kind_VarArg_Type); + va_type->elem = curr_param.local->type_node; + va_type->token = curr_param.local->type_node->token; + curr_param.local->type_node = (AstType *) va_type; + } + fori (i, 0, new_poly_params) { (*parser->polymorph_context.poly_params)[old_len + i].type_expr = curr_param.local->type_node; (*parser->polymorph_context.poly_params)[old_len + i].idx = param_idx; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index f023d71c..55bdd862 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -127,6 +127,13 @@ static AstType* symres_type(AstType* type) { return type; } + if (type->kind == Ast_Kind_VarArg_Type) { + AstVarArgType* va_node = (AstVarArgType *) type; + va_node->elem = symres_type(va_node->elem); + + return type; + } + return type; } diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 0132c26f..21908b52 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -392,6 +392,9 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) { return type_make_dynarray(alloc, type_build_from_ast(alloc, ((AstDynArrType *) type_node)->elem)); } + case Ast_Kind_VarArg_Type: + return type_make_varargs(alloc, type_build_from_ast(alloc, ((AstVarArgType *) type_node)->elem)); + case Ast_Kind_Basic_Type: return ((AstBasicType *) type_node)->type; diff --git a/src/onyxutils.c b/src/onyxutils.c index 1b330fcb..38cfc300 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -401,6 +401,13 @@ static Type* solve_poly_type(AstNode* target, AstType* type_expr, Type* actual) break; } + case Ast_Kind_VarArg_Type: + bh_arr_push(elem_queue, ((PolySolveElem) { + .type_expr = ((AstVarArgType *) elem.type_expr)->elem, + .actual = actual, + })); + break; + case Ast_Kind_Function_Type: { if (elem.actual->kind != Type_Kind_Function) break;