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;
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,
Ast_Flag_No_Clone = BH_BIT(18),
Ast_Flag_Cannot_Take_Addr = BH_BIT(19),
-
+
Ast_Flag_Arg_Is_VarArg = BH_BIT(20),
} AstFlags;
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;
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 {
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) {
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: ");
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;
}
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) {
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);
((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;
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);
}
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;
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;
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;
}
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;
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;