Skip to content
Snippets Groups Projects
Commit 101e58b8 authored by Nicholas Robinson's avatar Nicholas Robinson
Browse files

reachability basics

- change Test.py to run reachabilityChecking
- basic ASTNode reachCheck
- implemented reachability in: MethodNode, IfNode, WhileNode, ReturnNode
- tiny bit of cleanup (whitespace)
parent 0602fdeb
No related branches found
No related tags found
No related merge requests found
...@@ -14,6 +14,10 @@ class ASTNode(): ...@@ -14,6 +14,10 @@ class ASTNode():
self.children = [] self.children = []
self.myType = "" # either empty string or a TypeStruct self.myType = "" # either empty string or a TypeStruct
# reachability: None = not set, True = maybe, False = no
self.inMaybe = None # either None or True/False
self.outMaybe = None # either None or True/False
# Do certains actions on every node of the AST tree # Do certains actions on every node of the AST tree
# call the same method in each class and its children recursively # call the same method in each class and its children recursively
# the methods that represent an action would return arguments to be used in # the methods that represent an action would return arguments to be used in
...@@ -69,6 +73,24 @@ class ASTNode(): ...@@ -69,6 +73,24 @@ class ASTNode():
if c and hasattr(c, 'staticAnalysis'): if c and hasattr(c, 'staticAnalysis'):
c.staticAnalysis() c.staticAnalysis()
# return outMaybe
def reachCheck(self, inMaybe = True):
if inMaybe == False:
# error if in[s] = no for any s
# I don't think it should get to here... but maybe?
raise Exception("in[s] = no for a certain {}".format(type(self)))
self.inMaybe = inMaybe
self.outMaybe = self.inMaybe
lastOut = self.inMaybe
for c in self.children:
if c and hasattr(c, 'reachCheck'):
lastOut = c.reachCheck(lastOut)
self.outMaybe = self.outMaybe and lastOut
return self.outMaybe
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__)
......
...@@ -9,8 +9,6 @@ def astBuild(trees): ...@@ -9,8 +9,6 @@ def astBuild(trees):
ASTs.append((n, CompNode(t))) ASTs.append((n, CompNode(t)))
return ASTs return ASTs
def buildEnvAndLink(ASTs): def buildEnvAndLink(ASTs):
# build env # build env
globalEnv = GlobalEnv() globalEnv = GlobalEnv()
...@@ -51,4 +49,13 @@ def disamiguateAndTypeChecking(ASTs): ...@@ -51,4 +49,13 @@ def disamiguateAndTypeChecking(ASTs):
for t in ASTs: for t in ASTs:
t[1].checkType() t[1].checkType()
# resolving the rest of the name # resolving the rest of the name
\ No newline at end of file
#######################################################
def reachabilityChecking(ASTs):
for t in ASTs:
t[1].reachCheck()
# for t in ASTs:
# t[1].staticAnalysis()
...@@ -164,6 +164,27 @@ class IfNode(ASTNode): ...@@ -164,6 +164,27 @@ class IfNode(ASTNode):
if self.elseBody: if self.elseBody:
self.elseBody.checkType() self.elseBody.checkType()
def reachCheck(self, inMaybe = True):
if inMaybe == False:
# error if in[s] = no for any s
raise Exception("in[s] = no for IfNode in class {}".format(self.typeName))
self.inMaybe = inMaybe
s1 = self.ifBody.reachCheck(self.inMaybe)
if not self.elseBody:
# L : if (E) S
# in[S] = in[L]
# out[L] = in[L]
self.outMaybe = self.inMaybe
else:
# L : if (E) S1 else S2
# in[S1] = in[L]
# in[S2] = in[L]
# out[L] = out[S1] V out[S2]
s2 = self.elseBody.reachCheck(self.inMaybe)
self.outMaybe = s1 or s2
return self.outMaybe
# whileStatement, whileStatementNoShortIf # whileStatement, whileStatementNoShortIf
# Rules: # Rules:
# 1. whileStatement WHILE LPAREN expr RPAREN statement # 1. whileStatement WHILE LPAREN expr RPAREN statement
...@@ -197,6 +218,17 @@ class WhileNode(ASTNode): ...@@ -197,6 +218,17 @@ class WhileNode(ASTNode):
if con != None: if con != None:
print(con, self.whileBound.typeName) print(con, self.whileBound.typeName)
def reachCheck(self, inMaybe = True):
if inMaybe == False:
# error if in[s] = no for any s
raise Exception("in[s] = no for WhileNode in class {}".format(self.typeName))
# L : while (E) S
# in[S] = in[L]
# out[L] = in[L]
self.inMaybe = inMaybe
self.whileBound.reachCheck(self.inMaybe)
self.outMaybe = self.inMaybe
# returnStatement # returnStatement
# Rules: # Rules:
...@@ -226,6 +258,17 @@ class ReturnNode(ASTNode): ...@@ -226,6 +258,17 @@ class ReturnNode(ASTNode):
else: else:
self.myType = None # this is None as returning a value of type Void is invalid even in a function with type Void self.myType = None # this is None as returning a value of type Void is invalid even in a function with type Void
def reachCheck(self, inMaybe = True):
if inMaybe == False:
# error if in[s] = no for any s
raise Exception("in[s] = no for ReturnNode in class {}".format(self.typeName))
# L : return, L : return E
# out[L] = no
self.inMaybe = inMaybe
self.outMaybe = False
return self.outMaybe
# forStatement and forStatementNoShortIf # forStatement and forStatementNoShortIf
# Rules: # Rules:
# 1. forStatement FOR LPAREN forInit SEMICO forExpr SEMICO forInit RPAREN statement # 1. forStatement FOR LPAREN forInit SEMICO forExpr SEMICO forInit RPAREN statement
......
...@@ -169,6 +169,20 @@ class MethodNode(ASTNode): ...@@ -169,6 +169,20 @@ class MethodNode(ASTNode):
raise Exception("ERROR: return type of function {} doesn't match with return statement.".format(self.name)) raise Exception("ERROR: return type of function {} doesn't match with return statement.".format(self.name))
return return
def reachCheck(self, inMaybe = True):
# self.inMaybe is always true for methods
self.inMaybe = True
self.outMaybe = False
if self.body:
self.outMaybe = self.body.reachCheck()
# error if out[(non-void) method body] = maybe
# self.methodType is an empty string if it's a constructor
if type(self.methodType) != str and self.methodType.myType.name != "void" and self.outMaybe == True:
raise Exception("Non-void method '{}' in class '{}' does not return".format(self.name, self.typeName))
return self.outMaybe
############# helper for forward ref checking ######## ############# helper for forward ref checking ########
# Input: AST Node # Input: AST Node
# Output: A list of names to be check # Output: A list of names to be check
......
...@@ -6,7 +6,7 @@ import traceback ...@@ -6,7 +6,7 @@ import traceback
from Scanning import scan from Scanning import scan
from Parsing import parse from Parsing import parse
from AstBuilding import astBuild, buildEnvAndLink, disamiguateAndTypeChecking from AstBuilding import astBuild, buildEnvAndLink, disamiguateAndTypeChecking, reachabilityChecking
import Weeding import Weeding
...@@ -48,7 +48,7 @@ def a2Multiple(): ...@@ -48,7 +48,7 @@ def a2Multiple():
for c in testCases: for c in testCases:
# get all files from stdlib folder # get all files from stdlib folder
testFiles = [join(dp, f) for dp, dn, filenames in walk('stdlib/3.0/java/') for f in filenames] testFiles = [join(dp, f) for dp, dn, filenames in walk('stdlib/4.0/java/') for f in filenames]
if '.java' in c: if '.java' in c:
# add this one file # add this one file
...@@ -155,9 +155,11 @@ def run(testFiles): ...@@ -155,9 +155,11 @@ def run(testFiles):
disamiguateAndTypeChecking(ASTs) disamiguateAndTypeChecking(ASTs)
except Exception as e: except Exception as e:
return "disamiguateAndTypeChecking: " + e.args[0] return "disamiguateAndTypeChecking: " + e.args[0]
for t in ASTs: try:
t[1].staticAnalysis() reachabilityChecking(ASTs)
except Exception as e:
return "reachabilityChecking: " + e.args[0]
return "" return ""
......
...@@ -261,7 +261,6 @@ class ClassNode(ClassInterNode): ...@@ -261,7 +261,6 @@ class ClassNode(ClassInterNode):
raise Exception("ERROR: Constructor {0} doesn't have the same name as class {1}".format(constructor.name, self.name)) raise Exception("ERROR: Constructor {0} doesn't have the same name as class {1}".format(constructor.name, self.name))
return return
##################################################################### #####################################################################
# interface # interface
class InterNode(ClassInterNode): class InterNode(ClassInterNode):
......
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