diff --git a/src/main/java/chocopy/pa2/DeclarationAnalyzer.java b/src/main/java/chocopy/pa2/DeclarationAnalyzer.java index aa8724ad6eabf9c0c52c471a9e424ee04fd8f3d7..12c534b6f08a582ae715628c2e1ac88fd3da3d15 100644 --- a/src/main/java/chocopy/pa2/DeclarationAnalyzer.java +++ b/src/main/java/chocopy/pa2/DeclarationAnalyzer.java @@ -45,6 +45,7 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<SymbolType> { continue; } + // TODO: DO NOT throw on duplicate id. generate a compiler error. sym.put(name, type); } diff --git a/src/main/java/chocopy/pa2/TypeChecker.java b/src/main/java/chocopy/pa2/TypeChecker.java index 1bf1afa15c6f20ea29ce007f6d557d9e36676706..5b4e4903047ba8215de5f357fc04b760217532f0 100644 --- a/src/main/java/chocopy/pa2/TypeChecker.java +++ b/src/main/java/chocopy/pa2/TypeChecker.java @@ -7,12 +7,10 @@ import chocopy.common.analysis.types.ListValueType; import chocopy.common.analysis.types.SymbolType; import chocopy.common.analysis.types.ValueType; import chocopy.common.astnodes.*; -import org.jetbrains.annotations.NotNull; import java.util.*; -import static chocopy.common.analysis.types.SymbolType.INT_TYPE; -import static chocopy.common.analysis.types.SymbolType.OBJECT_TYPE; +import static chocopy.common.analysis.types.SymbolType.*; /** Analyzer that performs ChocoPy type checks on all nodes. Applied after * collecting declarations. */ @@ -66,7 +64,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { } @Override public SymbolType analyze(NoneLiteral node) { - return node.setInferredType(SymbolType.NONE_TYPE); + return node.setInferredType(NONE_TYPE); } @Override public SymbolType analyze(BooleanLiteral node) { @@ -77,7 +75,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { public SymbolType analyze(AssignStmt node) { SymbolType right_type = node.value.dispatch(this); if(right_type == null) - right_type = ValueType.NONE_TYPE; + right_type = NONE_TYPE; if(node.targets.size() == 1) { String target = node.targets.get(0).toString(); System.out.println("debug: assign to target " + target); @@ -108,6 +106,10 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { String op = node.operator; SymbolType left_type = node.left.dispatch(this); SymbolType right_type = node.right.dispatch(this); + if(left_type == null) + left_type = NONE_TYPE; + if(right_type == null) + right_type = NONE_TYPE; switch(op) { case "-": @@ -146,7 +148,7 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { } // Now set target type. - SymbolType result_type = ValueType.NONE_TYPE; + SymbolType result_type = NONE_TYPE; switch(op) { case "-": case "*": @@ -195,6 +197,56 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { return node.setInferredType(fType.returnType); } + @Override + public SymbolType analyze(UnaryExpr node) { + String op = node.operator; + switch(op) { + case "not": + if(!node.operand.dispatch(this).equals(ValueType.BOOL_TYPE)) { + err(node, "operand of not should be bool."); + } + return node.setInferredType(ValueType.BOOL_TYPE); + case "-": + if(!node.operand.dispatch(this).equals(INT_TYPE)) { + err(node, "operand of - should be int"); + } + return node.setInferredType(INT_TYPE); + default: + err(node, "operator " + op + " unknown."); + return node.setInferredType(NONE_TYPE); + } + } + + @Override + public SymbolType analyze(IfExpr node) { + SymbolType then_type = node.thenExpr.dispatch(this); + SymbolType else_type = node.elseExpr.dispatch(this); + if(!then_type.equals(else_type)) { + err(node, "then_type not equals to else_type. "); + } + return node.setInferredType(then_type); + } + + @Override + public SymbolType analyze(IndexExpr node) { + SymbolType list_type = node.list.dispatch(this); + SymbolType index_type = node.index.dispatch(this); + if(index_type != INT_TYPE) { + err(node, "index_type should be int."); + } + if(list_type == STR_TYPE) { + return node.setInferredType(STR_TYPE); + } + else if(list_type.isListType()) { + ListValueType t = (ListValueType) list_type; + return node.setInferredType(t.elementType); + } + else { + err(node, "type " + list_type.toString() + " is not index-able."); + return node.setInferredType(NONE_TYPE); + } + } + @Override public SymbolType analyze(Identifier id) { String varName = id.name;