added polymorphic varargs of a single type
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 8 Sep 2020 01:11:18 +0000 (20:11 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 8 Sep 2020 01:11:18 +0000 (20:11 -0500)
include/onyxastnodes.h
onyx
progs/poly_test.onyx
src/onyxchecker.c
src/onyxclone.c
src/onyxlex.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c
src/onyxutils.c

index 66da4b2b0c5c2fd0f0faa71a3bea6a501f443687..c0bda21051d8051c5a40860ffdcf6c0fb0509100 100644 (file)
@@ -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 ff1a0ff8ae1d724d2b2b21712a671a6750f46687..4f86f2c14aad708e0fc8c7dd3d15225d78378bf0 100755 (executable)
Binary files a/onyx and b/onyx differ
index 212d7a94dcca53e4a1daec816a5ae2e525205e7c..eff90783e71414964d00da9443124892e22fbba7 100644 (file)
@@ -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: ");
index 32a92b3e89da1a727397f790f2a58e7b5fc6d990..42781cd1cc824e2ae161a0bbcd48f2dc59c2a0e8 100644 (file)
@@ -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) {
index 78100a00fce036b3fc96ad13d32bdd1212b9c80b..87a437924c7ae6d192fa589c970126f3739c84d3 100644 (file)
@@ -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);
                        }
 
index d5a0a0fe3c978db274a6494d29ebbb9e61124f58..82167bfc305d8ed68ce927d65516e6b82447b744 100644 (file)
@@ -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;
index f31bb666046e16346bfb356219e1df0510e4372e..1bfd8aa2030c35eb6a0e834602e67a03680bdea6 100644 (file)
@@ -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;
index f023d71c5f1d3e39494ab6af7f4517ebf54d5d40..55bdd862e5326ab153130293a68e62e736614933 100644 (file)
@@ -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;
 }
 
index 0132c26fb7c0ff2c6c3b2b3d2dafc5937e51e48d..21908b522f1ac45ffff54a83b13fb70a06c62b12 100644 (file)
@@ -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;
 
index 1b330fcbde8603a1921b1b5aece1008a753d3b7e..38cfc3009504999ae461f0268e7d0395c5ea7e67 100644 (file)
@@ -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;