Skip to content
Snippets Groups Projects
Commit 5095c3ae authored by Nicholas Robinson's avatar Nicholas Robinson
Browse files

NameNode & disambigName & checkType stuff

- added fieldType to FieldNode
- added myType to NameNode
- fixed NameNode:checkStatic
- recursively calling disambigName exactly the same as how we do
checkType
- starting NameNode:checkType
- cleaned up Test.py commented code
parent 80f03bdb
No related branches found
No related tags found
No related merge requests found
...@@ -54,7 +54,9 @@ class ASTNode(): ...@@ -54,7 +54,9 @@ class ASTNode():
pass pass
def disambigName(self): def disambigName(self):
pass for c in self.children:
if c and hasattr(c, 'disambigName'):
c.disambigName()
def checkType(self): def checkType(self):
# self is type correct if all its children are type correct (no exception raised) # self is type correct if all its children are type correct (no exception raised)
......
...@@ -42,9 +42,6 @@ def buildEnvAndLink(ASTs): ...@@ -42,9 +42,6 @@ def buildEnvAndLink(ASTs):
for t in ASTs: for t in ASTs:
t[1].recurseAction("checkHierarchy") t[1].recurseAction("checkHierarchy")
for t in ASTs:
t[1].checkType()
####################################################### #######################################################
def disamiguateAndTypeChecking(ASTs): def disamiguateAndTypeChecking(ASTs):
...@@ -58,5 +55,7 @@ def disamiguateAndTypeChecking(ASTs): ...@@ -58,5 +55,7 @@ def disamiguateAndTypeChecking(ASTs):
t[1].disambigName() t[1].disambigName()
# type checking # type checking
for t in ASTs:
t[1].checkType()
# resolving the rest of the name # resolving the rest of the name
\ No newline at end of file
...@@ -170,7 +170,6 @@ class CompEnv(Env): ...@@ -170,7 +170,6 @@ class CompEnv(Env):
def getNode(self, name, namespace): def getNode(self, name, namespace):
key = (name, namespace) key = (name, namespace)
if key in self.map: if key in self.map:
return self.map.get(key) return self.map.get(key)
elif self.parentEnv: # globalEnv elif self.parentEnv: # globalEnv
......
...@@ -29,7 +29,7 @@ def makeNodeFromExpr(parseTree, typeName): ...@@ -29,7 +29,7 @@ def makeNodeFromExpr(parseTree, typeName):
if c.name == 'primaryAndArray': if c.name == 'primaryAndArray':
return makeNodeFromAllPrimary(c, typeName) return makeNodeFromAllPrimary(c, typeName)
elif c.name == 'ID' or c.name == 'COMPID': elif c.name == 'ID' or c.name == 'COMPID':
return NameNode(c, typeName, typeName) return NameNode(c, False, typeName) # TODO is this always False??
  • Owner

    Seems like the case to me. ID or COMPID can't be method invoke

  • Please register or sign in to reply
elif c.name == 'assignment': elif c.name == 'assignment':
return AssignNode(c, typeName) return AssignNode(c, typeName)
elif c.name == 'refType': elif c.name == 'refType':
...@@ -357,6 +357,7 @@ class FieldAccessNode(ASTNode): ...@@ -357,6 +357,7 @@ class FieldAccessNode(ASTNode):
self.ID = NameNode(parseTree.children[2], False, typeName) self.ID = NameNode(parseTree.children[2], False, typeName)
self.children.append(self.primary) self.children.append(self.primary)
self.children.append(self.ID)
def disambigName(self): def disambigName(self):
if not self.primary: # this implies that the ID has nothing that comes before it if not self.primary: # this implies that the ID has nothing that comes before it
...@@ -386,10 +387,11 @@ class MethodInvNode(ASTNode): ...@@ -386,10 +387,11 @@ class MethodInvNode(ASTNode):
self.children.append(self.primary) self.children.append(self.primary)
self.children.append(self.args) self.children.append(self.args)
self.children.append(self.ID)
def disambigName(self): def disambigName(self):
if not self.primary: # this implies our ID doesn't have anything that comes before it if not self.primary: # this implies our ID doesn't have anything that comes before it
if '.' in self.ID: if isinstance(self.ID, NameNode) and len(self.ID.IDs) > 1:
helperDisambigName(self.ID) helperDisambigName(self.ID)
def checkType1(self): def checkType1(self):
......
...@@ -12,6 +12,7 @@ class FieldNode(ASTNode): ...@@ -12,6 +12,7 @@ class FieldNode(ASTNode):
def __init__(self, parseTree, typeName, order): def __init__(self, parseTree, typeName, order):
self.parseTree = parseTree self.parseTree = parseTree
self.name = '' self.name = ''
self.fieldType = ''
  • Owner

    ?????????????? Variable Dcl should include type already

  • Please register or sign in to reply
self.variableDcl = None self.variableDcl = None
self.mods = [] self.mods = []
self.env = None self.env = None
...@@ -24,6 +25,10 @@ class FieldNode(ASTNode): ...@@ -24,6 +25,10 @@ class FieldNode(ASTNode):
for n in nameNodes: for n in nameNodes:
self.name = n.lex self.name = n.lex
nameNodes = getParseTreeNodes(['type'], parseTree, ['methodMod', 'methodBody', 'variableInit'])
for n in nameNodes:
self.fieldType = TypeNode(n, self.typeName)
for node in parseTree.children: for node in parseTree.children:
if node.name == 'methodMod': if node.name == 'methodMod':
for m in node.children: for m in node.children:
......
from AST import ASTNode, getParseTreeNodes from AST import ASTNode, getParseTreeNodes
from TheTypeNode import TypeStruct
import MemberNodes
import TypeNodes
from Environment import Env from Environment import Env
# name nodes: contains compID and IDs # name nodes: contains compID and IDs
...@@ -28,6 +31,7 @@ class NameNode(ASTNode): ...@@ -28,6 +31,7 @@ class NameNode(ASTNode):
self.env = None self.env = None
self.typeName = typeName # the name of the class or interface that this node belongs under self.typeName = typeName # the name of the class or interface that this node belongs under
self.children = [] self.children = []
self.myType = None # will become TypeStruct to tell us what the whole is/returns
self.name = getParseTreeNodes(["ID", "COMPID"], parseTree)[0].lex self.name = getParseTreeNodes(["ID", "COMPID"], parseTree)[0].lex
...@@ -37,7 +41,7 @@ class NameNode(ASTNode): ...@@ -37,7 +41,7 @@ class NameNode(ASTNode):
# ASSUMPTION: will never be called when self.IDs is empty # ASSUMPTION: will never be called when self.IDs is empty
def addToPrefix(self, node): def addToPrefix(self, node):
# If self.prefixLink is contain, that means our self.prefix wasn't resolved yet # If self.prefixLink is contain, that means our self.prefix wasn't resolved yet
if self.prefixLink == "contain": if type(self.prefixLink) is str and self.prefixLink == "contain":
self.prefixLink = node self.prefixLink = node
return return
...@@ -65,7 +69,7 @@ class NameNode(ASTNode): ...@@ -65,7 +69,7 @@ class NameNode(ASTNode):
if not self.IDs: if not self.IDs:
return True return True
ID = self.IDs[0] ID = self.IDs[0]
localVarNode = self.env.findNode(ID, "expr") localVarNode = self.env.findNode(ID, "expr") # TODO localVarNode is for some reason returning a tuple: (boolean, node) for example (False, <UnitNodes.ParamNode object at 0x7fb353b1e978>). This will need to be fixed in order for NameNode:checkType to work
if localVarNode: if localVarNode:
self.addToPrefix(localVarNode) self.addToPrefix(localVarNode)
return True return True
...@@ -80,7 +84,7 @@ class NameNode(ASTNode): ...@@ -80,7 +84,7 @@ class NameNode(ASTNode):
ID = self.IDs[0] ID = self.IDs[0]
if self.env.findNode(ID, "fieldDcl") or self.env.findNode(ID, "method"): if self.env.findNode(ID, "fieldDcl") or self.env.findNode(ID, "method"):
self.addToPrefix("contains") self.addToPrefix("contain")
return True return True
return False return False
...@@ -95,25 +99,33 @@ class NameNode(ASTNode): ...@@ -95,25 +99,33 @@ class NameNode(ASTNode):
if currPrefix: if currPrefix:
currPrefix += "." currPrefix += "."
currPrefix += ID currPrefix += ID
typeNode = self.env.getNode(currPrefix, "type") try:
if typeNode: typeNode = self.env.getNode(currPrefix, "type")
except Exception as e:
# checking if the next ID is a static field in the class/interface continue
if index+1 >= len(self.IDs):
return False # checking if the next ID is a static field in the class/interface
if index+1 >= len(self.IDs):
# if the next field is not a method inovocation return False
# (it could only be a method invocation if self.methodinvoke is true and the next field is the last element in the compID)
if not (self.methodInvoke and index+1 == len(self.IDs)): # if the next field is not a method inovocation
staticFieldName = self.IDs[index+1] # (it could only be a method invocation if self.methodinvoke is true and the next field is the last element in the compID)
typeFieldNode = typeNode.env.getNode(staticFieldName, "fieldDcl") if not (self.methodInvoke and index+1 == len(self.IDs) - 1):
if "static" in typeFieldNode.mods: staticFieldName = self.IDs[index+1]
self.prefixLink = typeFieldNode typeFieldNode = typeNode.env.getNode(staticFieldName, "fieldDcl")
self.prefix = currPrefix + "." + staticFieldName if "static" in typeFieldNode.mods:
self.IDs = self.IDs[index+2:] self.prefixLink = typeFieldNode
return True self.prefix = currPrefix + "." + staticFieldName
return False self.IDs = self.IDs[index+2:]
return True
return False
elif self.methodInvoke and index+1 == len(self.IDs) - 1:
# TODO set the most recent? is this the correct implementation we want?
self.prefixLink = typeNode
self.prefix = currPrefix
self.IDs = self.IDs[index+1:]
return True
return False return False
...@@ -125,7 +137,6 @@ class NameNode(ASTNode): ...@@ -125,7 +137,6 @@ class NameNode(ASTNode):
# (e.g. if there's sth like a.b.c().d, there would be 2 parse tree nodes: methodInvoke(a.b.c) and fieldAccess(d), # (e.g. if there's sth like a.b.c().d, there would be 2 parse tree nodes: methodInvoke(a.b.c) and fieldAccess(d),
# then disambigName is only called on the methodInvoke node) # then disambigName is only called on the methodInvoke node)
def disambigName(self): def disambigName(self):
# Checking if a1 is "this" # Checking if a1 is "this"
if self.checkThis(): if self.checkThis():
return return
...@@ -142,8 +153,37 @@ class NameNode(ASTNode): ...@@ -142,8 +153,37 @@ class NameNode(ASTNode):
# Checking if the shortest prefix is a static field # Checking if the shortest prefix is a static field
if self.checkStatic(): if self.checkStatic():
return return
raise Exception("ERROR at disambiguating namespace: no prefix of name {} is found in environment.".format(self.name)) raise Exception("ERROR at disambiguating namespace: no prefix of name {} is found in environment.".format(self.name))
def checkType(self):
# type checking: go through each prefix and determine what type it is, get that type, and check if that type contains the next access
# eg: a.b.c.d - disambigName would have already determined what the heck the shortest prefix is for this, so take that (let's say it's a.b) then check type c, see if it contains d, then get d return type and add it to self.myType
# if (self.typeName == "Main"):
# print('\nCheck contents of NameNode')
# print('self.typeName ', self.typeName)
# print('self.name ', self.name)
# print('self.IDs ', self.IDs)
# print('self.prefix ', self.prefix)
# print('self.prefixLink ', self.prefixLink)
# print('self.methodInvoke ', self.methodInvoke)
if self.methodInvoke \
or not self.prefixLink \
or (type(self.prefixLink) is str and self.prefixLink == 'contain') \
or not isinstance(self.prefixLink, ASTNode): # this is regarding the localVarNode issue I pointed out above
return
curType = self.prefixLink
if self.IDs: # go through remaining ids
for ID in self.IDs: # curType is a type
curType = curType.env.getNode(ID, 'fieldDcl')
self.myType = curType.fieldType.myType
else: # found the node for the whole call already
# find the return type for the whole thing
if isinstance(self.prefixLink, MemberNodes.FieldNode):
self.myType = self.prefixLink.fieldType.myType
...@@ -59,7 +59,6 @@ def a2Multiple(): ...@@ -59,7 +59,6 @@ def a2Multiple():
total += 1 total += 1
if ret == "": if ret == "":
# print(c)
if 'Je_' in c: if 'Je_' in c:
print(c) print(c)
print("JE Passed without error") print("JE Passed without error")
...@@ -82,7 +81,6 @@ def run(testFiles): ...@@ -82,7 +81,6 @@ def run(testFiles):
parseTrees = [] parseTrees = []
for f in testFiles: for f in testFiles:
# print(f)
if f.split("/")[-1] == ".DS_Store": if f.split("/")[-1] == ".DS_Store":
continue continue
content = open(f, "r").read() content = open(f, "r").read()
...@@ -120,7 +118,6 @@ def run(testFiles): ...@@ -120,7 +118,6 @@ def run(testFiles):
(tree, error) = parse(tokens) (tree, error) = parse(tokens)
except: except:
print("Exception in Parsing") print("Exception in Parsing")
# print(tree)
# Error in Parsing # Error in Parsing
if tree is None: if tree is None:
...@@ -134,15 +131,11 @@ def run(testFiles): ...@@ -134,15 +131,11 @@ def run(testFiles):
parseTrees.append((f, tree)) parseTrees.append((f, tree))
# print("Scan and Parse Succeeded") # for (n, t) in parseTrees:
# print("**********************************************************") # if n == "Tests/A3/J1_accessstaticfield/Main.java":
# print(n)
# print(t)
# try:
# ASTs = astBuild(parseTrees)
# except Exception as e:
# print("ERROR at AST building for file {}".format(f))
# traceback.print_stack()
# return "building AST: " + e.args[0]
ASTs = astBuild(parseTrees) ASTs = astBuild(parseTrees)
# for (n, t) in ASTs: # for (n, t) in ASTs:
...@@ -154,25 +147,13 @@ def run(testFiles): ...@@ -154,25 +147,13 @@ def run(testFiles):
try: try:
buildEnvAndLink(ASTs) buildEnvAndLink(ASTs)
except Exception as e: except Exception as e:
# print(testFiles)
# print("error at environment building and linking")
# print(e)
return "buildEnvAndLink: " + e.args[0] return "buildEnvAndLink: " + e.args[0]
# print("<<<<------- after buildEnvAndLink -------->>>>>>") try:
# for (n, t) in ASTs: disamiguateAndTypeChecking(ASTs)
# print(n) except Exception as e:
# print("--------------------") return "disamiguateAndTypeChecking: " + e.args[0]
# t.printTree()
# print("\n \n\n \n")
# try:
# disamiguateAndTypeChecking(ASTs)
# except Exception as e:
# return "Disambiguate and Type checking: " + e.args[0]
disamiguateAndTypeChecking(ASTs)
# print("Succeeded")
# print("**********************************************************")
return "" return ""
main() main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment