diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.c | 181 | ||||
| -rw-r--r-- | src/check_stmt.c | 30 | ||||
| -rw-r--r-- | src/checker.c | 99 | ||||
| -rw-r--r-- | src/entity.c | 1 | ||||
| -rw-r--r-- | src/ir.c | 170 | ||||
| -rw-r--r-- | src/ir_print.c | 21 | ||||
| -rw-r--r-- | src/parser.c | 118 | ||||
| -rw-r--r-- | src/tokenizer.c | 209 | ||||
| -rw-r--r-- | src/types.c | 91 |
9 files changed, 389 insertions, 531 deletions
diff --git a/src/check_expr.c b/src/check_expr.c index 04f246532..d3bc5895c 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -167,14 +167,6 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) { return 1; } - if (is_type_maybe(dst)) { - Type *elem = base_type(dst)->Maybe.elem; - if (are_types_identical(elem, s)) { - return 1; - } - return -1; - } - if (check_is_assignable_to_using_subtype(operand->type, type)) { return 4; } @@ -743,7 +735,13 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod } else if (str_eq(name, str_lit("max_value"))) { error_node(field, "`max_value` is a reserved identifier for enumerations"); continue; - } + } else if (str_eq(name, str_lit("names"))) { + error_node(field, "`names` is a reserved identifier for enumerations"); + continue; + }/* else if (str_eq(name, str_lit("base_type"))) { + error_node(field, "`base_type` is a reserved identifier for enumerations"); + continue; + } */ if (compare_exact_values(Token_Gt, min_value, iota)) { min_value = iota; @@ -779,6 +777,11 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod enum_type->Record.enum_max_value = make_entity_constant(c->allocator, c->context.scope, make_token_ident(str_lit("max_value")), constant_type, max_value); + enum_type->Record.enum_names = make_entity_field(c->allocator, c->context.scope, + make_token_ident(str_lit("names")), t_string_slice, false, 0); + enum_type->Record.enum_names->Variable.is_immutable = true; + enum_type->Record.enum_names->flags |= EntityFlag_EnumField; + gb_temp_arena_memory_end(tmp); } @@ -909,7 +912,7 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) { } -void check_ident (Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint) { +void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint) { GB_ASSERT(n->kind == AstNode_Ident); o->mode = Addressing_Invalid; o->expr = n; @@ -1285,12 +1288,6 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { goto end; case_end; - case_ast_node(mt, MaybeType, e); - Type *elem = check_type(c, mt->type); - type = make_type_maybe(c->allocator, elem); - goto end; - case_end; - case_ast_node(at, ArrayType, e); if (at->count != NULL) { Type *elem = check_type_extra(c, at->elem, NULL); @@ -1689,29 +1686,6 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) { o->type = make_type_pointer(c->allocator, o->type); return; } - - case Token_Maybe: { // Make maybe - Type *t = default_type(o->type); - - if (o->mode == Addressing_Type) { - o->type = make_type_pointer(c->allocator, t); - return; - } - - if (!is_operand_value(*o) || is_type_untyped(t)) { - if (ast_node_expect(node, AstNode_UnaryExpr)) { - ast_node(ue, UnaryExpr, node); - gbString str = expr_to_string(ue->expr); - error(op, "Cannot convert `%s` to a maybe", str); - gb_string_free(str); - } - o->mode = Addressing_Invalid; - return; - } - o->mode = Addressing_Value; - o->type = make_type_maybe(c->allocator, t); - return; - } } if (!check_unary_op(c, o, op)) { @@ -2436,13 +2410,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level } break; - case Type_Maybe: - if (is_type_untyped_nil(operand->type)) { - // Okay - } else if (level == 0) { - goto error; - } - default: if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) { goto error; @@ -2545,7 +2512,14 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h check_op_expr = false; entity = scope_lookup_entity(e->ImportName.scope, sel_name); - if (entity == NULL) { + bool is_declared = entity != NULL; + if (entity->kind == Entity_Builtin) { + is_declared = false; + } + if (entity->scope->is_global && !e->ImportName.scope->is_global) { + is_declared = false; + } + if (!is_declared) { error_node(op_expr, "`%.*s` is not declared by `%.*s`", LIT(sel_name), LIT(name)); goto error; } @@ -2638,6 +2612,11 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h if (entity == NULL && selector->kind == AstNode_Ident) { sel = lookup_field(c->allocator, operand->type, selector->Ident.string, operand->mode == Addressing_Type); entity = sel.entity; + + // NOTE(bill): Add enum type info needed for fields like `names` + if (entity != NULL && (entity->flags&EntityFlag_EnumField)) { + add_type_info_type(c, operand->type); + } } if (entity == NULL && selector->kind == AstNode_BasicLit) { if (is_type_struct(operand->type) || is_type_tuple(operand->type)) { @@ -2699,6 +2678,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } + add_entity_use(c, selector, entity); switch (entity->kind) { @@ -2755,10 +2735,11 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } if (err) { - ast_node(proc, Ident, ce->proc); - error(ce->close, "`%s` arguments for `%.*s`, expected %td, got %td", - err, LIT(proc->string), + gbString expr = expr_to_string(ce->proc); + error(ce->close, "`%s` arguments for `%s`, expected %td, got %td", + err, expr, bp->arg_count, ce->args.count); + gb_string_free(expr); return false; } } @@ -2852,19 +2833,12 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id case BuiltinProc_reserve: { - // reserve :: proc(^[dynamic]Type, count: int) { - // reserve :: proc(^map[Key]Type, count: int) { + // reserve :: proc([dynamic]Type, count: int) { + // reserve :: proc(map[Key]Type, count: int) { Type *type = operand->type; - if (!is_type_pointer(type)) { - gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer, got `%s`", str); - gb_string_free(str); - return false; - } - type = type_deref(type); if (!is_type_dynamic_array(type) && !is_type_dynamic_map(type)) { gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer to a dynamic array or dynamic map, got `%s`", str); + error_node(operand->expr, "Expected a dynamic array or dynamic map, got `%s`", str); gb_string_free(str); return false; } @@ -2887,16 +2861,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id case BuiltinProc_clear: { Type *type = operand->type; - if (!is_type_pointer(type)) { - gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer, got `%s`", str); - gb_string_free(str); - return false; - } - type = type_deref(type); if (!is_type_dynamic_array(type) && !is_type_map(type)) { gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer to a map or dynamic array, got `%s`", str); + error_node(operand->expr, "Expected a map or dynamic array, got `%s`", str); gb_string_free(str); return false; } @@ -2906,18 +2873,12 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } break; case BuiltinProc_append: { - // append :: proc(^[dynamic]Type, item: ...Type) { + // append :: proc([dynamic]Type, item: ...Type) { Type *type = operand->type; - if (!is_type_pointer(type)) { - gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer to a dynamic array, got `%s`", str); - gb_string_free(str); - return false; - } - type = base_type(type_deref(type)); + type = base_type(type); if (!is_type_dynamic_array(type)) { gbString str = type_to_string(type); - error_node(operand->expr, "Expected a pointer to a dynamic array, got `%s`", str); + error_node(operand->expr, "Expected a dynamic array, got `%s`", str); gb_string_free(str); return false; } @@ -3140,7 +3101,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } break; case BuiltinProc_compile_assert: - // compile_assert :: proc(cond: bool) + // compile_assert :: proc(cond: bool) -> bool if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) { gbString str = expr_to_string(ce->args.e[0]); @@ -3153,10 +3114,13 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id error_node(call, "Compile time assertion: `%s`", str); gb_string_free(str); } + + operand->mode = Addressing_Constant; + operand->type = t_untyped_bool; break; case BuiltinProc_assert: - // assert :: proc(cond: bool) + // assert :: proc(cond: bool) -> bool if (!is_type_boolean(operand->type)) { gbString str = expr_to_string(ce->args.e[0]); @@ -3165,7 +3129,8 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id return false; } - operand->mode = Addressing_NoValue; + operand->mode = Addressing_Value; + operand->type = t_untyped_bool; break; case BuiltinProc_panic: @@ -4801,11 +4766,12 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint o->expr = node; case_end; - case_ast_node(te, TagExpr, node); - // TODO(bill): Tag expressions - error_node(node, "Tag expressions are not supported yet"); - kind = check_expr_base(c, o, te->expr, type_hint); + String name = te->name.string; + error_node(node, "Unknown tag expression, #%.*s", LIT(name)); + if (te->expr) { + kind = check_expr_base(c, o, te->expr, type_hint); + } o->expr = node; case_end; @@ -5187,37 +5153,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint } case_end; - case_ast_node(de, DemaybeExpr, node); - check_expr_or_type(c, o, de->expr); - if (o->mode == Addressing_Invalid) { - goto error; - } else { - Type *t = base_type(o->type); - if (t->kind == Type_Maybe) { - Entity **variables = gb_alloc_array(c->allocator, Entity *, 2); - Type *elem = t->Maybe.elem; - Token tok = make_token_ident(str_lit("")); - variables[0] = make_entity_param(c->allocator, NULL, tok, elem, false, true); - variables[1] = make_entity_param(c->allocator, NULL, tok, t_bool, false, true); - - Type *tuple = make_type_tuple(c->allocator); - tuple->Tuple.variables = variables; - tuple->Tuple.variable_count = 2; - - o->type = tuple; - o->mode = Addressing_Variable; - } else { - gbString str = expr_to_string(o->expr); - error_node(o->expr, "Cannot demaybe `%s`", str); - gb_string_free(str); - goto error; - } - } - case_end; - case AstNode_ProcType: case AstNode_PointerType: - case AstNode_MaybeType: case AstNode_ArrayType: case AstNode_VectorType: case AstNode_StructType: @@ -5401,14 +5338,17 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = write_expr_to_string(str, ue->expr); case_end; - case_ast_node(de, DerefExpr, node); - str = write_expr_to_string(str, de->expr); - str = gb_string_appendc(str, "^"); + case_ast_node(ce, CastExpr, node); + str = string_append_token(str, ce->token); + str = gb_string_appendc(str, "("); + str = write_expr_to_string(str, ce->type); + str = gb_string_appendc(str, ")"); + str = write_expr_to_string(str, ce->expr); case_end; - case_ast_node(de, DemaybeExpr, node); + case_ast_node(de, DerefExpr, node); str = write_expr_to_string(str, de->expr); - str = gb_string_appendc(str, "?"); + str = gb_string_appendc(str, "^"); case_end; case_ast_node(be, BinaryExpr, node); @@ -5462,11 +5402,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = write_expr_to_string(str, pt->type); case_end; - case_ast_node(mt, MaybeType, node); - str = gb_string_appendc(str, "?"); - str = write_expr_to_string(str, mt->type); - case_end; - case_ast_node(at, ArrayType, node); str = gb_string_appendc(str, "["); str = write_expr_to_string(str, at->count); diff --git a/src/check_stmt.c b/src/check_stmt.c index 9155947fc..9067d1037 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -942,7 +942,25 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { bool is_union_ptr = false; bool is_any = false; - check_expr(c, &x, ms->tag); + if (ms->tag->kind != AstNode_AssignStmt) { + error_node(ms->tag, "Expected an `in` assignment for this type match statement"); + break; + } + + ast_node(as, AssignStmt, ms->tag); + Token as_token = ast_node_token(ms->tag); + if (as->lhs.count != 1) { + syntax_error(as_token, "Expected 1 name before `in`"); + break; + } + if (as->rhs.count != 1) { + syntax_error(as_token, "Expected 1 expression after `in`"); + break; + } + AstNode *lhs = as->lhs.e[0]; + AstNode *rhs = as->rhs.e[0]; + + check_expr(c, &x, rhs); check_assignment(c, &x, NULL, str_lit("type match expression")); if (!check_valid_type_match_type(x.type, &is_union_ptr, &is_any)) { gbString str = type_to_string(x.type); @@ -980,7 +998,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { } } - if (ms->var->kind != AstNode_Ident) { + + if (unparen_expr(lhs)->kind != AstNode_Ident) { + error_node(rhs, "Expected an identifier, got `%.*s`", LIT(ast_node_strings[rhs->kind])); break; } @@ -1056,10 +1076,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { tt = make_type_pointer(c->allocator, case_type); add_type_info_type(c, tt); } - Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, ms->var->Ident, tt, true); + Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, lhs->Ident, tt, true); tag_var->flags |= EntityFlag_Used; - add_entity(c, c->context.scope, ms->var, tag_var); - add_entity_use(c, ms->var, tag_var); + add_entity(c, c->context.scope, lhs, tag_var); + add_entity_use(c, lhs, tag_var); } check_stmt_list(c, cc->stmts, mod_flags); check_close_scope(c); diff --git a/src/checker.c b/src/checker.c index 09c97ceed..d991561ce 100644 --- a/src/checker.c +++ b/src/checker.c @@ -630,11 +630,12 @@ void init_universal_scope(BuildContext *bc) { } - t_u8_ptr = make_type_pointer(a, t_u8); - t_int_ptr = make_type_pointer(a, t_int); - t_i64_ptr = make_type_pointer(a, t_i64); - t_f64_ptr = make_type_pointer(a, t_f64); - t_byte_slice = make_type_slice(a, t_byte); + t_u8_ptr = make_type_pointer(a, t_u8); + t_int_ptr = make_type_pointer(a, t_int); + t_i64_ptr = make_type_pointer(a, t_i64); + t_f64_ptr = make_type_pointer(a, t_f64); + t_byte_slice = make_type_slice(a, t_byte); + t_string_slice = make_type_slice(a, t_string); } @@ -911,11 +912,6 @@ void add_type_info_type(Checker *c, Type *t) { } } break; - case Type_Maybe: - add_type_info_type(c, bt->Maybe.elem); - add_type_info_type(c, t_bool); - break; - case Type_Pointer: add_type_info_type(c, bt->Pointer.elem); break; @@ -1099,48 +1095,46 @@ void init_preload(Checker *c) { - if (record->field_count != 20) { + if (record->field_count != 19) { compiler_error("Invalid `Type_Info` layout"); } t_type_info_named = record->fields[ 1]->type; t_type_info_integer = record->fields[ 2]->type; t_type_info_float = record->fields[ 3]->type; - t_type_info_any = record->fields[ 4]->type; - t_type_info_string = record->fields[ 5]->type; - t_type_info_boolean = record->fields[ 6]->type; + t_type_info_string = record->fields[ 4]->type; + t_type_info_boolean = record->fields[ 5]->type; + t_type_info_any = record->fields[ 6]->type; t_type_info_pointer = record->fields[ 7]->type; - t_type_info_maybe = record->fields[ 8]->type; - t_type_info_procedure = record->fields[ 9]->type; - t_type_info_array = record->fields[10]->type; - t_type_info_dynamic_array = record->fields[11]->type; - t_type_info_slice = record->fields[12]->type; - t_type_info_vector = record->fields[13]->type; - t_type_info_tuple = record->fields[14]->type; - t_type_info_struct = record->fields[15]->type; - t_type_info_union = record->fields[16]->type; - t_type_info_raw_union = record->fields[17]->type; - t_type_info_enum = record->fields[18]->type; - t_type_info_map = record->fields[19]->type; - - t_type_info_named_ptr = make_type_pointer(heap_allocator(), t_type_info_named); - t_type_info_integer_ptr = make_type_pointer(heap_allocator(), t_type_info_integer); - t_type_info_float_ptr = make_type_pointer(heap_allocator(), t_type_info_float); - t_type_info_any_ptr = make_type_pointer(heap_allocator(), t_type_info_any); - t_type_info_string_ptr = make_type_pointer(heap_allocator(), t_type_info_string); - t_type_info_boolean_ptr = make_type_pointer(heap_allocator(), t_type_info_boolean); - t_type_info_pointer_ptr = make_type_pointer(heap_allocator(), t_type_info_pointer); - t_type_info_maybe_ptr = make_type_pointer(heap_allocator(), t_type_info_maybe); - t_type_info_procedure_ptr = make_type_pointer(heap_allocator(), t_type_info_procedure); - t_type_info_array_ptr = make_type_pointer(heap_allocator(), t_type_info_array); - t_type_info_dynamic_array_ptr = make_type_pointer(heap_allocator(), t_type_info_dynamic_array); - t_type_info_slice_ptr = make_type_pointer(heap_allocator(), t_type_info_slice); - t_type_info_vector_ptr = make_type_pointer(heap_allocator(), t_type_info_vector); - t_type_info_tuple_ptr = make_type_pointer(heap_allocator(), t_type_info_tuple); - t_type_info_struct_ptr = make_type_pointer(heap_allocator(), t_type_info_struct); - t_type_info_union_ptr = make_type_pointer(heap_allocator(), t_type_info_union); - t_type_info_raw_union_ptr = make_type_pointer(heap_allocator(), t_type_info_raw_union); - t_type_info_enum_ptr = make_type_pointer(heap_allocator(), t_type_info_enum); - t_type_info_map_ptr = make_type_pointer(heap_allocator(), t_type_info_map); + t_type_info_procedure = record->fields[ 8]->type; + t_type_info_array = record->fields[ 9]->type; + t_type_info_dynamic_array = record->fields[10]->type; + t_type_info_slice = record->fields[11]->type; + t_type_info_vector = record->fields[12]->type; + t_type_info_tuple = record->fields[13]->type; + t_type_info_struct = record->fields[14]->type; + t_type_info_union = record->fields[15]->type; + t_type_info_raw_union = record->fields[16]->type; + t_type_info_enum = record->fields[17]->type; + t_type_info_map = record->fields[18]->type; + + t_type_info_named_ptr = make_type_pointer(c->allocator, t_type_info_named); + t_type_info_integer_ptr = make_type_pointer(c->allocator, t_type_info_integer); + t_type_info_float_ptr = make_type_pointer(c->allocator, t_type_info_float); + t_type_info_string_ptr = make_type_pointer(c->allocator, t_type_info_string); + t_type_info_boolean_ptr = make_type_pointer(c->allocator, t_type_info_boolean); + t_type_info_any_ptr = make_type_pointer(c->allocator, t_type_info_any); + t_type_info_pointer_ptr = make_type_pointer(c->allocator, t_type_info_pointer); + t_type_info_procedure_ptr = make_type_pointer(c->allocator, t_type_info_procedure); + t_type_info_array_ptr = make_type_pointer(c->allocator, t_type_info_array); + t_type_info_dynamic_array_ptr = make_type_pointer(c->allocator, t_type_info_dynamic_array); + t_type_info_slice_ptr = make_type_pointer(c->allocator, t_type_info_slice); + t_type_info_vector_ptr = make_type_pointer(c->allocator, t_type_info_vector); + t_type_info_tuple_ptr = make_type_pointer(c->allocator, t_type_info_tuple); + t_type_info_struct_ptr = make_type_pointer(c->allocator, t_type_info_struct); + t_type_info_union_ptr = make_type_pointer(c->allocator, t_type_info_union); + t_type_info_raw_union_ptr = make_type_pointer(c->allocator, t_type_info_raw_union); + t_type_info_enum_ptr = make_type_pointer(c->allocator, t_type_info_enum); + t_type_info_map_ptr = make_type_pointer(c->allocator, t_type_info_map); } if (t_allocator == NULL) { @@ -1727,6 +1721,19 @@ void check_import_entities(Checker *c, MapScope *file_scopes) { file_str = import_file; } + if (fl->cond != NULL) { + Operand operand = {Addressing_Invalid}; + check_expr(c, &operand, fl->cond); + if (operand.mode != Addressing_Constant || !is_type_boolean(operand.type)) { + error_node(fl->cond, "Non-constant boolean `when` condition"); + continue; + } + if (operand.value.kind == ExactValue_Bool && + !operand.value.value_bool) { + continue; + } + } + String library_name = path_to_entity_name(fl->library_name.string, file_str); if (str_eq(library_name, str_lit("_"))) { error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string)); diff --git a/src/entity.c b/src/entity.c index 221ec91b6..37c79b488 100644 --- a/src/entity.c +++ b/src/entity.c @@ -37,6 +37,7 @@ typedef enum EntityFlag { EntityFlag_VectorElem = 1<<5, EntityFlag_Ellipsis = 1<<6, EntityFlag_NoAlias = 1<<7, + EntityFlag_EnumField = 1<<8, } EntityFlag; typedef enum OverloadKind { @@ -1788,11 +1788,6 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { case 0: result_type = make_type_pointer(a, t_type_info_ptr); break; case 1: result_type = make_type_pointer(a, t_rawptr); break; } - } else if (is_type_maybe(t)) { - switch (index) { - case 0: result_type = make_type_pointer(a, t->Maybe.elem); break; - case 1: result_type = make_type_pointer(a, t_bool); break; - } } else if (is_type_dynamic_array(t)) { switch (index) { case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->DynamicArray.elem)); break; @@ -1848,11 +1843,6 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) { case 0: result_type = t_type_info_ptr; break; case 1: result_type = t_rawptr; break; } - } else if (is_type_maybe(t)) { - switch (index) { - case 0: result_type = t->Maybe.elem; break; - case 1: result_type = t_bool; break; - } } else if (is_type_dynamic_array(t)) { switch (index) { case 0: result_type = make_type_pointer(a, t->DynamicArray.elem); break; @@ -2165,15 +2155,6 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { return value; } - if (is_type_maybe(dst)) { - irValue *maybe = ir_add_local_generated(proc, dst); - irValue *val = ir_emit_struct_ep(proc, maybe, 0); - irValue *set = ir_emit_struct_ep(proc, maybe, 1); - ir_emit_store(proc, val, value); - ir_emit_store(proc, set, v_true); - return ir_emit_load(proc, maybe); - } - // integer -> integer if (is_type_integer(src) && is_type_integer(dst)) { GB_ASSERT(src->kind == Type_Basic && @@ -2396,7 +2377,6 @@ bool ir_is_type_aggregate(Type *t) { case Type_Array: case Type_Slice: - case Type_Maybe: case Type_Record: case Type_Tuple: return true; @@ -3130,22 +3110,33 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv args[1] = ptr; return ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2); } else if (is_type_dynamic_map(type)) { - // irValue *val = ir_build_expr(proc, node); - // irValue *map_ptr = ir_address_from_load_or_generate_local(proc, val); - - // { - // irValue *array = ir_emit_conv(proc, ir_emit_struct_ep(proc, map_ptr, 0), t_raw_dynamic_array_ptr); - // irValue **args = gb_alloc_array(a, irValue *, 1); - // args[0] = array; - // ir_emit_global_call(proc, "__free_raw_dynamic_array", args, 1); - // } - // { - // irValue *array = ir_emit_conv(proc, ir_emit_struct_ep(proc, map_ptr, 1), t_raw_dynamic_array_ptr); - // irValue **args = gb_alloc_array(a, irValue *, 1); - // args[0] = array; - // ir_emit_global_call(proc, "__free_raw_dynamic_array", args, 1); - // } + irValue *map = ir_build_expr(proc, node); + irValue *map_ptr = ir_address_from_load_or_generate_local(proc, map); + + { + irValue *array = ir_emit_struct_ep(proc, map_ptr, 0); + irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3)); + irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0)); + da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr); + + irValue **args = gb_alloc_array(a, irValue *, 1); + args[0] = da_allocator; + args[1] = da_ptr; + ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2); + } + { + irValue *array = ir_emit_struct_ep(proc, map_ptr, 1); + + irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3)); + irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0)); + da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr); + + irValue **args = gb_alloc_array(a, irValue *, 1); + args[0] = da_allocator; + args[1] = da_ptr; + ir_emit_global_call(proc, "free_ptr_with_allocator", args, 2); + } return NULL; } @@ -3176,7 +3167,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv ir_emit_comment(proc, str_lit("reserve")); gbAllocator a = proc->module->allocator; - irValue *ptr = ir_build_expr(proc, ce->args.e[0]); + irValue *ptr = ir_build_addr(proc, ce->args.e[0]).addr; Type *type = ir_type(ptr); GB_ASSERT(is_type_pointer(type)); type = base_type(type_deref(type)); @@ -3208,8 +3199,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv } break; case BuiltinProc_clear: { - ir_emit_comment(proc, str_lit("reserve")); - irValue *ptr = ir_build_expr(proc, ce->args.e[0]); + ir_emit_comment(proc, str_lit("clear")); + irValue *ptr = ir_build_addr(proc, ce->args.e[0]).addr; Type *t = base_type(type_deref(ir_type(ptr))); if (is_type_dynamic_array(t)) { irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1); @@ -3229,7 +3220,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv ir_emit_comment(proc, str_lit("append")); gbAllocator a = proc->module->allocator; - irValue *array_ptr = ir_build_expr(proc, ce->args.e[0]); + irValue *array_ptr = ir_build_addr(proc, ce->args.e[0]).addr; Type *type = ir_type(array_ptr); GB_ASSERT(is_type_pointer(type)); type = base_type(type_deref(type)); @@ -3348,7 +3339,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv ir_emit_jump(proc, done); ir_start_block(proc, done); - return NULL; + return cond; } break; case BuiltinProc_panic: { @@ -3596,10 +3587,6 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv return ir_emit_call(proc, value, args, arg_count); case_end; - case_ast_node(de, DemaybeExpr, expr); - return ir_addr_load(proc, ir_build_addr(proc, expr)); - case_end; - case_ast_node(se, SliceExpr, expr); return ir_addr_load(proc, ir_build_addr(proc, expr)); case_end; @@ -3722,7 +3709,34 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { AstNode *sel = unparen_expr(se->selector); if (sel->kind == AstNode_Ident) { String selector = sel->Ident.string; - Type *type = base_type(type_of_expr(proc->module->info, se->expr)); + Type *type = type_of_expr(proc->module->info, se->expr); + + if (is_type_enum(type)) { + Selection sel = lookup_field(proc->module->allocator, type, selector, true); + Entity *e = sel.entity; + GB_ASSERT(e->kind == Entity_Variable); + i32 index = e->Variable.field_index; + switch (index) { + case 0: { + irValue *ti_ptr = ir_type_info(proc, type); + { + irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 1); + args[0] = ti_ptr; + ti_ptr = ir_emit_global_call(proc, "type_info_base", args, 1); + } + + + irValue *enum_info = ir_emit_conv(proc, ti_ptr, t_type_info_enum_ptr); + irValue *names_ptr = ir_emit_struct_ep(proc, enum_info, 1); + return ir_make_addr(names_ptr); + } break; + default: + GB_PANIC("Unhandled enum index %d %.*s", index, LIT(selector)); + break; + } + } + + type = base_type(type); if (type == t_invalid) { // NOTE(bill): Imports @@ -4056,18 +4070,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { return ir_make_addr(addr); case_end; - case_ast_node(de, DemaybeExpr, expr); - ir_emit_comment(proc, str_lit("DemaybeExpr")); - irValue *maybe = ir_build_expr(proc, de->expr); - Type *t = default_type(type_of_expr(proc->module->info, expr)); - GB_ASSERT(is_type_tuple(t)); - - irValue *result = ir_add_local_generated(proc, t); - ir_emit_store(proc, result, maybe); - - return ir_make_addr(result); - case_end; - case_ast_node(ce, CallExpr, expr); // NOTE(bill): This is make sure you never need to have an `array_ev` irValue *e = ir_build_expr(proc, expr); @@ -5253,7 +5255,13 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { ir_emit_comment(proc, str_lit("TypeMatchStmt")); gbAllocator allocator = proc->module->allocator; - irValue *parent = ir_build_expr(proc, ms->tag); + ast_node(as, AssignStmt, ms->tag); + GB_ASSERT(as->lhs.count == 1); + GB_ASSERT(as->rhs.count == 1); + AstNode *lhs = as->lhs.e[0]; + AstNode *rhs = as->rhs.e[0]; + + irValue *parent = ir_build_expr(proc, rhs); bool is_union_ptr = false; bool is_any = false; GB_ASSERT(check_valid_type_match_type(ir_type(parent), &is_union_ptr, &is_any)); @@ -5274,7 +5282,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { ast_node(body, BlockStmt, ms->body); - String tag_var_name = ms->var->Ident.string; + String tag_var_name = lhs->Ident.string; + AstNodeArray default_stmts = {0}; irBlock *default_block = NULL; @@ -5291,19 +5300,32 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { default_block = ir_new_block(proc, clause, "type-match.dflt.body"); continue; } + GB_ASSERT(cc->list.count == 1); irBlock *body = ir_new_block(proc, clause, "type-match.case.body"); - Scope *scope = *map_scope_get(&proc->module->info->scopes, hash_pointer(clause)); - Entity *tag_var_entity = current_scope_lookup_entity(scope, tag_var_name); - GB_ASSERT_MSG(tag_var_entity != NULL, "%.*s", LIT(tag_var_name)); + Entity *tag_var_entity = NULL; + Type *tag_var_type = NULL; + if (str_eq(tag_var_name, str_lit("_"))) { + Type *t = type_of_expr(proc->module->info, cc->list.e[0]); + if (is_union_ptr) { + t = make_type_pointer(proc->module->allocator, t); + } + tag_var_type = t; + } else { + Scope *scope = *map_scope_get(&proc->module->info->scopes, hash_pointer(clause)); + tag_var_entity = current_scope_lookup_entity(scope, tag_var_name); + GB_ASSERT_MSG(tag_var_entity != NULL, "%.*s", LIT(tag_var_name)); + tag_var_type = tag_var_entity->type; + } + GB_ASSERT(tag_var_type != NULL); irBlock *next_cond = NULL; irValue *cond = NULL; if (is_union_ptr) { - Type *bt = type_deref(tag_var_entity->type); + Type *bt = type_deref(tag_var_type); irValue *index = NULL; Type *ut = base_type(type_deref(ir_type(parent))); GB_ASSERT(ut->Record.kind == TypeRecord_Union); @@ -5316,16 +5338,25 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { } GB_ASSERT(index != NULL); - irValue *tag_var = ir_add_local(proc, tag_var_entity); - irValue *data_ptr = ir_emit_conv(proc, union_data, tag_var_entity->type); + irValue *tag_var = NULL; + if (tag_var_entity != NULL) { + tag_var = ir_add_local(proc, tag_var_entity); + } else { + tag_var = ir_add_local_generated(proc, tag_var_type); + } + + + irValue *data_ptr = ir_emit_conv(proc, union_data, tag_var_type); ir_emit_store(proc, tag_var, data_ptr); cond = ir_emit_comp(proc, Token_CmpEq, tag_index, index); } else if (is_any) { - Type *type = tag_var_entity->type; + Type *type = tag_var_type; irValue *any_data = ir_emit_struct_ev(proc, parent, 1); irValue *data = ir_emit_conv(proc, any_data, make_type_pointer(proc->module->allocator, type)); - ir_module_add_value(proc->module, tag_var_entity, data); + if (tag_var_entity != NULL) { + ir_module_add_value(proc->module, tag_var_entity, data); + } irValue *any_ti = ir_emit_struct_ev(proc, parent, 0); irValue *case_ti = ir_type_info(proc, type); @@ -6228,11 +6259,6 @@ void ir_gen_tree(irGen *s) { irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Pointer.elem); ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep); } break; - case Type_Maybe: { - tag = ir_emit_conv(proc, ti_ptr, t_type_info_maybe_ptr); - irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Maybe.elem); - ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), gep); - } break; case Type_Array: { tag = ir_emit_conv(proc, ti_ptr, t_type_info_array_ptr); irValue *gep = ir_get_type_info_ptr(proc, type_info_data, t->Array.elem); diff --git a/src/ir_print.c b/src/ir_print.c index 670db48cd..da411fdc6 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -172,13 +172,6 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) { ir_print_type(f, m, t->Pointer.elem); ir_fprintf(f, "*"); return; - case Type_Maybe: - ir_fprintf(f, "{"); - ir_print_type(f, m, t->Maybe.elem); - ir_fprintf(f, ", "); - ir_print_type(f, m, t_bool); - ir_fprintf(f, "}"); - return; case Type_Array: ir_fprintf(f, "[%lld x ", t->Array.count); ir_print_type(f, m, t->Array.elem); @@ -306,25 +299,11 @@ void ir_print_compound_element(irFileBuffer *f, irModule *m, ExactValue v, Type ir_print_type(f, m, elem_type); ir_fprintf(f, " "); - if (v.kind != ExactValue_Invalid && is_type_maybe(elem_type)) { - Type *t = base_type(elem_type)->Maybe.elem; - ir_fprintf(f, "{"); - ir_print_type(f, m, t); - ir_fprintf(f, " "); - } - if (v.kind == ExactValue_Invalid || base_type(elem_type) == t_any) { ir_fprintf(f, "zeroinitializer"); } else { ir_print_exact_value(f, m, v, elem_type); } - - if (v.kind != ExactValue_Invalid && is_type_maybe(elem_type)) { - ir_fprintf(f, ", "); - ir_print_type(f, m, t_bool); - ir_fprintf(f, " "); - ir_fprintf(f, "true}"); - } } void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *type) { diff --git a/src/parser.c b/src/parser.c index 079e39c2f..3179509e7 100644 --- a/src/parser.c +++ b/src/parser.c @@ -147,7 +147,6 @@ AST_NODE_KIND(_ExprBegin, "", i32) \ AST_NODE_KIND(SelectorExpr, "selector expression", struct { Token token; AstNode *expr, *selector; }) \ AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \ AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \ - AST_NODE_KIND(DemaybeExpr, "demaybe expression", struct { Token op; AstNode *expr; }) \ AST_NODE_KIND(SliceExpr, "slice expression", struct { \ AstNode *expr; \ Token open, close, interval; \ @@ -251,7 +250,6 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \ AST_NODE_KIND(TypeMatchStmt, "type match statement", struct { \ Token token; \ AstNode *tag; \ - AstNode *var; \ AstNode *body; \ }) \ AST_NODE_KIND(DeferStmt, "defer statement", struct { Token token; AstNode *stmt; }) \ @@ -333,10 +331,6 @@ AST_NODE_KIND(_TypeBegin, "", i32) \ Token token; \ AstNode *type; \ }) \ - AST_NODE_KIND(MaybeType, "maybe type", struct { \ - Token token; \ - AstNode *type; \ - }) \ AST_NODE_KIND(ArrayType, "array type", struct { \ Token token; \ AstNode *count; \ @@ -469,7 +463,6 @@ Token ast_node_token(AstNode *node) { case AstNode_CastExpr: return node->CastExpr.token; case AstNode_FieldValue: return node->FieldValue.eq; case AstNode_DerefExpr: return node->DerefExpr.op; - case AstNode_DemaybeExpr: return node->DemaybeExpr.op; case AstNode_BlockExpr: return node->BlockExpr.open; case AstNode_GiveExpr: return node->GiveExpr.token; case AstNode_IfExpr: return node->IfExpr.token; @@ -513,7 +506,6 @@ Token ast_node_token(AstNode *node) { case AstNode_HelperType: return node->HelperType.token; case AstNode_ProcType: return node->ProcType.token; case AstNode_PointerType: return node->PointerType.token; - case AstNode_MaybeType: return node->MaybeType.token; case AstNode_ArrayType: return node->ArrayType.token; case AstNode_DynamicArrayType: return node->DynamicArrayType.token; case AstNode_VectorType: return node->VectorType.token; @@ -693,13 +685,6 @@ AstNode *ast_deref_expr(AstFile *f, AstNode *expr, Token op) { return result; } -AstNode *ast_demaybe_expr(AstFile *f, AstNode *expr, Token op) { - AstNode *result = make_ast_node(f, AstNode_DemaybeExpr); - result->DemaybeExpr.expr = expr; - result->DemaybeExpr.op = op; - return result; -} - AstNode *ast_interval_expr(AstFile *f, Token op, AstNode *left, AstNode *right) { AstNode *result = make_ast_node(f, AstNode_IntervalExpr); @@ -907,11 +892,10 @@ AstNode *ast_match_stmt(AstFile *f, Token token, AstNode *init, AstNode *tag, As } -AstNode *ast_type_match_stmt(AstFile *f, Token token, AstNode *tag, AstNode *var, AstNode *body) { +AstNode *ast_type_match_stmt(AstFile *f, Token token, AstNode *tag, AstNode *body) { AstNode *result = make_ast_node(f, AstNode_TypeMatchStmt); result->TypeMatchStmt.token = token; result->TypeMatchStmt.tag = tag; - result->TypeMatchStmt.var = var; result->TypeMatchStmt.body = body; return result; } @@ -1031,13 +1015,6 @@ AstNode *ast_pointer_type(AstFile *f, Token token, AstNode *type) { return result; } -AstNode *ast_maybe_type(AstFile *f, Token token, AstNode *type) { - AstNode *result = make_ast_node(f, AstNode_MaybeType); - result->MaybeType.token = token; - result->MaybeType.type = type; - return result; -} - AstNode *ast_array_type(AstFile *f, Token token, AstNode *count, AstNode *elem) { AstNode *result = make_ast_node(f, AstNode_ArrayType); result->ArrayType.token = token; @@ -1777,6 +1754,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) { } else if (str_eq(name.string, str_lit("file"))) { return ast_basic_directive(f, token, name.string); } else if (str_eq(name.string, str_lit("line"))) { return ast_basic_directive(f, token, name.string); } else if (str_eq(name.string, str_lit("procedure"))) { return ast_basic_directive(f, token, name.string); + } else if (str_eq(name.string, str_lit("type"))) { return ast_helper_type(f, token, parse_type(f)); } else { operand = ast_tag_expr(f, token, name, parse_expr(f, false)); } @@ -1999,10 +1977,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { operand = ast_deref_expr(f, operand, expect_token(f, Token_Pointer)); break; - case Token_Maybe: // Demaybe - operand = ast_demaybe_expr(f, operand, expect_token(f, Token_Maybe)); - break; - case Token_OpenBrace: if (!lhs && is_literal_type(operand) && f->expr_level >= 0) { operand = parse_literal_value(f, operand); @@ -2205,9 +2179,7 @@ AstNode *parse_value_decl(AstFile *f, AstNodeArray lhs) { bool is_mutable = true; if (allow_token(f, Token_Colon)) { - if (!allow_token(f, Token_type)) { - type = parse_type_attempt(f); - } + type = parse_type_attempt(f); } else if (f->curr_token.kind != Token_Eq && f->curr_token.kind != Token_Semicolon) { syntax_error(f->curr_token, "Expected a type separator `:` or `=`"); @@ -2553,10 +2525,16 @@ AstNode *parse_type_or_ident(AstFile *f) { return e; } - case Token_type: { - Token token = expect_token(f, Token_type); - AstNode *type = parse_type(f); - return ast_helper_type(f, token, type); + case Token_Hash: { + Token hash_token = expect_token(f, Token_Hash); + Token name = expect_token(f, Token_Ident); + String tag = name.string; + if (str_eq(tag, str_lit("type"))) { + AstNode *type = parse_type(f); + return ast_helper_type(f, hash_token, type); + } + syntax_error(name, "Expected `type` after #"); + return ast_bad_expr(f, hash_token, f->curr_token); } case Token_Pointer: { @@ -2565,12 +2543,6 @@ AstNode *parse_type_or_ident(AstFile *f) { return ast_pointer_type(f, token, elem); } - case Token_Maybe: { - Token token = expect_token(f, Token_Maybe); - AstNode *elem = parse_type(f); - return ast_maybe_type(f, token, elem); - } - case Token_OpenBracket: { Token token = expect_token(f, Token_OpenBracket); AstNode *count_expr = NULL; @@ -2972,8 +2944,7 @@ AstNode *parse_for_stmt(AstFile *f) { f->expr_level = -1; if (f->curr_token.kind != Token_Semicolon) { cond = parse_simple_stmt(f, true); - if (cond->kind == AstNode_AssignStmt && - cond->AssignStmt.op.kind == Token_in) { + if (cond->kind == AstNode_AssignStmt && cond->AssignStmt.op.kind == Token_in) { is_range = true; } } @@ -3065,6 +3036,7 @@ AstNode *parse_for_stmt(AstFile *f) { #endif } + AstNode *parse_case_clause(AstFile *f) { Token token = f->curr_token; AstNodeArray list = make_ast_node_array(f); @@ -3097,6 +3069,7 @@ AstNode *parse_type_case_clause(AstFile *f) { } + AstNode *parse_match_stmt(AstFile *f) { if (f->curr_proc == NULL) { syntax_error(f->curr_token, "You cannot use a match statement in the file scope"); @@ -3108,37 +3081,16 @@ AstNode *parse_match_stmt(AstFile *f) { AstNode *tag = NULL; AstNode *body = NULL; Token open, close; + bool is_type_match = false; - if (allow_token(f, Token_type)) { + if (f->curr_token.kind != Token_OpenBrace) { isize prev_level = f->expr_level; f->expr_level = -1; - AstNode *var = parse_ident(f); - expect_token_after(f, Token_in, "match type name"); - tag = parse_simple_stmt(f, false); - - f->expr_level = prev_level; - - open = expect_token(f, Token_OpenBrace); - AstNodeArray list = make_ast_node_array(f); - - while (f->curr_token.kind == Token_case || - f->curr_token.kind == Token_default) { - array_add(&list, parse_type_case_clause(f)); - } - - close = expect_token(f, Token_CloseBrace); - body = ast_block_stmt(f, list, open, close); - - tag = convert_stmt_to_expr(f, tag, str_lit("type match expression")); - return ast_type_match_stmt(f, token, tag, var, body); - } else { - if (f->curr_token.kind != Token_OpenBrace) { - isize prev_level = f->expr_level; - f->expr_level = -1; - if (f->curr_token.kind != Token_Semicolon) { - tag = parse_simple_stmt(f, false); - } + tag = parse_simple_stmt(f, true); + if (tag->kind == AstNode_AssignStmt && tag->AssignStmt.op.kind == Token_in) { + is_type_match = true; + } else { if (allow_token(f, Token_Semicolon)) { init = tag; tag = NULL; @@ -3146,28 +3098,33 @@ AstNode *parse_match_stmt(AstFile *f) { tag = parse_simple_stmt(f, false); } } - - f->expr_level = prev_level; } + f->expr_level = prev_level; + } + open = expect_token(f, Token_OpenBrace); + AstNodeArray list = make_ast_node_array(f); - open = expect_token(f, Token_OpenBrace); - AstNodeArray list = make_ast_node_array(f); - - while (f->curr_token.kind == Token_case || - f->curr_token.kind == Token_default) { + while (f->curr_token.kind == Token_case || + f->curr_token.kind == Token_default) { + if (is_type_match) { + array_add(&list, parse_type_case_clause(f)); + } else { array_add(&list, parse_case_clause(f)); } + } - close = expect_token(f, Token_CloseBrace); + close = expect_token(f, Token_CloseBrace); - body = ast_block_stmt(f, list, open, close); + body = ast_block_stmt(f, list, open, close); + if (!is_type_match) { tag = convert_stmt_to_expr(f, tag, str_lit("match expression")); return ast_match_stmt(f, token, init, tag, body); + } else { + return ast_type_match_stmt(f, token, tag, body); } } - AstNode *parse_defer_stmt(AstFile *f) { if (f->curr_proc == NULL) { syntax_error(f->curr_token, "You cannot use a defer statement in the file scope"); @@ -3359,6 +3316,7 @@ AstNode *parse_stmt(AstFile *f) { Token hash_token = expect_token(f, Token_Hash); Token name = expect_token(f, Token_Ident); String tag = name.string; + if (str_eq(tag, str_lit("import"))) { AstNode *cond = NULL; Token import_name = {0}; diff --git a/src/tokenizer.c b/src/tokenizer.c index 9dacdba64..92256f021 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -12,23 +12,24 @@ TOKEN_KIND(Token__LiteralBegin, "_LiteralBegin"), \ TOKEN_KIND(Token__LiteralEnd, "_LiteralEnd"), \ \ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \ - TOKEN_KIND(Token_Eq, "="), \ - TOKEN_KIND(Token_Not, "!"), \ - TOKEN_KIND(Token_Hash, "#"), \ - TOKEN_KIND(Token_At, "@"), \ - TOKEN_KIND(Token_Pointer, "^"), \ - TOKEN_KIND(Token_Maybe, "?"), \ - TOKEN_KIND(Token_Add, "+"), \ - TOKEN_KIND(Token_Sub, "-"), \ - TOKEN_KIND(Token_Mul, "*"), \ - TOKEN_KIND(Token_Quo, "/"), \ - TOKEN_KIND(Token_Mod, "%"), \ - TOKEN_KIND(Token_And, "&"), \ - TOKEN_KIND(Token_Or, "|"), \ - TOKEN_KIND(Token_Xor, "~"), \ - TOKEN_KIND(Token_AndNot, "&~"), \ - TOKEN_KIND(Token_Shl, "<<"), \ - TOKEN_KIND(Token_Shr, ">>"), \ + TOKEN_KIND(Token_Eq, "="), \ + TOKEN_KIND(Token_Not, "!"), \ + TOKEN_KIND(Token_Hash, "#"), \ + TOKEN_KIND(Token_At, "@"), \ + TOKEN_KIND(Token_Dollar, "$"), \ + TOKEN_KIND(Token_Pointer, "^"), \ + TOKEN_KIND(Token_Question, "?"), \ + TOKEN_KIND(Token_Add, "+"), \ + TOKEN_KIND(Token_Sub, "-"), \ + TOKEN_KIND(Token_Mul, "*"), \ + TOKEN_KIND(Token_Quo, "/"), \ + TOKEN_KIND(Token_Mod, "%"), \ + TOKEN_KIND(Token_And, "&"), \ + TOKEN_KIND(Token_Or, "|"), \ + TOKEN_KIND(Token_Xor, "~"), \ + TOKEN_KIND(Token_AndNot, "&~"), \ + TOKEN_KIND(Token_Shl, "<<"), \ + TOKEN_KIND(Token_Shr, ">>"), \ \ /*TOKEN_KIND(Token_as, "as"), */\ /*TOKEN_KIND(Token_transmute, "transmute"), */\ @@ -55,6 +56,8 @@ TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \ TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \ TOKEN_KIND(Token_ArrowRight, "->"), \ TOKEN_KIND(Token_ArrowLeft, "<-"), \ + TOKEN_KIND(Token_Increment, "++"), \ + TOKEN_KIND(Token_Decrement, "--"), \ \ TOKEN_KIND(Token__ComparisonBegin, "_ComparisonBegin"), \ TOKEN_KIND(Token_CmpEq, "=="), \ @@ -80,45 +83,45 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \ TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \ \ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ - /* TODO(bill): So of these keywords are not used but "reserved", why not remove them? */ \ - TOKEN_KIND(Token_when, "when"), \ - TOKEN_KIND(Token_if, "if"), \ - TOKEN_KIND(Token_else, "else"), \ - TOKEN_KIND(Token_for, "for"), \ - TOKEN_KIND(Token_in, "in"), \ - TOKEN_KIND(Token_break, "break"), \ - TOKEN_KIND(Token_continue, "continue"), \ - TOKEN_KIND(Token_fallthrough, "fallthrough"), \ - TOKEN_KIND(Token_match, "match"), \ - TOKEN_KIND(Token_type, "type"), \ - TOKEN_KIND(Token_default, "default"), \ - TOKEN_KIND(Token_case, "case"), \ - TOKEN_KIND(Token_defer, "defer"), \ - TOKEN_KIND(Token_return, "return"), \ - TOKEN_KIND(Token_give, "give"), \ - TOKEN_KIND(Token_proc, "proc"), \ - TOKEN_KIND(Token_macro, "macro"), \ - TOKEN_KIND(Token_struct, "struct"), \ - TOKEN_KIND(Token_union, "union"), \ - TOKEN_KIND(Token_raw_union, "raw_union"), \ - TOKEN_KIND(Token_enum, "enum"), \ - TOKEN_KIND(Token_vector, "vector"), \ - TOKEN_KIND(Token_map, "map"), \ - TOKEN_KIND(Token_static, "static"), \ - TOKEN_KIND(Token_dynamic, "dynamic"), \ - TOKEN_KIND(Token_using, "using"), \ - TOKEN_KIND(Token_no_alias, "no_alias"), \ - /* TOKEN_KIND(Token_mutable, "mutable"), */\ + /* TODO(bill): Of these keywords are not used but "reserved", why not remove them? */ \ + TOKEN_KIND(Token_when, "when"), \ + TOKEN_KIND(Token_if, "if"), \ + TOKEN_KIND(Token_else, "else"), \ + TOKEN_KIND(Token_for, "for"), \ + TOKEN_KIND(Token_in, "in"), \ + TOKEN_KIND(Token_break, "break"), \ + TOKEN_KIND(Token_continue, "continue"), \ + TOKEN_KIND(Token_fallthrough, "fallthrough"), \ + TOKEN_KIND(Token_match, "match"), \ + /* TOKEN_KIND(Token_type, "type"), */ \ + TOKEN_KIND(Token_default, "default"), \ + TOKEN_KIND(Token_case, "case"), \ + TOKEN_KIND(Token_defer, "defer"), \ + TOKEN_KIND(Token_return, "return"), \ + TOKEN_KIND(Token_give, "give"), \ + TOKEN_KIND(Token_proc, "proc"), \ + TOKEN_KIND(Token_macro, "macro"), \ + TOKEN_KIND(Token_struct, "struct"), \ + TOKEN_KIND(Token_union, "union"), \ + TOKEN_KIND(Token_raw_union, "raw_union"), \ + TOKEN_KIND(Token_enum, "enum"), \ + TOKEN_KIND(Token_vector, "vector"), \ + TOKEN_KIND(Token_map, "map"), \ + TOKEN_KIND(Token_static, "static"), \ + TOKEN_KIND(Token_dynamic, "dynamic"), \ + TOKEN_KIND(Token_using, "using"), \ + TOKEN_KIND(Token_no_alias, "no_alias"), \ + /* TOKEN_KIND(Token_mutable, "mutable"), */ \ /* TOKEN_KIND(Token_immutable, "immutable"), */\ - TOKEN_KIND(Token_thread_local, "thread_local"), \ - TOKEN_KIND(Token_cast, "cast"), \ - TOKEN_KIND(Token_transmute, "transmute"), \ - TOKEN_KIND(Token_down_cast, "down_cast"), \ - TOKEN_KIND(Token_union_cast, "union_cast"), \ - TOKEN_KIND(Token_context, "context"), \ - TOKEN_KIND(Token_push_context, "push_context"), \ - TOKEN_KIND(Token_push_allocator, "push_allocator"), \ - TOKEN_KIND(Token_asm, "asm"), \ + TOKEN_KIND(Token_thread_local, "thread_local"), \ + TOKEN_KIND(Token_cast, "cast"), \ + TOKEN_KIND(Token_transmute, "transmute"), \ + TOKEN_KIND(Token_down_cast, "down_cast"), \ + TOKEN_KIND(Token_union_cast, "union_cast"), \ + TOKEN_KIND(Token_context, "context"), \ + TOKEN_KIND(Token_push_context, "push_context"), \ + TOKEN_KIND(Token_push_allocator, "push_allocator"), \ + TOKEN_KIND(Token_asm, "asm"), \ TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \ TOKEN_KIND(Token_Count, "") @@ -478,7 +481,6 @@ gb_inline void scan_mantissa(Tokenizer *t, i32 base, bool allow_underscore) { } } - Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) { Token token = {0}; token.kind = Token_Integer; @@ -734,20 +736,10 @@ Token tokenizer_get_token(Tokenizer *t) { // NOTE(bill): All keywords are > 1 if (token.string.len > 1) { - /* if (str_eq(token.string, token_strings[Token_as])) { - token.kind = Token_as; - } else if (str_eq(token.string, token_strings[Token_transmute])) { - token.kind = Token_transmute; - } else if (str_eq(token.string, token_strings[Token_down_cast])) { - token.kind = Token_down_cast; - } else if (str_eq(token.string, token_strings[Token_union_cast])) { - token.kind = Token_union_cast; - } else */{ - for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) { - if (str_eq(token.string, token_strings[k])) { - token.kind = cast(TokenKind)k; - break; - } + for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) { + if (str_eq(token.string, token_strings[k])) { + token.kind = cast(TokenKind)k; + break; } } } @@ -861,57 +853,28 @@ Token tokenizer_get_token(Tokenizer *t) { } break; - case '#': - token.kind = Token_Hash; - break; - case '@': - token.kind = Token_At; - break; - case '^': - token.kind = Token_Pointer; - break; - case '?': - token.kind = Token_Maybe; - break; - case ';': - token.kind = Token_Semicolon; - break; - case ',': - token.kind = Token_Comma; - break; - case ':': - token.kind = Token_Colon; - break; - case '(': - token.kind = Token_OpenParen; - break; - case ')': - token.kind = Token_CloseParen; - break; - case '[': - token.kind = Token_OpenBracket; - break; - case ']': - token.kind = Token_CloseBracket; - break; - case '{': - token.kind = Token_OpenBrace; - break; - case '}': - token.kind = Token_CloseBrace; - break; - - case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break; - case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq); break; - case '=': token.kind = token_kind_variant2(t, Token_Eq, Token_CmpEq); break; - case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break; - case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break; - case '+': - token.kind = token_kind_variant2(t, Token_Add, Token_AddEq); - break; - case '-': - token.kind = token_kind_variant3(t, Token_Sub, Token_SubEq, '>', Token_ArrowRight); - break; + case '#': token.kind = Token_Hash; break; + case '@': token.kind = Token_At; break; + case '$': token.kind = Token_Dollar; break; + case '?': token.kind = Token_Question; break; + case '^': token.kind = Token_Pointer; break; + case ';': token.kind = Token_Semicolon; break; + case ',': token.kind = Token_Comma; break; + case ':': token.kind = Token_Colon; break; + case '(': token.kind = Token_OpenParen; break; + case ')': token.kind = Token_CloseParen; break; + case '[': token.kind = Token_OpenBracket; break; + case ']': token.kind = Token_CloseBracket; break; + case '{': token.kind = Token_OpenBrace; break; + case '}': token.kind = Token_CloseBrace; break; + + case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break; + case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq); break; + case '=': token.kind = token_kind_variant2(t, Token_Eq, Token_CmpEq); break; + case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break; + case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break; + case '+': token.kind = token_kind_variant3(t, Token_Add, Token_AddEq, '+', Token_Increment); break; + case '-': token.kind = token_kind_variant4(t, Token_Sub, Token_SubEq, '-', Token_Decrement, '>', Token_ArrowRight); break; case '/': { if (t->curr_rune == '/') { while (t->curr_rune != '\n' && t->curr_rune != GB_RUNE_EOF) { @@ -951,9 +914,7 @@ Token tokenizer_get_token(Tokenizer *t) { token.kind = token_kind_dub_eq(t, '<', Token_Lt, Token_LtEq, Token_Shl, Token_ShlEq); } break; - case '>': - token.kind = token_kind_dub_eq(t, '>', Token_Gt, Token_GtEq, Token_Shr, Token_ShrEq); - break; + case '>': token.kind = token_kind_dub_eq(t, '>', Token_Gt, Token_GtEq, Token_Shr, Token_ShrEq); break; case '&': token.kind = Token_And; diff --git a/src/types.c b/src/types.c index dbded4a73..71888a372 100644 --- a/src/types.c +++ b/src/types.c @@ -11,6 +11,20 @@ typedef enum BasicKind { Basic_u32, Basic_i64, Basic_u64, + +/* Basic_i16le, + Basic_i16be, + Basic_u16le, + Basic_u16be, + Basic_i32le, + Basic_i32be, + Basic_u32le, + Basic_u32be, + Basic_i64le, + Basic_i64be, + Basic_u64le, + Basic_u64be, */ + // Basic_i128, // Basic_u128, // Basic_f16, @@ -93,6 +107,7 @@ typedef struct TypeRecord { Entity * enum_count; Entity * enum_min_value; Entity * enum_max_value; + Entity * enum_names; } TypeRecord; #define TYPE_KINDS \ @@ -102,7 +117,6 @@ typedef struct TypeRecord { TYPE_KIND(DynamicArray, struct { Type *elem; }) \ TYPE_KIND(Vector, struct { Type *elem; i64 count; }) \ TYPE_KIND(Slice, struct { Type *elem; }) \ - TYPE_KIND(Maybe, struct { Type *elem; }) \ TYPE_KIND(Record, TypeRecord) \ TYPE_KIND(Named, struct { \ String name; \ @@ -177,16 +191,16 @@ typedef struct BaseTypeSizes { } BaseTypeSizes; -typedef Array(isize) Array_isize; +typedef Array(i32) Array_i32; typedef struct Selection { - Entity * entity; - Array_isize index; - bool indirect; // Set if there was a pointer deref anywhere down the line + Entity * entity; + Array_i32 index; + bool indirect; // Set if there was a pointer deref anywhere down the line } Selection; Selection empty_selection = {0}; -Selection make_selection(Entity *entity, Array_isize index, bool indirect) { +Selection make_selection(Entity *entity, Array_i32 index, bool indirect) { Selection s = {entity, index, indirect}; return s; } @@ -273,6 +287,7 @@ gb_global Type *t_int_ptr = NULL; gb_global Type *t_i64_ptr = NULL; gb_global Type *t_f64_ptr = NULL; gb_global Type *t_byte_slice = NULL; +gb_global Type *t_string_slice = NULL; gb_global Type *t_type_info = NULL; @@ -289,7 +304,6 @@ gb_global Type *t_type_info_any = NULL; gb_global Type *t_type_info_string = NULL; gb_global Type *t_type_info_boolean = NULL; gb_global Type *t_type_info_pointer = NULL; -gb_global Type *t_type_info_maybe = NULL; gb_global Type *t_type_info_procedure = NULL; gb_global Type *t_type_info_array = NULL; gb_global Type *t_type_info_dynamic_array = NULL; @@ -310,7 +324,6 @@ gb_global Type *t_type_info_any_ptr = NULL; gb_global Type *t_type_info_string_ptr = NULL; gb_global Type *t_type_info_boolean_ptr = NULL; gb_global Type *t_type_info_pointer_ptr = NULL; -gb_global Type *t_type_info_maybe_ptr = NULL; gb_global Type *t_type_info_procedure_ptr = NULL; gb_global Type *t_type_info_array_ptr = NULL; gb_global Type *t_type_info_dynamic_array_ptr = NULL; @@ -393,12 +406,6 @@ Type *make_type_pointer(gbAllocator a, Type *elem) { return t; } -Type *make_type_maybe(gbAllocator a, Type *elem) { - Type *t = alloc_type(a, Type_Maybe); - t->Maybe.elem = elem; - return t; -} - Type *make_type_array(gbAllocator a, Type *elem, i64 count) { Type *t = alloc_type(a, Type_Array); t->Array.elem = elem; @@ -630,10 +637,6 @@ bool is_type_pointer(Type *t) { } return t->kind == Type_Pointer; } -bool is_type_maybe(Type *t) { - t = base_type(t); - return t->kind == Type_Maybe; -} bool is_type_tuple(Type *t) { t = base_type(t); return t->kind == Type_Tuple; @@ -780,7 +783,6 @@ bool type_has_nil(Type *t) { case Type_DynamicArray: case Type_Proc: case Type_Pointer: - case Type_Maybe: return true; } return false; @@ -890,12 +892,6 @@ bool are_types_identical(Type *x, Type *y) { } break; - case Type_Maybe: - if (y->kind == Type_Maybe) { - return are_types_identical(x->Maybe.elem, y->Maybe.elem); - } - break; - case Type_Named: if (y->kind == Type_Named) { return x->Named.base == y->Named.base; @@ -981,9 +977,6 @@ bool is_type_cte_safe(Type *type) { case Type_Slice: return false; - case Type_Maybe: - return is_type_cte_safe(type->Maybe.elem); - case Type_Record: { if (type->Record.kind != TypeRecord_Struct) { return false; @@ -1026,12 +1019,14 @@ typedef enum ProcTypeOverloadKind { ProcOverload_ResultCount, ProcOverload_ResultTypes, + ProcOverload_NotProcedure, + } ProcTypeOverloadKind; ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) { - GB_ASSERT(is_type_proc(x)); - GB_ASSERT(is_type_proc(y)); + if (!is_type_proc(x)) return ProcOverload_NotProcedure; + if (!is_type_proc(y)) return ProcOverload_NotProcedure; TypeProc *px = &base_type(x)->Proc; TypeProc *py = &base_type(y)->Proc; @@ -1113,7 +1108,7 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) { Entity *f = type->Record.fields[i]; if (f->kind == Entity_Variable) { if (f->Variable.field_src_index == index) { - Array_isize sel_array = {0}; + Array_i32 sel_array = {0}; array_init_count(&sel_array, a, 1); sel_array.e[0] = i; return make_selection(f, sel_array, false); @@ -1125,7 +1120,7 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) { for (isize i = 0; i < max_count; i++) { Entity *f = type->Tuple.variables[i]; if (i == index) { - Array_isize sel_array = {0}; + Array_i32 sel_array = {0}; array_init_count(&sel_array, a, 1); sel_array.e[0] = i; return make_selection(f, sel_array, false); @@ -1352,6 +1347,10 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n sel.entity = type->Record.enum_max_value; return sel; } + if (str_eq(field_name, str_lit("names"))) { + sel.entity = type->Record.enum_names; + return sel; + } } for (isize i = 0; i < type->Record.field_count; i++) { @@ -1558,17 +1557,6 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type return max; } break; - case Type_Maybe: { - Type *elem = t->Maybe.elem; - type_path_push(path, elem); - if (path->failure) { - return FAILURE_ALIGNMENT; - } - i64 align = gb_max(type_align_of_internal(s, allocator, t->Maybe.elem, path), type_align_of_internal(s, allocator, t_bool, path)); - type_path_pop(path); - return align; - } - case Type_Map: { if (t->Map.count == 0) { // Dynamic return type_align_of_internal(s, allocator, t->Map.generated_struct_type, path); @@ -1773,18 +1761,6 @@ i64 type_size_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypeP case Type_Slice: // ptr + count return 2 * s.word_size; - case Type_Maybe: { // value + bool - i64 align, size; - Type *elem = t->Maybe.elem; - align = type_align_of_internal(s, allocator, elem, path); - if (path->failure) { - return FAILURE_SIZE; - } - size = align_formula(type_size_of_internal(s, allocator, elem, path), align); - size += type_size_of_internal(s, allocator, t_bool, path); - return align_formula(size, align); - } - case Type_Map: { if (t->Map.count == 0) { // Dynamic return type_size_of_internal(s, allocator, t->Map.generated_struct_type, path); @@ -1969,11 +1945,6 @@ gbString write_type_to_string(gbString str, Type *type) { str = write_type_to_string(str, type->Pointer.elem); break; - case Type_Maybe: - str = gb_string_appendc(str, "?"); - str = write_type_to_string(str, type->Maybe.elem); - break; - case Type_Array: str = gb_string_appendc(str, gb_bprintf("[%lld]", type->Array.count)); str = write_type_to_string(str, type->Array.elem); |