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()) {