Skip to content
Snippets Groups Projects
Commit 0602fdeb authored by Xun Yang's avatar Xun Yang
Browse files

calculate constant expr

parent e94f3833
No related branches found
No related tags found
No related merge requests found
...@@ -64,6 +64,11 @@ class ASTNode(): ...@@ -64,6 +64,11 @@ class ASTNode():
if c and hasattr(c, 'checkType'): if c and hasattr(c, 'checkType'):
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): def printNodePretty(self, prefix=0):
pp = pprint.PrettyPrinter(indent=prefix) pp = pprint.PrettyPrinter(indent=prefix)
pp.pprint(self.__class__.__name__) pp.pprint(self.__class__.__name__)
......
...@@ -401,6 +401,59 @@ class ExprNode(ASTNode): ...@@ -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)) 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 # fieldAccess primary PERIOD ID
......
...@@ -189,6 +189,15 @@ class WhileNode(ASTNode): ...@@ -189,6 +189,15 @@ class WhileNode(ASTNode):
raise Exception("ERROR: Cannot use non-boolean type for whileBound.") raise Exception("ERROR: Cannot use non-boolean type for whileBound.")
self.whileBody.checkType() 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 # returnStatement
# Rules: # Rules:
# 1. returnStatement RETURN expr SEMICO # 1. returnStatement RETURN expr SEMICO
...@@ -279,3 +288,10 @@ class ForNode(ASTNode): ...@@ -279,3 +288,10 @@ class ForNode(ASTNode):
raise Exception("ERROR: Cannot use non-boolean type for forBound.") raise Exception("ERROR: Cannot use non-boolean type for forBound.")
self.forUpdate.checkType() self.forUpdate.checkType()
self.bodyStatement.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)
...@@ -38,7 +38,7 @@ def a2Multiple(): ...@@ -38,7 +38,7 @@ def a2Multiple():
testCases = [f for f in sys.argv[1:]] testCases = [f for f in sys.argv[1:]]
else: else:
# All files in the test directory # 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 f.is_dir()]
testCases += [f.path for f in scandir(testDirectory) if not f.is_dir()] testCases += [f.path for f in scandir(testDirectory) if not f.is_dir()]
...@@ -97,7 +97,7 @@ def run(testFiles): ...@@ -97,7 +97,7 @@ def run(testFiles):
print("ERROR in Scanning: " + error) print("ERROR in Scanning: " + error)
print("**********************************************************") print("**********************************************************")
return "ERROR in scanning" return "ERROR in scanning"
# s = "All Tokens: " # s = "All Tokens: "
# for token in tokens: # for token in tokens:
# if (token.name and token.lex): # if (token.name and token.lex):
...@@ -156,6 +156,9 @@ def run(testFiles): ...@@ -156,6 +156,9 @@ def run(testFiles):
except Exception as e: except Exception as e:
return "disamiguateAndTypeChecking: " + e.args[0] return "disamiguateAndTypeChecking: " + e.args[0]
for t in ASTs:
t[1].staticAnalysis()
return "" return ""
main() main()
...@@ -34,12 +34,21 @@ class LiteralNode(ASTNode): ...@@ -34,12 +34,21 @@ class LiteralNode(ASTNode):
self.value = False self.value = False
else: else:
self.value = True self.value = True
def linkType(self): def linkType(self):
if self.name == "java.lang.String": if self.name == "java.lang.String":
node = self.env.getNode(self.name, "type") node = self.env.getNode(self.name, "type")
self.myType = TypeStruct(self.name, node) 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 # param type ID
class ParamNode(ASTNode): class ParamNode(ASTNode):
......
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