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; } + }