From ef53dad4fe9878334bbee793e32e8092502ead14 Mon Sep 17 00:00:00 2001 From: vdka Date: Sat, 24 Feb 2018 22:38:01 +1000 Subject: [PATCH 1/4] Evaluate imports into file scope after collection is done closes #121 --- Sources/Core/Checker.swift | 42 ++++++++++++++--------- code/bugs/{open => closed}/issue121/a.kai | 0 code/bugs/{open => closed}/issue121/b.kai | 0 code/bugs/{open => closed}/issue121/c.kai | 0 4 files changed, 26 insertions(+), 16 deletions(-) rename code/bugs/{open => closed}/issue121/a.kai (100%) rename code/bugs/{open => closed}/issue121/b.kai (100%) rename code/bugs/{open => closed}/issue121/c.kai (100%) diff --git a/Sources/Core/Checker.swift b/Sources/Core/Checker.swift index 10059ad..4a7a754 100644 --- a/Sources/Core/Checker.swift +++ b/Sources/Core/Checker.swift @@ -88,6 +88,22 @@ struct Checker { extension Checker { mutating func checkFile() { + // Before we begin checking this file we import the entities from our imports where applicable + // We can't guarentee collecting happens in any sort of order because that is where we establish an ordering + // because of this importing entities into our scope is only possible now that all of the entities for + // the imported files exist + for i in file.imports { + if i.importSymbolsIntoScope { + for member in i.scope.members.values { + guard !member.isFile && !member.isLibrary else { + continue + } + + declare(member, scopeOwnsEntity: i.exportSymbolsOutOfScope) + } + } + } + for node in file.nodes { check(topLevelStmt: node) } @@ -134,9 +150,9 @@ extension Checker { // below return assert(file.errors.count > 0) } - var entity: Entity? + var fileEntity: Entity? if let alias = i.alias { - entity = newEntity(ident: alias, flags: .file) + fileEntity = newEntity(ident: alias, flags: .file) } else if !i.importSymbolsIntoScope { guard let name = i.resolvedName else { reportError("Cannot infer an import name for '\(i.path)'", at: i.path.start) @@ -144,22 +160,16 @@ extension Checker { return } let ident = Ident(start: noPos, name: name) - entity = newEntity(ident: ident, flags: .file) + fileEntity = newEntity(ident: ident, flags: .file) } - // TODO: Ensure the import has been fully checked - if i.importSymbolsIntoScope { - for member in i.scope.members.values { - guard !member.isFile && !member.isLibrary else { - continue - } - - declare(member, scopeOwnsEntity: i.exportSymbolsOutOfScope) - } - } else if let entity = entity { - entity.memberScope = i.scope - entity.type = ty.File(memberScope: i.scope) - declare(entity) + // NOTE: If i.importSymbolsIntoScope we leave the import of entities until the file containing the import + // statement is starting to be checked. Only then do we know that all of the entities for the imported file + // have been created. + if let fileEntity = fileEntity { + fileEntity.memberScope = i.scope + fileEntity.type = ty.File(memberScope: i.scope) + declare(fileEntity) } } diff --git a/code/bugs/open/issue121/a.kai b/code/bugs/closed/issue121/a.kai similarity index 100% rename from code/bugs/open/issue121/a.kai rename to code/bugs/closed/issue121/a.kai diff --git a/code/bugs/open/issue121/b.kai b/code/bugs/closed/issue121/b.kai similarity index 100% rename from code/bugs/open/issue121/b.kai rename to code/bugs/closed/issue121/b.kai diff --git a/code/bugs/open/issue121/c.kai b/code/bugs/closed/issue121/c.kai similarity index 100% rename from code/bugs/open/issue121/c.kai rename to code/bugs/closed/issue121/c.kai From 6a9d57df5502f3c250c6439afb9e28737fbbeace Mon Sep 17 00:00:00 2001 From: vdka Date: Sat, 24 Feb 2018 22:38:54 +1000 Subject: [PATCH 2/4] Fix enum type conversion making it more freely converting --- Sources/Core/Type.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Sources/Core/Type.swift b/Sources/Core/Type.swift index f80f8d2..80a415b 100644 --- a/Sources/Core/Type.swift +++ b/Sources/Core/Type.swift @@ -310,9 +310,14 @@ func convert(_ type: Type, to target: Type, at expr: Expr) -> Bool { case (is ty.Boolean, is ty.Boolean): allowed = true - case (let exprType as ty.Enum, let targetType as ty.Integer): + case (let enumType as ty.Enum, is ty.Integer), + (is ty.Integer, let enumType as ty.Enum): // FIXME: Decide the rules for casting to and from integers - allowed = canCast(exprType.backingType, to: targetType) + allowed = canCast(enumType.backingType, to: target) + + case (is ty.Enum, is ty.UntypedInteger), + (is ty.UntypedInteger, is ty.Enum): + allowed = true case (_, is ty.Anyy): allowed = true From 4dc12c09c357480baf33d6028e9209308cfda784 Mon Sep 17 00:00:00 2001 From: vdka Date: Sun, 25 Feb 2018 00:01:10 +1000 Subject: [PATCH 3/4] Actually error when an import results in redeclarations --- Sources/Core/Checker.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Core/Checker.swift b/Sources/Core/Checker.swift index 4a7a754..ad3f7b7 100644 --- a/Sources/Core/Checker.swift +++ b/Sources/Core/Checker.swift @@ -78,7 +78,7 @@ struct Checker { func declare(_ entity: Entity, scopeOwnsEntity: Bool = true) { let previous = context.scope.insert(entity, scopeOwnsEntity: scopeOwnsEntity) - if let previous = previous, entity.file === previous.file { + if let previous = previous, entity.file !== previous.file { reportError("Invalid redeclaration of '\(previous.name)'", at: entity.ident.start) file.attachNote("Previous declaration here: \(file.position(for: previous.ident.start).description)") } From 3df891f9a0abdd83c62f33d49562bfe9ba40bd3a Mon Sep 17 00:00:00 2001 From: vdka Date: Sun, 25 Feb 2018 00:12:03 +1000 Subject: [PATCH 4/4] Added reproduction for #122 --- code/bugs/open/issue122/a.kai | 7 +++++++ code/bugs/open/issue122/b.kai | 1 + code/bugs/open/issue122/c.kai | 1 + 3 files changed, 9 insertions(+) create mode 100644 code/bugs/open/issue122/a.kai create mode 100644 code/bugs/open/issue122/b.kai create mode 100644 code/bugs/open/issue122/c.kai diff --git a/code/bugs/open/issue122/a.kai b/code/bugs/open/issue122/a.kai new file mode 100644 index 0000000..568d2fb --- /dev/null +++ b/code/bugs/open/issue122/a.kai @@ -0,0 +1,7 @@ + +#import "b.kai" _ +#import "c.kai" _ +main :: fn() -> void { + z := ent +} + diff --git a/code/bugs/open/issue122/b.kai b/code/bugs/open/issue122/b.kai new file mode 100644 index 0000000..655fe60 --- /dev/null +++ b/code/bugs/open/issue122/b.kai @@ -0,0 +1 @@ +ent :: 1 diff --git a/code/bugs/open/issue122/c.kai b/code/bugs/open/issue122/c.kai new file mode 100644 index 0000000..1129ee2 --- /dev/null +++ b/code/bugs/open/issue122/c.kai @@ -0,0 +1 @@ +ent :: 2