diff --git a/src/main/java/chocopy/common/analysis/types/SymbolType.java b/src/main/java/chocopy/common/analysis/types/SymbolType.java
index 8b5b0e115acb28d20b0677caa9186c66222cb3bc..64ccbe72b75194b7d44b2d85deb03765a4299a69 100644
--- a/src/main/java/chocopy/common/analysis/types/SymbolType.java
+++ b/src/main/java/chocopy/common/analysis/types/SymbolType.java
@@ -55,6 +55,8 @@ public abstract class SymbolType {
 
     @JsonIgnore
     public boolean isListType() {
+        if(this == EMPTY_TYPE)
+            return true;
         return false;
     }
 
diff --git a/src/main/java/chocopy/pa2/TypeChecker.java b/src/main/java/chocopy/pa2/TypeChecker.java
index 5703e38c55cbe9a08d2b86600f7042351c175556..3343d51b77ff0e82a24de97b5beccfc447eec169 100644
--- a/src/main/java/chocopy/pa2/TypeChecker.java
+++ b/src/main/java/chocopy/pa2/TypeChecker.java
@@ -38,6 +38,30 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         errors.semError(node, message, args);
     }
 
+    ///////////////////////////// Program //////////////////////////////////////
+    @Override
+    public SymbolType analyze(Program program) {
+        for (Declaration decl : program.declarations) {
+            String name = decl.getIdentifier().name;
+
+            SymbolType type = decl.dispatch(this);
+            System.out.println("decl type " + type.toString());
+
+            // recolic: what's the teacher willing to do???
+            if (type == null) {
+                continue;
+            }
+
+            // TODO: DO NOT throw on duplicate id. generate a compiler error.
+            sym.put(name, type);
+        }
+        for (Stmt stmt : program.statements) {
+            stmt.dispatch(this);
+        }
+        return null;
+    }
+
+    ///////////////////////////// Def&decl s //////////////////////////////////////
     @Override
     public SymbolType analyze(VarDef varDef) {
         SymbolType lType = varDef.value.dispatch(this);
@@ -53,6 +77,10 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         classDef.memberMap = new HashMap<>();
         assert classDef.memberMap != null;
 
+        // My-name already pushed to symbolMap
+        classDef.name.dispatch(this);
+        classDef.superClass.dispatch(this);
+
         ClassValueType result_type = new ClassValueType(classDef.name.name);
         SymbolTable<SymbolType> symLayer = new SymbolTable<>(sym);
         symLayer.put("self", result_type);
@@ -121,42 +149,9 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         return T;
     }
 
-    // Just a helper..
-    @Override
-    public SymbolType analyze(TypedVar node) {
-        return ValueType.annotationToValueType(node.type);
-    }
-
     ///////// end
 
-    @Override
-    public SymbolType analyze(Program program) {
-        for (Declaration decl : program.declarations) {
-            String name = decl.getIdentifier().name;
-
-            SymbolType type = decl.dispatch(this);
-            System.out.println("decl type " + type.toString());
-
-            // recolic: what's the teacher willing to do???
-            if (type == null) {
-                continue;
-            }
-
-            // TODO: DO NOT throw on duplicate id. generate a compiler error.
-            sym.put(name, type);
-        }
-        for (Stmt stmt : program.statements) {
-            stmt.dispatch(this);
-        }
-        return null;
-    }
-
-    @Override
-    public SymbolType analyze(ExprStmt s) {
-        s.expr.dispatch(this);
-        return null;
-    }
-
+    ///////////////////////////// Literals //////////////////////////////////////
     @Override
     public SymbolType analyze(IntegerLiteral node) {
         return node.setInferredType(INT_TYPE);
@@ -174,6 +169,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         return node.setInferredType(BOOL_TYPE);
     }
 
+    ///////////////////////////// Statements //////////////////////////////////////
     @Override
     public SymbolType analyze(AssignStmt node) {
         SymbolType right_type = node.value.dispatch(this);
@@ -201,9 +197,64 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
                 err(node, "Syntax error: implicit type convertion failed.");
             }
         }
-        return left_type;
+        //return left_type;
+        return null; // silly ta is not willing to use `a = (b = c) => a = something` reduction. It's ugly and buggy and complex but let him go.
+    }
+
+    @Override
+    public SymbolType analyze(ForStmt node) {
+        SymbolType iterType = node.iterable.dispatch(this);
+        if(!(iterType.isListType() || iterType.equals(STR_TYPE))) {
+            err(node, "for target is not iterable.");
+        }
+        SymbolType ident = node.identifier.dispatch(this);
+
+        for(Stmt stmt : node.body) {
+            stmt.dispatch(this);
+        }
+        return null;
+    }
+
+    @Override
+    public SymbolType analyze(IfStmt node) {
+        SymbolType conditionType = node.condition.dispatch(this);
+        if(!conditionType.equals(BOOL_TYPE)) {
+            err(node, "if statement condition should be BOOL");
+        }
+        for(Stmt stmt : node.thenBody) {
+            stmt.dispatch(this);
+        }
+        for(Stmt stmt : node.elseBody) {
+            stmt.dispatch(this);
+        }
+        return null;
+    }
+
+    @Override
+    public SymbolType analyze(ExprStmt node) {
+        node.expr.dispatch(this);
+        return null;
+    }
+
+    @Override
+    public SymbolType analyze(ReturnStmt node) {
+        node.value.dispatch(this);
+        return null;
+    }
+
+    @Override
+    public SymbolType analyze(WhileStmt node) {
+        SymbolType conditionType = node.condition.dispatch(this);
+        if(!conditionType.equals(BOOL_TYPE)) {
+            err(node, "while statement condition should be BOOL");
+        }
+        for(Stmt stmt : node.body) {
+            stmt.dispatch(this);
+        }
+        return null;
     }
 
+    ///////////////////////////// Expressions //////////////////////////////////////
     @Override
     public SymbolType analyze(BinaryExpr node) {
         String op = node.operator;
@@ -410,6 +461,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         return funcType.returnType;
     }
 
+    ///////////////////////////// Others //////////////////////////////////////
     @Override
     public SymbolType analyze(Identifier id) {
         String varName = id.name;
@@ -424,6 +476,20 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         return id.setInferredType(ValueType.OBJECT_TYPE);
     }
 
+    @Override
+    public SymbolType analyze(TypedVar node) {
+        return ValueType.annotationToValueType(node.type);
+    }
+    @Override
+    public SymbolType analyze(ClassType node) {
+        return new ClassValueType(node.className);
+    }
+    @Override
+    public SymbolType analyze(ListType node) {
+        SymbolType elementType = node.elementType.dispatch(this);
+        return new ListValueType(elementType);
+    }
+
     private boolean typeConvertible(SymbolType from, SymbolType to) {
         if(from == null || to == null)
             throw new RuntimeException("debug: SymbolType can not be null");
@@ -454,4 +520,5 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
             return l;
         return OBJECT_TYPE;
     }
+
 }