mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fixed issues inferring length with subarrays. Removed old, non-working example. Infer length in the case of subarray literals.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
5
test/test_suite/arrays/inferred_subarray.c3
Normal file
5
test/test_suite/arrays/inferred_subarray.c3
Normal file
@@ -0,0 +1,5 @@
|
||||
fn void main()
|
||||
{
|
||||
int[*][*][] x = int[2][1][] { { { 1, 2 } } };
|
||||
int[*][*][*] y = int[2][1][] { { { 1, 2 } } };
|
||||
}
|
||||
Reference in New Issue
Block a user