diff --git a/.gitignore b/.gitignore index 21cc758a806c9378f9087be9df7e86c57a6c1137..6fb050f33df6f21162c8152feb2c2b9d7e8bb16b 100644 --- a/.gitignore +++ b/.gitignore @@ -147,3 +147,7 @@ tramp Session.vim .netrwhist *~ + +### recolic +*.gi + diff --git a/src/main/java/chocopy/pa2/DeclarationAnalyzer.java b/src/main/java/chocopy/pa2/DeclarationAnalyzer.java index 24eebdc58a457f77ed8364d90457c5e2055eff5b..92f02035d7cb4fad52e77efeb6bf4c488ea2415c 100644 --- a/src/main/java/chocopy/pa2/DeclarationAnalyzer.java +++ b/src/main/java/chocopy/pa2/DeclarationAnalyzer.java @@ -4,11 +4,9 @@ import chocopy.common.analysis.AbstractNodeAnalyzer; import chocopy.common.analysis.SymbolTable; import chocopy.common.analysis.types.SymbolType; import chocopy.common.analysis.types.ValueType; -import chocopy.common.astnodes.Declaration; -import chocopy.common.astnodes.Errors; -import chocopy.common.astnodes.Identifier; -import chocopy.common.astnodes.Program; -import chocopy.common.astnodes.VarDef; +import chocopy.common.astnodes.*; + +import javax.management.RuntimeErrorException; /** * Analyzes declarations to create a top-level symbol table. @@ -59,7 +57,78 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<SymbolType> { @Override public SymbolType analyze(VarDef varDef) { - return ValueType.annotationToValueType(varDef.var.type); + return analyze(varDef.var); + } + + @Override + public SymbolType analyze(TypedVar node) { + return ValueType.annotationToValueType(node.type); + } + + @Override + public SymbolType analyze(BinaryExpr node) { + String op = node.operator; + + // Check operand type. + SymbolType left_type = node.left.getInferredType(); + SymbolType right_type = node.left.getInferredType(); + switch(op) { + case "-": + case "*": + case "//": + case "%": + case ">": + case "<": + case ">=": + case "<=": + if(left_type != ValueType.INT_TYPE || right_type != ValueType.INT_TYPE) + throw new RuntimeException("Syntax Error: operand should be INT"); + break; + case "and": + case "or": + if(left_type != ValueType.BOOL_TYPE || right_type != ValueType.BOOL_TYPE) + throw new RuntimeException("Syntax Error: operand should be BOOL"); + break; + case "+": + if(left_type != ValueType.INT_TYPE && left_type != ValueType.STR_TYPE && ! left_type.isListType()) + throw new RuntimeException("Syntax Error: operand of + should be INT or STR or LIST"); + // fallthrough + case "==": + case "!=": + case "is": + if(node.left.getInferredType() != node.right.getInferredType()) + throw new RuntimeException("Syntax Error: binary operator operand type mismatch"); + break; + default: + throw new RuntimeException("Syntax Error: binary operator operand type not supported."); + } + + // Now set target type. + SymbolType result_type = ValueType.NONE_TYPE; + switch(op) { + case "-": + case "*": + case "//": + case "%": + case "and": + case "or": + case "+": + result_type = left_type; + break; + case ">": + case "<": + case ">=": + case "<=": + case "==": + case "!=": + case "is": + result_type = ValueType.BOOL_TYPE; + break; + default: + throw new RuntimeException("Logic error"); + } + + return result_type; }