diff --git a/src/main/java/chocopy/common/astnodes/FuncDef.java b/src/main/java/chocopy/common/astnodes/FuncDef.java
index 8913791e3889754bad12dca6a6bf4465b08bcc4f..45c69a05b2733eba85a258edc0c03a0aedb884e7 100644
--- a/src/main/java/chocopy/common/astnodes/FuncDef.java
+++ b/src/main/java/chocopy/common/astnodes/FuncDef.java
@@ -5,6 +5,7 @@ import java.util.List;
 import chocopy.common.analysis.NodeAnalyzer;
 import chocopy.common.analysis.SymbolTable;
 import chocopy.common.analysis.types.SymbolType;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import java_cup.runtime.ComplexSymbolFactory.Location;
 
 /** Def statements. */
@@ -22,6 +23,7 @@ public class FuncDef extends Declaration {
     public final List<Stmt> statements;
 
     // recolic
+    @JsonIgnore
     public SymbolTable<SymbolType> symTable = null;
 
     /** The AST for
diff --git a/src/main/java/chocopy/pa2/StudentAnalysis.java b/src/main/java/chocopy/pa2/StudentAnalysis.java
index 0676798f61e5783947f0db46bfcc50698ab622e9..aa5410dca2739ecdc9572922f60b4920e27809d5 100644
--- a/src/main/java/chocopy/pa2/StudentAnalysis.java
+++ b/src/main/java/chocopy/pa2/StudentAnalysis.java
@@ -22,10 +22,14 @@ public class StudentAnalysis {
         //    declarationAnalyzer.getGlobals();
         SymbolTable<SymbolType> globalSym = new SymbolTable<>();
 
-        if (!program.hasErrors()) {
-            TypeChecker typeChecker =
-                new TypeChecker(globalSym, program.errors);
-            program.dispatch(typeChecker);
+        //if (!program.hasErrors()) {
+        TypeChecker typeChecker = new TypeChecker(globalSym, program.errors, true);
+        program.dispatch(typeChecker);
+        //}
+
+        if(!program.hasErrors()) {
+            TypeChecker next_time = new TypeChecker(typeChecker.getGlobals(), program.errors, false);
+            program.dispatch(next_time);
         }
 
         return program;
diff --git a/src/main/java/chocopy/pa2/TypeChecker.java b/src/main/java/chocopy/pa2/TypeChecker.java
index 3343d51b77ff0e82a24de97b5beccfc447eec169..75e7c2ff6dfced6fa173b46419f29844987a4f69 100644
--- a/src/main/java/chocopy/pa2/TypeChecker.java
+++ b/src/main/java/chocopy/pa2/TypeChecker.java
@@ -18,17 +18,24 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
 //    private SymbolTable<SymbolType> sym;
 
     /** Current symbol table.  Changes with new declarative region. */
-    private SymbolTable<SymbolType> sym = new SymbolTable<>();
+    private SymbolTable<SymbolType> sym;
     /** Global symbol table. */
-    private final SymbolTable<SymbolType> globals = sym;
+    private final SymbolTable<SymbolType> globals;
     /** Collector for errors. */
     private Errors errors;
 
+    private boolean isFirstRun;
+
     /** Creates a type checker using GLOBALSYMBOLS for the initial global
      *  symbol table and ERRORS0 to receive semantic errors. */
-    public TypeChecker(SymbolTable<SymbolType> globalSymbols, Errors errors0) {
+    public TypeChecker(SymbolTable<SymbolType> globalSymbols, Errors errors0, boolean firstRun) {
         sym = globalSymbols;
+        globals = sym;
         errors = errors0;
+        isFirstRun = firstRun;
+    }
+    public SymbolTable<SymbolType> getGlobals() {
+        return globals;
     }
 
     /** Inserts an error message in NODE if there isn't one already.
@@ -53,7 +60,8 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
             }
 
             // TODO: DO NOT throw on duplicate id. generate a compiler error.
-            sym.put(name, type);
+            if(isFirstRun)
+                sym.put(name, type);
         }
         for (Stmt stmt : program.statements) {
             stmt.dispatch(this);
@@ -73,8 +81,10 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
 
     @Override
     public SymbolType analyze(ClassDef classDef) {
-        assert classDef.memberMap == null;
-        classDef.memberMap = new HashMap<>();
+        if(isFirstRun) {
+            assert classDef.memberMap == null;
+            classDef.memberMap = new HashMap<>();
+        }
         assert classDef.memberMap != null;
 
         // My-name already pushed to symbolMap
@@ -89,7 +99,8 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         for(Declaration decl : classDef.declarations) {
             String name = decl.getIdentifier().name;
             SymbolType type = decl.dispatch(this);
-            classDef.memberMap.put(name, type);
+            if(isFirstRun)
+                classDef.memberMap.put(name, type);
         }
 
         sym = sym.getParent();
@@ -98,9 +109,12 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
 
     @Override
     public SymbolType analyze(FuncDef funcDef) {
-        System.out.println("debug: start funcDef: " + funcDef.getClass().getName());
-        assert funcDef.symTable == null;
-        sym = funcDef.symTable = new SymbolTable<SymbolType>(sym);
+        if(isFirstRun) {
+            assert funcDef.symTable == null;
+            sym = funcDef.symTable = new SymbolTable<SymbolType>(sym);
+        }
+        else
+            sym = funcDef.symTable;
         assert funcDef.symTable != null; // may suck if partial-compiling happens...
 
         // Func parameter list
@@ -108,14 +122,20 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         for(TypedVar param : funcDef.params) {
             String name = param.identifier.name;
             ValueType type = ValueType.annotationToValueType(param.type);
-            sym.put(name, type);
+            if(isFirstRun)
+                sym.put(name, type);
             args.add(type);
         }
 
         for(Declaration decl : funcDef.declarations) {
             String name = decl.getIdentifier().name;
             SymbolType type = decl.dispatch(this);
-            sym.put(name, type);
+            if(isFirstRun)
+                sym.put(name, type);
+        }
+
+        for(Stmt stmt : funcDef.statements) {
+            stmt.dispatch(this);
         }
 
         // function scope ends.. backtracking...
@@ -340,11 +360,11 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
         SymbolType funcType = sym.get(node.function.name);
         if(funcType == null) {
             err(node, "calling undeclared function " + node.function.name);
-            return OBJECT_TYPE;
+            return null;
         }
         if(!funcType.isFuncType()) {
             err(node, "calling non-function variable " + node.function.name);
-            return OBJECT_TYPE;
+            return null;
         }
         FuncType fType = (FuncType)funcType;
         List<SymbolType> args_type = new ArrayList<SymbolType>();
@@ -354,6 +374,7 @@ 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);
     }
 
@@ -466,6 +487,10 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> {
     public SymbolType analyze(Identifier id) {
         String varName = id.name;
         SymbolType varType = sym.get(varName);
+        if(varType == null) {
+            err(id, "undefined id " + varName);
+            return null;
+        }
         System.out.println("var " + varName + "->" + varType.toString());
 
         if (varType != null && varType.isValueType()) {