Allow an expression list be an lvalue if the last value is an lvalue. Fix indexing from back for [] overloads.

This commit is contained in:
Christoffer Lerno
2022-12-05 15:42:24 +01:00
parent c15fb7460c
commit eb87eb1987
5 changed files with 67 additions and 17 deletions

View File

@@ -36,7 +36,7 @@ fn void List.tinit(List* list, usz initial_capacity = 16)
list.init(initial_capacity, mem::temp_allocator()) @inline;
}
fn void List.push(List *list, Type element) @inline
fn void List.push(List* list, Type element) @inline
{
list.append(element);
}
@@ -58,14 +58,14 @@ fn Type List.pop(List* list)
/**
* @require list.size > 0
*/
fn Type List.pop_first(List *list)
fn Type List.pop_first(List* list)
{
Type value = list.entries[0];
list.remove_at(0);
return value;
}
fn void List.remove_at(List *list, usz index)
fn void List.remove_at(List* list, usz index)
{
for (usz i = index + 1; i < list.size; i++)
{
@@ -74,7 +74,7 @@ fn void List.remove_at(List *list, usz index)
list.size--;
}
fn void List.push_front(List *list, Type type) @inline
fn void List.push_front(List* list, Type type) @inline
{
list.insert_at(0, type);
}
@@ -95,37 +95,37 @@ fn void List.remove_last(List* list)
list.size--;
}
fn void List.remove_first(List *list)
fn void List.remove_first(List* list)
{
list.remove_at(0);
}
fn Type* List.first(List *list)
fn Type* List.first(List* list)
{
return list.size ? &list.entries[0] : null;
}
fn Type* List.last(List *list)
fn Type* List.last(List* list)
{
return list.size ? &list.entries[list.size - 1] : null;
}
fn bool List.is_empty(List *list)
fn bool List.is_empty(List* list)
{
return !list.size;
}
fn usz List.len(List *list) @operator(len)
fn usz List.len(List* list) @operator(len)
{
return list.size;
}
fn Type List.get(List *list, usz index)
fn Type List.get(List* list, usz index)
{
return list.entries[index];
}
fn void List.free(List *list)
fn void List.free(List* list)
{
if (!list.allocator) return;
list.allocator.free_aligned(list.entries)!!;
@@ -134,7 +134,7 @@ fn void List.free(List *list)
list.entries = null;
}
fn void List.swap(List *list, usz i, usz j)
fn void List.swap(List* list, usz i, usz j)
{
@swap(list.entries[i], list.entries[j]);
}
@@ -142,7 +142,7 @@ fn void List.swap(List *list, usz i, usz j)
/**
* Reserve at least min_capacity
**/
fn void List.reserve(List *list, usz min_capacity)
fn void List.reserve(List* list, usz min_capacity)
{
if (!min_capacity) return;
if (list.capacity >= min_capacity) return;
@@ -163,7 +163,7 @@ macro Type* List.@item_ref(List &list, usz index) @operator(&[])
}
private fn void List.ensure_capacity(List *list) @inline
private fn void List.ensure_capacity(List* list) @inline
{
if (list.capacity == list.size)
{

View File

@@ -2137,6 +2137,8 @@ void expr_rewrite_to_builtin_access(Expr *expr, Expr *parent, BuiltinAccessKind
void expr_rewrite_to_string(Expr *expr_to_rewrite, const char *string);
void expr_rewrite_to_const_zero(Expr *expr, Type *type);
bool expr_rewrite_to_const_initializer_index(Type *list_type, ConstInitializer *list, Expr *result, unsigned index);
void expr_rewrite_to_variable(Expr *expr, Decl *decl);
void expr_rewrite_to_binary(Expr *expr_to_rewrite, Expr *left, Expr *right, BinaryOp op);
bool expr_const_in_range(const ExprConst *left, const ExprConst *right, const ExprConst *right_to);
bool expr_const_compare(const ExprConst *left, const ExprConst *right, BinaryOp op);
@@ -3050,7 +3052,6 @@ INLINE void expr_rewrite_const_typeid(Expr *expr, Type *type)
expr->resolve_status = RESOLVE_DONE;
}
INLINE void expr_rewrite_const_int(Expr *expr, Type *type, uint64_t v, bool narrowable)
{
expr->expr_kind = EXPR_CONST;

View File

@@ -883,6 +883,20 @@ Expr *expr_variable(Decl *decl)
return expr;
}
void expr_rewrite_to_variable(Expr *expr, Decl *decl)
{
expr->expr_kind = EXPR_IDENTIFIER;
if (decl->resolve_status == RESOLVE_DONE)
{
expr->identifier_expr.decl = decl;
expr->resolve_status = RESOLVE_DONE;
expr->type = decl->type;
return;
}
expr->identifier_expr.ident = decl->name;
expr->resolve_status = RESOLVE_NOT_DONE;
}
void expr_rewrite_insert_deref(Expr *original)
{
// Assume *(&x) => x
@@ -921,3 +935,9 @@ void expr_rewrite_to_string(Expr *expr_to_rewrite, const char *string)
expr_to_rewrite->resolve_status = RESOLVE_DONE;
expr_to_rewrite->type = type_get_ptr(type_get_array(type_char, len));
}
void expr_rewrite_to_binary(Expr *expr_to_rewrite, Expr *left, Expr *right, BinaryOp op)
{
expr_to_rewrite->binary_expr = (ExprBinary) { .operator = op, .left = exprid(left), .right = exprid(right) };
expr_to_rewrite->expr_kind = EXPR_BINARY;
}

View File

@@ -426,6 +426,9 @@ static bool sema_binary_is_expr_lvalue(Expr *top_expr, Expr *expr)
case EXPR_HASH_IDENT:
SEMA_ERROR(top_expr, "You cannot assign to an unevaluated expression.");
return false;
case EXPR_EXPRESSION_LIST:
if (!vec_size(expr->expression_list)) return false;
return sema_binary_is_expr_lvalue(top_expr, VECLAST(expr->expression_list));
case EXPR_POISONED:
case EXPR_ARGV_TO_SUBARRAY:
case EXPR_ASM:
@@ -448,7 +451,6 @@ static bool sema_binary_is_expr_lvalue(Expr *top_expr, Expr *expr)
case EXPR_DECL:
case EXPR_DESIGNATED_INITIALIZER_LIST:
case EXPR_DESIGNATOR:
case EXPR_EXPRESSION_LIST:
case EXPR_EXPR_BLOCK:
case EXPR_FAILABLE:
case EXPR_FLATPATH:
@@ -2386,6 +2388,33 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
}
if (overload)
{
if (start_from_end)
{
Decl *len = sema_find_operator(context, current_expr, OVERLOAD_LEN);
if (!len)
{
SEMA_ERROR(subscripted, "Cannot index '%s' from the end, since there is no 'len' overload.", type_to_error_string(subscripted->type));
return false;
}
if (!sema_analyse_expr(context, current_expr)) return false;
Decl *temp = decl_new_generated_var(current_expr->type, VARDECL_PARAM, current_expr->span);
Expr *decl = expr_generate_decl(temp, expr_copy(current_expr));
current_expr->expr_kind = EXPR_EXPRESSION_LIST;
current_expr->expression_list = NULL;
vec_add(current_expr->expression_list, decl);
vec_add(current_expr->expression_list, expr_variable(temp));
if (!sema_analyse_expr(context, current_expr)) return false;
Expr *var_for_len = expr_variable(temp);
Expr *len_expr = expr_new(EXPR_CALL, expr->span);
if (!sema_insert_method_call(context, len_expr, len, var_for_len, NULL)) return false;
if (!sema_analyse_expr(context, len_expr)) return false;
Expr *index_copy = expr_copy(index);
if (!sema_analyse_expr(context, index_copy)) return false;
if (!cast(index_copy, len_expr->type)) return false;
expr_rewrite_to_binary(index, len_expr, index_copy, BINARYOP_SUB);
index->resolve_status = RESOLVE_NOT_DONE;
if (!sema_analyse_expr(context, index)) return false;
}
if (eval_type == SUBSCRIPT_EVAL_ASSIGN)
{
expr->expr_kind = EXPR_SUBSCRIPT_ASSIGN;

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.3.104"
#define COMPILER_VERSION "0.3.105"