diff --git a/src/main/java/chocopy/pa2/TypeChecker.java b/src/main/java/chocopy/pa2/TypeChecker.java
index 75e7c2ff6dfced6fa173b46419f29844987a4f69..ff5519c2f0d6111d691d70b279526d8df76aa048 100644
--- a/src/main/java/chocopy/pa2/TypeChecker.java
+++ b/src/main/java/chocopy/pa2/TypeChecker.java
@@ -42,7 +42,8 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
      *  The message is constructed with MESSAGE and ARGS as for
      *  String.format. */
     private void err(Node node, String message, Object... args) {
-        errors.semError(node, message, args);
+        if(!isFirstRun)
+            errors.semError(node, message, args);
     }
 
     ///////////////////////////// Program //////////////////////////////////////
@@ -138,11 +139,17 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
             stmt.dispatch(this);
         }
 
+        FuncType funcT = new FuncType(args, ValueType.annotationToValueType(funcDef.returnType));
+        if(isFirstRun)
+            sym.put(funcDef.name.name, funcT); // this funcdef should be add to both parentSym and localSym to support recursive func.
+
+        // TA don't like it. OK I won't dispatch this id...
+        //funcDef.name.dispatch(this); // dispatch it.
+
         // function scope ends.. backtracking...
         sym = sym.getParent();
         if(sym == null)
             throw new RuntimeException("logic error: sym parent is null while returning..");
-        FuncType funcT = new FuncType(args, ValueType.annotationToValueType(funcDef.returnType));
         return funcT;
     }
 
@@ -357,7 +364,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
 
     @Override
     public SymbolType analyze(CallExpr node) {
-        SymbolType funcType = sym.get(node.function.name);
+        SymbolType funcType = node.function.dispatch(this);
         if(funcType == null) {
             err(node, "calling undeclared function " + node.function.name);
             return null;
@@ -366,7 +373,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
             err(node, "calling non-function variable " + node.function.name);
             return null;
         }
-        FuncType fType = (FuncType)funcType;
+        FuncType fType = (FuncType) funcType;
         List<SymbolType> args_type = new ArrayList<SymbolType>();
         for(Expr arg : node.args) {
             args_type.add(arg.dispatch(this));
@@ -374,7 +381,6 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         if(!fType.parameters.equals(args_type)) {
             err(node, "function parameter type list mismatch: " + node.function.name + ". Expected " + fType.parameters.toString() + ", got " + args_type.toString());
         }
-        System.out.println("debug: callexpr set type = " + fType.returnType.toString());
         return node.setInferredType(fType.returnType);
     }
 
@@ -493,7 +499,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         }
         System.out.println("var " + varName + "->" + varType.toString());
 
-        if (varType != null && varType.isValueType()) {
+        if (varType != null) {
             return id.setInferredType(varType);
         }