diff --git a/src/main/java/chocopy/pa2/TypeChecker.java b/src/main/java/chocopy/pa2/TypeChecker.java index 4fc86621feed4c9713794f17f2d57167a55cd294..759f1772f1ee85c2b6b8d94a5afff475a853e964 100644 --- a/src/main/java/chocopy/pa2/TypeChecker.java +++ b/src/main/java/chocopy/pa2/TypeChecker.java @@ -53,7 +53,10 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { public SymbolType analyze(Program program) { if(isBuildingSym) { sym.put("object", OBJECT_TYPE); - sym.put("print", new FuncType(new ArrayList<ValueType>(Arrays.asList(OBJECT_TYPE)), NONE_TYPE)); + sym.put("print", new FuncType(Arrays.asList(OBJECT_TYPE), NONE_TYPE)); + // sym.put("len", new FuncType(Arrays.asList(new ListValueType(OBJECT_TYPE)), INT_TYPE)); + // SILLY FUCKING EXAMPLE PROGRAM SAYS: len(object). OK OK OK I'll DO IT. + sym.put("len", new FuncType(Arrays.asList(OBJECT_TYPE), INT_TYPE)); } for (Declaration decl : program.declarations) { @@ -375,7 +378,6 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { // fallthrough: do left-right match check. case "==": case "!=": - case "is": 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()); @@ -385,6 +387,8 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { err(node, "Syntax Error: binary operator operand type mismatch: left=" + left_type.toString() + ", right=" + right_type.toString()); } break; + case "is": + break; default: err(node, "Syntax Error: binary operator operand type not supported."); return OBJECT_TYPE; @@ -629,20 +633,25 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { return true; if(from.equals(EMPTY_TYPE)) from = new ListValueType(NONE_TYPE); if(to.equals(EMPTY_TYPE)) to = new ListValueType(NONE_TYPE); - if(!from.isListType() || !to.isListType()) { - // Cast class to parent - if(from instanceof ClassValueType && to instanceof ClassValueType) { - if(_typeConvertible_calcClassInheritChainCommonNode((ClassValueType) from, (ClassValueType) to).equals(to)) - return true; // Can cast from->to - } - return from.equals(to); + + if(from.isListType() && to.isListType()) { + // Convert list to list: + ListValueType lsFrom = (ListValueType) from, lsTo = (ListValueType) to; + if(lsFrom.elementType == null || lsFrom.elementType.equals(NONE_TYPE)) + return true; + return typeConvertible(lsFrom.elementType, lsTo.elementType); } - // Convert list to list: - ListValueType lsFrom = (ListValueType) from, lsTo = (ListValueType) to; - if(lsFrom.elementType == null || lsFrom.elementType.equals(NONE_TYPE)) - return true; - return typeConvertible(lsFrom.elementType, lsTo.elementType); + if(from.equals(STR_TYPE) && to.isListType()) { + // STR -> [STR, ...], so len(list) works to len(str). + return typeConvertible(from, ((ListValueType) to).elementType); + } + // Cast class to parent + if(from instanceof ClassValueType && to instanceof ClassValueType) { + if(_typeConvertible_calcClassInheritChainCommonNode((ClassValueType) from, (ClassValueType) to).equals(to)) + return true; // Can cast from->to + } + return from.equals(to); } private ClassValueType _typeConvertible_calcClassInheritChainCommonNode(ClassValueType l, ClassValueType r) { int l_depth = 1, r_depth = 1;