diff --git a/AST.py b/AST.py
index 885000ea05442e6e2712bfd6b9c618da066a1d69..fbb2702a388b4f85e59647e4c5ccf691f38ca527 100644
--- a/AST.py
+++ b/AST.py
@@ -14,6 +14,10 @@ class ASTNode():
         self.children = []
         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
     #   call the same method in each class and its children recursively
     #   the methods that represent an action would return arguments to be used in
@@ -64,6 +68,29 @@ 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()
+
+    # 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):
         pp = pprint.PrettyPrinter(indent=prefix)
         pp.pprint(self.__class__.__name__)
diff --git a/AstBuilding.py b/AstBuilding.py
index 035a8f9c43a2f6db093c7f7adc1c148777b21b1a..5563a7ba29c93890efc6d715949c8bdeeabf3e41 100644
--- a/AstBuilding.py
+++ b/AstBuilding.py
@@ -9,8 +9,6 @@ def astBuild(trees):
         ASTs.append((n, CompNode(t)))
     return ASTs
 
-
-
 def buildEnvAndLink(ASTs):
     # build env
     globalEnv = GlobalEnv()
@@ -51,4 +49,13 @@ def disamiguateAndTypeChecking(ASTs):
     for t in ASTs:
         t[1].checkType()
 
-    # resolving the rest of the name
\ No newline at end of file
+    # resolving the rest of the name
+
+#######################################################
+
+def reachabilityChecking(ASTs):
+    for t in ASTs:
+        t[1].reachCheck()
+
+    # for t in ASTs:
+    #     t[1].staticAnalysis()
diff --git a/ExprPrimaryNodes.py b/ExprPrimaryNodes.py
index c1a0593225ea49303d8242f945afc73efd3d7b81..e6b44162c2c9bee4d2abc90f55de9dfc30708993 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..30058be18c264c95e1c898912f5d4f41fbe3b677 100644
--- a/LineNodes.py
+++ b/LineNodes.py
@@ -164,6 +164,27 @@ class IfNode(ASTNode):
         if self.elseBody:
             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
 # Rules:
 # 1. whileStatement WHILE LPAREN expr RPAREN statement
@@ -189,6 +210,26 @@ 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)
+
+    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
 # Rules:
 # 1. returnStatement RETURN expr SEMICO
@@ -217,6 +258,17 @@ class ReturnNode(ASTNode):
         else:
             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
 # Rules:
 # 1. forStatement FOR LPAREN forInit SEMICO forExpr SEMICO forInit RPAREN statement
@@ -279,3 +331,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/MemberNodes.py b/MemberNodes.py
index 7a0bb3e89844dd4766598e43684404054b52e6e2..cfafa1adfae0220f1dc632fdc6562fa7e0f38576 100644
--- a/MemberNodes.py
+++ b/MemberNodes.py
@@ -169,6 +169,20 @@ class MethodNode(ASTNode):
                 raise Exception("ERROR: return type of function {} doesn't match with return statement.".format(self.name))
         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 ########
 # Input: AST Node
 # Output: A list of names to be check
diff --git a/Test.py b/Test.py
index 0dec390f9fe1fd9dc118dd146583edfd000d44de..a08be2a913508ac004e0297f812f77447c24e606 100644
--- a/Test.py
+++ b/Test.py
@@ -6,7 +6,7 @@ import traceback
 
 from Scanning import scan
 from Parsing import parse
-from AstBuilding import astBuild, buildEnvAndLink, disamiguateAndTypeChecking
+from AstBuilding import astBuild, buildEnvAndLink, disamiguateAndTypeChecking, reachabilityChecking
 import Weeding
 
 
@@ -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()]
 
@@ -48,7 +48,7 @@ def a2Multiple():
 
     for c in testCases:
         # 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:
             # add this one file
@@ -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):
@@ -155,6 +155,11 @@ def run(testFiles):
         disamiguateAndTypeChecking(ASTs)
     except Exception as e:
         return "disamiguateAndTypeChecking: " + e.args[0]
+    
+    try:
+        reachabilityChecking(ASTs)
+    except Exception as e:
+        return "reachabilityChecking: " + e.args[0]
 
     return ""
 
diff --git a/TypeNodes.py b/TypeNodes.py
index 20cd7a5a001fb394f250ce40be429ea9ecf03dbd..87c79ada6845fed783b92c5cf3153bfd5a7635a7 100644
--- a/TypeNodes.py
+++ b/TypeNodes.py
@@ -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))
         return
 
-
 #####################################################################
 # interface
 class InterNode(ClassInterNode):
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):