From 6512a3e5f24a3aecb1451f921455a93231412104 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 29 Jul 2018 10:50:15 +0100 Subject: [PATCH] using Foo :: enum {A, B, C}; len(Foo) --- core/fmt/fmt.odin | 1 - core/runtime/core.odin | 2 +- examples/demo/demo.odin | 11 ++++++----- src/big_int.cpp | 1 - src/check_expr.cpp | 16 ++++++++++++++- src/check_type.cpp | 23 ++++------------------ src/checker.cpp | 8 ++++++++ src/ir.cpp | 4 ++-- src/parser.cpp | 43 ++++++++++++++++++++--------------------- src/parser.hpp | 2 +- src/types.cpp | 22 ++------------------- 11 files changed, 60 insertions(+), 73 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index aef743ee9..bfa108aad 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -290,7 +290,6 @@ write_type :: proc(buf: ^String_Buffer, ti: ^runtime.Type_Info) { case runtime.Type_Info_Enum: write_string(buf, "enum "); write_type(buf, info.base); - if info.is_export do write_string(buf, " #export"); write_string(buf, " {"); for name, i in info.names { if i > 0 do write_string(buf, ", "); diff --git a/core/runtime/core.odin b/core/runtime/core.odin index d1f9994c0..fee2780a7 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -88,7 +88,7 @@ Type_Info_Enum :: struct { base: ^Type_Info, names: []string, values: []Type_Info_Enum_Value, - is_export: bool, + is_using: bool, // TODO(bill): Should this be in the `Type_Info`? }; Type_Info_Map :: struct { key: ^Type_Info, diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 7106b2438..558ef94e4 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -608,15 +608,16 @@ named_proc_return_parameters :: proc() { } -enum_export :: proc() { - fmt.println("# enum #export"); +using_enum :: proc() { + fmt.println("# using enum"); - Foo :: enum #export {A, B, C}; + using Foo :: enum {A, B, C}; f0 := A; f1 := B; f2 := C; fmt.println(f0, f1, f2); + fmt.println(len(Foo)); } explicit_procedure_overloading :: proc() { @@ -656,7 +657,7 @@ explicit_procedure_overloading :: proc() { complete_switch :: proc() { fmt.println("# complete_switch"); { // enum - Foo :: enum #export { + using Foo :: enum { A, B, C, @@ -723,7 +724,7 @@ main :: proc() { threading_example(); array_programming(); named_proc_return_parameters(); - enum_export(); + using_enum(); explicit_procedure_overloading(); complete_switch(); cstring_example(); diff --git a/src/big_int.cpp b/src/big_int.cpp index f7f51df6a..e177763f8 100644 --- a/src/big_int.cpp +++ b/src/big_int.cpp @@ -510,7 +510,6 @@ void big_int_add(BigInt *dst, BigInt const *x, BigInt const *y) { u64 first_word = dst->d.word; big_int_alloc(dst, 0, bigger->len); - GB_ASSERT(dst->len > 1); dst->d.words[0] = first_word; i32 i = 0; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 03747a26f..5596eb106 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2788,6 +2788,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_offset_of: case BuiltinProc_type_info_of: case BuiltinProc_typeid_of: + case BuiltinProc_len: // NOTE(bill): The first arg may be a Type, this will be checked case by case break; default: @@ -2860,9 +2861,17 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } case BuiltinProc_len: - case BuiltinProc_cap: { + check_expr_or_type(c, operand, ce->args[0]); + if (operand->mode == Addressing_Invalid) { + return false; + } + /* fallthrough */ + + case BuiltinProc_cap: + { // len :: proc(Type) -> int // cap :: proc(Type) -> int + Type *op_type = type_deref(operand->type); Type *type = t_int; AddressingMode mode = Addressing_Invalid; @@ -2890,6 +2899,11 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 mode = Addressing_Value; } else if (is_type_map(op_type)) { mode = Addressing_Value; + } else if (operand->mode == Addressing_Type && is_type_enum(op_type) && id == BuiltinProc_len) { + Type *bt = base_type(op_type); + mode = Addressing_Constant; + value = exact_value_i64(bt->Enum.fields.count); + type = t_untyped_integer; } if (mode == Addressing_Invalid) { diff --git a/src/check_type.cpp b/src/check_type.cpp index b73389865..4f44e0c4d 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -571,22 +571,10 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast // NOTE(bill): Skip blank identifiers if (is_blank_ident(name)) { continue; - } else if (name == "count") { - error(field, "'count' is a reserved identifier for enumerations"); - continue; - } else if (name == "min_value") { - error(field, "'min_value' is a reserved identifier for enumerations"); - continue; - } else if (name == "max_value") { - error(field, "'max_value' is a reserved identifier for enumerations"); - continue; } else if (name == "names") { error(field, "'names' is a reserved identifier for enumerations"); continue; - }/* else if (name == "base_type") { - error(field, "'base_type' is a reserved identifier for enumerations"); - continue; - } */ + } if (compare_exact_values(Token_Gt, min_value, iota)) { min_value = iota; @@ -613,8 +601,9 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast enum_type->Enum.fields = fields; - enum_type->Enum.is_export = et->is_export; - if (et->is_export) { + enum_type->Enum.is_using = et->is_using; + // TODO(bill): Should this be done elsewhere? e.g. delayed + if (et->is_using) { Scope *parent = ctx->scope->parent; if (parent->flags&ScopeFlag_File) { // NOTE(bill): Use package scope @@ -634,10 +623,6 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast } Scope *s = ctx->scope; - enum_type->Enum.count = alloc_entity_constant(s, make_token_ident(str_lit("count")), t_int, exact_value_i64(fields.count)); - enum_type->Enum.min_value = alloc_entity_constant(s, make_token_ident(str_lit("min_value")), constant_type, min_value); - enum_type->Enum.max_value = alloc_entity_constant(s, make_token_ident(str_lit("max_value")), constant_type, max_value); - enum_type->Enum.names = make_names_field_for_struct(ctx, ctx->scope); } diff --git a/src/checker.cpp b/src/checker.cpp index 58ba4aa68..9f59788b8 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2121,6 +2121,14 @@ void check_collect_value_decl(CheckerContext *c, Ast *decl) { } e->identifier = name; + if (vd->is_using) { + if (e->kind == Entity_TypeName && init->kind == Ast_EnumType) { + init->EnumType.is_using = true; + } else { + error(name, "'using' is not allowed on this constant value declaration"); + } + } + if (e->kind != Entity_Procedure) { if (fl != nullptr || c->foreign_context.in_export) { AstKind kind = init->kind; diff --git a/src/ir.cpp b/src/ir.cpp index e546015d7..3a7691326 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8163,8 +8163,8 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info irValue *base = ir_type_info(proc, t->Enum.base_type); ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), base); - // is_export - ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), ir_const_bool(t->Enum.is_export)); + // is_using + ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), ir_const_bool(t->Enum.is_using)); if (t->Enum.fields.count > 0) { auto fields = t->Enum.fields; diff --git a/src/parser.cpp b/src/parser.cpp index c2e0130ce..9d8e90347 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -920,11 +920,10 @@ Ast *ast_union_type(AstFile *f, Token token, Array variants, Ast *align) } -Ast *ast_enum_type(AstFile *f, Token token, Ast *base_type, bool is_export, Array fields) { +Ast *ast_enum_type(AstFile *f, Token token, Ast *base_type, Array fields) { Ast *result = alloc_ast_node(f, Ast_EnumType); result->EnumType.token = token; result->EnumType.base_type = base_type; - result->EnumType.is_export = is_export; result->EnumType.fields = fields; return result; } @@ -1903,34 +1902,34 @@ Ast *parse_operand(AstFile *f, bool lhs) { } break; case Token_enum: { - bool is_export = false; + // bool is_export = false; Token token = expect_token(f, Token_enum); Ast *base_type = nullptr; if (f->curr_token.kind != Token_OpenBrace) { if (f->curr_token.kind != Token_Hash) { base_type = parse_type(f); } - while (allow_token(f, Token_Hash)) { - Token tag = f->curr_token; - if (!allow_token(f, Token_Ident) && !allow_token(f, Token_export)) { - expect_token_after(f, Token_Ident, "#"); - } - if (tag.string == "export") { - if (is_export) { - syntax_error(tag, "Duplicate enum tag '#%.*s'", LIT(tag.string)); - } - is_export = true; - } else { - syntax_error(tag, "Invalid enum tag '#%.*s'", LIT(tag.string)); - } - } + // while (allow_token(f, Token_Hash)) { + // Token tag = f->curr_token; + // if (!allow_token(f, Token_Ident) && !allow_token(f, Token_export)) { + // expect_token_after(f, Token_Ident, "#"); + // } + // if (tag.string == "export") { + // if (is_export) { + // syntax_error(tag, "Duplicate enum tag '#%.*s'", LIT(tag.string)); + // } + // is_export = true; + // } else { + // syntax_error(tag, "Invalid enum tag '#%.*s'", LIT(tag.string)); + // } + // } } Token open = expect_token(f, Token_OpenBrace); Array values = parse_element_list(f); Token close = expect_token(f, Token_CloseBrace); - return ast_enum_type(f, token, base_type, is_export, values); + return ast_enum_type(f, token, base_type, values); } break; case Token_bit_field: { @@ -3591,10 +3590,10 @@ Ast *parse_stmt(AstFile *f) { decl = parse_value_decl(f, list, docs); if (decl != nullptr && decl->kind == Ast_ValueDecl) { - if (!decl->ValueDecl.is_mutable) { - syntax_error(token, "'using' may only be applied to variable declarations"); - return decl; - } + // if (!decl->ValueDecl.is_mutable) { + // syntax_error(token, "'using' may only be applied to variable declarations"); + // return decl; + // } decl->ValueDecl.is_using = true; return decl; } diff --git a/src/parser.hpp b/src/parser.hpp index 14eee643a..30ce225e5 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -478,7 +478,7 @@ AST_KIND(_TypeBegin, "", bool) \ Token token; \ Ast * base_type; \ Array fields; /* FieldValue */ \ - bool is_export; \ + bool is_using; \ }) \ AST_KIND(BitFieldType, "bit field type", struct { \ Token token; \ diff --git a/src/types.cpp b/src/types.cpp index 46ce0ee26..e0ab91e90 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -131,14 +131,11 @@ struct TypeStruct { TYPE_KIND(Struct, TypeStruct) \ TYPE_KIND(Enum, struct { \ Array fields; \ - Ast *node; \ + Ast *node; \ Scope * scope; \ Entity * names; \ Type * base_type; \ - bool is_export; \ - Entity * count; \ - Entity * min_value; \ - Entity * max_value; \ + bool is_using; \ }) \ TYPE_KIND(Union, struct { \ Array variants; \ @@ -1657,21 +1654,6 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty if (is_type_enum(type)) { // NOTE(bill): These may not have been added yet, so check in case - if (type->Enum.count != nullptr) { - if (field_name == "count") { - sel.entity = type->Enum.count; - return sel; - } - if (field_name == "min_value") { - sel.entity = type->Enum.min_value; - return sel; - } - if (field_name == "max_value") { - sel.entity = type->Enum.max_value; - return sel; - } - } - for_array(i, type->Enum.fields) { Entity *f = type->Enum.fields[i]; GB_ASSERT(f->kind == Entity_Constant);