diff --git a/AST.py b/AST.py index 885000ea05442e6e2712bfd6b9c618da066a1d69..5e8ed05642564b504b0314aba83d6a9d77a09035 100644 --- a/AST.py +++ b/AST.py @@ -64,6 +64,11 @@ class ASTNode(): if c and hasattr(c, 'checkType'): c.checkType() + def staticAnalysis(self): + for c in self.children: + if c and hasattr(c, 'staticAnalysis'): + c.staticAnalysis() + def printNodePretty(self, prefix=0): pp = pprint.PrettyPrinter(indent=prefix) pp.pprint(self.__class__.__name__) diff --git a/ExprPrimaryNodes.py b/ExprPrimaryNodes.py index c00680a400a63fb5dc50ce22225387f5234cc632..d22d024aa85b59200bf4b3d3082c5cc99b71b56d 100644 --- a/ExprPrimaryNodes.py +++ b/ExprPrimaryNodes.py @@ -401,6 +401,59 @@ class ExprNode(ASTNode): raise Exception("ERROR: Incompatible types. Left of {} type can't be used with right of {} type on operation {}".format(self.left.myType.name, self.right.myType.name, self.op)) + # returns True, False, Int or None (for non-constant expr) + # children of exprNode is either exprNode or literalNode + def getConstant(self): + if not hasattr(self.right, "getConstant"): + return None + cRight = self.right.getConstant() + if cRight == None: + return None + + # Unary Ops + if not self.left: + if self.op == '-': + return -cRight + return not cRight # op = '!' + + else: + if not hasattr(self.left, "getConstant"): + return None + cLeft = self.left.getConstant() + if cLeft == None: + return None + + # arithmetic + if self.op == '+': + return cLeft + cRight + elif self.op == '-': + return cLeft - cRight + elif self.op == '*': + return cLeft * cRight + elif self.op == '/': + return cLeft // cRight + elif self.op == '%': + return cLeft % cRight + # Comparison + elif self.op == '==': + return cLeft == cRight + elif self.op == '!=': + return cLeft != cRight + elif self.op == '>': + return cLeft > cRight + elif self.op == '<': + return cLeft < cRight + elif self.op == '>=': + return cLeft >= cRight + elif self.op == '<=': + return cLeft <= cRight + # boolean Ops + elif self.op == '&&' or self.op == '&': + return cLeft and cRight + elif self.op == '||' or self.op == '|': + return cLeft or cRight + else: + return None ################################################################################### # fieldAccess primary PERIOD ID diff --git a/LineNodes.py b/LineNodes.py index 89cf11878b4004a351f427c9c23a48180e853d14..8a0b2a4c75ed66eb373317a4f8e5b296bd0e194d 100644 --- a/LineNodes.py +++ b/LineNodes.py @@ -189,6 +189,15 @@ class WhileNode(ASTNode): raise Exception("ERROR: Cannot use non-boolean type for whileBound.") self.whileBody.checkType() + def staticAnalysis(self): + # check constant expr + if hasattr(self.whileBound, "getConstant"): + con = self.whileBound.getConstant() + + if con != None: + print(con, self.whileBound.typeName) + + # returnStatement # Rules: # 1. returnStatement RETURN expr SEMICO @@ -279,3 +288,10 @@ class ForNode(ASTNode): raise Exception("ERROR: Cannot use non-boolean type for forBound.") self.forUpdate.checkType() self.bodyStatement.checkType() + + def staticAnalysis(self): + # check constant expr + if hasattr(self.forBound, "getConstant"): + con = self.forBound.getConstant() + if con != None: + print(con, self.whileBound.typeNam) diff --git a/Test.py b/Test.py index 0dec390f9fe1fd9dc118dd146583edfd000d44de..de43b308f5f1a469ed63812f7909cf2da7faf41c 100644 --- a/Test.py +++ b/Test.py @@ -38,7 +38,7 @@ def a2Multiple(): testCases = [f for f in sys.argv[1:]] else: # All files in the test directory - testDirectory = "./Tests/A3/" + testDirectory = "./Tests/A4/" testCases = [f.path for f in scandir(testDirectory) if f.is_dir()] testCases += [f.path for f in scandir(testDirectory) if not f.is_dir()] @@ -97,7 +97,7 @@ def run(testFiles): print("ERROR in Scanning: " + error) print("**********************************************************") return "ERROR in scanning" - + # s = "All Tokens: " # for token in tokens: # if (token.name and token.lex): @@ -156,6 +156,9 @@ def run(testFiles): except Exception as e: return "disamiguateAndTypeChecking: " + e.args[0] + for t in ASTs: + t[1].staticAnalysis() + return "" main() diff --git a/UnitNodes.py b/UnitNodes.py index 5a19d39828f153a77abe244e9a5ebb27a83f5a5a..c015457cf708cb5c1ba913c8b155b400d57db5af 100644 --- a/UnitNodes.py +++ b/UnitNodes.py @@ -34,12 +34,21 @@ class LiteralNode(ASTNode): self.value = False else: self.value = True - + def linkType(self): if self.name == "java.lang.String": node = self.env.getNode(self.name, "type") self.myType = TypeStruct(self.name, node) + def getConstant(self): + if self.name == 'int': + return int(self.value) + elif self.name == 'boolean': + if self.value == 'true': + return True + return False + return self.value + ################################################################################## # param type ID class ParamNode(ASTNode):