diff --git a/src/main/java/chocopy/pa2/TypeChecker.java b/src/main/java/chocopy/pa2/TypeChecker.java index 08faeb74a2afd82f5481e3da57ef4ac6222b5465..3a915a3df6e4d5c04dbacf5d00240ea8ad027824 100644 --- a/src/main/java/chocopy/pa2/TypeChecker.java +++ b/src/main/java/chocopy/pa2/TypeChecker.java @@ -131,12 +131,17 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { if(left_type != ValueType.INT_TYPE && left_type != ValueType.STR_TYPE && ! left_type.isListType()) { err(node, "Syntax Error: operand of + should be INT or STR or LIST"); } - // fallthrough + // fallthrough: do left-right match check. case "==": case "!=": case "is": - if(node.left.getInferredType() != node.right.getInferredType()) { - err(node, "Syntax Error: binary operator operand type mismatch"); + if(!left_type.equals(right_type)) { + if(left_type.isListType() && right_type.isListType()) { + System.out.println("debug: left_type=" + left_type.toString() + ", right=" + right_type.toString()); + left_type = new ListValueType(OBJECT_TYPE); + break; // list-type mismatch is OK. but you should return [Object] + } + err(node, "Syntax Error: binary operator operand type mismatch: left=" + left_type.toString() + ", right=" + right_type.toString()); } break; default: @@ -244,6 +249,20 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { } } + @Override + public SymbolType analyze(ListExpr node) { + SymbolType elementType = null; + for(Expr expr : node.elements) { + SymbolType this_type = expr.dispatch(this); + if(elementType == null) + elementType = this_type; + if(this_type != elementType) + err(node, "list elements must have the same type."); + } + ListValueType resultType = new ListValueType(elementType); + return node.setInferredType(resultType); + } + @Override public SymbolType analyze(MemberExpr node) { ClassValueType objType = (ClassValueType) node.object.dispatch(this); @@ -259,6 +278,23 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { return resultType; } + @Override + public SymbolType analyze(MethodCallExpr node) { + FuncType funcType = (FuncType) node.method.dispatch(this); + if(funcType == null) { + err(node, "method is not callable."); + return NONE_TYPE; + } + List<SymbolType> args_type = new ArrayList<>(); + for(Expr expr : node.args) { + args_type.add(expr.dispatch(this)); + } + if(!args_type.equals(funcType.parameters)) { + err(node, "function/method parameter list mismatch"); + } + return funcType.returnType; + } + @Override public SymbolType analyze(Identifier id) { String varName = id.name;