diff --git a/CompNode.py b/CompNode.py index e87e4057a9e2d64715303e185c7d9b7f78806607..819b061f85f623c5d23ba11a6a32d5745d219a14 100644 --- a/CompNode.py +++ b/CompNode.py @@ -40,14 +40,19 @@ class CompNode(ASTNode): return env def linkType(self): + seenImports = set() # check for repeated Imports, which are allowed + for i in self.importNames: if ".*" not in i: # add single Type import to self.env under their simple name sImport = self.env.getNode(i, "type") if not sImport: raise Exception("ERROR: Importing non existing type.") - self.env.addtoEnv(sImport) + + if i not in seenImports and sImport != self.typeDcl: # can import self + self.env.addtoEnv(sImport) + seenImports.add(i) else: # check if on demand import package exists # remove last two char .* to get package name - p = self.env.parentEnv.getNodesByPackage(i[:-2]) + p = self.env.parentEnv.ExistPackage(i[:-2]) diff --git a/Environment.py b/Environment.py index e8d1ff752d668f6845a373a281fc0ff7e4cfbcad..a0ab6fe2e59fbf07a4fdb883cef6e81ee294f55a 100644 --- a/Environment.py +++ b/Environment.py @@ -137,10 +137,18 @@ class GlobalEnv(Env): # method for getting all the nodes under a package (import All) # returns a dict of types under that package name - def getNodesByPackage(self, pName): - if not pName in self.packageMap: - raise Exception("ERROR: Can't find definition of package {} in the Environment".format(pName)) - return self.packageMap.get(pName) + def ExistPackage(self, pName): + p = pName.split(".") + for k in self.packageMap.keys(): #check if package Name is a prefix + kk = k.split(".") + found = True + for i in range(len(p)): + if kk[i] != p[i]: + found = False + break + if found: + return + raise Exception("ERROR: Can't find definition of package {} in the Environment".format(pName)) ################################### diff --git a/TypeNodes.py b/TypeNodes.py index 05bb041257eaff9addca42c47f9c62756c550af7..5ed16376391912cde1280d1f08d956e8b4c1c5c3 100644 --- a/TypeNodes.py +++ b/TypeNodes.py @@ -4,7 +4,7 @@ from Environment import Env # types: class , interface -class ClassInterNode(ASTNode): +class ClassInterNode(ASTNode): def checkHierarchy(self): # 3. An interface must not be repeated in an implements clause if self.superInter: @@ -13,7 +13,7 @@ class ClassInterNode(ASTNode): if inter.name in unique: raise Exception("ERROR: Class/Interface '{}' implements duplicate interfaces '{}'".format(self.name, inter.name)) unique.append(inter.name) - + # 7. A class or interface must not declare two methods with the same signature (name and parameter types). unique = [] for method in self.methods: @@ -21,15 +21,15 @@ class ClassInterNode(ASTNode): if key in unique: raise Exception("ERROR: Class/Interface '{}' declares 2 methods with the same signature '{}'".format(self.name, key[0])) unique.append(key) - + # 6. The hierarchy must be acyclic # 9. A class or interface must not contain (declare or inherit) two methods with the same signature but different return types # 11. A nonstatic method must not replace a static method # 13. A protected method must not replace a public method - # 14. A method must not replace a final method + return self.getContains([]) - def getContains(self, hierarchy): + def getContains(self, hierarchy): # check if not acyclic if self.name in hierarchy: raise Exception("ERROR: The hierarchy is not acyclic '{}', saw '{}'".format(hierarchy, self.name)) @@ -37,7 +37,7 @@ class ClassInterNode(ASTNode): # get contains contains = self.methods - + for inter in self.superInter: superContains = inter.getContains(hierarchy) for con in superContains: @@ -50,11 +50,14 @@ class ClassInterNode(ASTNode): # protected must not replace public if 'protected' in method.mods and 'public' in con.mods: raise Exception("ERROR: Protected method '{}' in class '{}' replaces public method '{}' in class {}".format(method.name, self.name, con.name, inter.name)) + # 14. A method must not replace a final method + if 'final' in con.mods: + raise Exception("ERROR: Final method '{}' in class '{}' can't be overrided by method '{}' in class {}".format(method.name, self.name, con.name, inter.name)) conOverwritten = True break if not conOverwritten: contains.append(con) - + return contains # class @@ -150,7 +153,7 @@ class ClassNode(ClassInterNode): if key in unique: raise Exception("ERROR: Class '{}' declares 2 constructors with the same parameter types".format(self.name)) unique.append(key) - + # centralized point for overlapping class & interface logic contains = super().checkHierarchy() @@ -163,7 +166,7 @@ class ClassNode(ClassInterNode): def getContains(self, hierarchy): # centralized logic contains = super().getContains(hierarchy) - + # get contains from extends class if self.superClass: addToContains = []