diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-10-06 17:11:17 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-10-06 17:11:17 +0100 |
| commit | 50301557b2425fc0b4dd213ad03fb635cbd6e454 (patch) | |
| tree | bcb09c25f839099ac172529283bc7e4a147614d8 /src/checker | |
| parent | fee504636f9cd7633217e1877ee1b99e555bba63 (diff) | |
Untyped `nil`
Diffstat (limited to 'src/checker')
| -rw-r--r-- | src/checker/checker.cpp | 20 | ||||
| -rw-r--r-- | src/checker/entity.cpp | 9 | ||||
| -rw-r--r-- | src/checker/expr.cpp | 215 | ||||
| -rw-r--r-- | src/checker/stmt.cpp | 52 | ||||
| -rw-r--r-- | src/checker/type.cpp | 57 |
5 files changed, 241 insertions, 112 deletions
diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index c69b5d27e..90f04c588 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -33,6 +33,10 @@ struct Operand { BuiltinProcId builtin_id; }; +b32 is_operand_nil(Operand *o) { + return o->mode == Addressing_Value && o->type == t_untyped_nil; +} + struct TypeAndValue { AddressingMode mode; Type *type; @@ -241,7 +245,9 @@ struct Checker { gbArray(ProcedureInfo) procs; // NOTE(bill): Procedures to check gbArena arena; + gbArena tmp_arena; gbAllocator allocator; + gbAllocator tmp_allocator; CheckerContext context; @@ -501,9 +507,10 @@ void init_universal_scope(void) { } // Constants - add_global_constant(a, make_string("true"), t_untyped_bool, make_exact_value_bool(true)); - add_global_constant(a, make_string("false"), t_untyped_bool, make_exact_value_bool(false)); - add_global_constant(a, make_string("null"), t_untyped_pointer, make_exact_value_pointer(NULL)); + add_global_constant(a, make_string("true"), t_untyped_bool, make_exact_value_bool(true)); + add_global_constant(a, make_string("false"), t_untyped_bool, make_exact_value_bool(false)); + + add_global_entity(make_entity_nil(a, NULL, make_token_ident(make_string("nil")), t_untyped_nil)); // Builtin Procedures for (isize i = 0; i < gb_count_of(builtin_procs); i++) { @@ -564,7 +571,10 @@ void init_checker(Checker *c, Parser *parser, BaseTypeSizes sizes) { } isize arena_size = 2 * item_size * total_token_count; gb_arena_init_from_allocator(&c->arena, a, arena_size); + gb_arena_init_from_allocator(&c->tmp_arena, a, arena_size); + c->allocator = gb_arena_allocator(&c->arena); + c->tmp_allocator = gb_arena_allocator(&c->tmp_arena); c->global_scope = make_scope(universal_scope, c->allocator); c->context.scope = c->global_scope; @@ -705,6 +715,10 @@ void add_type_info_type(Checker *c, Type *t) { return; } t = default_type(t); + if (is_type_untyped(t)) { + return; // Could be nil + } + if (map_get(&c->info.type_info_map, hash_pointer(t)) != NULL) { // Types have already been added return; diff --git a/src/checker/entity.cpp b/src/checker/entity.cpp index 138e46236..8c1f254f3 100644 --- a/src/checker/entity.cpp +++ b/src/checker/entity.cpp @@ -10,6 +10,7 @@ enum BuiltinProcId; ENTITY_KIND(Procedure), \ ENTITY_KIND(Builtin), \ ENTITY_KIND(ImportName), \ + ENTITY_KIND(Nil), \ ENTITY_KIND(Count), @@ -68,6 +69,8 @@ struct Entity { Scope *scope; b32 used; } ImportName; + struct { + } Nil; }; }; @@ -155,6 +158,12 @@ Entity *make_entity_import_name(gbAllocator a, Scope *scope, Token token, Type * return entity; } +Entity *make_entity_nil(gbAllocator a, Scope *scope, Token token, Type *type) { + Entity *entity = alloc_entity(a, Entity_Nil, scope, token, type); + return entity; +} + + Entity *make_entity_dummy_variable(gbAllocator a, Scope *file_scope, Token token) { token.string = make_string("_"); return make_entity_variable(a, file_scope, token, NULL); diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index bf17cf2e3..3b1881ea0 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -68,13 +68,16 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu if (is_type_untyped(src)) { switch (dst->kind) { case Type_Basic: - if (operand->mode == Addressing_Constant) + if (operand->mode == Addressing_Constant) { return check_value_is_expressible(c, operand->value, dst, NULL); - if (src->kind == Type_Basic) - return src->Basic.kind == Basic_UntypedBool && is_type_boolean(dst); + } + if (src->kind == Type_Basic && src->Basic.kind == Basic_UntypedBool) { + return is_type_boolean(dst); + } break; - case Type_Pointer: - return src->Basic.kind == Basic_UntypedPointer; + } + if (type_has_nil(dst)) { + return is_operand_nil(operand); } } @@ -85,6 +88,10 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu return true; } + if (is_type_untyped_nil(src)) { + return type_has_nil(dst); + } + // ^T <- rawptr // TODO(bill): Should C-style (not C++) pointer cast be allowed? // if (is_type_pointer(dst) && is_type_rawptr(src)) { @@ -146,7 +153,13 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n if (is_type_untyped(operand->type)) { Type *target_type = type; - if (type == NULL || is_type_any(type)) { + if (type == NULL || is_type_any(type) || is_type_untyped_nil(type)) { + if (type == NULL && base_type(operand->type) == t_untyped_nil) { + error(ast_node_token(operand->expr), "Use of untyped nil in %.*s", LIT(context_name)); + operand->mode = Addressing_Invalid; + return; + } + add_type_info_type(c, type); target_type = default_type(operand->type); } @@ -229,14 +242,15 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls, isize other_field_index = 0; Entity *using_index_expr = NULL; + + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); struct Delay { Entity *e; AstNode *t; }; - gbArray(Delay) delayed_const; gb_array_init(delayed_const, gb_heap_allocator()); - gbArray(Delay) delayed_type; gb_array_init(delayed_type, gb_heap_allocator()); - defer (gb_array_free(delayed_const)); - defer (gb_array_free(delayed_type)); + gbArray(Delay) delayed_const; gb_array_init_reserve(delayed_const, c->tmp_allocator, other_field_count); + gbArray(Delay) delayed_type; gb_array_init_reserve(delayed_type, c->tmp_allocator, other_field_count); gb_for_array(decl_index, decls) { AstNode *decl = decls[decl_index]; @@ -729,8 +743,8 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod make_token_ident(make_string("max_value")), constant_type, make_exact_value_integer(max_value)); } -Type *check_get_params(Checker *c, Scope *scope, AstNodeArray fields, b32 *is_variadic_) { - if (fields == NULL || gb_array_count(fields) == 0) +Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, b32 *is_variadic_) { + if (params == NULL || gb_array_count(params) == 0) return NULL; b32 is_variadic = false; @@ -738,33 +752,32 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray fields, b32 *is_va Type *tuple = make_type_tuple(c->allocator); isize variable_count = 0; - gb_for_array(i, fields) { - AstNode *field = fields[i]; - ast_node(f, Field, field); - variable_count += gb_array_count(f->names); + gb_for_array(i, params) { + AstNode *field = params[i]; + ast_node(p, Parameter, field); + variable_count += gb_array_count(p->names); } Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count); isize variable_index = 0; - gb_for_array(i, fields) { - AstNode *field = fields[i]; - ast_node(f, Field, field); - AstNode *type_expr = f->type; + gb_for_array(i, params) { + ast_node(p, Parameter, params[i]); + AstNode *type_expr = p->type; if (type_expr) { if (type_expr->kind == AstNode_Ellipsis) { type_expr = type_expr->Ellipsis.expr; - if (i+1 == gb_array_count(fields)) { + if (i+1 == gb_array_count(params)) { is_variadic = true; } else { - error(ast_node_token(field), "Invalid AST: Invalid variadic parameter"); + error(ast_node_token(params[i]), "Invalid AST: Invalid variadic parameter"); } } Type *type = check_type(c, type_expr); - gb_for_array(j, f->names) { - AstNode *name = f->names[j]; + gb_for_array(j, p->names) { + AstNode *name = p->names[j]; if (name->kind == AstNode_Ident) { - Entity *param = make_entity_param(c->allocator, scope, name->Ident, type, f->is_using); + Entity *param = make_entity_param(c->allocator, scope, name->Ident, type, p->is_using); add_entity(c, scope, name, param); variables[variable_index++] = param; } else { @@ -774,10 +787,10 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray fields, b32 *is_va } } - if (is_variadic && gb_array_count(fields) > 0) { + if (is_variadic && gb_array_count(params) > 0) { // NOTE(bill): Change last variadic parameter to be a slice // Custom Calling convention for variadic parameters - Entity *end = variables[gb_array_count(fields)-1]; + Entity *end = variables[gb_array_count(params)-1]; end->type = make_type_slice(c->allocator, end->type); } @@ -927,6 +940,10 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl error(ast_node_token(n), "Use of import `%.*s` not in selector", LIT(e->ImportName.name)); return; + case Entity_Nil: + o->mode = Addressing_Value; + break; + default: compiler_error("Compiler error: Unknown EntityKind"); break; @@ -1184,15 +1201,20 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) { } break; - case Token_Mod: case Token_And: case Token_Or: + case Token_AndEq: + case Token_OrEq: + if (!is_type_integer(type) && !is_type_boolean(type)) { + error(op, "Operator `%.*s` is only allowed with integers or booleans", LIT(op.string)); + return false; + } + break; + + case Token_Mod: case Token_Xor: case Token_AndNot: - case Token_ModEq: - case Token_AndEq: - case Token_OrEq: case Token_XorEq: case Token_AndNotEq: if (!is_type_integer(type)) { @@ -1350,7 +1372,17 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) { if (o->mode == Addressing_Constant) { Type *type = base_type(o->type); - GB_ASSERT(type->kind == Type_Basic); + if (type->kind != Type_Basic) { + gbString xt = type_to_string(o->type); + gbString err_str = expr_to_string(node); + defer (gb_string_free(xt)); + defer (gb_string_free(err_str)); + error(op, "Invalid type, `%s`, for constant unary expression `%s`", xt, err_str); + o->mode = Addressing_Invalid; + return; + } + + i32 precision = 0; if (is_type_unsigned(type)) precision = cast(i32)(8 * type_size_of(c->sizes, c->allocator, type)); @@ -1368,6 +1400,9 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) { } void check_comparison(Checker *c, Operand *x, Operand *y, Token op) { + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); + gbString err_str = NULL; defer ({ if (err_str != NULL) @@ -1392,16 +1427,16 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) { if (!defined) { gbString type_string = type_to_string(x->type); - err_str = gb_string_make(gb_heap_allocator(), + defer (gb_string_free(type_string)); + err_str = gb_string_make(c->tmp_allocator, gb_bprintf("operator `%.*s` not defined for type `%s`", LIT(op.string), type_string)); - gb_string_free(type_string); } } else { gbString xt = type_to_string(x->type); gbString yt = type_to_string(y->type); defer(gb_string_free(xt)); defer(gb_string_free(yt)); - err_str = gb_string_make(gb_heap_allocator(), + err_str = gb_string_make(c->tmp_allocator, gb_bprintf("mismatched types `%s` and `%s`", xt, yt)); } @@ -1853,7 +1888,15 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { ExactValue b = y->value; Type *type = base_type(x->type); - GB_ASSERT(type->kind == Type_Basic); + if (type->kind != Type_Basic) { + gbString xt = type_to_string(x->type); + defer (gb_string_free(xt)); + err_str = expr_to_string(node); + error(op, "Invalid type, `%s`, for constant binary expression `%s`", xt, err_str); + x->mode = Addressing_Invalid; + return; + } + if (op.kind == Token_Quo && is_type_integer(type)) { op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers } @@ -1932,8 +1975,10 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) { if (operand->mode == Addressing_Constant) { if (operand->value.value_integer == 0) { - // NOTE(bill): Doesn't matter what the type is as it's still zero in the union - extra_text = " - Did you want `null`?"; + if (make_string(expr_str) != "nil") { // HACK NOTE(bill): Just in case + // NOTE(bill): Doesn't matter what the type is as it's still zero in the union + extra_text = " - Did you want `nil`?"; + } } } error(ast_node_token(operand->expr), "Cannot convert `%s` to `%s`%s", expr_str, type_str, extra_text); @@ -1989,36 +2034,27 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) { return; } break; + + case Basic_UntypedNil: + if (!type_has_nil(target_type)) { + convert_untyped_error(c, operand, target_type); + return; + } + break; } } break; - case Type_Pointer: - switch (operand->type->Basic.kind) { - case Basic_UntypedPointer: - target_type = t_untyped_pointer; - break; - default: - convert_untyped_error(c, operand, target_type); - return; - } - break; - case Type_Proc: - switch (operand->type->Basic.kind) { - case Basic_UntypedPointer: - break; - default: + default: + if (!type_has_nil(target_type)) { convert_untyped_error(c, operand, target_type); return; } break; - - default: - convert_untyped_error(c, operand, target_type); - return; } operand->type = target_type; + update_expr_type(c, operand->expr, target_type, true); } b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) { @@ -2415,6 +2451,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) error(ast_node_token(expr), "Invalid argument to `type_info`"); return false; } + add_type_info_type(c, type); operand->mode = Addressing_Value; @@ -2993,10 +3030,12 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode return; } + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); + isize operand_count = 0; gbArray(Operand) operands; - gb_array_init_reserve(operands, gb_heap_allocator(), 2*param_count); - defer (gb_array_free(operands)); + gb_array_init_reserve(operands, c->tmp_allocator, 2*param_count); gb_for_array(i, ce->args) { Operand o = {}; @@ -3374,12 +3413,12 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint error(ast_node_token(e), "Index %lld is out of bounds (>= %lld) for vector literal", index, t->Vector.count); } - Operand o = {}; - check_expr_with_type_hint(c, &o, e, elem_type); - check_assignment(c, &o, elem_type, context_name); + Operand operand = {}; + check_expr_with_type_hint(c, &operand, e, elem_type); + check_assignment(c, &operand, elem_type, context_name); if (is_constant) { - is_constant = o.mode == Addressing_Constant; + is_constant = operand.mode == Addressing_Constant; } } if (max < index) @@ -3730,10 +3769,9 @@ void check_expr_or_type(Checker *c, Operand *o, AstNode *e) { check_expr_base(c, o, e); check_not_tuple(c, o); if (o->mode == Addressing_NoValue) { - AstNode *e = o->expr; - gbString str = expr_to_string(e); + gbString str = expr_to_string(o->expr); defer (gb_string_free(str)); - error(ast_node_token(e), + error(ast_node_token(o->expr), "`%s` used as value or type", str); o->mode = Addressing_Invalid; } @@ -3742,15 +3780,14 @@ void check_expr_or_type(Checker *c, Operand *o, AstNode *e) { gbString write_expr_to_string(gbString str, AstNode *node); -gbString write_fields_to_string(gbString str, AstNodeArray fields, char *sep) { - gb_for_array(i, fields) { - AstNode *field = fields[i]; - ast_node(f, Field, field); +gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) { + gb_for_array(i, params) { + ast_node(p, Parameter, params[i]); if (i > 0) { str = gb_string_appendc(str, sep); } - str = write_expr_to_string(str, field); + str = write_expr_to_string(str, params[i]); } return str; } @@ -3885,19 +3922,19 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = write_expr_to_string(str, vt->elem); case_end; - case_ast_node(f, Field, node); - if (f->is_using) { + case_ast_node(p, Parameter, node); + if (p->is_using) { str = gb_string_appendc(str, "using "); } - gb_for_array(i, f->names) { - AstNode *name = f->names[i]; + gb_for_array(i, p->names) { + AstNode *name = p->names[i]; if (i > 0) str = gb_string_appendc(str, ", "); str = write_expr_to_string(str, name); } str = gb_string_appendc(str, ": "); - str = write_expr_to_string(str, f->type); + str = write_expr_to_string(str, p->type); case_end; case_ast_node(ce, CallExpr, node); @@ -3916,7 +3953,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) { case_ast_node(pt, ProcType, node); str = gb_string_appendc(str, "proc("); - str = write_fields_to_string(str, pt->params, ", "); + str = write_params_to_string(str, pt->params, ", "); str = gb_string_appendc(str, ")"); case_end; @@ -3924,19 +3961,37 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = gb_string_appendc(str, "struct "); if (st->is_packed) str = gb_string_appendc(str, "#packed "); if (st->is_ordered) str = gb_string_appendc(str, "#ordered "); - // str = write_fields_to_string(str, st->decl_list, ", "); + gb_for_array(i, st->decls) { + if (i > 0) { + str = gb_string_appendc(str, "; "); + } + str = write_expr_to_string(str, st->decls[i]); + } + // str = write_params_to_string(str, st->decl_list, ", "); str = gb_string_appendc(str, "}"); case_end; case_ast_node(st, RawUnionType, node); str = gb_string_appendc(str, "raw_union {"); - // str = write_fields_to_string(str, st->decl_list, ", "); + gb_for_array(i, st->decls) { + if (i > 0) { + str = gb_string_appendc(str, "; "); + } + str = write_expr_to_string(str, st->decls[i]); + } + // str = write_params_to_string(str, st->decl_list, ", "); str = gb_string_appendc(str, "}"); case_end; case_ast_node(st, UnionType, node); str = gb_string_appendc(str, "union {"); - // str = write_fields_to_string(str, st->decl_list, ", "); + gb_for_array(i, st->decls) { + if (i > 0) { + str = gb_string_appendc(str, "; "); + } + str = write_expr_to_string(str, st->decls[i]); + } + // str = write_params_to_string(str, st->decl_list, ", "); str = gb_string_appendc(str, "}"); case_end; diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index 0ca457c9a..e4d9115d7 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -11,14 +11,19 @@ void check_stmt(Checker *c, AstNode *node, u32 flags); void check_proc_decl(Checker *c, Entity *e, DeclInfo *d); void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) { + if (stmts == NULL) { + return; + } + + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); + struct Delay { Entity *e; DeclInfo *d; }; - gbArray(Delay) delayed_const; gb_array_init(delayed_const, gb_heap_allocator()); - gbArray(Delay) delayed_type; gb_array_init(delayed_type, gb_heap_allocator()); - defer (gb_array_free(delayed_const)); - defer (gb_array_free(delayed_type)); + gbArray(Delay) delayed_const; gb_array_init_reserve(delayed_const, c->tmp_allocator, gb_array_count(stmts)); + gbArray(Delay) delayed_type; gb_array_init_reserve(delayed_type, c->tmp_allocator, gb_array_count(stmts)); gb_for_array(i, stmts) { AstNode *node = stmts[i]; @@ -312,8 +317,8 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex // NOTE(bill): Use the type of the operand Type *t = operand->type; if (is_type_untyped(t)) { - if (t == t_invalid) { - error(e->token, "Use of untyped thing in %.*s", LIT(context_name)); + if (t == t_invalid || is_type_untyped_nil(t)) { + error(e->token, "Use of untyped nil in %.*s", LIT(context_name)); e->type = t_invalid; return NULL; } @@ -331,13 +336,17 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex } void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArray inits, String context_name) { - if ((lhs == NULL || lhs_count == 0) && gb_array_count(inits) == 0) + if ((lhs == NULL || lhs_count == 0) && (inits == NULL || gb_array_count(inits) == 0)) { return; + } + + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); - // TODO(bill): Do not use heap allocation here if I can help it + // NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be + // an extra allocation gbArray(Operand) operands; - gb_array_init_reserve(operands, gb_heap_allocator(), 2*lhs_count); - defer (gb_array_free(operands)); + gb_array_init_reserve(operands, c->tmp_allocator, 2*lhs_count); gb_for_array(i, inits) { AstNode *rhs = inits[i]; @@ -907,10 +916,13 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { return; } - // TODO(bill): Do not use heap allocation here if I can help it + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); + + // NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be + // an extra allocation gbArray(Operand) operands; - gb_array_init(operands, gb_heap_allocator()); - defer (gb_array_free(operands)); + gb_array_init_reserve(operands, c->tmp_allocator, 2 * gb_array_count(as->lhs)); gb_for_array(i, as->rhs) { AstNode *rhs = as->rhs[i]; @@ -1091,8 +1103,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { AstNode *stmt = bs->stmts[i]; AstNode *default_stmt = NULL; if (stmt->kind == AstNode_CaseClause) { - ast_node(c, CaseClause, stmt); - if (gb_array_count(c->list) == 0) { + ast_node(cc, CaseClause, stmt); + if (gb_array_count(cc->list) == 0) { default_stmt = stmt; } } else { @@ -1158,9 +1170,11 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { HashKey key = hash_exact_value(y.value); auto *found = map_get(&seen, key); if (found != NULL) { + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); + isize count = multi_map_count(&seen, key); - TypeAndToken *taps = gb_alloc_array(gb_heap_allocator(), TypeAndToken, count); - defer (gb_free(gb_heap_allocator(), taps)); + TypeAndToken *taps = gb_alloc_array(c->tmp_allocator, TypeAndToken, count); multi_map_get_all(&seen, key, taps); b32 continue_outer = false; @@ -1227,8 +1241,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { AstNode *stmt = bs->stmts[i]; AstNode *default_stmt = NULL; if (stmt->kind == AstNode_CaseClause) { - ast_node(c, CaseClause, stmt); - if (gb_array_count(c->list) == 0) { + ast_node(cc, CaseClause, stmt); + if (gb_array_count(cc->list) == 0) { default_stmt = stmt; } } else { diff --git a/src/checker/type.cpp b/src/checker/type.cpp index dded3826e..1ebb48c4f 100644 --- a/src/checker/type.cpp +++ b/src/checker/type.cpp @@ -22,9 +22,9 @@ enum BasicKind { Basic_UntypedBool, Basic_UntypedInteger, Basic_UntypedFloat, - Basic_UntypedPointer, Basic_UntypedString, Basic_UntypedRune, + Basic_UntypedNil, Basic_Count, @@ -309,9 +309,9 @@ gb_global Type basic_types[] = { {Type_Basic, 0, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}}, {Type_Basic, 0, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}}, {Type_Basic, 0, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}}, - {Type_Basic, 0, {Basic_UntypedPointer, BasicFlag_Pointer | BasicFlag_Untyped, STR_LIT("untyped pointer")}}, {Type_Basic, 0, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, STR_LIT("untyped string")}}, {Type_Basic, 0, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped rune")}}, + {Type_Basic, 0, {Basic_UntypedNil, BasicFlag_Untyped, STR_LIT("untyped nil")}}, }; gb_global Type basic_type_aliases[] = { @@ -339,9 +339,9 @@ gb_global Type *t_any = &basic_types[Basic_any]; gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool]; gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger]; gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat]; -gb_global Type *t_untyped_pointer = &basic_types[Basic_UntypedPointer]; gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString]; gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune]; +gb_global Type *t_untyped_nil = &basic_types[Basic_UntypedNil]; gb_global Type *t_byte = &basic_type_aliases[0]; gb_global Type *t_rune = &basic_type_aliases[1]; @@ -548,6 +548,11 @@ b32 is_type_any(Type *t) { t = base_type(t); return (t->kind == Type_Basic && t->Basic.kind == Basic_any); } +b32 is_type_untyped_nil(Type *t) { + t = base_type(t); + return (t->kind == Type_Basic && t->Basic.kind == Basic_UntypedNil); +} + b32 is_type_indexable(Type *t) { @@ -555,12 +560,31 @@ b32 is_type_indexable(Type *t) { } +b32 type_has_nil(Type *t) { + t = base_type(t); + switch (t->kind) { + case Type_Basic: + return is_type_rawptr(t); + + case Type_Tuple: + return false; + + case Type_Record: + switch (t->Record.kind) { + case TypeRecord_Enum: + return false; + } + break; + } + return true; +} + b32 is_type_comparable(Type *t) { t = base_type(t); switch (t->kind) { case Type_Basic: - return true; + return t->kind != Basic_UntypedNil; case Type_Pointer: return true; case Type_Record: { @@ -681,12 +705,12 @@ b32 are_types_identical(Type *x, Type *y) { Type *default_type(Type *type) { if (type->kind == Type_Basic) { switch (type->Basic.kind) { - case Basic_UntypedBool: return &basic_types[Basic_bool]; - case Basic_UntypedInteger: return &basic_types[Basic_int]; - case Basic_UntypedFloat: return &basic_types[Basic_f64]; - case Basic_UntypedString: return &basic_types[Basic_string]; - case Basic_UntypedRune: return &basic_types[Basic_rune]; - case Basic_UntypedPointer: return &basic_types[Basic_rawptr]; + case Basic_UntypedBool: return t_bool; + case Basic_UntypedInteger: return t_int; + case Basic_UntypedFloat: return t_f64; + case Basic_UntypedString: return t_string; + case Basic_UntypedRune: return t_rune; + // case Basic_UntypedPointer: return &basic_types[Basic_rawptr]; } } return type; @@ -952,6 +976,17 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { return gb_clamp(size, 1, s.max_align); } break; + case Type_Tuple: { + i64 max = 1; + for (isize i = 0; i < t->Tuple.variable_count; i++) { + i64 align = type_align_of(s, allocator, t->Tuple.variables[i]->type); + if (max < align) { + max = align; + } + } + return max; + } break; + case Type_Record: { switch (t->Record.kind) { case TypeRecord_Struct: @@ -964,6 +999,8 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { } } return max; + } else if (t->Record.field_count > 0) { + return type_align_of(s, allocator, t->Record.fields[0]->type); } break; case TypeRecord_Union: { |