diff options
| author | gingerBill <ginger.bill.22@gmail.com> | 2016-07-23 11:41:11 +0100 |
|---|---|---|
| committer | gingerBill <ginger.bill.22@gmail.com> | 2016-07-23 11:41:11 +0100 |
| commit | 3fe7fc344d7d17a571a01e531db4a0e5ff057c9f (patch) | |
| tree | ca617e7e190fd9cf2989bdd3a12e8bff37004f26 /src/checker/expression.cpp | |
| parent | f8fd6fce0b9aabd9562ac8d0dda712154b829f26 (diff) | |
Compound literals and Warnings
Diffstat (limited to 'src/checker/expression.cpp')
| -rw-r--r-- | src/checker/expression.cpp | 285 |
1 files changed, 196 insertions, 89 deletions
diff --git a/src/checker/expression.cpp b/src/checker/expression.cpp index 47823a6b2..1cc36cc65 100644 --- a/src/checker/expression.cpp +++ b/src/checker/expression.cpp @@ -18,7 +18,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { GB_ASSERT(struct_type->kind == Type_Structure); auto *st = &node->struct_type; if (st->field_count == 0) { - checker_err(c, ast_node_token(node), "Empty struct{} definition"); + error(&c->error_collector, ast_node_token(node), "Empty struct{} definition"); return; } @@ -42,11 +42,11 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { GB_ASSERT(name->kind == AstNode_Identifier); Token name_token = name->identifier.token; // TODO(bill): is the curr_scope correct? - Entity *e = make_entity_field(c->allocator, c->proc_context.scope, name_token, type); + Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type); u64 key = hash_string(name_token.string); if (map_get(&entity_map, key)) { // TODO(bill): Scope checking already checks the declaration - checker_err(c, name_token, "`%.*s` is already declared in this structure", LIT(name_token.string)); + error(&c->error_collector, name_token, "`%.*s` is already declared in this structure", LIT(name_token.string)); } else { map_set(&entity_map, key, e); fields[field_index++] = e; @@ -77,8 +77,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *field_list, isize fiel add_entity(c, scope, name, param); variables[variable_index++] = param; } else { - checker_err(c, ast_node_token(name), - "Invalid parameter (invalid AST)"); + error(&c->error_collector, ast_node_token(name), "Invalid parameter (invalid AST)"); } } } @@ -107,7 +106,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *list, isize list_coun if (get_base_type(type)->kind == Type_Array) { // TODO(bill): Should I allow array's to returned? - checker_err(c, token, "You cannot return an array from a procedure"); + error(&c->error_collector, token, "You cannot return an array from a procedure"); } } tuple->tuple.variables = variables; @@ -123,10 +122,10 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) { // gb_printf("%td -> %td\n", param_count, result_count); - Type *params = check_get_params(c, c->proc_context.scope, proc_type_node->procedure_type.param_list, param_count); - Type *results = check_get_results(c, c->proc_context.scope, proc_type_node->procedure_type.results_list, result_count); + Type *params = check_get_params(c, c->context.scope, proc_type_node->procedure_type.param_list, param_count); + Type *results = check_get_results(c, c->context.scope, proc_type_node->procedure_type.results_list, result_count); - type->procedure.scope = c->proc_context.scope; + type->procedure.scope = c->context.scope; type->procedure.params = params; type->procedure.params_count = proc_type_node->procedure_type.param_count; type->procedure.results = results; @@ -138,11 +137,10 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) { GB_ASSERT(n->kind == AstNode_Identifier); o->mode = Addressing_Invalid; o->expression = n; - Entity *e = NULL; - scope_lookup_parent_entity(c->proc_context.scope, n->identifier.token.string, NULL, &e); + Entity *e = scope_lookup_entity(c->context.scope, n->identifier.token.string); if (e == NULL) { - checker_err(c, n->identifier.token, - "Undeclared type or identifier `%.*s`", LIT(n->identifier.token.string)); + error(&c->error_collector, n->identifier.token, + "Undeclared type or identifier `%.*s`", LIT(n->identifier.token.string)); return; } add_entity_use(c, n, e); @@ -200,7 +198,7 @@ i64 check_array_count(Checker *c, AstNode *e) { check_expression(c, &o, e); if (o.mode != Addressing_Constant) { if (o.mode != Addressing_Invalid) { - checker_err(c, ast_node_token(e), "Array count must be a constant"); + error(&c->error_collector, ast_node_token(e), "Array count must be a constant"); } return 0; } @@ -209,12 +207,12 @@ i64 check_array_count(Checker *c, AstNode *e) { i64 count = o.value.value_integer; if (count >= 0) return count; - checker_err(c, ast_node_token(e), "Invalid array count"); + error(&c->error_collector, ast_node_token(e), "Invalid array count"); return 0; } } - checker_err(c, ast_node_token(e), "Array count must be an integer"); + error(&c->error_collector, ast_node_token(e), "Array count must be an integer"); } return 0; } @@ -239,11 +237,11 @@ Type *check_type_expression_extra(Checker *c, AstNode *e, Type *named_type) { case Addressing_NoValue: err_str = expression_to_string(e); - checker_err(c, ast_node_token(e), "`%s` used as a type", err_str); + error(&c->error_collector, ast_node_token(e), "`%s` used as a type", err_str); break; default: err_str = expression_to_string(e); - checker_err(c, ast_node_token(e), "`%s` used as a type when not a type", err_str); + error(&c->error_collector, ast_node_token(e), "`%s` used as a type when not a type", err_str); break; } } break; @@ -289,7 +287,7 @@ Type *check_type_expression_extra(Checker *c, AstNode *e, Type *named_type) { default: err_str = expression_to_string(e); - checker_err(c, ast_node_token(e), "`%s` is not a type", err_str); + error(&c->error_collector, ast_node_token(e), "`%s` is not a type", err_str); break; } @@ -321,11 +319,11 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) { case Addressing_NoValue: err_str = expression_to_string(e); - checker_err(c, ast_node_token(e), "`%s` used as a type", err_str); + error(&c->error_collector, ast_node_token(e), "`%s` used as a type", err_str); break; default: err_str = expression_to_string(e); - checker_err(c, ast_node_token(e), "`%s` used as a type when not a type", err_str); + error(&c->error_collector, ast_node_token(e), "`%s` used as a type when not a type", err_str); break; } } break; @@ -378,7 +376,7 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) { default: err_str = expression_to_string(e); - checker_err(c, ast_node_token(e), "`%s` is not a type", err_str); + error(&c->error_collector, ast_node_token(e), "`%s` is not a type", err_str); break; } @@ -401,25 +399,25 @@ b32 check_unary_op(Checker *c, Operand *o, Token op) { case Token_Sub: if (!is_type_numeric(o->type)) { str = expression_to_string(o->expression); - checker_err(c, op, "Operator `%.*s` is not allowed with `%s`", LIT(op.string), str); + error(&c->error_collector, op, "Operator `%.*s` is not allowed with `%s`", LIT(op.string), str); } break; case Token_Xor: if (!is_type_integer(o->type)) { - checker_err(c, op, "Operator `%.*s` is only allowed with integers", LIT(op.string)); + error(&c->error_collector, op, "Operator `%.*s` is only allowed with integers", LIT(op.string)); } break; case Token_Not: if (!is_type_boolean(o->type)) { str = expression_to_string(o->expression); - checker_err(c, op, "Operator `%.*s` is only allowed on boolean expression", LIT(op.string)); + error(&c->error_collector, op, "Operator `%.*s` is only allowed on boolean expression", LIT(op.string)); } break; default: - checker_err(c, op, "Unknown operator `%.*s`", LIT(op.string)); + error(&c->error_collector, op, "Unknown operator `%.*s`", LIT(op.string)); return false; } @@ -439,7 +437,7 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) { case Token_MulEq: case Token_QuoEq: if (!is_type_numeric(o->type)) { - checker_err(c, op, "Operator `%.*s` is only allowed with numeric expressions", LIT(op.string)); + error(&c->error_collector, op, "Operator `%.*s` is only allowed with numeric expressions", LIT(op.string)); return false; } break; @@ -456,7 +454,7 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) { case Token_XorEq: case Token_AndNotEq: if (!is_type_integer(o->type)) { - checker_err(c, op, "Operator `%.*s` is only allowed with integers", LIT(op.string)); + error(&c->error_collector, op, "Operator `%.*s` is only allowed with integers", LIT(op.string)); return false; } break; @@ -467,13 +465,13 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) { case Token_CmpAndEq: case Token_CmpOrEq: if (!is_type_boolean(o->type)) { - checker_err(c, op, "Operator `%.*s` is only allowed with boolean expressions", LIT(op.string)); + error(&c->error_collector, op, "Operator `%.*s` is only allowed with boolean expressions", LIT(op.string)); return false; } break; default: - checker_err(c, op, "Unknown operator `%.*s`", LIT(op.string)); + error(&c->error_collector, op, "Unknown operator `%.*s`", LIT(op.string)); return false; } @@ -559,12 +557,12 @@ void check_is_expressible(Checker *c, Operand *o, Type *type) { defer (gb_string_free(b)); if (is_type_numeric(o->type) && is_type_numeric(type)) { if (!is_type_integer(o->type) && is_type_integer(type)) { - checker_err(c, ast_node_token(o->expression), "`%s` truncated to `%s`", a, b); + error(&c->error_collector, ast_node_token(o->expression), "`%s` truncated to `%s`", a, b); } else { - checker_err(c, ast_node_token(o->expression), "`%s` overflows to `%s`", a, b); + error(&c->error_collector, ast_node_token(o->expression), "`%s` overflows to `%s`", a, b); } } else { - checker_err(c, ast_node_token(o->expression), "Cannot convert `%s` to `%s`", a, b); + error(&c->error_collector, ast_node_token(o->expression), "Cannot convert `%s` to `%s`", a, b); } o->mode = Addressing_Invalid; @@ -577,7 +575,7 @@ void check_unary_expression(Checker *c, Operand *o, Token op, AstNode *node) { if (o->mode != Addressing_Variable) { gbString str = expression_to_string(node->unary_expression.operand); defer (gb_string_free(str)); - checker_err(c, op, "Cannot take the pointer address of `%s`", str); + error(&c->error_collector, op, "Cannot take the pointer address of `%s`", str); o->mode = Addressing_Invalid; return; } @@ -646,7 +644,7 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) { } if (err_str) { - checker_err(c, op, "Cannot compare expression, %s", err_str); + error(&c->error_collector, op, "Cannot compare expression, %s", err_str); return; } @@ -697,7 +695,7 @@ void check_binary_expression(Checker *c, Operand *x, AstNode *node) { defer (gb_string_free(xt)); defer (gb_string_free(yt)); err_str = expression_to_string(x->expression); - checker_err(c, op, "Mismatched types in binary expression `%s` : `%s` vs `%s`", err_str, xt, yt); + error(&c->error_collector, op, "Mismatched types in binary expression `%s` : `%s` vs `%s`", err_str, xt, yt); } x->mode = Addressing_Invalid; return; @@ -728,7 +726,7 @@ void check_binary_expression(Checker *c, Operand *x, AstNode *node) { } if (fail) { - checker_err(c, ast_node_token(y->expression), "Division by zero not allowed"); + error(&c->error_collector, ast_node_token(y->expression), "Division by zero not allowed"); x->mode = Addressing_Invalid; return; } @@ -805,7 +803,7 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) { extra_text = " - Did you want `null`?"; } } - checker_err(c, ast_node_token(operand->expression), "Cannot convert `%s` to `%s`%s", expr_str, type_str, extra_text); + error(&c->error_collector, ast_node_token(operand->expression), "Cannot convert `%s` to `%s`%s", expr_str, type_str, extra_text); operand->mode = Addressing_Invalid; } @@ -896,7 +894,7 @@ b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *valu if (!is_type_integer(operand.type)) { gbString expr_str = expression_to_string(operand.expression); - checker_err(c, ast_node_token(operand.expression), + error(&c->error_collector, ast_node_token(operand.expression), "Index `%s` must be an integer", expr_str); gb_string_free(expr_str); if (value) *value = 0; @@ -908,7 +906,7 @@ b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *valu i64 i = exact_value_to_integer(operand.value).value_integer; if (i < 0) { gbString expr_str = expression_to_string(operand.expression); - checker_err(c, ast_node_token(operand.expression), + error(&c->error_collector, ast_node_token(operand.expression), "Index `%s` cannot be a negative value", expr_str); gb_string_free(expr_str); if (value) *value = 0; @@ -919,7 +917,7 @@ b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *valu if (i >= max_count) { gbString expr_str = expression_to_string(operand.expression); - checker_err(c, ast_node_token(operand.expression), + error(&c->error_collector, ast_node_token(operand.expression), "Index `%s` is out of bounds range [0, %lld)", expr_str, max_count); gb_string_free(expr_str); return false; @@ -973,7 +971,7 @@ void check_selector(Checker *c, Operand *operand, AstNode *node) { gbString sel_str = expression_to_string(selector); defer (gb_string_free(op_str)); defer (gb_string_free(sel_str)); - checker_err(c, ast_node_token(op_expr), "`%s` has no field `%s`", op_str, sel_str); + error(&c->error_collector, ast_node_token(op_expr), "`%s` has no field `%s`", op_str, sel_str); operand->mode = Addressing_Invalid; operand->expression = node; return; @@ -1002,9 +1000,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) if (ce->arg_list_count > bp->arg_count && !bp->variadic) err = "Too many"; if (err) { - checker_err(c, ce->close, "`%s` arguments for `%.*s`, expected %td, got %td", - err, LIT(call->call_expression.proc->identifier.token.string), - bp->arg_count, ce->arg_list_count); + error(&c->error_collector, ce->close, "`%s` arguments for `%.*s`, expected %td, got %td", + err, LIT(call->call_expression.proc->identifier.token.string), + bp->arg_count, ce->arg_list_count); return false; } } @@ -1024,7 +1022,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) // size_of :: proc(Type) Type *type = check_type(c, ce->arg_list); if (!type) { - checker_err(c, ast_node_token(ce->arg_list), "Expected a type for `size_of`"); + error(&c->error_collector, ast_node_token(ce->arg_list), "Expected a type for `size_of`"); return false; } @@ -1049,7 +1047,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) // align_of :: proc(Type) Type *type = check_type(c, ce->arg_list); if (!type) { - checker_err(c, ast_node_token(ce->arg_list), "Expected a type for `align_of`"); + error(&c->error_collector, ast_node_token(ce->arg_list), "Expected a type for `align_of`"); return false; } operand->mode = Addressing_Constant; @@ -1074,12 +1072,12 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) AstNode *field_arg = unparen_expression(ce->arg_list->next); if (type) { if (type->kind != Type_Structure) { - checker_err(c, ast_node_token(ce->arg_list), "Expected a structure type for `offset_of`"); + error(&c->error_collector, ast_node_token(ce->arg_list), "Expected a structure type for `offset_of`"); return false; } if (field_arg == NULL || field_arg->kind != AstNode_Identifier) { - checker_err(c, ast_node_token(field_arg), "Expected an identifier for field argument"); + error(&c->error_collector, ast_node_token(field_arg), "Expected an identifier for field argument"); return false; } } @@ -1088,8 +1086,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Entity *entity = lookup_field(type, field_arg, &index); if (entity == NULL) { gbString type_str = type_to_string(type); - checker_err(c, ast_node_token(ce->arg_list), - "`%s` has no field named `%.*s`", type_str, LIT(field_arg->identifier.token.string)); + error(&c->error_collector, ast_node_token(ce->arg_list), + "`%s` has no field named `%.*s`", type_str, LIT(field_arg->identifier.token.string)); return false; } @@ -1103,7 +1101,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) AstNode *arg = unparen_expression(ce->arg_list); if (arg->kind != AstNode_SelectorExpression) { gbString str = expression_to_string(arg); - checker_err(c, ast_node_token(arg), "`%s` is not a selector expression", str); + error(&c->error_collector, ast_node_token(arg), "`%s` is not a selector expression", str); return false; } auto *s = &arg->selector_expression; @@ -1123,8 +1121,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Entity *entity = lookup_field(type, s->selector, &index); if (entity == NULL) { gbString type_str = type_to_string(type); - checker_err(c, ast_node_token(arg), - "`%s` has no field named `%.*s`", type_str, LIT(s->selector->identifier.token.string)); + error(&c->error_collector, ast_node_token(arg), + "`%s` has no field named `%.*s`", type_str, LIT(s->selector->identifier.token.string)); return false; } @@ -1141,15 +1139,15 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) !is_type_boolean(operand->type)) { gbString str = expression_to_string(ce->arg_list); defer (gb_string_free(str)); - checker_err(c, ast_node_token(call), - "`%s` is not a constant boolean", str); + error(&c->error_collector, ast_node_token(call), + "`%s` is not a constant boolean", str); return false; } if (!operand->value.value_bool) { gbString str = expression_to_string(ce->arg_list); defer (gb_string_free(str)); - checker_err(c, ast_node_token(call), - "Static assertion: `%s`", str); + error(&c->error_collector, ast_node_token(call), + "Static assertion: `%s`", str); return true; } break; @@ -1188,9 +1186,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) if (mode == Addressing_Invalid) { gbString str = expression_to_string(operand->expression); - checker_err(c, ast_node_token(operand->expression), - "Invalid expression `%s` for `%.*s`", - str, LIT(bp->name)); + error(&c->error_collector, ast_node_token(operand->expression), + "Invalid expression `%s` for `%.*s`", + str, LIT(bp->name)); gb_string_free(str); return false; } @@ -1219,7 +1217,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) src_type = s->slice.element; if (dest_type == NULL || src_type == NULL) { - checker_err(c, ast_node_token(call), "`copy` only expects slices as arguments"); + error(&c->error_collector, ast_node_token(call), "`copy` only expects slices as arguments"); return false; } @@ -1232,9 +1230,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) defer (gb_string_free(s_arg)); defer (gb_string_free(d_str)); defer (gb_string_free(s_str)); - checker_err(c, ast_node_token(call), - "Arguments to `copy`, %s, %s, have different element types: %s vs %s", - d_arg, s_arg, d_str, s_str); + error(&c->error_collector, ast_node_token(call), + "Arguments to `copy`, %s, %s, have different element types: %s vs %s", + d_arg, s_arg, d_str, s_str); return false; } @@ -1259,7 +1257,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) src_type = s; if (dest_type == NULL || src_type == NULL) { - checker_err(c, ast_node_token(call), "`copy_bytes` only expects pointers for the destintation and source"); + error(&c->error_collector, ast_node_token(call), "`copy_bytes` only expects pointers for the destintation and source"); return false; } @@ -1273,13 +1271,13 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) op.type->basic.kind != Basic_int) { gbString str = type_to_string(op.type); defer (gb_string_free(str)); - checker_err(c, ast_node_token(call), "`copy_bytes` 3rd argument must be of type `int`, a `%s` was given", str); + error(&c->error_collector, ast_node_token(call), "`copy_bytes` 3rd argument must be of type `int`, a `%s` was given", str); return false; } if (op.mode == Addressing_Constant) { if (exact_value_to_integer(op.value).value_integer <= 0) { - checker_err(c, ast_node_token(call), "You cannot copy a zero or negative amount of bytes with `copy_bytes`"); + error(&c->error_collector, ast_node_token(call), "You cannot copy a zero or negative amount of bytes with `copy_bytes`"); return false; } } @@ -1372,7 +1370,7 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode } gbString proc_str = expression_to_string(ce->proc); - checker_err(c, ast_node_token(call), err_fmt, proc_str, param_count); + error(&c->error_collector, ast_node_token(call), err_fmt, proc_str, param_count); gb_string_free(proc_str); operand->mode = Addressing_Invalid; @@ -1406,7 +1404,7 @@ ExpressionKind check_call_expression(Checker *c, Operand *operand, AstNode *call AstNode *e = operand->expression; gbString str = expression_to_string(e); defer (gb_string_free(str)); - checker_err(c, ast_node_token(e), "Cannot call a non-procedure: `%s`", str); + error(&c->error_collector, ast_node_token(e), "Cannot call a non-procedure: `%s`", str); operand->mode = Addressing_Invalid; operand->expression = call; @@ -1494,7 +1492,7 @@ void check_cast_expression(Checker *c, Operand *operand, Type *type) { gbString type_str = type_to_string(type); defer (gb_string_free(expr_str)); defer (gb_string_free(type_str)); - checker_err(c, ast_node_token(operand->expression), "Cannot cast `%s` to `%s`", expr_str, type_str); + error(&c->error_collector, ast_node_token(operand->expression), "Cannot cast `%s` to `%s`", expr_str, type_str); operand->mode = Addressing_Invalid; return; @@ -1503,6 +1501,28 @@ void check_cast_expression(Checker *c, Operand *operand, Type *type) { operand->type = type; } +void check_expression_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t) { + check_expression_base(c, o, e, t); + check_not_tuple(c, o); + char *err_str = NULL; + switch (o->mode) { + case Addressing_NoValue: + err_str = "used as a value"; + break; + case Addressing_Type: + err_str = "is not an expression"; + break; + case Addressing_Builtin: + err_str = "must be called"; + break; + } + if (err_str != NULL) { + gbString str = expression_to_string(e); + defer (gb_string_free(str)); + error(&c->error_collector, ast_node_token(e), "`%s` %s", str, err_str); + o->mode = Addressing_Invalid; + } +} ExpressionKind check__expression_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) { @@ -1534,20 +1554,104 @@ ExpressionKind check__expression_base(Checker *c, Operand *o, AstNode *node, Typ } break; case AstNode_ProcedureLiteral: { - Scope *origin_curr_scope = c->proc_context.scope; + Scope *origin_curr_scope = c->context.scope; Type *proc_type = check_type(c, node->procedure_literal.type); if (proc_type != NULL) { - check_procedure_body(c, empty_token, c->proc_context.decl, proc_type, node->procedure_literal.body); + check_procedure_body(c, empty_token, c->context.decl, proc_type, node->procedure_literal.body); o->mode = Addressing_Value; o->type = proc_type; } else { gbString str = expression_to_string(node); - checker_err(c, ast_node_token(node), "Invalid procedure literal `%s`", str); + error(&c->error_collector, ast_node_token(node), "Invalid procedure literal `%s`", str); gb_string_free(str); goto error; } } break; + case AstNode_CompoundLiteral: { + auto *cl = &node->compound_literal; + Type *type = type_hint; + if (cl->type_expression != NULL) { + type = check_type(c, cl->type_expression); + } + + if (type == NULL) { + error(&c->error_collector, ast_node_token(node), "Missing type in compound literal"); + goto error; + } + + Type *t = get_base_type(type); + switch (t->kind) { + case Type_Structure: { + if (cl->element_count == 0) + break; // NOTE(bill): No need to init + { // Checker values + AstNode *elem = cl->element_list; + isize field_count = t->structure.field_count; + isize index = 0; + for (; + elem != NULL; + elem = elem->next, index++) { + Entity *field = t->structure.fields[index]; + + check_expression(c, o, elem); + if (index >= field_count) { + error(&c->error_collector, ast_node_token(o->expression), "Too many values in structure literal, expected %td", field_count); + break; + } + check_assignment(c, o, field->type, make_string("structure literal")); + } + if (cl->element_count < field_count) { + error(&c->error_collector, node->compound_literal.close, "Too few values in structure literal, expected %td, got %td", field_count, cl->element_count); + } + } + + } break; + + case Type_Slice: + case Type_Array: + { + Type *element_type = NULL; + String context_name = {}; + if (t->kind == Type_Slice) { + element_type = t->slice.element; + context_name = make_string("slice literal"); + } else { + element_type = t->array.element; + context_name = make_string("array literal"); + } + + + i64 index = 0; + i64 max = 0; + for (AstNode *elem = cl->element_list; elem != NULL; elem = elem->next, index++) { + AstNode *e = elem; + if (t->kind == Type_Array && + t->array.count >= 0 && + index >= t->array.count) { + error(&c->error_collector, ast_node_token(elem), "Index %lld is out of bounds (>= %lld)", index, t->array.count); + } + + Operand o = {}; + check_expression_with_type_hint(c, &o, e, element_type); + check_assignment(c, &o, element_type, context_name); + } + if (max < index) + max = index; + } break; + + default: { + gbString str = type_to_string(t); + error(&c->error_collector, ast_node_token(node), "Invalid compound literal type `%s`", str); + gb_string_free(str); + goto error; + } break; + } + + o->mode = Addressing_Value; + o->type = type; + } break; + case AstNode_ParenExpression: kind = check_expression_base(c, o, node->paren_expression.expression, type_hint); o->expression = node; @@ -1555,7 +1659,7 @@ ExpressionKind check__expression_base(Checker *c, Operand *o, AstNode *node, Typ case AstNode_TagExpression: // TODO(bill): Tag expressions - checker_err(c, ast_node_token(node), "Tag expressions are not supported yet"); + error(&c->error_collector, ast_node_token(node), "Tag expressions are not supported yet"); kind = check_expression_base(c, o, node->tag_expression.expression, type_hint); o->expression = node; break; @@ -1624,14 +1728,14 @@ ExpressionKind check__expression_base(Checker *c, Operand *o, AstNode *node, Typ if (!valid) { gbString str = expression_to_string(o->expression); - checker_err(c, ast_node_token(o->expression), "Cannot index `%s`", str); + error(&c->error_collector, ast_node_token(o->expression), "Cannot index `%s`", str); gb_string_free(str); goto error; } if (node->index_expression.value == NULL) { gbString str = expression_to_string(o->expression); - checker_err(c, ast_node_token(o->expression), "Missing index for `%s`", str); + error(&c->error_collector, ast_node_token(o->expression), "Missing index for `%s`", str); gb_string_free(str); goto error; } @@ -1665,7 +1769,7 @@ ExpressionKind check__expression_base(Checker *c, Operand *o, AstNode *node, Typ max_count = t->array.count; if (o->mode != Addressing_Variable) { gbString str = expression_to_string(node); - checker_err(c, ast_node_token(node), "Cannot slice array `%s`, value is not addressable", str); + error(&c->error_collector, ast_node_token(node), "Cannot slice array `%s`, value is not addressable", str); gb_string_free(str); goto error; } @@ -1687,7 +1791,7 @@ ExpressionKind check__expression_base(Checker *c, Operand *o, AstNode *node, Typ if (!valid) { gbString str = expression_to_string(o->expression); - checker_err(c, ast_node_token(o->expression), "Cannot slice `%s`", str); + error(&c->error_collector, ast_node_token(o->expression), "Cannot slice `%s`", str); gb_string_free(str); goto error; } @@ -1715,7 +1819,7 @@ ExpressionKind check__expression_base(Checker *c, Operand *o, AstNode *node, Typ for (isize j = i+1; j < gb_count_of(indices); j++) { i64 b = indices[j]; if (a > b && b >= 0) { - checker_err(c, se->close, "Invalid slice indices: [%td > %td]", a, b); + error(&c->error_collector, se->close, "Invalid slice indices: [%td > %td]", a, b); } } } @@ -1744,7 +1848,7 @@ ExpressionKind check__expression_base(Checker *c, Operand *o, AstNode *node, Typ o->type = t->pointer.element; } else { gbString str = expression_to_string(o->expression); - checker_err(c, ast_node_token(o->expression), "Cannot dereference `%s`", str); + error(&c->error_collector, ast_node_token(o->expression), "Cannot dereference `%s`", str); gb_string_free(str); goto error; } @@ -1812,11 +1916,11 @@ void check_multi_expression(Checker *c, Operand *o, AstNode *e) { case Addressing_NoValue: err_str = expression_to_string(e); - checker_err(c, ast_node_token(e), "`%s` used as value", err_str); + error(&c->error_collector, ast_node_token(e), "`%s` used as value", err_str); break; case Addressing_Type: err_str = expression_to_string(e); - checker_err(c, ast_node_token(e), "`%s` is not an expression", err_str); + error(&c->error_collector, ast_node_token(e), "`%s` is not an expression", err_str); break; } o->mode = Addressing_Invalid; @@ -1829,8 +1933,8 @@ void check_not_tuple(Checker *c, Operand *o) { if (o->type->kind == Type_Tuple) { isize count = o->type->tuple.variable_count; GB_ASSERT(count != 1); - checker_err(c, ast_node_token(o->expression), - "%td-valued tuple found where single value expected", count); + error(&c->error_collector, ast_node_token(o->expression), + "%td-valued tuple found where single value expected", count); o->mode = Addressing_Invalid; } } @@ -1849,8 +1953,8 @@ void check_expression_or_type(Checker *c, Operand *o, AstNode *e) { AstNode *e = o->expression; gbString str = expression_to_string(e); defer (gb_string_free(str)); - checker_err(c, ast_node_token(e), - "`%s` used as value or type", str); + error(&c->error_collector, ast_node_token(e), + "`%s` used as value or type", str); o->mode = Addressing_Invalid; } } @@ -1898,14 +2002,17 @@ gbString write_expression_to_string(gbString str, AstNode *node) { case AstNode_Identifier: str = string_append_token(str, node->identifier.token); break; - case AstNode_BasicLiteral: str = string_append_token(str, node->basic_literal); break; - case AstNode_ProcedureLiteral: str = write_expression_to_string(str, node->procedure_literal.type); break; + case AstNode_CompoundLiteral: + str = gb_string_appendc(str, "("); + str = write_expression_to_string(str, node->compound_literal.type_expression); + str = gb_string_appendc(str, " literal)"); + break; case AstNode_TagExpression: str = gb_string_appendc(str, "#"); |