From 885c5dc8b75dd88d376627195a5468d12264bcc5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 15 Mar 2019 16:39:49 +0000 Subject: Fix issue with `deferred_*` attributes --- src/checker.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 0253bc86b..8e8afc621 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2005,7 +2005,7 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { if (value != nullptr) { Operand o = {}; check_expr(c, &o, value); - Entity *e = entity_of_ident(o.expr); + Entity *e = entity_of_node(o.expr); if (e != nullptr && e->kind == Entity_Procedure) { warning(elem, "'%.*s' is deprecated, please use one of the following instead: 'deferred_none', 'deferred_in', 'deferred_out'", LIT(name)); if (ac->deferred_procedure.entity != nullptr) { @@ -2022,7 +2022,7 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { if (value != nullptr) { Operand o = {}; check_expr(c, &o, value); - Entity *e = entity_of_ident(o.expr); + Entity *e = entity_of_node(o.expr); if (e != nullptr && e->kind == Entity_Procedure) { ac->deferred_procedure.kind = DeferredProcedure_none; ac->deferred_procedure.entity = e; @@ -2035,7 +2035,7 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { if (value != nullptr) { Operand o = {}; check_expr(c, &o, value); - Entity *e = entity_of_ident(o.expr); + Entity *e = entity_of_node(o.expr); if (e != nullptr && e->kind == Entity_Procedure) { if (ac->deferred_procedure.entity != nullptr) { error(elem, "Previous usage of a 'deferred_*' attribute"); @@ -2051,7 +2051,7 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) { if (value != nullptr) { Operand o = {}; check_expr(c, &o, value); - Entity *e = entity_of_ident(o.expr); + Entity *e = entity_of_node(o.expr); if (e != nullptr && e->kind == Entity_Procedure) { if (ac->deferred_procedure.entity != nullptr) { error(elem, "Previous usage of a 'deferred_*' attribute"); -- cgit v1.2.3 From fdb60b2d511f99dd9b8b427d032333992b10fd6a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 15 Mar 2019 18:30:39 +0000 Subject: Improve package strings --- core/strings/builder.odin | 4 + core/strings/strings.odin | 200 +++++++++++++++++++++++++++++++++++++++++++++- core/sync/atomic.odin | 146 ++++++++++++++++----------------- src/check_stmt.cpp | 3 +- src/checker.cpp | 19 +++-- 5 files changed, 285 insertions(+), 87 deletions(-) (limited to 'src/checker.cpp') diff --git a/core/strings/builder.odin b/core/strings/builder.odin index 547c456ba..922412638 100644 --- a/core/strings/builder.odin +++ b/core/strings/builder.odin @@ -17,6 +17,10 @@ destroy_builder :: proc(b: ^Builder) { clear(&b.buf); } +grow_builder :: proc(b: ^Builder, cap: int) { + reserve(&b.buf, cap); +} + builder_from_slice :: proc(backing: []byte) -> Builder { s := transmute(mem.Raw_Slice)backing; d := mem.Raw_Dynamic_Array{ diff --git a/core/strings/strings.odin b/core/strings/strings.odin index edf288c16..df3d69732 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -3,6 +3,21 @@ package strings import "core:mem" import "core:unicode/utf8" +clone :: proc(s: string, allocator := context.allocator) -> string { + c := make([]byte, len(s)+1, allocator); + copy(c, cast([]byte)s); + c[len(s)] = 0; + return string(c[:len(s)]); +} + +clone_to_cstring :: proc(s: string, allocator := context.allocator) -> cstring { + c := make([]byte, len(s)+1, allocator); + copy(c, cast([]byte)s); + c[len(s)] = 0; + return cstring(&c[0]); +} + +@(deprecated="Please use 'strings.clone'") new_string :: proc(s: string, allocator := context.allocator) -> string { c := make([]byte, len(s)+1, allocator); copy(c, cast([]byte)s); @@ -10,6 +25,7 @@ new_string :: proc(s: string, allocator := context.allocator) -> string { return string(c[:len(s)]); } +@(deprecated="Please use 'strings.clone_to_cstring'") new_cstring :: proc(s: string, allocator := context.allocator) -> cstring { c := make([]byte, len(s)+1, allocator); copy(c, cast([]byte)s); @@ -46,6 +62,10 @@ contains_any :: proc(s, chars: string) -> bool { } +rune_count :: proc(s: string) -> int { + return utf8.rune_count_in_string(s); +} + equal_fold :: proc(s, t: string) -> bool { loop: for s != "" && t != "" { @@ -209,7 +229,7 @@ last_index_any :: proc(s, chars: string) -> int { count :: proc(s, substr: string) -> int { if len(substr) == 0 { // special case - return utf8.rune_count_in_string(s) + 1; + return rune_count(s) + 1; } if len(substr) == 1 { c := substr[0]; @@ -493,3 +513,181 @@ trim_null :: proc(s: string) -> string { return trim_right_null(trim_left_null(s)); } +// scrub scruvs invalid utf-8 characters and replaces them with the replacement string +// Adjacent invalid bytes are only replaced once +scrub :: proc(str: string, replacement: string, allocator := context.allocator) -> string { + b := make_builder(allocator);; + grow_builder(&b, len(str)); + + has_error := false; + cursor := 0; + origin := str; + + for len(str) > 0 { + r, w := utf8.decode_rune_in_string(str); + + if r == utf8.RUNE_ERROR { + if !has_error { + has_error = true; + write_string(&b, origin[:cursor]); + } + } else if has_error { + has_error = false; + write_string(&b, replacement); + + origin = origin[cursor:]; + cursor = 0; + } + + cursor += w; + str = str[w:]; + } + + return to_string(b); +} + + +reverse :: proc(str: string, allocator := context.allocator) -> string { + n := len(str); + buf := make([]byte, n); + i := 0; + + for len(str) > 0 { + _, w := utf8.decode_rune_in_string(str); + copy(buf[i:], cast([]byte)str[:w]); + str = str[w:]; + } + return string(buf); +} + +expand_tabs :: proc(str: string, tab_size: int, allocator := context.allocator) -> string { + if tab_size <= 0 { + panic("tab size must be positive"); + } + + if str == "" { + return ""; + } + + b := make_builder(allocator); + + column: int; + + for len(str) > 0 { + r, w := utf8.decode_rune_in_string(str); + + if r == '\t' { + expand := tab_size - column%tab_size; + + for i := 0; i < expand; i += 1 { + write_byte(&b, ' '); + } + + column += expand; + } else { + if r == '\n' { + column = 0; + } else { + column += w; + } + + write_rune(&b, r); + } + + str = str[w:]; + } + + return to_string(b); +} + + +partition :: proc(str, sep: string) -> (head, match, tail: string) { + i := index(str, sep); + if i == -1 { + head = str; + return; + } + + head = str[:i]; + match = str[i:i+len(sep)]; + tail = str[i+len(sep):]; + return; +} + +center_justify :: centre_justify; // NOTE(bill): Because Americans exist + +// centre_justify returns a string with a pad string at boths sides if the str's rune length is smaller than length +centre_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> string { + n := rune_count(str); + if n >= length || pad == "" { + return clone(str, allocator); + } + + remains := length-1; + pad_len := rune_count(pad); + + b := make_builder(allocator); + grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)); + + write_pad_string(&b, pad, pad_len, remains/2); + write_string(&b, str); + write_pad_string(&b, pad, pad_len, (remains+1)/2); + + return to_string(b); +} + +// left_justify returns a string with a pad string at left side if the str's rune length is smaller than length +left_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> string { + n := rune_count(str); + if n >= length || pad == "" { + return clone(str, allocator); + } + + remains := length-1; + pad_len := rune_count(pad); + + b := make_builder(allocator); + grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)); + + write_string(&b, str); + write_pad_string(&b, pad, pad_len, remains); + + return to_string(b); +} + +// right_justify returns a string with a pad string at right side if the str's rune length is smaller than length +right_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> string { + n := rune_count(str); + if n >= length || pad == "" { + return clone(str, allocator); + } + + remains := length-1; + pad_len := rune_count(pad); + + b := make_builder(allocator); + grow_builder(&b, len(str) + (remains/pad_len + 1)*len(pad)); + + write_pad_string(&b, pad, pad_len, remains); + write_string(&b, str); + + return to_string(b); +} + + +@private +write_pad_string :: proc(b: ^Builder, pad: string, pad_len, remains: int) { + repeats := remains / pad_len; + + for i := 0; i < repeats; i += 1 { + write_string(b, pad); + } + + remains = remains % pad_len; + + if remains != 0 do for i := 0; i < remains; i += 1 { + r, w := utf8.decode_rune_in_string(pad); + write_rune(b, r); + pad = pad[w:]; + } +} diff --git a/core/sync/atomic.odin b/core/sync/atomic.odin index 4ea715bb4..9b2a0b3d1 100644 --- a/core/sync/atomic.odin +++ b/core/sync/atomic.odin @@ -11,92 +11,86 @@ Ordering :: enum { } strongest_failure_ordering :: inline proc "contextless" (order: Ordering) -> Ordering { - using Ordering; #complete switch order { - case Relaxed: return Relaxed; - case Release: return Relaxed; - case Acquire: return Acquire; - case Acquire_Release: return Acquire; - case Sequentially_Consistent: return Sequentially_Consistent; + case .Relaxed: return .Relaxed; + case .Release: return .Relaxed; + case .Acquire: return .Acquire; + case .Acquire_Release: return .Acquire; + case .Sequentially_Consistent: return .Sequentially_Consistent; } - return Relaxed; + return .Relaxed; } fence :: inline proc "contextless" (order: Ordering) { - using Ordering; #complete switch order { - case Relaxed: panic("there is no such thing as a relaxed fence"); - case Release: intrinsics.atomic_fence_rel(); - case Acquire: intrinsics.atomic_fence_acq(); - case Acquire_Release: intrinsics.atomic_fence_acqrel(); - case Sequentially_Consistent: intrinsics.atomic_fence(); + case .Relaxed: panic("there is no such thing as a relaxed fence"); + case .Release: intrinsics.atomic_fence_rel(); + case .Acquire: intrinsics.atomic_fence_acq(); + case .Acquire_Release: intrinsics.atomic_fence_acqrel(); + case .Sequentially_Consistent: intrinsics.atomic_fence(); case: panic("unknown order"); } } atomic_store :: inline proc "contextless" (dst: ^$T, val: T, order: Ordering) { - using Ordering; #complete switch order { - case Relaxed: intrinsics.atomic_store_relaxed(dst, val); - case Release: intrinsics.atomic_store_rel(dst, val); - case Sequentially_Consistent: intrinsics.atomic_store(dst, val); - case Acquire: panic("there is not such thing as an acquire store"); - case Acquire_Release: panic("there is not such thing as an acquire/release store"); + case .Relaxed: intrinsics.atomic_store_relaxed(dst, val); + case .Release: intrinsics.atomic_store_rel(dst, val); + case .Sequentially_Consistent: intrinsics.atomic_store(dst, val); + case .Acquire: panic("there is not such thing as an acquire store"); + case .Acquire_Release: panic("there is not such thing as an acquire/release store"); case: panic("unknown order"); } } atomic_load :: inline proc "contextless" (dst: ^$T, order: Ordering) -> T { - using Ordering; #complete switch order { - case Relaxed: return intrinsics.atomic_load_relaxed(dst); - case Acquire: return intrinsics.atomic_load_acq(dst); - case Sequentially_Consistent: return intrinsics.atomic_load(dst); - case Release: panic("there is no such thing as a release load"); - case Acquire_Release: panic("there is no such thing as an acquire/release load"); + case .Relaxed: return intrinsics.atomic_load_relaxed(dst); + case .Acquire: return intrinsics.atomic_load_acq(dst); + case .Sequentially_Consistent: return intrinsics.atomic_load(dst); + case .Release: panic("there is no such thing as a release load"); + case .Acquire_Release: panic("there is no such thing as an acquire/release load"); } panic("unknown order"); return T{}; } atomic_swap :: inline proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T { - using Ordering; #complete switch order { - case Relaxed: return intrinsics.atomic_xchg_relaxed(dst, val); - case Release: return intrinsics.atomic_xchg_rel(dst, val); - case Acquire: return intrinsics.atomic_xchg_acq(dst, val); - case Acquire_Release: return intrinsics.atomic_xchg_acqrel(dst, val); - case Sequentially_Consistent: return intrinsics.atomic_xchg(dst, val); + case .Relaxed: return intrinsics.atomic_xchg_relaxed(dst, val); + case .Release: return intrinsics.atomic_xchg_rel(dst, val); + case .Acquire: return intrinsics.atomic_xchg_acq(dst, val); + case .Acquire_Release: return intrinsics.atomic_xchg_acqrel(dst, val); + case .Sequentially_Consistent: return intrinsics.atomic_xchg(dst, val); } panic("unknown order"); return T{}; } atomic_compare_exchange :: inline proc "contextless" (dst: ^$T, old, new: T, success, failure: Ordering) -> (val: T, ok: bool) { - using Ordering; switch failure { - case Relaxed: + case .Relaxed: switch success { - case Relaxed: return intrinsics.atomic_cxchg_relaxed(dst, old, new); - case Acquire: return intrinsics.atomic_cxchg_acq_failrelaxed(dst, old, new); - case Acquire_Release: return intrinsics.atomic_cxchg_acqrel_failrelaxed(dst, old, new); - case Sequentially_Consistent: return intrinsics.atomic_cxchg_failrelaxed(dst, old, new); + case .Relaxed: return intrinsics.atomic_cxchg_relaxed(dst, old, new); + case .Acquire: return intrinsics.atomic_cxchg_acq_failrelaxed(dst, old, new); + case .Acquire_Release: return intrinsics.atomic_cxchg_acqrel_failrelaxed(dst, old, new); + case .Sequentially_Consistent: return intrinsics.atomic_cxchg_failrelaxed(dst, old, new); case: panic("an unknown ordering combination"); } - case Acquire: + case .Acquire: switch success { - case Acquire: return intrinsics.atomic_cxchg_acq(dst, old, new); + case .Acquire: return intrinsics.atomic_cxchg_acq(dst, old, new); case: panic("an unknown ordering combination"); } - case Sequentially_Consistent: + case .Sequentially_Consistent: switch success { - case Sequentially_Consistent: return intrinsics.atomic_cxchg(dst, old, new); + case .Sequentially_Consistent: return intrinsics.atomic_cxchg(dst, old, new); case: panic("an unknown ordering combination"); } - case Acquire_Release: + case .Acquire_Release: panic("there is not such thing as an acquire/release failure ordering"); - case Release: + case .Release: panic("there is not such thing as an release failure ordering"); } return T{}, false; @@ -105,78 +99,72 @@ atomic_compare_exchange :: inline proc "contextless" (dst: ^$T, old, new: T, suc atomic_add :: inline proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T { - using Ordering; #complete switch order { - case Relaxed: return intrinsics.atomic_add_relaxed(dst, val); - case Release: return intrinsics.atomic_add_rel(dst, val); - case Acquire: return intrinsics.atomic_add_acq(dst, val); - case Acquire_Release: return intrinsics.atomic_add_acqrel(dst, val); - case Sequentially_Consistent: return intrinsics.atomic_add(dst, val); + case .Relaxed: return intrinsics.atomic_add_relaxed(dst, val); + case .Release: return intrinsics.atomic_add_rel(dst, val); + case .Acquire: return intrinsics.atomic_add_acq(dst, val); + case .Acquire_Release: return intrinsics.atomic_add_acqrel(dst, val); + case .Sequentially_Consistent: return intrinsics.atomic_add(dst, val); } panic("unknown order"); return T{}; } atomic_sub :: inline proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T { - using Ordering; #complete switch order { - case Relaxed: return intrinsics.atomic_sub_relaxed(dst, val); - case Release: return intrinsics.atomic_sub_rel(dst, val); - case Acquire: return intrinsics.atomic_sub_acq(dst, val); - case Acquire_Release: return intrinsics.atomic_sub_acqrel(dst, val); - case Sequentially_Consistent: return intrinsics.atomic_sub(dst, val); + case .Relaxed: return intrinsics.atomic_sub_relaxed(dst, val); + case .Release: return intrinsics.atomic_sub_rel(dst, val); + case .Acquire: return intrinsics.atomic_sub_acq(dst, val); + case .Acquire_Release: return intrinsics.atomic_sub_acqrel(dst, val); + case .Sequentially_Consistent: return intrinsics.atomic_sub(dst, val); } panic("unknown order"); return T{}; } atomic_and :: inline proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T { - using Ordering; #complete switch order { - case Relaxed: return intrinsics.atomic_and_relaxed(dst, val); - case Release: return intrinsics.atomic_and_rel(dst, val); - case Acquire: return intrinsics.atomic_and_acq(dst, val); - case Acquire_Release: return intrinsics.atomic_and_acqrel(dst, val); - case Sequentially_Consistent: return intrinsics.atomic_and(dst, val); + case .Relaxed: return intrinsics.atomic_and_relaxed(dst, val); + case .Release: return intrinsics.atomic_and_rel(dst, val); + case .Acquire: return intrinsics.atomic_and_acq(dst, val); + case .Acquire_Release: return intrinsics.atomic_and_acqrel(dst, val); + case .Sequentially_Consistent: return intrinsics.atomic_and(dst, val); } panic("unknown order"); return T{}; } atomic_nand :: inline proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T { - using Ordering; #complete switch order { - case Relaxed: return intrinsics.atomic_nand_relaxed(dst, val); - case Release: return intrinsics.atomic_nand_rel(dst, val); - case Acquire: return intrinsics.atomic_nand_acq(dst, val); - case Acquire_Release: return intrinsics.atomic_nand_acqrel(dst, val); - case Sequentially_Consistent: return intrinsics.atomic_nand(dst, val); + case .Relaxed: return intrinsics.atomic_nand_relaxed(dst, val); + case .Release: return intrinsics.atomic_nand_rel(dst, val); + case .Acquire: return intrinsics.atomic_nand_acq(dst, val); + case .Acquire_Release: return intrinsics.atomic_nand_acqrel(dst, val); + case .Sequentially_Consistent: return intrinsics.atomic_nand(dst, val); } panic("unknown order"); return T{}; } atomic_or :: inline proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T { - using Ordering; #complete switch order { - case Relaxed: return intrinsics.atomic_or_relaxed(dst, val); - case Release: return intrinsics.atomic_or_rel(dst, val); - case Acquire: return intrinsics.atomic_or_acq(dst, val); - case Acquire_Release: return intrinsics.atomic_or_acqrel(dst, val); - case Sequentially_Consistent: return intrinsics.atomic_or(dst, val); + case .Relaxed: return intrinsics.atomic_or_relaxed(dst, val); + case .Release: return intrinsics.atomic_or_rel(dst, val); + case .Acquire: return intrinsics.atomic_or_acq(dst, val); + case .Acquire_Release: return intrinsics.atomic_or_acqrel(dst, val); + case .Sequentially_Consistent: return intrinsics.atomic_or(dst, val); } panic("unknown order"); return T{}; } atomic_xor :: inline proc "contextless" (dst: ^$T, val: T, order: Ordering) -> T { - using Ordering; #complete switch order { - case Relaxed: return intrinsics.atomic_xor_relaxed(dst, val); - case Release: return intrinsics.atomic_xor_rel(dst, val); - case Acquire: return intrinsics.atomic_xor_acq(dst, val); - case Acquire_Release: return intrinsics.atomic_xor_acqrel(dst, val); - case Sequentially_Consistent: return intrinsics.atomic_xor(dst, val); + case .Relaxed: return intrinsics.atomic_xor_relaxed(dst, val); + case .Release: return intrinsics.atomic_xor_rel(dst, val); + case .Acquire: return intrinsics.atomic_xor_acq(dst, val); + case .Acquire_Release: return intrinsics.atomic_xor_acqrel(dst, val); + case .Sequentially_Consistent: return intrinsics.atomic_xor(dst, val); } panic("unknown order"); return T{}; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index cead61ce8..07de5dc2e 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -474,10 +474,11 @@ bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, Ast *expr, b case Entity_ImportName: { Scope *scope = e->ImportName.scope; for_array(i, scope->elements.entries) { + String name = scope->elements.entries[i].key.string; Entity *decl = scope->elements.entries[i].value; if (!is_entity_exported(decl)) continue; - Entity *found = scope_insert(ctx->scope, decl); + Entity *found = scope_insert_with_name(ctx->scope, name, decl); if (found != nullptr) { gbString expr_str = expr_to_string(expr); error(us->token, diff --git a/src/checker.cpp b/src/checker.cpp index 8e8afc621..887f1af67 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -388,8 +388,7 @@ Entity *scope_lookup(Scope *s, String name) { -Entity *scope_insert(Scope *s, Entity *entity) { - String name = entity->token.string; +Entity *scope_insert_with_name(Scope *s, String name, Entity *entity) { if (name == "") { return nullptr; } @@ -406,6 +405,11 @@ Entity *scope_insert(Scope *s, Entity *entity) { return nullptr; } +Entity *scope_insert(Scope *s, Entity *entity) { + String name = entity->token.string; + return scope_insert_with_name(s, name, entity); +} + GB_COMPARE_PROC(entity_variable_pos_cmp) { Entity *x = *cast(Entity **)a; @@ -1023,11 +1027,10 @@ void add_entity_definition(CheckerInfo *i, Ast *identifier, Entity *entity) { array_add(&i->definitions, entity); } -bool add_entity(Checker *c, Scope *scope, Ast *identifier, Entity *entity) { +bool add_entity_with_name(Checker *c, Scope *scope, Ast *identifier, Entity *entity, String name) { if (scope == nullptr) { return false; } - String name = entity->token.string; if (!is_blank_ident(name)) { Entity *ie = scope_insert(scope, entity); if (ie != nullptr) { @@ -1063,6 +1066,9 @@ bool add_entity(Checker *c, Scope *scope, Ast *identifier, Entity *entity) { } return true; } +bool add_entity(Checker *c, Scope *scope, Ast *identifier, Entity *entity) { + return add_entity_with_name(c, scope, identifier, entity, entity->token.string); +} void add_entity_use(CheckerContext *c, Ast *identifier, Entity *entity) { if (entity == nullptr) { @@ -3050,12 +3056,13 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { // NOTE(bill): Add imported entities to this file's scope for_array(elem_index, scope->elements.entries) { + String name = scope->elements.entries[elem_index].key.string; Entity *e = scope->elements.entries[elem_index].value; if (e->scope == parent_scope) continue; if (is_entity_exported(e)) { - Entity *prev = scope_lookup(parent_scope, e->token.string); - add_entity(ctx->checker, parent_scope, e->identifier, e); + Entity *prev = scope_lookup(parent_scope, name); + add_entity_with_name(ctx->checker, parent_scope, e->identifier, e, name); } } } -- cgit v1.2.3 From 1eaa47ebae4daf31ad2071a39d978fdbf32f1082 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 17 Mar 2019 13:03:39 +0000 Subject: Fix `using import` behaviour - #352 --- core/sys/win32/kernel32.odin | 3 +- src/checker.cpp | 65 ++++++++++++++++++++++++++------------------ src/tokenizer.cpp | 8 ++++-- 3 files changed, 45 insertions(+), 31 deletions(-) (limited to 'src/checker.cpp') diff --git a/core/sys/win32/kernel32.odin b/core/sys/win32/kernel32.odin index 479e116a0..3cedf72e4 100644 --- a/core/sys/win32/kernel32.odin +++ b/core/sys/win32/kernel32.odin @@ -5,7 +5,6 @@ foreign import "system:kernel32.lib" @(default_calling_convention = "std") foreign kernel32 { - @(link_name="GetLastError") get_last_error :: proc() -> i32 ---; @(link_name="CreateProcessA") create_process_a :: proc(application_name, command_line: cstring, process_attributes, thread_attributes: ^Security_Attributes, inherit_handle: Bool, creation_flags: u32, environment: rawptr, @@ -119,6 +118,8 @@ foreign kernel32 { @(default_calling_convention = "c") foreign kernel32 { + @(link_name="GetLastError") get_last_error :: proc() -> i32 ---; + @(link_name="GetFileAttributesA") get_file_attributes_a :: proc(filename: cstring) -> u32 ---; @(link_name="GetFileAttributesW") get_file_attributes_w :: proc(filename: Wstring) -> u32 ---; @(link_name="GetFileAttributesExA") get_file_attributes_ex_a :: proc(filename: cstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: ^File_Attribute_Data) -> Bool ---; diff --git a/src/checker.cpp b/src/checker.cpp index 887f1af67..3b161d95a 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1027,6 +1027,33 @@ void add_entity_definition(CheckerInfo *i, Ast *identifier, Entity *entity) { array_add(&i->definitions, entity); } +bool redeclaration_error(String name, Entity *prev, Entity *found) { + TokenPos pos = found->token.pos; + Entity *up = found->using_parent; + if (up != nullptr) { + if (pos == up->token.pos) { + // NOTE(bill): Error should have been handled already + return false; + } + error(prev->token, + "Redeclaration of '%.*s' in this scope through 'using'\n" + "\tat %.*s(%td:%td)", + LIT(name), + LIT(up->token.pos.file), up->token.pos.line, up->token.pos.column); + } else { + if (pos == prev->token.pos) { + // NOTE(bill): Error should have been handled already + return false; + } + error(prev->token, + "Redeclaration of '%.*s' in this scope\n" + "\tat %.*s(%td:%td)", + LIT(name), + LIT(pos.file), pos.line, pos.column); + } + return false; +} + bool add_entity_with_name(Checker *c, Scope *scope, Ast *identifier, Entity *entity, String name) { if (scope == nullptr) { return false; @@ -1034,31 +1061,7 @@ bool add_entity_with_name(Checker *c, Scope *scope, Ast *identifier, Entity *ent if (!is_blank_ident(name)) { Entity *ie = scope_insert(scope, entity); if (ie != nullptr) { - TokenPos pos = ie->token.pos; - Entity *up = ie->using_parent; - if (up != nullptr) { - if (pos == up->token.pos) { - // NOTE(bill): Error should have been handled already - return false; - } - error(entity->token, - "Redeclaration of '%.*s' in this scope through 'using'\n" - "\tat %.*s(%td:%td)", - LIT(name), - LIT(up->token.pos.file), up->token.pos.line, up->token.pos.column); - return false; - } else { - if (pos == entity->token.pos) { - // NOTE(bill): Error should have been handled already - return false; - } - error(entity->token, - "Redeclaration of '%.*s' in this scope\n" - "\tat %.*s(%td:%td)", - LIT(name), - LIT(pos.file), pos.line, pos.column); - return false; - } + return redeclaration_error(name, entity, ie); } } if (identifier != nullptr) { @@ -3061,8 +3064,16 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { if (e->scope == parent_scope) continue; if (is_entity_exported(e)) { - Entity *prev = scope_lookup(parent_scope, name); - add_entity_with_name(ctx->checker, parent_scope, e->identifier, e, name); + Entity *found = scope_lookup(parent_scope, name); + if (found != nullptr) { + // NOTE(bill): + // Date: 2019-03-17 + // The order has to be the other way around as `using` adds the entity into the that + // file scope otherwise the error would be the wrong way around + redeclaration_error(name, found, e); + } else { + add_entity_with_name(ctx->checker, parent_scope, e->identifier, e, name); + } } } } diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index d7a39e824..48f7af19c 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -212,6 +212,8 @@ void warning_va(Token token, char *fmt, va_list va) { gb_mutex_unlock(&global_error_collector.mutex); } +#define MAX_ERROR_COLLECTOR_COUNT (36) + void error_va(Token token, char *fmt, va_list va) { gb_mutex_lock(&global_error_collector.mutex); global_error_collector.count++; @@ -225,7 +227,7 @@ void error_va(Token token, char *fmt, va_list va) { gb_bprintf_va(fmt, va)); } gb_mutex_unlock(&global_error_collector.mutex); - if (global_error_collector.count > 20) { + if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT) { gb_exit(1); } } @@ -243,7 +245,7 @@ void error_no_newline_va(Token token, char *fmt, va_list va) { gb_bprintf_va(fmt, va)); } gb_mutex_unlock(&global_error_collector.mutex); - if (global_error_collector.count > 20) { + if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT) { gb_exit(1); } } @@ -263,7 +265,7 @@ void syntax_error_va(Token token, char *fmt, va_list va) { } gb_mutex_unlock(&global_error_collector.mutex); - if (global_error_collector.count > 20) { + if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT) { gb_exit(1); } } -- cgit v1.2.3 From a6fb2dd5877cf1af1911451d31bf3ba042315c57 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 17 Mar 2019 20:43:54 +0000 Subject: Fix Erroneous redeclaration error with `using import` #354 --- src/checker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/checker.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 3b161d95a..130c4aee5 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3064,7 +3064,7 @@ void check_add_import_decl(CheckerContext *ctx, Ast *decl) { if (e->scope == parent_scope) continue; if (is_entity_exported(e)) { - Entity *found = scope_lookup(parent_scope, name); + Entity *found = scope_lookup_current(parent_scope, name); if (found != nullptr) { // NOTE(bill): // Date: 2019-03-17 -- cgit v1.2.3