aboutsummaryrefslogtreecommitdiff
path: root/src/check_stmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/check_stmt.cpp')
-rw-r--r--src/check_stmt.cpp125
1 files changed, 70 insertions, 55 deletions
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp
index a3c9a529c..7772b5c97 100644
--- a/src/check_stmt.cpp
+++ b/src/check_stmt.cpp
@@ -7,7 +7,7 @@ bool is_diverging_stmt(Ast *stmt) {
return false;
}
if (expr->CallExpr.proc->kind == Ast_BasicDirective) {
- String name = expr->CallExpr.proc->BasicDirective.name;
+ String name = expr->CallExpr.proc->BasicDirective.name.string;
return name == "panic";
}
Ast *proc = unparen_expr(expr->CallExpr.proc);
@@ -939,6 +939,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
TokenKind upper_op = Token_Invalid;
switch (be->op.kind) {
case Token_Ellipsis: upper_op = Token_GtEq; break;
+ case Token_RangeFull: upper_op = Token_GtEq; break;
case Token_RangeHalf: upper_op = Token_Gt; break;
default: GB_PANIC("Invalid range operator"); break;
}
@@ -960,9 +961,44 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
Operand b1 = rhs;
check_comparison(ctx, &a1, &b1, Token_LtEq);
- add_constant_switch_case(ctx, &seen, lhs);
- if (upper_op == Token_GtEq) {
- add_constant_switch_case(ctx, &seen, rhs);
+ if (is_type_enum(x.type)) {
+ // TODO(bill): Fix this logic so it's fast!!!
+
+ i64 v0 = exact_value_to_i64(lhs.value);
+ i64 v1 = exact_value_to_i64(rhs.value);
+ Operand v = {};
+ v.mode = Addressing_Constant;
+ v.type = x.type;
+ v.expr = x.expr;
+
+ Type *bt = base_type(x.type);
+ GB_ASSERT(bt->kind == Type_Enum);
+ for (i64 vi = v0; vi <= v1; vi++) {
+ if (upper_op != Token_GtEq && vi == v1) {
+ break;
+ }
+
+ bool found = false;
+ for_array(j, bt->Enum.fields) {
+ Entity *f = bt->Enum.fields[j];
+ GB_ASSERT(f->kind == Entity_Constant);
+
+ i64 fv = exact_value_to_i64(f->Constant.value);
+ if (fv == vi) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ v.value = exact_value_i64(vi);
+ add_constant_switch_case(ctx, &seen, v);
+ }
+ }
+ } else {
+ add_constant_switch_case(ctx, &seen, lhs);
+ if (upper_op == Token_GtEq) {
+ add_constant_switch_case(ctx, &seen, rhs);
+ }
}
if (is_type_string(x.type)) {
@@ -1400,6 +1436,28 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
gbString expr_str = expr_to_string(operand.expr);
error(node, "Expression is not used: '%s'", expr_str);
gb_string_free(expr_str);
+ if (operand.expr->kind == Ast_BinaryExpr) {
+ ast_node(be, BinaryExpr, operand.expr);
+ if (be->op.kind != Token_CmpEq) {
+ break;
+ }
+
+ switch (be->left->tav.mode) {
+ case Addressing_Context:
+ case Addressing_Variable:
+ case Addressing_MapIndex:
+ case Addressing_SoaVariable:
+ {
+ gbString lhs = expr_to_string(be->left);
+ gbString rhs = expr_to_string(be->right);
+ error_line("\tSuggestion: Did you mean to do an assignment?\n", lhs, rhs);
+ error_line("\t '%s = %s;'\n", lhs, rhs);
+ gb_string_free(rhs);
+ gb_string_free(lhs);
+ }
+ break;
+ }
+ }
break;
}
@@ -1454,53 +1512,6 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
auto lhs_to_ignore = array_make<bool>(temporary_allocator(), lhs_count);
isize max = gb_min(lhs_count, rhs_count);
- // NOTE(bill, 2020-05-02): This is an utter hack to get these custom atom operations working
- // correctly for assignments
- for (isize i = 0; i < max; i++) {
- if (lhs_operands[i].mode == Addressing_AtomOpAssign) {
- Operand lhs = lhs_operands[i];
-
- Type *t = base_type(lhs.type);
- GB_ASSERT(t->kind == Type_Struct);
- ast_node(ie, IndexExpr, unparen_expr(lhs.expr));
-
- TypeAtomOpTable *atom_op_table = t->Struct.atom_op_table;
- GB_ASSERT(atom_op_table->op[TypeAtomOp_index_set] != nullptr);
- Entity *e = atom_op_table->op[TypeAtomOp_index_set];
-
- GB_ASSERT(e->identifier != nullptr);
- Ast *proc_ident = clone_ast(e->identifier);
- GB_ASSERT(ctx->file != nullptr);
-
-
- TypeAndValue tv = type_and_value_of_expr(ie->expr);
- Ast *expr = ie->expr;
- if (is_type_pointer(tv.type)) {
- // Okay
- } else if (tv.mode == Addressing_Variable) {
- // NOTE(bill): Hack it to take the address instead
- expr = ast_unary_expr(ctx->file, {Token_And, STR_LIT("&")}, ie->expr);
- } else {
- continue;
- }
-
- auto args = array_make<Ast *>(heap_allocator(), 3);
- args[0] = expr;
- args[1] = ie->index;
- args[2] = rhs_operands[i].expr;
-
- Ast *fake_call = ast_call_expr(ctx->file, proc_ident, args, ie->open, ie->close, {});
- Operand fake_operand = {};
- fake_operand.expr = lhs.expr;
- check_expr_base(ctx, &fake_operand, fake_call, nullptr);
- AtomOpMapEntry entry = {TypeAtomOp_index_set, fake_call};
- map_set(&ctx->info->atom_op_map, hash_pointer(lhs.expr), entry);
-
- lhs_to_ignore[i] = true;
-
- }
- }
-
for (isize i = 0; i < max; i++) {
if (lhs_to_ignore[i]) {
continue;
@@ -1526,8 +1537,8 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
}
Operand lhs = {Addressing_Invalid};
Operand rhs = {Addressing_Invalid};
- Ast binary_expr = {Ast_BinaryExpr};
- ast_node(be, BinaryExpr, &binary_expr);
+ Ast *binary_expr = alloc_ast_node(node->file, Ast_BinaryExpr);
+ ast_node(be, BinaryExpr, binary_expr);
be->op = op;
be->op.kind = cast(TokenKind)(cast(i32)be->op.kind - (Token_AddEq - Token_Add));
// NOTE(bill): Only use the first one will be used
@@ -1535,7 +1546,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
be->right = as->rhs[0];
check_expr(ctx, &lhs, as->lhs[0]);
- check_binary_expr(ctx, &rhs, &binary_expr, nullptr, true);
+ check_binary_expr(ctx, &rhs, binary_expr, nullptr, true);
if (rhs.mode == Addressing_Invalid) {
return;
}
@@ -1632,7 +1643,11 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
} else {
for (isize i = 0; i < result_count; i++) {
Entity *e = pt->results->Tuple.variables[i];
- check_assignment(ctx, &operands[i], e->type, str_lit("return statement"));
+ Operand *o = &operands[i];
+ check_assignment(ctx, o, e->type, str_lit("return statement"));
+ if (is_type_untyped(o->type)) {
+ update_expr_type(ctx, o->expr, e->type, true);
+ }
}
}
case_end;