diff --git a/AST.py b/AST.py index 45489ad9d141677117ea8bd91094c31ed8b24aca..32e405a9fab05d0b83d826918ba919ef04711b7f 100644 --- a/AST.py +++ b/AST.py @@ -11,6 +11,7 @@ class ASTNode(): # but we will keep it for easier debugging, since effeciency is not a concern here def __init__(self, parseTree): self.parseTree = parseTree + self.children = [] # Do certains actions on every node of the AST tree # call the same method in each class and its children recursively @@ -27,6 +28,21 @@ class ASTNode(): if hasattr(c, 'recurseAction'): c.recurseAction(actionName, result) + # This is a function to recursively build environment + # Modified from the function recurseAction above, to handle the proper linking of local variable environments + def recurseBuildEnv(self, parentEnv): + result = self.buildEnv(parentEnv) + preVarDcl = None + for c in self.children: + if c and hasattr(c, 'recurseBuildEnv'): + if preVarDcl: + c.recurseBuildEnv(preVarDcl.env) + else: + c.recurseBuildEnv(result) + if c.__class__.__name__ == 'VarDclNode': + preVarDcl = c + + def buildEnv(self, parentEnv): self.env = parentEnv return parentEnv diff --git a/AstBuilding.py b/AstBuilding.py index e4c74cd012bc694e71e963f9ece80deacdb7c1e3..032b03e8871e4925c835c5faf0cd0c48be9d03ab 100644 --- a/AstBuilding.py +++ b/AstBuilding.py @@ -9,6 +9,8 @@ def astBuild(trees): ASTs.append((n, CompNode(t))) return ASTs + + def buildEnvAndLink(ASTs): # build env globalEnv = GlobalEnv() @@ -19,10 +21,13 @@ def buildEnvAndLink(ASTs): pprint(vars(globalEnv)) for t in ASTs: - t[1].recurseAction("buildEnv", globalEnv) + try: + t[1].recurseBuildEnv(globalEnv) + except Exception as e: # to handle double local variable declaration print('\n\n\n', t[0]) print("###################### Comp Unit Env ####################") t[1].recurseAction("printEnv") + # type Linking print('--------->>> type linking time!') diff --git a/Environment.py b/Environment.py index 4db58767685e4383ee2d401c3b43ddd637c14efc..eab2c5d9d3de3556a12476d57c57737906a0b93e 100644 --- a/Environment.py +++ b/Environment.py @@ -2,10 +2,12 @@ import string class Env: nodeToNamespace = dict({ - 'FieldNode': 'expr', + 'FieldNode': 'fieldDcl', 'InterNode': 'type', 'ClassNode': 'type', - 'MethodNode': 'method' + 'MethodNode': 'method', + 'VarDclNode': 'expr' + }) def __init__(self, parentEnv): @@ -49,6 +51,16 @@ class Env: return self.parentEnv.getNode(name, namespace) raise Exception("ERROR: Can't find definition of {} in the Environment".format(name)) + # A wrapper around getNode to find if node exists in environment already + def findNode(self, name, namespace): + try: + self.getNode(name, namespace) + except: + return False # node is not found in environment + + return True + + ################################### class GlobalEnv(Env): diff --git a/LineNodes.py b/LineNodes.py index e0a992c6e3bbea9dcdfaa5b84dc58a7da82790e3..5c2b43c53b8b80ecb26348c8384e08dea4a6c396 100644 --- a/LineNodes.py +++ b/LineNodes.py @@ -80,12 +80,12 @@ class BlockNode(ASTNode): self.children = self.statements - # def buildEnv(self, parentEnv): + def buildEnv(self, parentEnv): + env = Env(parentEnv) + self.env = env + return self.env - - - # variableDcl # Rules: # 1. variableDcl type ID @@ -94,23 +94,30 @@ class VarDclNode(ASTNode): def __init__(self, parseTree): self.parseTree = parseTree self.dclType = None - self.varName = None + self.name = None # variable name self.variableInit = None # could be none if not intialized self.env = None self.children = [] self.dclType = TypeNode(parseTree.children[0]) - self.varName = parseTree.children[1].lex + self.name = parseTree.children[1].lex if len(parseTree.children) > 2: # Handling rule: variableInit expr self.variableInit = makeNodeFromExpr(parseTree.children[3].children[0]) self.children.append(self.dclType) - self.children.append(self.varName) self.children.append(self.variableInit) - - + + def buildEnv(self, parentEnv): + env = Env(parentEnv) + self.env = env + # check if the node already exists in environment + if parentEnv.findNode(self.name, 'expr'): + raise Exception("ERROR: Double Local Variable Declaration {}".format(self.name)) + else: + env.addtoEnv(self) + return self.env # ifStatement, ifElseStatement, ifElseStatementNoShortIf # Rules: @@ -145,7 +152,7 @@ class WhileNode(ASTNode): self.env = None self.children = [] self.whileBound = None - self.whileBody = None + self.whileBody = None self.whileBound = makeNodeFromExpr(parseTree.children[2]) self.whileBody = makeNodeFromAllStatement(parseTree.children[4])