From 0602fdebee4de4de4e82f3738365444ae0ebb937 Mon Sep 17 00:00:00 2001 From: Xun Yang <x299yang@uwaterloo.ca> Date: Wed, 11 Mar 2020 01:38:33 -0400 Subject: [PATCH] calculate constant expr --- AST.py | 5 +++++ ExprPrimaryNodes.py | 53 +++++++++++++++++++++++++++++++++++++++++++++ LineNodes.py | 16 ++++++++++++++ Test.py | 7 ++++-- UnitNodes.py | 11 +++++++++- 5 files changed, 89 insertions(+), 3 deletions(-) diff --git a/AST.py b/AST.py index 885000e..5e8ed05 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 c00680a..d22d024 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 89cf118..8a0b2a4 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 0dec390..de43b30 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 5a19d39..c015457 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): -- GitLab