mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
Improve proc group scoring algorithm
This commit is contained in:
+10
-9
@@ -24,6 +24,7 @@ Allocator :: struct {
|
|||||||
|
|
||||||
|
|
||||||
alloc_with_allocator :: inline proc(a: Allocator, size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> rawptr {
|
alloc_with_allocator :: inline proc(a: Allocator, size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> rawptr {
|
||||||
|
if size == 0 do return nil;
|
||||||
return a.procedure(a.data, Allocator_Mode.Alloc, size, alignment, nil, 0, 0, loc);
|
return a.procedure(a.data, Allocator_Mode.Alloc, size, alignment, nil, 0, 0, loc);
|
||||||
}
|
}
|
||||||
alloc :: inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> rawptr {
|
alloc :: inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> rawptr {
|
||||||
@@ -45,6 +46,10 @@ free_all :: inline proc(loc := #caller_location) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resize_with_allocator :: inline proc(a: Allocator, ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> rawptr {
|
resize_with_allocator :: inline proc(a: Allocator, ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> rawptr {
|
||||||
|
if new_size == 0 {
|
||||||
|
free_ptr_with_allocator(a, ptr, loc);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
return a.procedure(a.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, 0, loc);
|
return a.procedure(a.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, 0, loc);
|
||||||
}
|
}
|
||||||
resize :: inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> rawptr {
|
resize :: inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, loc := #caller_location) -> rawptr {
|
||||||
@@ -82,33 +87,30 @@ delete :: proc[
|
|||||||
|
|
||||||
new :: inline proc(T: type, loc := #caller_location) -> ^T {
|
new :: inline proc(T: type, loc := #caller_location) -> ^T {
|
||||||
ptr := (^T)(alloc(size_of(T), align_of(T), loc));
|
ptr := (^T)(alloc(size_of(T), align_of(T), loc));
|
||||||
ptr^ = T{};
|
if ptr != nil do ptr^ = T{};
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
new_clone :: inline proc(data: $T, loc := #caller_location) -> ^T {
|
new_clone :: inline proc(data: $T, loc := #caller_location) -> ^T {
|
||||||
ptr := (^T)(alloc(size_of(T), align_of(T), loc));
|
ptr := (^T)(alloc(size_of(T), align_of(T), loc));
|
||||||
ptr^ = data;
|
if ptr != nil do ptr^ = data;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_with_allocator :: inline proc(a: Allocator, T: type, loc := #caller_location) -> ^T {
|
new_with_allocator :: inline proc(a: Allocator, T: type, loc := #caller_location) -> ^T {
|
||||||
ptr := (^T)(alloc_with_allocator(a, size_of(T), align_of(T), loc));
|
ptr := (^T)(alloc_with_allocator(a, size_of(T), align_of(T), loc));
|
||||||
ptr^ = T{};
|
if ptr != nil do ptr^ = T{};
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_clone_with_allocator :: inline proc(a: Allocator, data: $T, loc := #caller_location) -> ^T {
|
new_clone_with_allocator :: inline proc(a: Allocator, data: $T, loc := #caller_location) -> ^T {
|
||||||
ptr := (^T)(alloc_with_allocator(a, size_of(T), align_of(T), loc));
|
ptr := (^T)(alloc_with_allocator(a, size_of(T), align_of(T), loc));
|
||||||
ptr^ = data;
|
if ptr != nil do ptr^ = data;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
make_slice :: proc(T: type/[]$E, auto_cast len: int, loc := #caller_location) -> T {
|
make_slice :: proc(T: type/[]$E, auto_cast len: int, loc := #caller_location) -> T {
|
||||||
runtime.make_slice_error_loc(loc, len);
|
runtime.make_slice_error_loc(loc, len);
|
||||||
if len == 0 {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
data := alloc(size_of(E)*len, align_of(E));
|
data := alloc(size_of(E)*len, align_of(E));
|
||||||
s := Raw_Slice{data, len};
|
s := Raw_Slice{data, len};
|
||||||
return transmute(T)s;
|
return transmute(T)s;
|
||||||
@@ -121,8 +123,7 @@ make_dynamic_array_len :: proc(T: type/[dynamic]$E, auto_cast len: int, loc := #
|
|||||||
}
|
}
|
||||||
make_dynamic_array_len_cap :: proc(T: type/[dynamic]$E, auto_cast len: int, auto_cast cap: int, loc := #caller_location) -> T {
|
make_dynamic_array_len_cap :: proc(T: type/[dynamic]$E, auto_cast len: int, auto_cast cap: int, loc := #caller_location) -> T {
|
||||||
runtime.make_dynamic_array_error_loc(loc, len, cap);
|
runtime.make_dynamic_array_error_loc(loc, len, cap);
|
||||||
data: rawptr;
|
data := alloc(size_of(E)*cap, align_of(E));
|
||||||
if cap > 0 do data = alloc(size_of(E)*cap, align_of(E));
|
|
||||||
s := Raw_Dynamic_Array{data, len, cap, context.allocator};
|
s := Raw_Dynamic_Array{data, len, cap, context.allocator};
|
||||||
return transmute(T)s;
|
return transmute(T)s;
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-4
@@ -366,7 +366,27 @@ delete_key :: proc(m: ^$T/map[$K]$V, key: K) {
|
|||||||
|
|
||||||
|
|
||||||
@(builtin)
|
@(builtin)
|
||||||
append :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> int {
|
append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> int {
|
||||||
|
if array == nil do return 0;
|
||||||
|
|
||||||
|
arg_len := 1;
|
||||||
|
|
||||||
|
if cap(array) <= len(array)+arg_len {
|
||||||
|
cap := 2 * cap(array) + max(8, arg_len);
|
||||||
|
_ = reserve(array, cap, loc);
|
||||||
|
}
|
||||||
|
arg_len = min(cap(array)-len(array), arg_len);
|
||||||
|
if arg_len > 0 {
|
||||||
|
a := (^mem.Raw_Dynamic_Array)(array);
|
||||||
|
data := (^E)(a.data);
|
||||||
|
assert(data != nil);
|
||||||
|
mem.copy(mem.ptr_offset(data, a.len), &arg, size_of(E));
|
||||||
|
a.len += arg_len;
|
||||||
|
}
|
||||||
|
return len(array);
|
||||||
|
}
|
||||||
|
@(builtin)
|
||||||
|
append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> int {
|
||||||
if array == nil do return 0;
|
if array == nil do return 0;
|
||||||
|
|
||||||
arg_len := len(args);
|
arg_len := len(args);
|
||||||
@@ -387,6 +407,9 @@ append :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> in
|
|||||||
}
|
}
|
||||||
return len(array);
|
return len(array);
|
||||||
}
|
}
|
||||||
|
@(builtin) append :: proc[append_elem, append_elems];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@(builtin)
|
@(builtin)
|
||||||
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> int {
|
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> int {
|
||||||
@@ -428,14 +451,42 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(builtin)
|
@(builtin)
|
||||||
incl :: inline proc(s: ^$B/bit_set[$T], elem: T) {
|
incl_elem :: inline proc(s: ^$S/bit_set[$E; $U], elem: E) -> S {
|
||||||
s^ |= {elem};
|
s^ |= {elem};
|
||||||
|
return s^;
|
||||||
}
|
}
|
||||||
@(builtin)
|
@(builtin)
|
||||||
excl :: inline proc(s: ^$B/bit_set[$T], elem: T) {
|
incl_elems :: inline proc(s: ^$S/bit_set[$E; $U], elems: ..E) -> S {
|
||||||
s^ &~= {elem};
|
for elem in elems do s^ |= {elem};
|
||||||
|
return s^;
|
||||||
}
|
}
|
||||||
|
@(builtin)
|
||||||
|
incl_bit_set :: inline proc(s: ^$S/bit_set[$E; $U], other: S) -> S {
|
||||||
|
s^ |= other;
|
||||||
|
return s^;
|
||||||
|
}
|
||||||
|
@(builtin)
|
||||||
|
excl_elem :: inline proc(s: ^$S/bit_set[$E; $U], elem: E) -> S {
|
||||||
|
s^ &~= {elem};
|
||||||
|
return s^;
|
||||||
|
}
|
||||||
|
@(builtin)
|
||||||
|
excl_elems :: inline proc(s: ^$S/bit_set[$E; $U], elems: ..E) -> S {
|
||||||
|
for elem in elems do s^ &~= {elem};
|
||||||
|
return s^;
|
||||||
|
}
|
||||||
|
@(builtin)
|
||||||
|
excl_bit_set :: inline proc(s: ^$S/bit_set[$E; $U], other: S) -> S {
|
||||||
|
s^ &~= other;
|
||||||
|
return s^;
|
||||||
|
}
|
||||||
|
|
||||||
|
@(builtin) incl :: proc[incl_elem, incl_elems, incl_bit_set];
|
||||||
|
@(builtin) excl :: proc[excl_elem, excl_elems, excl_bit_set];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+46
-23
@@ -403,6 +403,8 @@ bool check_type_specialization_to(CheckerContext *c, Type *specialization, Type
|
|||||||
bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, bool compound, bool modify_type);
|
bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, bool compound, bool modify_type);
|
||||||
bool check_cast_internal(CheckerContext *c, Operand *x, Type *type);
|
bool check_cast_internal(CheckerContext *c, Operand *x, Type *type);
|
||||||
|
|
||||||
|
#define MAXIMUM_TYPE_DISTANCE 10
|
||||||
|
|
||||||
i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type) {
|
i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type) {
|
||||||
if (operand->mode == Addressing_Invalid ||
|
if (operand->mode == Addressing_Invalid ||
|
||||||
type == t_invalid) {
|
type == t_invalid) {
|
||||||
@@ -443,7 +445,7 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
|
|||||||
if (is_type_any(dst)) {
|
if (is_type_any(dst)) {
|
||||||
// NOTE(bill): Anything can cast to 'Any'
|
// NOTE(bill): Anything can cast to 'Any'
|
||||||
add_type_info_type(c, s);
|
add_type_info_type(c, s);
|
||||||
return 10;
|
return MAXIMUM_TYPE_DISTANCE;
|
||||||
}
|
}
|
||||||
if (dst->kind == Type_Basic) {
|
if (dst->kind == Type_Basic) {
|
||||||
if (operand->mode == Addressing_Constant) {
|
if (operand->mode == Addressing_Constant) {
|
||||||
@@ -577,7 +579,7 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
|
|||||||
} else {
|
} else {
|
||||||
// NOTE(bill): Anything can cast to 'Any'
|
// NOTE(bill): Anything can cast to 'Any'
|
||||||
add_type_info_type(c, s);
|
add_type_info_type(c, s);
|
||||||
return 10;
|
return MAXIMUM_TYPE_DISTANCE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -588,7 +590,7 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
|
|||||||
x.expr = expr->AutoCast.expr;
|
x.expr = expr->AutoCast.expr;
|
||||||
bool ok = check_cast_internal(c, &x, type);
|
bool ok = check_cast_internal(c, &x, type);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
return 10;
|
return MAXIMUM_TYPE_DISTANCE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,18 +598,26 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
i64 assign_score_function(i64 distance) {
|
i64 assign_score_function(i64 distance, bool is_variadic=false) {
|
||||||
|
// 3*x^2 + 1 > x^2 + x + 1 (for positive x)
|
||||||
|
i64 const c = 3*MAXIMUM_TYPE_DISTANCE*MAXIMUM_TYPE_DISTANCE + 1;
|
||||||
|
|
||||||
// TODO(bill): A decent score function
|
// TODO(bill): A decent score function
|
||||||
return gb_max(1000000 - distance*distance, 0);
|
GB_ASSERT(distance <= MAXIMUM_TYPE_DISTANCE);
|
||||||
|
i64 d = distance*distance; // x^2
|
||||||
|
if (is_variadic && d >= 0) {
|
||||||
|
d += distance + 1; // x^2 + x + 1
|
||||||
|
}
|
||||||
|
return gb_max(c - d, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool check_is_assignable_to_with_score(CheckerContext *c, Operand *operand, Type *type, i64 *score_) {
|
bool check_is_assignable_to_with_score(CheckerContext *c, Operand *operand, Type *type, i64 *score_, bool is_variadic=false) {
|
||||||
i64 score = 0;
|
i64 score = 0;
|
||||||
i64 distance = check_distance_between_types(c, operand, type);
|
i64 distance = check_distance_between_types(c, operand, type);
|
||||||
bool ok = distance >= 0;
|
bool ok = distance >= 0;
|
||||||
if (ok) {
|
if (ok) {
|
||||||
score = assign_score_function(distance);
|
score = assign_score_function(distance, is_variadic);
|
||||||
}
|
}
|
||||||
if (score_) *score_ = score;
|
if (score_) *score_ = score;
|
||||||
return ok;
|
return ok;
|
||||||
@@ -837,7 +847,17 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source,
|
|||||||
|
|
||||||
case Type_BitSet:
|
case Type_BitSet:
|
||||||
if (source->kind == Type_BitSet) {
|
if (source->kind == Type_BitSet) {
|
||||||
return is_polymorphic_type_assignable(c, poly->BitSet.elem, source->BitSet.elem, true, modify_type);
|
if (!is_polymorphic_type_assignable(c, poly->BitSet.elem, source->BitSet.elem, true, modify_type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (poly->BitSet.underlying == nullptr) {
|
||||||
|
if (modify_type) {
|
||||||
|
poly->BitSet.underlying = source->BitSet.underlying;
|
||||||
|
}
|
||||||
|
} else if (!is_polymorphic_type_assignable(c, poly->BitSet.underlying, source->BitSet.underlying, true, modify_type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -3198,7 +3218,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|||||||
}
|
}
|
||||||
|
|
||||||
case BuiltinProc_swizzle: {
|
case BuiltinProc_swizzle: {
|
||||||
// swizzle :: proc(v: [N]T, ...int) -> [M]T
|
// swizzle :: proc(v: [N]T, ..int) -> [M]T
|
||||||
Type *type = base_type(operand->type);
|
Type *type = base_type(operand->type);
|
||||||
if (!is_type_array(type)) {
|
if (!is_type_array(type)) {
|
||||||
gbString type_str = type_to_string(operand->type);
|
gbString type_str = type_to_string(operand->type);
|
||||||
@@ -3926,14 +3946,14 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
|||||||
if (vari_expand && !variadic) {
|
if (vari_expand && !variadic) {
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
error(ce->ellipsis,
|
error(ce->ellipsis,
|
||||||
"Cannot use '...' in call to a non-variadic procedure: '%.*s'",
|
"Cannot use '..' in call to a non-variadic procedure: '%.*s'",
|
||||||
LIT(ce->proc->Ident.token.string));
|
LIT(ce->proc->Ident.token.string));
|
||||||
}
|
}
|
||||||
err = CallArgumentError_NonVariadicExpand;
|
err = CallArgumentError_NonVariadicExpand;
|
||||||
} else if (vari_expand && pt->c_vararg) {
|
} else if (vari_expand && pt->c_vararg) {
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
error(ce->ellipsis,
|
error(ce->ellipsis,
|
||||||
"Cannot use '...' in call to a '#c_vararg' variadic procedure: '%.*s'",
|
"Cannot use '..' in call to a '#c_vararg' variadic procedure: '%.*s'",
|
||||||
LIT(ce->proc->Ident.token.string));
|
LIT(ce->proc->Ident.token.string));
|
||||||
}
|
}
|
||||||
err = CallArgumentError_NonVariadicExpand;
|
err = CallArgumentError_NonVariadicExpand;
|
||||||
@@ -3998,21 +4018,22 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
|||||||
if (are_types_identical(e->type, o.type)) {
|
if (are_types_identical(e->type, o.type)) {
|
||||||
score += assign_score_function(1);
|
score += assign_score_function(1);
|
||||||
} else {
|
} else {
|
||||||
score += assign_score_function(10);
|
score += assign_score_function(MAXIMUM_TYPE_DISTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool param_is_variadic = pt->variadic && pt->variadic_index == operand_index;
|
||||||
|
|
||||||
i64 s = 0;
|
i64 s = 0;
|
||||||
if (!check_is_assignable_to_with_score(c, &o, t, &s)) {
|
if (!check_is_assignable_to_with_score(c, &o, t, &s, param_is_variadic)) {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
if (e->flags & EntityFlag_AutoCast) {
|
if (e->flags & EntityFlag_AutoCast) {
|
||||||
ok = check_is_castable_to(c, &o, t);
|
ok = check_is_castable_to(c, &o, t);
|
||||||
}
|
}
|
||||||
if (ok) {
|
if (ok) {
|
||||||
s = assign_score_function(10);
|
s = assign_score_function(MAXIMUM_TYPE_DISTANCE);
|
||||||
} else {
|
} else {
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
check_assignment(c, &o, t, str_lit("argument"));
|
check_assignment(c, &o, t, str_lit("argument"));
|
||||||
@@ -4036,7 +4057,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
|||||||
t = slice;
|
t = slice;
|
||||||
if (operand_index != param_count) {
|
if (operand_index != param_count) {
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
error(o.expr, "'...' in a variadic procedure can only have one variadic argument at the end");
|
error(o.expr, "'..' in a variadic procedure can only have one variadic argument at the end");
|
||||||
}
|
}
|
||||||
if (data) {
|
if (data) {
|
||||||
data->score = score;
|
data->score = score;
|
||||||
@@ -4047,7 +4068,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
i64 s = 0;
|
i64 s = 0;
|
||||||
if (!check_is_assignable_to_with_score(c, &o, t, &s)) {
|
if (!check_is_assignable_to_with_score(c, &o, t, &s, true)) {
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
check_assignment(c, &o, t, str_lit("argument"));
|
check_assignment(c, &o, t, str_lit("argument"));
|
||||||
}
|
}
|
||||||
@@ -4224,17 +4245,18 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
if (are_types_identical(e->type, o->type)) {
|
if (are_types_identical(e->type, o->type)) {
|
||||||
score += assign_score_function(1);
|
score += assign_score_function(1);
|
||||||
} else {
|
} else {
|
||||||
score += assign_score_function(10);
|
score += assign_score_function(MAXIMUM_TYPE_DISTANCE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i64 s = 0;
|
i64 s = 0;
|
||||||
if (!check_is_assignable_to_with_score(c, o, e->type, &s)) {
|
bool param_is_variadic = pt->variadic && pt->variadic_index == i;
|
||||||
|
if (!check_is_assignable_to_with_score(c, o, e->type, &s, param_is_variadic)) {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
if (e->flags & EntityFlag_AutoCast) {
|
if (e->flags & EntityFlag_AutoCast) {
|
||||||
ok = check_is_castable_to(c, o, e->type);
|
ok = check_is_castable_to(c, o, e->type);
|
||||||
}
|
}
|
||||||
if (ok) {
|
if (ok) {
|
||||||
s = assign_score_function(10);
|
s = assign_score_function(MAXIMUM_TYPE_DISTANCE);
|
||||||
} else {
|
} else {
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
check_assignment(c, o, e->type, str_lit("procedure argument"));
|
check_assignment(c, o, e->type, str_lit("procedure argument"));
|
||||||
@@ -4276,7 +4298,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|||||||
|
|
||||||
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
||||||
if (vari_expand) {
|
if (vari_expand) {
|
||||||
// error(ce->ellipsis, "Invalid use of '...' with 'field = value' call'");
|
// error(ce->ellipsis, "Invalid use of '..' with 'field = value' call'");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -4451,6 +4473,7 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
|
|||||||
sep = ":=";
|
sep = ":=";
|
||||||
}
|
}
|
||||||
gb_printf_err("\t%.*s %s %s at %.*s(%td:%td)\n", LIT(name), sep, pt, LIT(pos.file), pos.line, pos.column);
|
gb_printf_err("\t%.*s %s %s at %.*s(%td:%td)\n", LIT(name), sep, pt, LIT(pos.file), pos.line, pos.column);
|
||||||
|
// gb_printf_err("\t%.*s %s %s at %.*s(%td:%td) %lld\n", LIT(name), sep, pt, LIT(pos.file), pos.line, pos.column, valids[i].score);
|
||||||
}
|
}
|
||||||
result_type = t_invalid;
|
result_type = t_invalid;
|
||||||
} else {
|
} else {
|
||||||
@@ -4538,7 +4561,7 @@ CallArgumentError check_polymorphic_struct_type(CheckerContext *c, Operand *oper
|
|||||||
|
|
||||||
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
||||||
if (vari_expand) {
|
if (vari_expand) {
|
||||||
error(ce->ellipsis, "Invalid use of '...' in a polymorphic type call'");
|
error(ce->ellipsis, "Invalid use of '..' in a polymorphic type call'");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -4637,7 +4660,7 @@ CallArgumentError check_polymorphic_struct_type(CheckerContext *c, Operand *oper
|
|||||||
if (are_types_identical(e->type, o->type)) {
|
if (are_types_identical(e->type, o->type)) {
|
||||||
score += assign_score_function(1);
|
score += assign_score_function(1);
|
||||||
} else {
|
} else {
|
||||||
score += assign_score_function(10);
|
score += assign_score_function(MAXIMUM_TYPE_DISTANCE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i64 s = 0;
|
i64 s = 0;
|
||||||
@@ -6256,7 +6279,7 @@ gbString write_expr_to_string(gbString str, Ast *node) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(e, Ellipsis, node);
|
case_ast_node(e, Ellipsis, node);
|
||||||
str = gb_string_appendc(str, "...");
|
str = gb_string_appendc(str, "..");
|
||||||
str = write_expr_to_string(str, e->expr);
|
str = write_expr_to_string(str, e->expr);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2554,7 +2554,7 @@ gbString write_type_to_string(gbString str, Type *type) {
|
|||||||
}
|
}
|
||||||
if (var->flags&EntityFlag_Ellipsis) {
|
if (var->flags&EntityFlag_Ellipsis) {
|
||||||
Type *slice = base_type(var->type);
|
Type *slice = base_type(var->type);
|
||||||
str = gb_string_appendc(str, "...");
|
str = gb_string_appendc(str, "..");
|
||||||
GB_ASSERT(var->type->kind == Type_Slice);
|
GB_ASSERT(var->type->kind == Type_Slice);
|
||||||
str = write_type_to_string(str, slice->Slice.elem);
|
str = write_type_to_string(str, slice->Slice.elem);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user