diff --git a/code/demo.odin b/code/demo.odin index 3eb810e82..30a2b639e 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,5 +1,27 @@ #import "fmt.odin" as fmt +main :: proc() { + Fruit :: enum { + APPLE = -2, + BANANA, + GRAPE, + MELON = 123, + TOMATO, + } + + s1 := enum_to_string(Fruit.BANANA) + e := Fruit.MELON + s2 := enum_to_string(e) + + fmt.println(Fruit.APPLE) + fmt.println(Fruit.count) + fmt.println(Fruit.min_value) + fmt.println(Fruit.max_value) +} + + +// #import "fmt.odin" as fmt + // #foreign_system_library "Ws2_32" // WSADESCRIPTION_LEN :: 256 @@ -147,7 +169,7 @@ // Demo Title // // -//

Odin Server Demo

+//

Odin Server Demo

// // // ` @@ -174,19 +196,3 @@ // shutdown(client, SD_SEND) // } - -main :: proc() { - Fruit :: enum { - APPLE, - BANANA, - GRAPE, - MELON, - } - - s1 := enum_to_string(Fruit.APPLE) - e := Fruit.APPLE - s2 := enum_to_string(e) - - fmt.println(s1) - fmt.println(s2) -} diff --git a/core/fmt.odin b/core/fmt.odin index d838b236e..cd8c45434 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -437,10 +437,30 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) { print_pointer_to_buffer(buf, v) case Enum: - v: any - v.data = arg.data - v.type_info = info.base - print_any_to_buffer(buf, v) + value: i64 = 0 + match type i : info.base { + case Integer: + if i.signed { + if arg.data != null { + match i.size { + case 1: value = (arg.data as ^i8)^ as i64 + case 2: value = (arg.data as ^i16)^ as i64 + case 4: value = (arg.data as ^i32)^ as i64 + case 8: value = (arg.data as ^i64)^ as i64 + } + } + } else { + if arg.data != null { + match i.size { + case 1: value = (arg.data as ^u8)^ as i64 + case 2: value = (arg.data as ^u16)^ as i64 + case 4: value = (arg.data as ^u32)^ as i64 + case 8: value = (arg.data as ^u64)^ as i64 + } + } + } + } + print_string_to_buffer(buf, __enum_to_string(arg.type_info, value)) case Array: diff --git a/core/runtime.odin b/core/runtime.odin index 98c2ab6ec..8fa840597 100644 --- a/core/runtime.odin +++ b/core/runtime.odin @@ -354,7 +354,6 @@ __enum_to_string :: proc(info: ^Type_Info, value: i64) -> string { match type ti : info { case Type_Info.Enum: - fmt.println("Here: ", ti.values.count) for i := 0; i < ti.values.count; i++ { if ti.values[i] == value { return ti.names[i] diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 483b6c0ef..c891b3024 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -631,7 +631,7 @@ void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) } b32 add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) { - if (!are_strings_equal(entity->token.string, make_string("_"))) { + if (entity->token.string != make_string("_")) { Entity *insert_entity = scope_insert_entity(scope, entity); if (insert_entity) { Entity *up = insert_entity->using_parent; @@ -676,7 +676,7 @@ void add_entity_use(CheckerInfo *i, AstNode *identifier, Entity *entity) { void add_file_entity(Checker *c, Scope *file_scope, AstNode *identifier, Entity *e, DeclInfo *d) { - GB_ASSERT(are_strings_equal(identifier->Ident.string, e->token.string)); + GB_ASSERT(identifier->Ident.string == e->token.string); add_entity(c, file_scope, identifier, e); map_set(&c->info.entities, hash_pointer(e), d); } @@ -1048,7 +1048,7 @@ void check_parsed_files(Checker *c) { warning(id->token, "Multiple #import of the same file within this scope"); } - if (are_strings_equal(id->import_name.string, make_string("_"))) { + if (id->import_name.string == make_string("_")) { // NOTE(bill): Add imported entities to this file's scope gb_for_array(elem_index, scope->elements.entries) { Entity *e = scope->elements.entries[elem_index].value; diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 05e539bac..231e467bf 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -545,6 +545,7 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node, CycleChec } + void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) { GB_ASSERT(node->kind == AstNode_EnumType); GB_ASSERT(is_type_enum(enum_type)); @@ -571,12 +572,37 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod Entity **fields = gb_alloc_array(c->allocator, Entity *, gb_array_count(et->fields)); isize field_index = 0; ExactValue iota = make_exact_value_integer(-1); + i64 min_value = 0; + i64 max_value = 0; + + Type *constant_type = enum_type; + if (named_type != NULL) { + constant_type = named_type; + } + Token blank_token = {Token_Identifier}; + blank_token.string = make_string(""); + Entity *blank_entity = make_entity_constant(c->allocator, c->context.scope, blank_token, constant_type, make_exact_value_integer(0));; + gb_for_array(i, et->fields) { AstNode *field = et->fields[i]; ast_node(f, FieldValue, field); Token name_token = f->field->Ident; + if (name_token.string == make_string("count")) { + error(name_token, "`count` is a reserved identifier for enums"); + fields[field_index++] = blank_entity; + continue; + } else if (name_token.string == make_string("min_value")) { + error(name_token, "`min_value` is a reserved identifier for enums"); + fields[field_index++] = blank_entity; + continue; + } else if (name_token.string == make_string("max_value")) { + error(name_token, "`max_value` is a reserved identifier for enums"); + fields[field_index++] = blank_entity; + continue; + } + Operand o = {}; if (f->value != NULL) { check_expr(c, &o, f->value); @@ -598,11 +624,14 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod iota = exact_binary_operator_value(add_token, iota, make_exact_value_integer(1)); } - Type *constant_type = enum_type; - if (named_type != NULL) { - constant_type = named_type; - } + Entity *e = make_entity_constant(c->allocator, c->context.scope, name_token, constant_type, iota); + if (min_value > iota.value_integer) { + min_value = iota.value_integer; + } + if (max_value < iota.value_integer) { + max_value = iota.value_integer; + } HashKey key = hash_string(name_token.string); if (map_get(&entity_map, key)) { @@ -614,6 +643,8 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod } add_entity_use(&c->info, f->field, e); } + enum_type->Record.min_value = min_value; + enum_type->Record.max_value = max_value; enum_type->Record.other_fields = fields; enum_type->Record.other_field_count = gb_array_count(et->fields); } @@ -732,7 +763,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl o->expr = n; Entity *e = scope_lookup_entity(c->context.scope, n->Ident.string); if (e == NULL) { - if (are_strings_equal(n->Ident.string, make_string("_"))) { + if (n->Ident.string == make_string("_")) { error(n->Ident, "`_` cannot be used as a value type"); } else { auto *entries = c->context.scope->elements.entries; diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index 9acf62c6d..2c7b36848 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -162,7 +162,7 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) { // NOTE(bill): Ignore assignments to `_` if (node->kind == AstNode_Ident) { ast_node(i, Ident, node); - if (are_strings_equal(i->string, make_string("_"))) { + if (i->string == make_string("_")) { add_entity_definition(&c->info, node, NULL); check_assignment(c, op_a, NULL, make_string("assignment to `_` identifier")); if (op_a->mode == Addressing_Invalid) @@ -503,7 +503,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { if ((d->scope->is_file || d->scope->is_global) && - are_strings_equal(e->token.string, make_string("main"))) { + e->token.string == make_string("main")) { if (proc_type != NULL) { auto *pt = &proc_type->Proc; if (pt->param_count != 0 || @@ -701,7 +701,7 @@ void check_var_decl_node(Checker *c, AstNode *node) { String str = token.string; Entity *found = NULL; // NOTE(bill): Ignore assignments to `_` - b32 can_be_ignored = are_strings_equal(str, make_string("_")); + b32 can_be_ignored = str == make_string("_"); if (!can_be_ignored) { found = current_scope_lookup_entity(c->context.scope, str); } diff --git a/src/checker/type.cpp b/src/checker/type.cpp index 6caf12141..215df1612 100644 --- a/src/checker/type.cpp +++ b/src/checker/type.cpp @@ -120,6 +120,8 @@ struct Type { // enum only Type * enum_base; // Default is `int` + i64 min_value; + i64 max_value; // struct only i64 * struct_offsets; @@ -710,12 +712,12 @@ void selection_add_index(Selection *s, isize index) { gb_global Entity *entity__any_type_info = NULL; gb_global Entity *entity__any_data = NULL; gb_global Entity *entity__string_data = NULL; -gb_global Entity *entity__string_count = NULL; +gb_global Entity *entity__string_count = NULL; Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection sel = empty_selection) { GB_ASSERT(type_ != NULL); - if (are_strings_equal(field_name, make_string("_"))) { + if (field_name == make_string("_")) { return empty_selection; } @@ -740,11 +742,11 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se entity__any_data = make_entity_field(a, NULL, token, t_rawptr, false, 1); } - if (are_strings_equal(field_name, type_info_str)) { + if (field_name == type_info_str) { selection_add_index(&sel, 0); sel.entity = entity__any_type_info; return sel; - } else if (are_strings_equal(field_name, data_str)) { + } else if (field_name == data_str) { selection_add_index(&sel, 1); sel.entity = entity__any_data; return sel; @@ -765,11 +767,11 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se entity__string_count = make_entity_field(a, NULL, token, t_int, false, 1); } - if (are_strings_equal(field_name, data_str)) { + if (field_name == data_str) { selection_add_index(&sel, 0); sel.entity = entity__string_data; return sel; - } else if (are_strings_equal(field_name, count_str)) { + } else if (field_name == count_str) { selection_add_index(&sel, 1); sel.entity = entity__string_count; return sel; @@ -780,8 +782,8 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se return sel; } else if (type->kind == Type_Array) { String count_str = make_string("count"); - // NOTE(bill):U nderlying memory address cannot be changed - if (are_strings_equal(field_name, count_str)) { + // NOTE(bill): Underlying memory address cannot be changed + if (field_name == count_str) { Token token = {Token_Identifier}; token.string = count_str; // HACK(bill): Memory leak @@ -791,7 +793,7 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se } else if (type->kind == Type_Vector) { String count_str = make_string("count"); // NOTE(bill): Vectors are not addressable - if (are_strings_equal(field_name, count_str)) { + if (field_name == count_str) { Token token = {Token_Identifier}; token.string = count_str; // HACK(bill): Memory leak @@ -803,21 +805,21 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se String count_str = make_string("count"); String capacity_str = make_string("capacity"); - if (are_strings_equal(field_name, data_str)) { + if (field_name == data_str) { selection_add_index(&sel, 0); Token token = {Token_Identifier}; token.string = data_str; // HACK(bill): Memory leak sel.entity = make_entity_field(a, NULL, token, make_type_pointer(a, type->Slice.elem), false, 0); return sel; - } else if (are_strings_equal(field_name, count_str)) { + } else if (field_name == count_str) { selection_add_index(&sel, 1); Token token = {Token_Identifier}; token.string = count_str; // HACK(bill): Memory leak sel.entity = make_entity_field(a, NULL, token, t_int, false, 1); return sel; - } else if (are_strings_equal(field_name, capacity_str)) { + } else if (field_name == capacity_str) { selection_add_index(&sel, 2); Token token = {Token_Identifier}; token.string = capacity_str; @@ -837,7 +839,7 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se GB_ASSERT(f->kind == Entity_TypeName); String str = f->token.string; - if (are_strings_equal(field_name, str)) { + if (field_name == str) { return make_selection(f, NULL, i); } } @@ -848,16 +850,43 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se GB_ASSERT(f->kind != Entity_Variable); String str = f->token.string; - if (are_strings_equal(field_name, str)) { + if (field_name == str) { return make_selection(f, NULL, i); } } + + if (is_type_enum(type)) { + String count_str = make_string("count"); + String min_value_str = make_string("min_value"); + String max_value_str = make_string("max_value"); + + if (field_name == count_str) { + Token token = {Token_Identifier}; + token.string = count_str; + // HACK(bill): Memory leak + sel.entity = make_entity_constant(a, NULL, token, t_int, make_exact_value_integer(type->Record.other_field_count)); + return sel; + } else if (field_name == min_value_str) { + Token token = {Token_Identifier}; + token.string = min_value_str; + // HACK(bill): Memory leak + sel.entity = make_entity_constant(a, NULL, token, type->Record.enum_base, make_exact_value_integer(type->Record.min_value)); + return sel; + } else if (field_name == max_value_str) { + Token token = {Token_Identifier}; + token.string = max_value_str; + // HACK(bill): Memory leak + sel.entity = make_entity_constant(a, NULL, token, type->Record.enum_base, make_exact_value_integer(type->Record.max_value)); + return sel; + } + } + } else if (!is_type_enum(type) && !is_type_union(type)) { for (isize i = 0; i < type->Record.field_count; i++) { Entity *f = type->Record.fields[i]; GB_ASSERT(f->kind == Entity_Variable && f->Variable.is_field); String str = f->token.string; - if (are_strings_equal(field_name, str)) { + if (field_name == str) { selection_add_index(&sel, i); sel.entity = f; return sel; diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index 54ec5f2ba..e021069b2 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -16,6 +16,7 @@ b32 ssa_gen_init(ssaGen *s, Checker *c) { } ssa_init_module(&s->module, c); + s->module.generate_debug_info = false; // TODO(bill): generate appropriate output name isize pos = string_extension_position(c->parser->init_fullpath); diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index b13644a5f..301bfd924 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -121,7 +121,7 @@ void ssa_print_encoded_local(ssaFileBuffer *f, String name) { void ssa_print_encoded_global(ssaFileBuffer *f, String name, b32 global_scope) { ssa_fprintf(f, "@"); - if (!global_scope && !are_strings_equal(name, make_string("main"))) { + if (!global_scope && name != make_string("main")) { ssa_fprintf(f, "."); } ssa_print_escape_string(f, name, true); @@ -818,7 +818,7 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { if (proc->module->generate_debug_info && proc->entity != NULL) { ssaDebugInfo *di = *map_get(&proc->module->debug_info, hash_pointer(proc->entity)); GB_ASSERT(di->kind == ssaDebugInfo_Proc); - ssa_fprintf(f, "!dbg !%d ", di->id); + ssa_fprintf(f, "!dbg !%d ", di->id); } @@ -839,6 +839,8 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { } } ssa_fprintf(f, "}\n"); + } else { + ssa_fprintf(f, "\n"); } gb_for_array(i, proc->children) { diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index dd230577c..d04938f26 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -1566,7 +1566,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg if (value->kind == ssaValue_Constant) { if (is_type_any(dst)) { - Type *dt = default_type(src); + Type *dt = default_type(get_base_type(src_type)); ssaValue *default_value = ssa_add_local_generated(proc, dt); ssa_emit_store(proc, default_value, value); return ssa_emit_conv(proc, ssa_emit_load(proc, default_value), t_any, is_argument); @@ -3680,14 +3680,14 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { void ssa_emit_startup_runtime(ssaProcedure *proc) { - GB_ASSERT(proc->parent == NULL && are_strings_equal(proc->name, make_string("main"))); + GB_ASSERT(proc->parent == NULL && proc->name == make_string("main")); ssa_emit(proc, ssa_alloc_instr(proc, ssaInstr_StartupRuntime)); } void ssa_insert_code_before_proc(ssaProcedure* proc, ssaProcedure *parent) { if (parent == NULL) { - if (are_strings_equal(proc->name, make_string("main"))) { + if (proc->name == make_string("main")) { ssa_emit_startup_runtime(proc); } } diff --git a/src/common.cpp b/src/common.cpp index db0a6ebdb..bbad5b845 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -51,7 +51,7 @@ b32 hash_key_equal(HashKey a, HashKey b) { if (a.key == b.key) { // NOTE(bill): If two string's hashes collide, compare the strings themselves if (a.is_string) { - if (b.is_string) return are_strings_equal(a.string, b.string); + if (b.is_string) return a.string == b.string; return false; } return true; diff --git a/src/parser.cpp b/src/parser.cpp index 87cee80fa..e34756daa 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1179,11 +1179,11 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n String tag_name = te->name.string; #define ELSE_IF_ADD_TAG(name) \ - else if (are_strings_equal(tag_name, make_string(#name))) { \ + else if (tag_name == make_string(#name)) { \ check_proc_add_tag(f, tag_expr, tags, ProcTag_##name, tag_name); \ } - if (are_strings_equal(tag_name, make_string("foreign"))) { + if (tag_name == make_string("foreign")) { check_proc_add_tag(f, tag_expr, tags, ProcTag_foreign, tag_name); if (f->cursor[0].kind == Token_String) { *foreign_name = f->cursor[0].string; @@ -1194,7 +1194,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n next_token(f); } - } else if (are_strings_equal(tag_name, make_string("link_name"))) { + } else if (tag_name == make_string("link_name")) { check_proc_add_tag(f, tag_expr, tags, ProcTag_link_name, tag_name); if (f->cursor[0].kind == Token_String) { *link_name = f->cursor[0].string; @@ -1277,7 +1277,7 @@ AstNode *parse_operand(AstFile *f, b32 lhs) { case Token_Hash: { operand = parse_tag_expr(f, NULL); String name = operand->TagExpr.name.string; - if (are_strings_equal(name, make_string("rune"))) { + if (name == make_string("rune")) { if (f->cursor[0].kind == Token_String) { Token *s = &f->cursor[0]; @@ -1289,12 +1289,12 @@ AstNode *parse_operand(AstFile *f, b32 lhs) { expect_token(f, Token_String); } operand = parse_operand(f, lhs); - } else if (are_strings_equal(name, make_string("file"))) { + } else if (name == make_string("file")) { Token token = operand->TagExpr.name; token.kind = Token_String; token.string = token.pos.file; return make_basic_lit(f, token); - } else if (are_strings_equal(name, make_string("line"))) { + } else if (name == make_string("line")) { Token token = operand->TagExpr.name; token.kind = Token_Integer; char *str = gb_alloc_array(gb_arena_allocator(&f->arena), char, 20); @@ -1930,11 +1930,11 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) { b32 is_ordered = false; while (allow_token(f, Token_Hash)) { Token tag = expect_token(f, Token_Identifier); - if (are_strings_equal(tag.string, make_string("packed"))) { + if (tag.string == make_string("packed")) { is_packed = true; - } else if (are_strings_equal(tag.string, make_string("ordered"))) { + } else if (tag.string == make_string("ordered")) { is_ordered = true; - } else { + } else { syntax_error(tag, "Expected a `#packed` or `#ordered` tag"); } } @@ -2137,7 +2137,7 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) { if (name->kind == AstNode_Ident) { String n = name->Ident.string; // NOTE(bill): Check for reserved identifiers - if (are_strings_equal(n, make_string("context"))) { + if (n == make_string("context")) { syntax_error(ast_node_token(name), "`context` is a reserved identifier"); break; } @@ -2578,14 +2578,14 @@ AstNode *parse_stmt(AstFile *f) { case Token_Hash: { s = parse_tag_stmt(f, NULL); String tag = s->TagStmt.name.string; - if (are_strings_equal(tag, make_string("shared_global_scope"))) { + if (tag == make_string("shared_global_scope")) { if (f->curr_proc == NULL) { f->is_global_scope = true; return make_empty_stmt(f, f->cursor[0]); } syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope."); return make_bad_decl(f, token, f->cursor[0]); - } else if (are_strings_equal(tag, make_string("import"))) { + } else if (tag == make_string("import")) { // TODO(bill): better error messages Token import_name; Token file_path = expect_token(f, Token_String); @@ -2597,7 +2597,7 @@ AstNode *parse_stmt(AstFile *f) { } syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope."); return make_bad_decl(f, token, file_path); - } else if (are_strings_equal(tag, make_string("load"))) { + } else if (tag == make_string("load")) { // TODO(bill): better error messages Token file_path = expect_token(f, Token_String); Token import_name = file_path; @@ -2608,14 +2608,14 @@ AstNode *parse_stmt(AstFile *f) { } syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope."); return make_bad_decl(f, token, file_path); - } else if (are_strings_equal(tag, make_string("foreign_system_library"))) { + } else if (tag == make_string("foreign_system_library")) { Token file_path = expect_token(f, Token_String); if (f->curr_proc == NULL) { return make_foreign_system_library(f, s->TagStmt.token, file_path); } syntax_error(token, "You cannot use #foreign_system_library within a procedure. This must be done at the file scope."); return make_bad_decl(f, token, file_path); - } else if (are_strings_equal(tag, make_string("thread_local"))) { + } else if (tag == make_string("thread_local")) { AstNode *var_decl = parse_simple_stmt(f); if (var_decl->kind != AstNode_VarDecl) { syntax_error(token, "#thread_local may only be applied to variable declarations"); @@ -2627,14 +2627,14 @@ AstNode *parse_stmt(AstFile *f) { } var_decl->VarDecl.tags |= VarDeclTag_thread_local; return var_decl; - } else if (are_strings_equal(tag, make_string("bounds_check"))) { + } else if (tag == make_string("bounds_check")) { s = parse_stmt(f); s->stmt_state_flags |= StmtStateFlag_bounds_check; if ((s->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together"); } return s; - } else if (are_strings_equal(tag, make_string("no_bounds_check"))) { + } else if (tag == make_string("no_bounds_check")) { s = parse_stmt(f); s->stmt_state_flags |= StmtStateFlag_no_bounds_check; if ((s->stmt_state_flags & StmtStateFlag_bounds_check) != 0) { @@ -2760,7 +2760,7 @@ void destroy_parser(Parser *p) { b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) { gb_for_array(i, p->imports) { String import = p->imports[i].path; - if (are_strings_equal(import, path)) { + if (import == path) { return false; } } @@ -2814,7 +2814,7 @@ String get_fullpath_core(gbAllocator a, String path) { b32 try_add_foreign_system_library_path(Parser *p, String import_file) { gb_for_array(i, p->system_libraries) { String import = p->system_libraries[i]; - if (are_strings_equal(import, import_file)) { + if (import == import_file) { return false; } } diff --git a/src/string.cpp b/src/string.cpp index 496c81d26..3843fa676 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -88,6 +88,15 @@ GB_COMPARE_PROC(string_cmp_proc) { } +bool operator ==(String a, String b) { return are_strings_equal(a, b) != 0; } +bool operator !=(String a, String b) { return !operator==(a, b); } +bool operator < (String a, String b) { return string_compare(a, b) < 0; } +bool operator > (String a, String b) { return string_compare(a, b) > 0; } +bool operator <=(String a, String b) { return string_compare(a, b) <= 0; } +bool operator >=(String a, String b) { return string_compare(a, b) >= 0; } + + + gb_inline isize string_extension_position(String str) { isize dot_pos = -1; isize i = str.len; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 6c3604406..f0aa0dc66 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -675,15 +675,15 @@ Token tokenizer_get_token(Tokenizer *t) { // NOTE(bill): All keywords are > 1 if (token.string.len > 1) { - if (are_strings_equal(token.string, token_strings[Token_as])) { + if (token.string == token_strings[Token_as]) { token.kind = Token_as; - } else if (are_strings_equal(token.string, token_strings[Token_transmute])) { + } else if (token.string == token_strings[Token_transmute]) { token.kind = Token_transmute; - } else if (are_strings_equal(token.string, token_strings[Token_down_cast])) { + } else if (token.string == token_strings[Token_down_cast]) { token.kind = Token_down_cast; } else { for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) { - if (are_strings_equal(token.string, token_strings[k])) { + if (token.string == token_strings[k]) { token.kind = cast(TokenKind)k; break; }