diff --git a/src/main/java/chocopy/common/analysis/SymbolTable.java b/src/main/java/chocopy/common/analysis/SymbolTable.java
index 930ea9da597d163b60dccee3317d89c7144c773b..41b9ab018d131504960957576c1efc3519770394 100644
--- a/src/main/java/chocopy/common/analysis/SymbolTable.java
+++ b/src/main/java/chocopy/common/analysis/SymbolTable.java
@@ -1,5 +1,7 @@
 package chocopy.common.analysis;
 
+import org.apache.tools.ant.taskdefs.PathConvert;
+
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
@@ -66,4 +68,13 @@ public class SymbolTable<T> {
         return tab.isEmpty();
     }
 
+    public String toString() {
+        String res = "{";
+        for(String k : tab.keySet()) {
+            res += k + "->" + tab.get(k).toString() + ";";
+        }
+        res += "}";
+        return res;
+    }
+
 }
diff --git a/src/main/java/chocopy/pa2/StudentAnalysis.java b/src/main/java/chocopy/pa2/StudentAnalysis.java
index aa5410dca2739ecdc9572922f60b4920e27809d5..b8e6f266ddf97cbdecf3ed4d857543b47da088f9 100644
--- a/src/main/java/chocopy/pa2/StudentAnalysis.java
+++ b/src/main/java/chocopy/pa2/StudentAnalysis.java
@@ -23,12 +23,13 @@ public class StudentAnalysis {
         SymbolTable<SymbolType> globalSym = new SymbolTable<>();
 
         //if (!program.hasErrors()) {
-        TypeChecker typeChecker = new TypeChecker(globalSym, program.errors, true);
-        program.dispatch(typeChecker);
+        // TODO: I should run this part again and again, until symbolTable convergences.
+        TypeChecker symBuilder = new TypeChecker(globalSym, program.errors, true);
+        program.dispatch(symBuilder);
         //}
 
         if(!program.hasErrors()) {
-            TypeChecker next_time = new TypeChecker(typeChecker.getGlobals(), program.errors, false);
+            TypeChecker next_time = new TypeChecker(symBuilder.getGlobals(), program.errors, false);
             program.dispatch(next_time);
         }
 
diff --git a/src/main/java/chocopy/pa2/TypeChecker.java b/src/main/java/chocopy/pa2/TypeChecker.java
index aade9b8862b126f5740a1af9e1781f0258675f36..2b4ea8f58bb6f397168222799375f9f8614d9e70 100644
--- a/src/main/java/chocopy/pa2/TypeChecker.java
+++ b/src/main/java/chocopy/pa2/TypeChecker.java
@@ -67,6 +67,10 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
             if(isFirstRun)
                 sym.put(name, type);
         }
+
+        if(isFirstRun)
+            // firstRun: symbolTable and memberMap is not useable now. STOP dispatching to avoid crash.
+            return null;
         for (Stmt stmt : program.statements) {
             stmt.dispatch(this);
         }
@@ -76,6 +80,10 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
     ///////////////////////////// Def&decl s //////////////////////////////////////
     @Override
     public SymbolType analyze(VarDef varDef) {
+        if(isFirstRun) {
+            // firstRun: symbolTable and memberMap is not useable now. STOP dispatching to avoid crash.
+            return resolveTypeAnnotation(varDef.var.type);
+        }
         SymbolType lType = varDef.value.dispatch(this);
         SymbolType vType = varDef.var.dispatch(this);
         if(!(vType.equals(lType) || lType.equals(NONE_TYPE)))
@@ -87,7 +95,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
     public SymbolType analyze(ClassDef classDef) {
         if(isFirstRun) {
             assert classDef.memberMap == null;
-            classDef.memberMap = new HashMap<>();
+            classDef.memberMap = new HashMap<>(); // clearing may prevent symTable from convergence forever.
         }
         assert classDef.memberMap != null;
 
@@ -95,9 +103,24 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         // TA doesn't like this: // classDef.name.dispatch(this);
         // TA doesn't like this: // classDef.superClass.dispatch(this);
 
+        // Append parent to child if not exist.
+        if(!classDef.superClass.name.equals("object")) {
+            // This logic doesn't allow superClass use-before-decl, unless loop again and again until convergence.
+            ClassValueType superClassType = (ClassValueType) sym.get(classDef.superClass.name);
+            if(superClassType.memberMap != null) {
+                for(String k : superClassType.memberMap.keySet()) {
+                    if(!classDef.memberMap.containsKey(k))
+                        classDef.memberMap.put(k, superClassType.memberMap.get(k));
+                }
+            }
+        }
+
         ClassValueType result_type = new ClassValueType(classDef.name.name);
+        result_type.memberMap = classDef.memberMap;
         SymbolTable<SymbolType> symLayer = new SymbolTable<>(sym);
+        // TODO: Maybe this is not necessary. I'm a cxx programmer.
         symLayer.put("self", result_type);
+        System.out.println("debug: self_type=" + result_type.toString() + ", where symbolMap=" + result_type.memberMap);
         sym = symLayer;
 
         for(Declaration decl : classDef.declarations) {
@@ -106,9 +129,10 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
             if(isFirstRun)
                 classDef.memberMap.put(name, type);
         }
+        System.out.println("debug: self_type=" + result_type.toString() + ", where symbolMap=" + result_type.memberMap);
 
         sym = sym.getParent();
-        return new ClassValueType(classDef.name.name);
+        return result_type;
     }
 
     @Override
@@ -125,7 +149,9 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         List<ValueType> args = new ArrayList<>();
         for(TypedVar param : funcDef.params) {
             String name = param.identifier.name;
-            ValueType type = ValueType.annotationToValueType(param.type);
+            ValueType type = resolveTypeAnnotation(param.type);
+            //if(typeIsUserDefinedClass(type))
+            //    type = (ValueType) sym.get(((ClassValueType) type).className());
             if(isFirstRun)
                 sym.put(name, type);
             args.add(type);
@@ -138,11 +164,14 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
                 sym.put(name, type);
         }
 
-        for(Stmt stmt : funcDef.statements) {
-            stmt.dispatch(this);
+        if(!isFirstRun) {
+            // firstRun: symbolTable and memberMap is not useable now. STOP dispatching to avoid crash.
+            for(Stmt stmt : funcDef.statements) {
+                stmt.dispatch(this);
+            }
         }
 
-        FuncType funcT = new FuncType(args, ValueType.annotationToValueType(funcDef.returnType));
+        FuncType funcT = new FuncType(args, resolveTypeAnnotation(funcDef.returnType));
         if(isFirstRun)
             sym.put(funcDef.name.name, funcT); // this funcdef should be add to both parentSym and localSym to support recursive func.
 
@@ -217,7 +246,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
                 left_type = id.dispatch(this);
             }
             else {
-                err(node, "Not implemented assignStmt");
+                err(node, "Not implemented assignStmt, target=" + target.getClass().getName());
             }
             if(left_type == null) {
                 err(node, "Syntax error: assign to non-declared variable");
@@ -475,7 +504,10 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
             err(node, ". operator left operand is not object type.");
             return NONE_TYPE;
         }
-        SymbolType resultType = objType.memberMap.get(node.member.name); // currently won't work. classDef not analyzed.
+        //System.out.println("manual lookup: memberMap=" + ((ClassValueType)sym.get(objType.toString())).memberMap );
+        System.out.println("debug: isFirstRun=" + isFirstRun + ", memberMap=" + objType.memberMap + ", objtype=" + objType.toString());
+        // Won't work.
+        SymbolType resultType = objType.memberMap.get(node.member.name);
         if(resultType == null) {
             err(node, "undefined identifier " + node.member.name + " as object member.");
             return NONE_TYPE;
@@ -485,11 +517,13 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
 
     @Override
     public SymbolType analyze(MethodCallExpr node) {
-        FuncType funcType = (FuncType) node.method.dispatch(this);
-        if(funcType == null) {
-            err(node, "method is not callable.");
+        SymbolType methodType = node.method.dispatch(this);
+        if(!( methodType instanceof FuncType)) {
+            err(node, "method is not callable or not found.");
             return NONE_TYPE;
         }
+
+        FuncType funcType = (FuncType) methodType;
         List<SymbolType> args_type = new ArrayList<>();
         for(Expr expr : node.args) {
             args_type.add(expr.dispatch(this));
@@ -511,6 +545,12 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         }
         System.out.println("var " + varName + "->" + varType.toString());
 
+        if(varType instanceof ClassValueType) {
+            // TODO: This is just a workaround. I don't know why this line is required.
+            //       Should debug it sometime.
+            varType = fixClassTypeProblem((ValueType) varType);
+        }
+
         if (varType != null) {
             return id.setInferredType(varType);
         }
@@ -521,11 +561,17 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
 
     @Override
     public SymbolType analyze(TypedVar node) {
-        return ValueType.annotationToValueType(node.type);
+        SymbolType result_type = resolveTypeAnnotation(node.type);
+        //if(typeIsUserDefinedClass(result_type))
+        //    result_type = sym.get(((ClassValueType)result_type).className());
+        return result_type;
     }
+
     @Override
     public SymbolType analyze(ClassType node) {
-        return new ClassValueType(node.className);
+        // TODO: verify it.
+        throw new RuntimeException("TODO: not verified.");
+        //return new ClassValueType(node.className);
     }
     @Override
     public SymbolType analyze(ListType node) {
@@ -563,5 +609,33 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
             return l;
         return OBJECT_TYPE;
     }
+    private boolean typeIsUserDefinedClass(SymbolType type) {
+        if(type instanceof ClassValueType) {
+            if(type.equals(INT_TYPE) || type.equals(BOOL_TYPE) || type.equals(STR_TYPE) || type.equals(NONE_TYPE) || type.equals(EMPTY_TYPE) || type.equals(OBJECT_TYPE))
+                return false;
+            if(type.isFuncType() || type.isListType())
+                return false;
+            return true;
+        }
+        else
+            return false;
+    }
+    private ValueType fixClassTypeProblem(ValueType valType) {
+        if(typeIsUserDefinedClass(valType)) {
+            System.out.println("debug: annotation class name resolved." + valType.className());
+            ClassValueType realType = (ClassValueType)sym.get(valType.className());
+            if(realType == null) {
+                System.out.println("FIXME: annotation uses an unknown class type. Unable to assign member map.");
+                return valType;
+            }
+            System.out.println("debug: -m- " + realType.memberMap);
+            return realType;
+        }
+        else
+            return valType;
+    }
+    private ValueType resolveTypeAnnotation(TypeAnnotation annotation) {
+        return fixClassTypeProblem(ValueType.annotationToValueType(annotation));
+    }
 
 }