diff options
Diffstat (limited to 'src/check_expr.c')
| -rw-r--r-- | src/check_expr.c | 50 |
1 files changed, 47 insertions, 3 deletions
diff --git a/src/check_expr.c b/src/check_expr.c index bd8183069..0096c7566 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1398,7 +1398,8 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type return true; } if (in_value.kind == ExactValue_Integer) { - return true; + return false; + // return true; } if (out_value) *out_value = in_value; } @@ -1727,6 +1728,7 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) { return true; } + if (dst->kind == Type_Array && src->kind == Type_Array) { if (are_types_identical(dst->Array.elem, src->Array.elem)) { return dst->Array.count == src->Array.count; @@ -1868,6 +1870,8 @@ void check_conversion(Checker *c, Operand *x, Type *type) { if (bt->kind == Type_Basic) { if (check_representable_as_constant(c, x->value, bt, &x->value)) { can_convert = true; + } else if (is_type_pointer(type) && check_is_castable_to(c, x, type)) { + can_convert = true; } } } else if (check_is_castable_to(c, x, type)) { @@ -2478,8 +2482,10 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h goto error; } - if (ast_node_expect(selector, AstNode_Ident)) { - + // if (selector->kind != AstNode_Ident && selector->kind != AstNode_BasicLit) { + if (selector->kind != AstNode_Ident) { + error_node(selector, "Illegal selector kind: `%.*s`", LIT(ast_node_strings[selector->kind])); + goto error; } if (op_expr->kind == AstNode_Ident) { @@ -2577,6 +2583,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } } } + if (check_op_expr) { check_expr_base(c, operand, op_expr, NULL); if (operand->mode == Addressing_Invalid) { @@ -2589,6 +2596,43 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h sel = lookup_field(c->allocator, operand->type, selector->Ident.string, operand->mode == Addressing_Type); entity = sel.entity; } + if (entity == NULL && selector->kind == AstNode_BasicLit) { + if (is_type_struct(operand->type) || is_type_tuple(operand->type)) { + Type *type = base_type(operand->type); + Operand o = {0}; + check_expr(c, &o, selector); + if (o.mode != Addressing_Constant || + !is_type_integer(o.type)) { + error_node(op_expr, "Indexed based selectors must be a constant integer %s"); + goto error; + } + i64 index = o.value.value_integer; + if (index < 0) { + error_node(o.expr, "Index %lld cannot be a negative value", index); + goto error; + } + + i64 max_count = 0; + switch (type->kind) { + case Type_Record: max_count = type->Record.field_count; break; + case Type_Tuple: max_count = type->Tuple.variable_count; break; + } + + if (index >= max_count) { + error_node(o.expr, "Index %lld is out of bounds range 0..<%lld", index, max_count); + goto error; + } + + sel = lookup_field_from_index(heap_allocator(), type, index); + entity = sel.entity; + + GB_ASSERT(entity != NULL); + + } else { + error_node(op_expr, "Indexed based selectors may only be used on structs or tuples"); + goto error; + } + } if (entity == NULL) { gbString op_str = expr_to_string(op_expr); gbString type_str = type_to_string(operand->type); |