aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.c
diff options
context:
space:
mode:
authorZac Pierson <zacpiersonhehe@gmail.com>2017-02-15 10:21:38 -0600
committerZac Pierson <zacpiersonhehe@gmail.com>2017-02-15 10:21:38 -0600
commitaaa4dd5c363f2cb4643cd6489108d5be7c9d17de (patch)
treecb6b93596135d2a7f868acc73fcea1536e3d7ab9 /src/check_expr.c
parent9d19ee7e4c285d5d881570be3328d81bdff40368 (diff)
parent71100ed427ee2eec8d8a9d4d9616102738097e80 (diff)
Merge https://github.com/gingerBill/odin
Diffstat (limited to 'src/check_expr.c')
-rw-r--r--src/check_expr.c477
1 files changed, 157 insertions, 320 deletions
diff --git a/src/check_expr.c b/src/check_expr.c
index 3b58dc904..687f4ebea 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -265,8 +265,6 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
}
-
-
if (type == NULL) {
return;
}
@@ -1030,7 +1028,7 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
}
o->mode = Addressing_Variable;
if (e->Variable.is_immutable) {
- o->mode = Addressing_Value;
+ o->mode = Addressing_Immutable;
}
break;
@@ -1073,7 +1071,7 @@ i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) {
}
Operand o = {0};
if (e->kind == AstNode_UnaryExpr &&
- e->UnaryExpr.op.kind == Token_Question) {
+ e->UnaryExpr.op.kind == Token_Ellipsis) {
return -1;
}
@@ -1115,12 +1113,13 @@ i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) {
return 0;
}
-Type *make_map_tuple_type(gbAllocator a, Type *value) {
+Type *make_optional_ok_type(gbAllocator a, Type *value) {
+ bool typed = true;
Type *t = make_type_tuple(a);
t->Tuple.variables = gb_alloc_array(a, Entity *, 2);
t->Tuple.variable_count = 2;
t->Tuple.variables[0] = make_entity_field(a, NULL, blank_token, value, false, 0);
- t->Tuple.variables[1] = make_entity_field(a, NULL, blank_token, t_bool, false, 1);
+ t->Tuple.variables[1] = make_entity_field(a, NULL, blank_token, typed ? t_bool : t_untyped_bool, false, 1);
return t;
}
@@ -1221,7 +1220,7 @@ void check_map_type(Checker *c, Type *type, AstNode *node) {
type->Map.generated_struct_type = generated_struct_type;
}
- type->Map.lookup_result_type = make_map_tuple_type(a, value);
+ type->Map.lookup_result_type = make_optional_ok_type(a, value);
// error_node(node, "`map` types are not yet implemented");
}
@@ -1929,6 +1928,76 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
x->mode = Addressing_Value;
}
+
+String check_down_cast_name(Type *dst_, Type *src_) {
+ String result = {0};
+ Type *dst = type_deref(dst_);
+ Type *src = type_deref(src_);
+ Type *dst_s = base_type(dst);
+ GB_ASSERT(is_type_struct(dst_s) || is_type_raw_union(dst_s));
+ for (isize i = 0; i < dst_s->Record.field_count; i++) {
+ Entity *f = dst_s->Record.fields[i];
+ GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
+ if (f->flags & EntityFlag_Anonymous) {
+ if (are_types_identical(f->type, src_)) {
+ return f->token.string;
+ }
+ if (are_types_identical(type_deref(f->type), src_)) {
+ return f->token.string;
+ }
+
+ if (!is_type_pointer(f->type)) {
+ result = check_down_cast_name(f->type, src_);
+ if (result.len > 0) {
+ return result;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+Operand check_ptr_addition(Checker *c, TokenKind op, Operand *ptr, Operand *offset, AstNode *node) {
+ GB_ASSERT(node->kind == AstNode_BinaryExpr);
+ ast_node(be, BinaryExpr, node);
+ GB_ASSERT(is_type_pointer(ptr->type));
+ GB_ASSERT(is_type_integer(offset->type));
+ GB_ASSERT(op == Token_Add || op == Token_Sub);
+
+ Operand operand = {0};
+ operand.mode = Addressing_Value;
+ operand.type = ptr->type;
+ operand.expr = node;
+
+ if (base_type(ptr->type) == t_rawptr) {
+ gbString str = type_to_string(ptr->type);
+ error_node(node, "Invalid pointer type for pointer arithmetic: `%s`", str);
+ gb_string_free(str);
+ operand.mode = Addressing_Invalid;
+ return operand;
+ }
+
+
+ if (ptr->mode == Addressing_Constant && offset->mode == Addressing_Constant) {
+ i64 elem_size = type_size_of(c->allocator, ptr->type);
+ i64 ptr_val = ptr->value.value_pointer;
+ i64 offset_val = exact_value_to_integer(offset->value).value_integer;
+ i64 new_ptr_val = ptr_val;
+ if (op == Token_Add) {
+ new_ptr_val += elem_size*offset_val;
+ } else {
+ new_ptr_val -= elem_size*offset_val;
+ }
+ operand.mode = Addressing_Constant;
+ operand.value = make_exact_value_pointer(new_ptr_val);
+ }
+
+ return operand;
+}
+
+
+
bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
if (check_is_assignable_to(c, operand, y)) {
return true;
@@ -1968,10 +2037,21 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
// Cast between pointers
if (is_type_pointer(src) && is_type_pointer(dst)) {
+ Type *s = base_type(type_deref(src));
+ if (is_type_union(s)) {
+ // NOTE(bill): Should the error be here?!
+ // NOTE(bill): This error should suppress the next casting error as it's at the same position
+ gbString xs = type_to_string(x);
+ gbString ys = type_to_string(y);
+ error_node(operand->expr, "Cannot cast from a union pointer `%s` to `%s`, try using `union_cast` or cast to a `rawptr`", xs, ys);
+ gb_string_free(ys);
+ gb_string_free(xs);
+ return false;
+ }
return true;
}
- // (u)int <-> pointer
+ // (u)int <-> rawptr
if (is_type_int_or_uint(src) && is_type_rawptr(dst)) {
return true;
}
@@ -2006,75 +2086,7 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
return false;
}
-String check_down_cast_name(Type *dst_, Type *src_) {
- String result = {0};
- Type *dst = type_deref(dst_);
- Type *src = type_deref(src_);
- Type *dst_s = base_type(dst);
- GB_ASSERT(is_type_struct(dst_s) || is_type_raw_union(dst_s));
- for (isize i = 0; i < dst_s->Record.field_count; i++) {
- Entity *f = dst_s->Record.fields[i];
- GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
- if (f->flags & EntityFlag_Anonymous) {
- if (are_types_identical(f->type, src_)) {
- return f->token.string;
- }
- if (are_types_identical(type_deref(f->type), src_)) {
- return f->token.string;
- }
-
- if (!is_type_pointer(f->type)) {
- result = check_down_cast_name(f->type, src_);
- if (result.len > 0) {
- return result;
- }
- }
- }
- }
-
- return result;
-}
-
-Operand check_ptr_addition(Checker *c, TokenKind op, Operand *ptr, Operand *offset, AstNode *node) {
- GB_ASSERT(node->kind == AstNode_BinaryExpr);
- ast_node(be, BinaryExpr, node);
- GB_ASSERT(is_type_pointer(ptr->type));
- GB_ASSERT(is_type_integer(offset->type));
- GB_ASSERT(op == Token_Add || op == Token_Sub);
-
- Operand operand = {0};
- operand.mode = Addressing_Value;
- operand.type = ptr->type;
- operand.expr = node;
-
- if (base_type(ptr->type) == t_rawptr) {
- gbString str = type_to_string(ptr->type);
- error_node(node, "Invalid pointer type for pointer arithmetic: `%s`", str);
- gb_string_free(str);
- operand.mode = Addressing_Invalid;
- return operand;
- }
-
-
- if (ptr->mode == Addressing_Constant && offset->mode == Addressing_Constant) {
- i64 elem_size = type_size_of(c->allocator, ptr->type);
- i64 ptr_val = ptr->value.value_pointer;
- i64 offset_val = exact_value_to_integer(offset->value).value_integer;
- i64 new_ptr_val = ptr_val;
- if (op == Token_Add) {
- new_ptr_val += elem_size*offset_val;
- } else {
- new_ptr_val -= elem_size*offset_val;
- }
- operand.mode = Addressing_Constant;
- operand.value = make_exact_value_pointer(new_ptr_val);
- }
-
- return operand;
-}
-
-
-void check_conversion(Checker *c, Operand *x, Type *type) {
+void check_cast(Checker *c, Operand *x, Type *type) {
bool is_const_expr = x->mode == Addressing_Constant;
bool can_convert = false;
@@ -2714,7 +2726,9 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
break;
case Entity_Variable:
// TODO(bill): This is the rule I need?
- if (sel.indirect || operand->mode != Addressing_Value) {
+ if (operand->mode == Addressing_Immutable) {
+ // Okay
+ } else if (sel.indirect || operand->mode != Addressing_Value) {
operand->mode = Addressing_Variable;
} else {
operand->mode = Addressing_Value;
@@ -3819,17 +3833,16 @@ int valid_proc_and_score_cmp(void const *a, void const *b) {
typedef Array(Operand) ArrayOperand;
-void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, AstNodeArray args, bool allow_map_ok) {
- for_array(i, args) {
+bool check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, AstNodeArray rhs, bool allow_ok) {
+ bool optional_ok = false;
+ for_array(i, rhs) {
Operand o = {0};
- check_multi_expr(c, &o, args.e[i]);
+ check_multi_expr(c, &o, rhs.e[i]);
if (o.type == NULL || o.type->kind != Type_Tuple) {
- if (o.mode == Addressing_MapIndex &&
- allow_map_ok &&
- lhs_count == 2 &&
- args.count == 1) {
- Type *tuple = make_map_tuple_type(c->allocator, o.type);
+ if (allow_ok && lhs_count == 2 && rhs.count == 1 &&
+ (o.mode == Addressing_MapIndex || o.mode == Addressing_OptionalOk)) {
+ Type *tuple = make_optional_ok_type(c->allocator, o.type);
add_type_and_value(&c->info, o.expr, o.mode, tuple, o.value);
Operand val = o;
@@ -3839,9 +3852,11 @@ void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands,
ok.type = t_bool;
array_add(operands, val);
array_add(operands, ok);
- continue;
+
+ optional_ok = true;
+ } else {
+ array_add(operands, o);
}
- array_add(operands, o);
} else {
TypeTuple *tuple = &o.type->Tuple;
for (isize j = 0; j < tuple->variable_count; j++) {
@@ -3850,6 +3865,8 @@ void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands,
}
}
}
+
+ return optional_ok;
}
Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) {
@@ -3998,7 +4015,7 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
case 1:
check_expr(c, operand, ce->args.e[0]);
if (operand->mode != Addressing_Invalid) {
- check_conversion(c, operand, t);
+ check_cast(c, operand, t);
}
break;
}
@@ -4097,8 +4114,19 @@ void check_expr_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t) {
}
}
-bool check_set_index_data(Operand *o, Type *t, i64 *max_count) {
- t = base_type(type_deref(t));
+void check_set_mode_with_indirection(Operand *o, bool indirection) {
+ if (o->mode != Addressing_Immutable) {
+ if (indirection) {
+ o->mode = Addressing_Variable;
+ } else if (o->mode != Addressing_Variable &&
+ o->mode != Addressing_Constant) {
+ o->mode = Addressing_Value;
+ }
+ }
+}
+
+bool check_set_index_data(Operand *o, Type *type, bool indirection, i64 *max_count) {
+ Type *t = base_type(type_deref(type));
switch (t->kind) {
case Type_Basic:
@@ -4106,9 +4134,7 @@ bool check_set_index_data(Operand *o, Type *t, i64 *max_count) {
if (o->mode == Addressing_Constant) {
*max_count = o->value.value_string.len;
}
- if (o->mode != Addressing_Variable) {
- o->mode = Addressing_Value;
- }
+ check_set_mode_with_indirection(o, indirection);
o->type = t_u8;
return true;
}
@@ -4116,69 +4142,33 @@ bool check_set_index_data(Operand *o, Type *t, i64 *max_count) {
case Type_Array:
*max_count = t->Array.count;
- if (o->mode != Addressing_Variable) {
- o->mode = Addressing_Value;
- }
+ check_set_mode_with_indirection(o, indirection);
o->type = t->Array.elem;
return true;
case Type_Vector:
*max_count = t->Vector.count;
- if (o->mode != Addressing_Variable) {
- o->mode = Addressing_Value;
- }
+ check_set_mode_with_indirection(o, indirection);
o->type = t->Vector.elem;
return true;
case Type_Slice:
o->type = t->Slice.elem;
- o->mode = Addressing_Variable;
+ if (o->mode != Addressing_Immutable) {
+ o->mode = Addressing_Variable;
+ }
return true;
case Type_DynamicArray:
o->type = t->DynamicArray.elem;
- o->mode = Addressing_Variable;
+ check_set_mode_with_indirection(o, indirection);
return true;
}
return false;
}
-
-bool check_is_giving(AstNode *node, AstNode **give_expr) {
- switch (node->kind) {
- case_ast_node(es, ExprStmt, node);
- if (es->expr->kind == AstNode_GiveExpr) {
- if (give_expr) *give_expr = es->expr;
- return true;
- }
- case_end;
-
- case_ast_node(ge, GiveExpr, node);
- if (give_expr) *give_expr = node;
- return true;
- case_end;
-
- case_ast_node(be, BlockExpr, node);
- // Iterate backwards
- for (isize n = be->stmts.count-1; n >= 0; n--) {
- AstNode *stmt = be->stmts.e[n];
- if (stmt->kind == AstNode_EmptyStmt) {
- continue;
- }
- if (stmt->kind == AstNode_ExprStmt && stmt->ExprStmt.expr->kind == AstNode_GiveExpr) {
- if (give_expr) *give_expr = stmt->ExprStmt.expr;
- return true;
- }
- }
- case_end;
- }
-
- if (give_expr) *give_expr = NULL;
- return false;
-}
-
ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) {
ExprKind kind = Expr_Stmt;
@@ -4280,177 +4270,30 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
o->type = type;
case_end;
- case_ast_node(ge, GiveExpr, node);
- if (c->proc_stack.count == 0) {
- error_node(node, "A give expression is only allowed within a procedure");
- goto error;
- }
-
- if (ge->results.count == 0) {
- error_node(node, "`give` has no results");
- goto error;
- }
-
- gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-
- Array(Operand) operands;
- array_init_reserve(&operands, c->tmp_allocator, 2*ge->results.count);
-
- for_array(i, ge->results) {
- AstNode *rhs = ge->results.e[i];
- Operand o = {0};
- check_multi_expr(c, &o, rhs);
- if (!is_operand_value(o)) {
- error_node(rhs, "Expected a value for a `give`");
- continue;
- }
- if (o.type->kind != Type_Tuple) {
- array_add(&operands, o);
- } else {
- TypeTuple *tuple = &o.type->Tuple;
- for (isize j = 0; j < tuple->variable_count; j++) {
- o.type = tuple->variables[j]->type;
- array_add(&operands, o);
- }
- }
- }
-
- if (operands.count == 0) {
- error_node(node, "`give` has no value");
- gb_temp_arena_memory_end(tmp);
- goto error;
- } else if (operands.count == 1) {
- Operand operand = operands.e[0];
- Type *th = type_hint != NULL ? type_hint : c->context.type_hint;
- if (th != NULL) {
- convert_to_typed(c, &operand, th, 0);
- }
- // IMPORTANT NOTE(bill): This type could be untyped!!!
- o->type = default_type(operand.type);
- o->mode = Addressing_Value;
- } else {
- Type *tuple = make_type_tuple(c->allocator);
-
- Entity **variables = gb_alloc_array(c->allocator, Entity *, operands.count);
- isize variable_index = 0;
- for_array(i, operands) {
- Operand operand = operands.e[i];
- // Type *type = default_type(operand.type);
- Type *type = operand.type;
- switch (operand.mode) {
- case Addressing_Constant:
- variables[variable_index++] = make_entity_constant(c->allocator, NULL, empty_token, type, operand.value);
- break;
- default:
- variables[variable_index++] = make_entity_param(c->allocator, NULL, empty_token, type, false, true);
- break;
- }
- }
- tuple->Tuple.variables = variables;
- tuple->Tuple.variable_count = operands.count;
-
- o->type = tuple;
- o->mode = Addressing_Value;
- }
- gb_temp_arena_memory_end(tmp);
- case_end;
-
- case_ast_node(be, BlockExpr, node);
+ case_ast_node(te, TernaryExpr, node);
if (c->proc_stack.count == 0) {
- error_node(node, "A block expression is only allowed within a procedure");
+ error_node(node, "A ternary expression is only allowed within a procedure");
goto error;
}
-
- for (isize i = be->stmts.count-1; i >= 0; i--) {
- if (be->stmts.e[i]->kind != AstNode_EmptyStmt) {
- break;
- }
- be->stmts.count--;
- }
-
- if (be->stmts.count == 0) {
- error_node(node, "Empty block expression");
- goto error;
- }
-
- CheckerContext prev_context = c->context;
- c->context.type_hint = type_hint;
- check_open_scope(c, node);
- check_stmt_list(c, be->stmts, Stmt_GiveAllowed);
- check_close_scope(c);
-
- c->context = prev_context;
-
- AstNode *give_node = NULL;
- if (!check_is_giving(node, &give_node) || give_node == NULL) {
- error_node(node, "Missing give statement at end of block expression");
- goto error;
- }
-
- GB_ASSERT(give_node != NULL && give_node->kind == AstNode_GiveExpr);
- be->give_node = give_node;
-
- Type *type = type_of_expr(&c->info, give_node);
- if (type == NULL) {
- goto error;
- } else if (type == t_invalid) {
- o->type = t_invalid;
- o->mode = Addressing_Invalid;
- } else {
- o->type = type;
- o->mode = Addressing_Value;
- }
- case_end;
-
- case_ast_node(ie, IfExpr, node);
- if (c->proc_stack.count == 0) {
- error_node(node, "An if expression is only allowed within a procedure");
- goto error;
- }
-
- check_open_scope(c, node);
-
- if (ie->init != NULL) {
- check_stmt(c, ie->init, 0);
- }
-
Operand operand = {Addressing_Invalid};
- check_expr(c, &operand, ie->cond);
+ check_expr(c, &operand, te->cond);
if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) {
- error_node(ie->cond, "Non-boolean condition in if expression");
+ error_node(te->cond, "Non-boolean condition in if expression");
}
Operand x = {Addressing_Invalid};
Operand y = {Addressing_Invalid};
- Type *if_type = NULL;
- Type *else_type = NULL;
- if (type_hint) {
- gb_printf_err("here\n");
- }
- check_expr_with_type_hint(c, &x, ie->body, type_hint);
- if_type = x.type;
-
- if (ie->else_expr != NULL) {
- switch (ie->else_expr->kind) {
- case AstNode_IfExpr:
- case AstNode_BlockExpr:
- check_expr_with_type_hint(c, &y, ie->else_expr, if_type);
- else_type = y.type;
- break;
- default:
- error_node(ie->else_expr, "Invalid else expression in if expression");
- break;
- }
+ check_expr_with_type_hint(c, &x, te->x, type_hint);
+
+ if (te->y != NULL) {
+ check_expr_with_type_hint(c, &y, te->y, type_hint);
} else {
- error_node(ie->else_expr, "An if expression must have an else expression");
- check_close_scope(c);
+ error_node(node, "A ternary expression must have an else clause");
goto error;
}
- check_close_scope(c);
-
- if (if_type == NULL || if_type == t_invalid ||
- else_type == NULL || else_type == t_invalid) {
+ if (x.type == NULL || x.type == t_invalid ||
+ y.type == NULL || y.type == t_invalid) {
goto error;
}
@@ -4465,16 +4308,16 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
}
- if (!are_types_identical(if_type, else_type)) {
- gbString its = type_to_string(if_type);
- gbString ets = type_to_string(else_type);
- error_node(node, "Mismatched types in if expression, %s vs %s", its, ets);
+ if (!are_types_identical(x.type, y.type)) {
+ gbString its = type_to_string(x.type);
+ gbString ets = type_to_string(y.type);
+ error_node(node, "Mismatched types in ternary expression, %s vs %s", its, ets);
gb_string_free(ets);
gb_string_free(its);
goto error;
}
- o->type = if_type;
+ o->type = x.type;
o->mode = Addressing_Value;
case_end;
@@ -4489,7 +4332,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
if (cl->type->kind == AstNode_ArrayType && cl->type->ArrayType.count != NULL) {
AstNode *count = cl->type->ArrayType.count;
if (count->kind == AstNode_UnaryExpr &&
- count->UnaryExpr.op.kind == Token_Question) {
+ count->UnaryExpr.op.kind == Token_Ellipsis) {
type = make_type_array(c->allocator, check_type(c, cl->type->ArrayType.elem), -1);
is_to_be_determined_array_count = true;
}
@@ -4820,7 +4663,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
}
switch (ce->token.kind) {
case Token_cast:
- check_conversion(c, o, t);
+ check_cast(c, o, t);
break;
case Token_transmute: {
if (o->mode == Addressing_Constant) {
@@ -4913,16 +4756,11 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
goto error;
}
- Entity **variables = gb_alloc_array(c->allocator, Entity *, 2);
- variables[0] = make_entity_param(c->allocator, NULL, empty_token, t, false, true);
- variables[1] = make_entity_param(c->allocator, NULL, empty_token, t_bool, false, true);
-
- Type *tuple = make_type_tuple(c->allocator);
- tuple->Tuple.variables = variables;
- tuple->Tuple.variable_count = 2;
+ add_type_info_type(c, o->type);
+ add_type_info_type(c, t);
- o->type = tuple;
- o->mode = Addressing_Value;
+ o->type = t;
+ o->mode = Addressing_OptionalOk;
} break;
case Token_down_cast: {
if (o->mode == Addressing_Constant) {
@@ -5023,6 +4861,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
}
Type *t = base_type(type_deref(o->type));
+ bool is_ptr = is_type_pointer(o->type);
bool is_const = o->mode == Addressing_Constant;
if (is_type_map(t)) {
@@ -5039,7 +4878,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
}
i64 max_count = -1;
- bool valid = check_set_index_data(o, t, &max_count);
+ bool valid = check_set_index_data(o, t, is_ptr, &max_count);
if (is_const) {
valid = false;
@@ -5048,7 +4887,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
if (!valid && (is_type_struct(t) || is_type_raw_union(t))) {
Entity *found = find_using_index_expr(t);
if (found != NULL) {
- valid = check_set_index_data(o, found->type, &max_count);
+ valid = check_set_index_data(o, found->type, is_type_pointer(found->type), &max_count);
}
}
@@ -5125,7 +4964,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
goto error;
}
- o->mode = Addressing_Value;
+ if (o->mode != Addressing_Immutable) {
+ o->mode = Addressing_Value;
+ }
i64 indices[2] = {0};
AstNode *nodes[2] = {se->low, se->high};
@@ -5173,7 +5014,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
} else {
Type *t = base_type(o->type);
if (t->kind == Type_Pointer) {
- o->mode = Addressing_Variable;
+ if (o->mode != Addressing_Immutable) {
+ o->mode = Addressing_Variable;
+ }
o->type = t->Pointer.elem;
} else {
gbString str = expr_to_string(o->expr);
@@ -5354,12 +5197,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = gb_string_appendc(str, "}");
case_end;
- case_ast_node(be, BlockExpr, node);
- str = gb_string_appendc(str, "block expression");
- case_end;
- case_ast_node(ie, IfExpr, node);
- str = gb_string_appendc(str, "if expression");
- case_end;
case_ast_node(te, TagExpr, node);
str = gb_string_appendc(str, "#");