Fixed issues inferring length with subarrays. Removed old, non-working example. Infer length in the case of subarray literals.

This commit is contained in:
Christoffer Lerno
2023-09-12 22:24:20 +02:00
parent d61482dffc
commit 1d04b70efe
9 changed files with 61 additions and 81 deletions

View File

@@ -72,9 +72,7 @@ fn ulong! poll(Poll[] polls, Duration timeout)
$else
CInt result = os::poll((Posix_pollfd*)polls.ptr, (Posix_nfds_t)polls.len, (CInt)time_ms);
$endif
if (result == 0) return 0;
if (result > 0) return (ulong)result;
return os::socket_error()?;
return result < 0 ? os::socket_error()? : (ulong)result;
}
macro Socket new_socket(fd, ai)

View File

@@ -1,35 +0,0 @@
module globals;
const String CLICK_ME = "Click Me";
uint counter = 0;
fn void clickedme(GtkButton *o, void *d)
{
(GtkLabel*)(d).set_text(string.format("You clicked me %d times", ++counter));
}
fn void main(String[] argv)
{
gtk::init(&argc, &argv);
GtkWindow *win = gtk::windowCreate(GtkWindow.TOPLEVEL);
win.set_title(CLICK_ME);
GtkButton *button = gtk::buttonCreateWithLabel(CLICK_ME);
GtkLabel *label = GtkLabel.new("There have been no clicks yet");
label.setSingleLineMode(true);
GtkVBox vbox = gtk::vBoxCreate(true, 1);
vbox.add(label);
vbox.add(button);
win.add(vbox);
win.connectSignal("delete-event", gtk::mainQuit, NULL);
button.connectSignal("clicked", &clickedme, label);
win.showAll();
gtk::main();
}

View File

@@ -2100,7 +2100,6 @@ bool cast_explicit(SemaContext *context, Expr *expr, Type *to_type);
bool may_cast(SemaContext *cc, Expr *expr, Type *to_type, bool is_explicit);
void cast_no_check(Expr *expr, Type *to_type, bool add_optional);
Type *type_infer_len_from_actual_type(Type *to_infer, Type *actual_type);
bool cast_to_index(SemaContext *context, Expr *index);
CastKind cast_to_bool_kind(Type *type);

View File

@@ -255,13 +255,12 @@ Type *type_infer_len_from_actual_type(Type *to_infer, Type *actual_type)
case TYPE_INFERRED_VECTOR:
assert(type_is_arraylike(type_flatten(actual_type)));
return type_add_optional(type_get_vector(indexed, type_flatten(actual_type)->array.len), is_optional);
case TYPE_SUBARRAY:
return type_add_optional(type_get_subarray(indexed), is_optional);
case TYPE_VECTOR:
// This is unreachable, because unlike arrays, there is no inner type that may be
// the inferred part.
UNREACHABLE
case TYPE_SUBARRAY:
// The case of int[*][] y = ... is disallowed
UNREACHABLE
default:
UNREACHABLE
}
@@ -761,7 +760,7 @@ static bool rule_int_to_ptr(CastContext *cc, bool is_explicit, bool is_silent)
static bool rule_ptr_to_int(CastContext *cc, bool is_explicit, bool is_silent)
{
bool too_small = type_size(cc->to_type) < type_size(type_uptr);
bool too_small = type_size(cc->to) < type_size(type_uptr);
if (!is_explicit) return sema_cast_error(cc, !too_small, is_silent);
// The type must be uptr or bigger.
@@ -883,7 +882,7 @@ static bool rule_arr_to_arr(CastContext *cc, bool is_explicit, bool is_silent)
static bool rule_arr_to_vec(CastContext *cc, bool is_explicit, bool is_silent)
{
ArraySize len = cc->from_type->array.len;
if (len != cc->to_type->array.len) return sema_cast_error(cc, false, is_silent);
if (len != cc->to->array.len) return sema_cast_error(cc, false, is_silent);
Type *base = cc->from_type->array.base;
switch (type_to_group(type_flatten(base)))
{
@@ -908,7 +907,7 @@ static bool rule_arr_to_vec(CastContext *cc, bool is_explicit, bool is_silent)
static bool rule_vec_to_arr(CastContext *cc, bool is_explicit, bool is_silent)
{
ArraySize len = cc->from_type->array.len;
if (len != cc->to_type->array.len) return sema_cast_error(cc, false, is_silent);
if (len != cc->to->array.len) return sema_cast_error(cc, false, is_silent);
Type *base = cc->from_type->array.base;
cast_context_set_from(cc, type_get_array(base, len));
return cast_is_allowed(cc, is_explicit, is_silent);
@@ -946,6 +945,14 @@ static bool rule_sa_to_vecarr(CastContext *cc, bool is_explicit, bool is_silent)
static bool rule_sa_to_infer(CastContext *cc, bool is_explicit, bool is_silent)
{
Expr *expr = cc->expr;
// 1. We might infer something above.
if (cc->to->type_kind == TYPE_SUBARRAY)
{
cast_context_set_from(cc, cc->from_type->array.base);
cast_context_set_to(cc, cc->to->array.base);
return cast_is_allowed(cc, is_explicit, is_silent);
}
// 2. Otherwise there is a vector matching.
MemberIndex size = sema_len_from_const(expr);
if (size < 0)
{
@@ -963,16 +970,16 @@ static bool rule_sa_to_infer(CastContext *cc, bool is_explicit, bool is_silent)
static bool rule_vecarr_to_infer(CastContext *cc, bool is_explicit, bool is_silent)
{
Type *new_type = type_infer_len_from_actual_type(cc->from_type, cc->to_type);
Type *new_type = type_infer_len_from_actual_type(cc->to, cc->from_type);
cast_context_set_to(cc, new_type);
return cast_is_allowed(cc, is_explicit, is_silent);
}
static bool rule_ptr_to_infer(CastContext *cc, bool is_explicit, bool is_silent)
{
if (cc->to_type->type_kind != TYPE_POINTER) return sema_cast_error(cc, false, is_silent);
if (cc->to->type_kind != TYPE_POINTER) return sema_cast_error(cc, false, is_silent);
Type *new_type = type_infer_len_from_actual_type(cc->from_type, cc->to_type);
Type *new_type = type_infer_len_from_actual_type(cc->to, cc->from_type);
cast_context_set_to(cc, new_type->pointer->canonical);
cast_context_set_from(cc, cc->from_type->pointer);
return cast_is_allowed(cc, is_explicit, is_silent);
@@ -1108,7 +1115,7 @@ static bool rule_struct_to_struct(CastContext *cc, bool is_explicit, bool is_sil
static bool rule_vec_to_vec(CastContext *cc, bool is_explicit, bool is_silent)
{
if (cc->from_type->array.len != cc->to_type->array.len) return sema_cast_error(cc, false, is_silent);
if (cc->from_type->array.len != cc->to->array.len) return sema_cast_error(cc, false, is_silent);
Type *from_base = cc->from_type->array.base;
cast_context_set_to(cc, cc->to->array.base);
// Allow bool vectors to expand to any int.
@@ -1167,8 +1174,8 @@ static bool rule_bits_to_arr(CastContext *cc, bool is_explicit, bool is_silent)
{
if (is_silent && !is_explicit) return false;
Type *base_type = cc->from_type->decl->bitstruct.base_type->type->canonical;
Type *to_type = cc->to_type;
if (base_type != to_type) return sema_cast_error(cc, false, is_silent);
Type *to = cc->to;
if (base_type != to) return sema_cast_error(cc, false, is_silent);
if (!is_explicit) return sema_cast_error(cc, true, is_silent);
return true;
}
@@ -1177,10 +1184,10 @@ static bool rule_bits_to_int(CastContext *cc, bool is_explicit, bool is_silent)
{
if (is_silent && !is_explicit) return false;
Type *base_type = cc->from_type->decl->bitstruct.base_type->type->canonical;
Type *to_type = cc->to_type;
if (base_type != to_type)
Type *to = cc->to;
if (base_type != to)
{
if (!type_is_integer(base_type) || type_size(to_type) != type_size(base_type))
if (!type_is_integer(base_type) || type_size(to) != type_size(base_type))
{
return sema_cast_error(cc, false, is_silent);
}
@@ -1729,6 +1736,14 @@ static void cast_sa_to_sa(Expr *expr, Type *to_type)
static void cast_sa_to_vecarr(Expr *expr, Type *to_type)
{
if (!expr_is_const(expr))
{
assert(expr->expr_kind == EXPR_CAST);
Expr *inner = exprptr(expr->cast_expr.expr)->unary_expr.expr;
expr_replace(expr, inner);
cast_no_check(expr, to_type, false);
return;
}
assert(expr_is_const(expr));
expr->type = to_type;
return;
@@ -1736,18 +1751,11 @@ static void cast_sa_to_vecarr(Expr *expr, Type *to_type)
static void cast_sa_to_infer(Expr *expr, Type *to_type)
{
assert(expr_is_const(expr));
Type *index = type_get_indexed_type(to_type);
MemberIndex size = sema_len_from_const(expr);
assert(size > 0);
if (type_flatten(to_type)->type_kind == TYPE_VECTOR)
{
expr->type = type_get_vector(index, size);
}
else
{
expr->type = type_get_array(index, size);
}
ArraySize len = sema_len_from_const(expr);
assert(len > 0);
Type *indexed = type_get_indexed_type(expr->type);
to_type = type_infer_len_from_actual_type(to_type, type_get_array(indexed, len));
cast_no_check(expr, to_type, false);
}
static void cast_vecarr_to_infer(Expr *expr, Type *to_type)

View File

@@ -3046,12 +3046,7 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
if (infer_len)
{
if (type_is_inferred(init->type))
{
SEMA_ERROR(decl->var.type_info, "You cannot use [*] and [<*>] underlying types with initializers.");
return decl_poison(decl);
}
decl->type = type_infer_len_from_actual_type(decl->type, init->type);
decl->type = type_add_optional(init->type, IS_OPTIONAL(decl));
}
Expr *init_expr = decl->var.init_expr;

View File

@@ -8109,10 +8109,21 @@ static MemberIndex len_from_const_initializer(ConstInitializer *init)
}
UNREACHABLE
}
MemberIndex sema_len_from_const(Expr *expr_maybe_const)
MemberIndex sema_len_from_const(Expr *expr)
{
if (!expr_is_const(expr_maybe_const)) return -1;
switch (expr_maybe_const->const_expr.const_kind)
// We also handle the case where we have a cast from a const array.
if (!expr_is_const(expr))
{
if (expr->type->type_kind != TYPE_SUBARRAY) return -1;
if (expr->expr_kind != EXPR_CAST) return -1;
if (expr->cast_expr.kind != CAST_APTSA) return -1;
Expr *inner = exprptr(expr->cast_expr.expr);
if (inner->expr_kind != EXPR_UNARY || inner->unary_expr.operator != UNARYOP_ADDR) return -1;
inner = inner->unary_expr.expr;
if (!expr_is_const(inner)) return -1;
expr = inner;
}
switch (expr->const_expr.const_kind)
{
case CONST_FLOAT:
case CONST_INTEGER:
@@ -8125,11 +8136,11 @@ MemberIndex sema_len_from_const(Expr *expr_maybe_const)
return -1;
case CONST_BYTES:
case CONST_STRING:
return expr_maybe_const->const_expr.bytes.len;
return expr->const_expr.bytes.len;
case CONST_INITIALIZER:
return len_from_const_initializer(expr_maybe_const->const_expr.initializer);
return len_from_const_initializer(expr->const_expr.initializer);
case CONST_UNTYPED_LIST:
return vec_size(expr_maybe_const->const_expr.untyped_list);
return vec_size(expr->const_expr.untyped_list);
}
UNREACHABLE
}

View File

@@ -308,7 +308,6 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
if (!sema_analyse_expr_rhs(context, inner_type, element, true)) return false;
if (inner_is_inferred)
{
Type *element_type = type_no_optional(element->type);
if (inferred_element)
{
if (!cast_implicit(context, element, inferred_element))
@@ -319,7 +318,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
}
else
{
inferred_element = type_infer_len_from_actual_type(inner_type, element_type);
inferred_element = element->type;
}
}
}

View File

@@ -81,7 +81,7 @@ int sema_check_comp_time_bool(SemaContext *context, Expr *expr);
bool sema_expr_check_assign(SemaContext *c, Expr *expr);
bool sema_analyse_function_signature(SemaContext *context, Decl *func_decl, CallABI abi, Signature *signature, bool is_real_function);
bool cast_widen_top_down(SemaContext *context, Expr *expr, Type *type);
MemberIndex sema_len_from_const(Expr *expr_maybe_const);
MemberIndex sema_len_from_const(Expr *expr);
void cast_promote_vararg(Expr *arg);
Type *cast_numeric_arithmetic_promotion(Type *type);

View File

@@ -0,0 +1,5 @@
fn void main()
{
int[*][*][] x = int[2][1][] { { { 1, 2 } } };
int[*][*][*] y = int[2][1][] { { { 1, 2 } } };
}