diff --git a/AstBuilding.py b/AstBuilding.py index 5a8bb3907d098af1390a9a56351f7e5f4414fcc0..035a8f9c43a2f6db093c7f7adc1c148777b21b1a 100644 --- a/AstBuilding.py +++ b/AstBuilding.py @@ -32,13 +32,10 @@ def buildEnvAndLink(ASTs): # type Linking - # print('--------->>> type linking time!') for t in ASTs: - # t[1].buildEnvFromImports(globalEnv) t[1].recurseAction("linkType") # hierarchy checking - # print('--------->>> hierarchy checking time!') for t in ASTs: t[1].recurseAction("checkHierarchy") @@ -46,12 +43,8 @@ def buildEnvAndLink(ASTs): def disamiguateAndTypeChecking(ASTs): - # disambiguate namesapce: figuring out the meaning of the shortest prefix of names + # disambiguate namespace: figuring out the meaning of the shortest prefix of names for t in ASTs: - # try: - # t[1].recurseAction("disambigName") - # except Exception as e: - # raise e t[1].disambigName() # type checking diff --git a/Environment.py b/Environment.py index 921ec8efd6901e6aff48f8e5249f556ca09f12f1..5e0ecdbf550f7d4a341e90495e8200dfa67512ae 100644 --- a/Environment.py +++ b/Environment.py @@ -79,9 +79,11 @@ class GlobalEnv(Env): namespace = self.nodeToNamespace.get(typeDclType) # Add to map - mapKey = pName + '.' + typeDcl.name + mapKey = pName + '.' + typeDcl.name + if not pName: + mapKey = typeDcl.name if mapKey in self.map: - raise Exception('ERROR: Declaration of {} is already in current Environment'.format(pName + '.' + typeDcl.name)) + raise Exception('ERROR: Declaration of {} is already in current Environment'.format(mapKey)) self.map[mapKey] = typeDcl # Add to packageMap @@ -90,52 +92,85 @@ class GlobalEnv(Env): self.packageMap[pName] = {} if pMapKey in self.packageMap[pName]: - raise Exception('ERROR: Declaration of {} is already in current Environment'.format(pName + '.' + typeDcl.name)) + raise Exception('ERROR: Declaration of {} is already in current Environment'.format(mapKey)) self.packageMap[pName][pMapKey] = typeDcl def weedGlobalEnv(self): # call after building global Env to resolve clashes: + # TODO crashing some A2 tests + + # from pprint import pprint + # print('self.map') + # pprint(self.map) + # print('self.packageMap') + # pprint(self.packageMap) + # pprint(self.packageMap.keys()) + for i in self.map.keys(): for j in self.packageMap.keys(): - if i in j: + iNode = self.map.get(i) + # if j == "java.util.ArrayList.foo" and "java.util.ArrayList.foo" in i: + # print('j ', j) + # print('i ', i) + # print('iNode.packageName ', iNode.packageName) + # i.rpartition('.')[0] == j + if i in j and iNode.packageName: + # print('i ({}) is in j ({})'.format(i,j)) raise Exception('ERROR: Package name {} clashing with Type name {}'.format(j, i)) # Use getNode() from base class to get node using Canonical Name (full name) def getNode(self, key, imported, packageName): - # TODO: error if ambiguous - # TODO: not sure whether name is canonical or not???? - # i.e. there are more than one of this type. Currently it only gets the first occurence name = key[0] + found = [] # list of found nodes # 1. enclosing class/interface # - already did + # fully qualified name (canonName) if name in self.map: return self.map.get(name) + # 2. single-type import (simple Name) for i in imported: if not '*' in i: - simpleName = i.split(".")[-1] - if simpleName == name: - return self.map.get(i) + full = i.split(".")[-1] + if full == name: + found.append(self.map.get(i)) + # 3. type in the current package full = packageName + '.' + name - # print(full) if full in self.map: return self.map.get(full) + # 4. import-on-demand + checked = [] for i in imported: - if '*' in i: + if '*' in i and i not in checked: + checked.append(i) full = i.replace("*", name) if full in self.map: - return self.map.get(full) + found.append(self.map.get(full)) + # imported implicitly: java.io.*, java.lang.*, java.util.* - implicitly = ['java.lang.', 'java.io.', 'java.util.'] + implicitly = ['java.lang.'] + + # remove from implicitly if we are in that package already + if (packageName + '.') in implicitly: + implicitly.remove(packageName + '.') + + # remove from implicitly if we explicitly imported it + for i in imported: + if '*' in i and i.replace("*", "") in implicitly: + implicitly.remove(i.replace("*", "")) + for i in implicitly: - if i in name and name in self.map: - return self.map.get(name) - elif (i+name) in self.map: - return self.map.get(i+name) + if (i+name) in self.map: + found.append(self.map.get(i+name)) + + if len(found) == 1: + return found[0] + elif len(found) > 1: + raise Exception("ERROR: Trying to access ambiguous name '{}' in the Environment".format(key)) raise Exception("ERROR: Can't find definition of {} in the Environment".format(key)) diff --git a/Test.py b/Test.py index 0a434959180eccf450a3b62922b43524e6dbb9ba..0dec390f9fe1fd9dc118dd146583edfd000d44de 100644 --- a/Test.py +++ b/Test.py @@ -1,4 +1,5 @@ import sys +import time from os import listdir, scandir, walk from os.path import isfile, join import traceback @@ -43,6 +44,7 @@ def a2Multiple(): total = 0 correct = 0 + start = time.time() for c in testCases: # get all files from stdlib folder @@ -73,9 +75,9 @@ def a2Multiple(): else: correct += 1 - print("\nSCORE: {} / {} -> {:.3g}%".format(correct, total, (correct/total)*100)) - - + end = time.time() + print("\nTime Elapsed: {}".format(time.strftime('%H:%M:%S', time.gmtime(end - start)))) + print("SCORE: {} / {} -> {:.3g}%".format(correct, total, (correct/total)*100)) def run(testFiles): parseTrees = []