diff --git a/Environment.py b/Environment.py index a0ab6fe2e59fbf07a4fdb883cef6e81ee294f55a..4c542c393e860ce8eb341d3f8c7bb02d99399507 100644 --- a/Environment.py +++ b/Environment.py @@ -111,9 +111,15 @@ class GlobalEnv(Env): # 1. enclosing class/interface # - already did - # 2. single-type import - if name in imported and name in self.map: + # 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) # 3. type in the current package full = packageName + '.' + name # print(full) diff --git a/ExprPrimaryNodes.py b/ExprPrimaryNodes.py index 75f4f10a4c8a08355af02050d939624a62634ef5..6ac4f8372528f858c0cfdbb4327cba537b3acf61 100644 --- a/ExprPrimaryNodes.py +++ b/ExprPrimaryNodes.py @@ -1,6 +1,7 @@ from AST import ASTNode, getParseTreeNodes from Environment import Env -from UnitNodes import TypeNode, LiteralNode +from UnitNodes import LiteralNode +from TheTypeNode import TypeNode # file containing smaller (lower level nodes) in the AST # nodes in this file: diff --git a/LineNodes.py b/LineNodes.py index 5c2b43c53b8b80ecb26348c8384e08dea4a6c396..3bb53480a208fd9e8692a4a06a2d4f65d202f494 100644 --- a/LineNodes.py +++ b/LineNodes.py @@ -1,11 +1,11 @@ from AST import ASTNode, getParseTreeNodes from Environment import Env from ExprPrimaryNodes import makeNodeFromExpr, makeNodeFromAllPrimary, MethodInvNode -from UnitNodes import TypeNode +from TheTypeNode import TypeNode -# Contains: -# block -# for/while/if +# Contains: +# block +# for/while/if # declaration # return statement @@ -77,7 +77,7 @@ class BlockNode(ASTNode): for node in allStatements: self.statements.append(makeNodeFromAllStatement(node)) - + self.children = self.statements def buildEnv(self, parentEnv): @@ -87,7 +87,7 @@ class BlockNode(ASTNode): # variableDcl -# Rules: +# Rules: # 1. variableDcl type ID # 2. variableDcl type ID ASSIGN variableInit class VarDclNode(ASTNode): @@ -105,10 +105,10 @@ class VarDclNode(ASTNode): 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.variableInit) - + def buildEnv(self, parentEnv): env = Env(parentEnv) self.env = env @@ -117,7 +117,7 @@ class VarDclNode(ASTNode): raise Exception("ERROR: Double Local Variable Declaration {}".format(self.name)) else: env.addtoEnv(self) - return self.env + return self.env # ifStatement, ifElseStatement, ifElseStatementNoShortIf # Rules: @@ -130,7 +130,7 @@ class IfNode(ASTNode): self.env = None self.children = [] self.ifConditional = None # the check for the if statement - self.ifBody = None # the body of the if statement + self.ifBody = None # the body of the if statement self.elseBody = None # there are if statements without the else statement self.ifConditional = makeNodeFromExpr(parseTree.children[2]) @@ -141,7 +141,7 @@ class IfNode(ASTNode): self.children.append(self.ifConditional) self.children.append(self.ifBody) self.children.append(self.elseBody) - + # whileStatement, whileStatementNoShortIf # Rules: # 1. whileStatement WHILE LPAREN expr RPAREN statement @@ -169,15 +169,15 @@ class ReturnNode(ASTNode): self.parseTree = parseTree self.env = None self.children = [] - self.expr = None # could be None + self.expr = None # could be None if len(parseTree.children) == 3: self.expr = makeNodeFromExpr(parseTree.children[1]) - + self.children.append(self.expr) # forStatement and forStatementNoShortIf -# Rules: +# Rules: # 1. forStatement FOR LPAREN forInit SEMICO forExpr SEMICO forInit RPAREN statement # 2. forStatementNoShortIf FOR LPAREN forInit SEMICO forExpr SEMICO forInit RPAREN statementNoShortIf class ForNode(ASTNode): @@ -186,7 +186,7 @@ class ForNode(ASTNode): self.forInit = None # could be None self.forBound = None # could be None self.forUpdate = None # could be None - self.bodyStatement = None + self.bodyStatement = None self.env = None self.children = [] @@ -194,7 +194,7 @@ class ForNode(ASTNode): for node in parseTree.children: if node.name == 'forInit': - # Handling case where forInit could derive empty + # Handling case where forInit could derive empty if not node.children: InitFlag = True continue @@ -212,16 +212,16 @@ class ForNode(ASTNode): InitFlag = True else: - self.forUpdate = exprAstNode - + self.forUpdate = exprAstNode + elif node.name == 'forExpr': - # Handling case where forExpr could derive empty + # Handling case where forExpr could derive empty if not node.children: continue - + self.forBound = makeNodeFromExpr(node.children[0]) - + elif node.name == 'statement' or node.name == 'statementNoShortIf': self.bodyStatement = makeNodeFromAllStatement(node) @@ -229,10 +229,3 @@ class ForNode(ASTNode): self.children.append(self.forBound) self.children.append(self.forUpdate) self.children.append(self.bodyStatement) - - - - - - - diff --git a/MemberNodes.py b/MemberNodes.py index b80514189e450cccb109ed5bce496a9d4e7b1f09..0b07d9eb7bcaca246e678c79ee425ed2009dd41c 100644 --- a/MemberNodes.py +++ b/MemberNodes.py @@ -1,7 +1,8 @@ from AST import ASTNode, getParseTreeNodes from LineNodes import BlockNode, VarDclNode from ExprPrimaryNodes import makeNodeFromExpr -from UnitNodes import TypeNode, ParamNode +from UnitNodes import ParamNode +from TheTypeNode import TypeNode from Environment import Env from collections import OrderedDict @@ -82,7 +83,16 @@ class MethodNode(ASTNode): if self.body: self.children.append(self.body) def __eq__(self, other): - return self.name == other.name and self.paramTypes == other.paramTypes + if self.name == other.name and len(self.params) == len(other.params): + for i in range(len(self.params)): + if not self.params[i].paramType == other.params[i].paramType: + if self.name == 'addAll': + raise Exception('HERE {}, {}'.format(self.params[i].paramType.name, other.params[i].paramType.name)) + return False + return True + if self.name == 'addAll': + raise Exception('THERE') + return False def buildEnv(self, parentEnv): env = Env(parentEnv) diff --git a/TheTypeNode.py b/TheTypeNode.py new file mode 100644 index 0000000000000000000000000000000000000000..0752c341b632cbad627958594c3b068ee9f2f51e --- /dev/null +++ b/TheTypeNode.py @@ -0,0 +1,53 @@ +from AST import ASTNode, getParseTreeNodes +################################################################################## +# type: primitiveType, ArrayType, RefType +class TypeNode(ASTNode): + # always list all fields in the init method to show the class structure + def __init__(self, parseTree): + self.parseTree = parseTree + self.name = '' + self.isArray = False + self.isPrimitive = False + self.env = None + self.children = [] + self.myType = None # pointer pointing to the type + + if parseTree == 'VOID': + self.name = 'void' + self.isPrimitive = True + else: + nameNodes = getParseTreeNodes(['BOOLEAN', 'BYTE', 'CHAR', 'INT', 'SHORT'], parseTree) + if nameNodes: + self.isPrimitive = True + self.name = nameNodes[0].lex + else: + self.name = getParseTreeNodes(['ID', 'COMPID'], parseTree)[0].lex + + nameNodes = getParseTreeNodes(['LSQRBRACK'], parseTree) + if nameNodes: + self.isArray = True + + def __eq__(self, other): + return self.name == other.name + + def linkType(self): + if not self.isPrimitive: + self.myType = self.env.getNode(self.name, 'type') + self.name = self.myType.canonName # Use canonName instead of simple name for comparison + else: + self.myType = self.name + + def isNum(self): + return self.name in ['int', 'short', 'char', 'byte'] + + # if self is assignable to input typeNode: left := self + def assignable(self, left): + if self == left \ + or (self.name in ['short', 'char', 'byte'] and left.name == 'int') \ + or (self.name == 'byte' and left.name == 'short') \ + or (not left.isPrimitive and self.name == 'null'): + return True + return False + + + # is java.Object added to super class of everything/ diff --git a/TypeNodes.py b/TypeNodes.py index 18bf449e7477cadfa78e6298df59820676fb1635..4238daba4a82e2355719dce38eeacfd905cbe405 100644 --- a/TypeNodes.py +++ b/TypeNodes.py @@ -32,6 +32,8 @@ class ClassInterNode(ASTNode): def getContains(self, hierarchy): # check if not acyclic canonName = self.packageName + '.' + self.name + self.canonName = canonName + if canonName in hierarchy: raise Exception("ERROR: The hierarchy is not acyclic '{}', saw '{}'".format(hierarchy, canonName)) @@ -75,6 +77,7 @@ class ClassNode(ClassInterNode): self.superInter = [] # class/Interface's name, then stores a pointer to the class after type linking self.env = None self.children = [] + self.canonName = "" for node in parseTree.children: if node.name == 'classMod': @@ -170,6 +173,7 @@ class ClassNode(ClassInterNode): # centralized logic contains = super().getContains(hierarchy) canonName = self.packageName + '.' + self.name + self.canonName = canonName # get contains from extends class if self.superClass: @@ -218,6 +222,7 @@ class InterNode(ClassInterNode): self.superInter = [] # list of strings of extendInterface's name, then stores a pointer to the node after type linking self.env = None self.children = [] + self.canonName = "" for node in parseTree.children: if node.name == 'ID': @@ -270,6 +275,7 @@ class InterNode(ClassInterNode): # centralized logic contains = super().getContains(hierarchy) canonName = self.packageName + '.' + self.name + self.canonName = canonName # an interface without any super interfaces implicitly declares an abstract version of every public method in java.lang.Object if not self.superInter: diff --git a/UnitNodes.py b/UnitNodes.py index 108dc37d780411113f39c2c8d16a7c7cdc342771..eeddabe333001a3c508789befba0f8d30b795031 100644 --- a/UnitNodes.py +++ b/UnitNodes.py @@ -1,9 +1,9 @@ from AST import ASTNode, getParseTreeNodes from Environment import Env +from TheTypeNode import TypeNode # LiteralNode # ParamNode -# TypeNode # maybe add a nameNode? ################################################################################# @@ -43,33 +43,3 @@ class ParamNode(ASTNode): self.name = parseTree.children[1].lex self.env = None self.children = [self.paramType] - -################################################################################## -# type: primitiveType, ArrayType, RefType -class TypeNode(ASTNode): - # always list all fields in the init method to show the class structure - def __init__(self, parseTree): - self.parseTree = parseTree - self.name = '' - self.isArray = False - self.isPrimitive = False - self.env = None - self.children = [] - - if parseTree == 'VOID': - self.name = 'void' - self.isPrimitive = True - else: - nameNodes = getParseTreeNodes(['BOOLEAN', 'BYTE', 'CHAR', 'INT', 'SHORT'], parseTree) - if nameNodes: - self.isPrimType = True - self.name = nameNodes[0].lex - else: - self.name = getParseTreeNodes(['ID', 'COMPID'], parseTree)[0].lex - - nameNodes = getParseTreeNodes(['LSQRBRACK'], parseTree) - if nameNodes: - self.isArray = True - - def __eq__(self, other): - return self.name == other.name \ No newline at end of file