diff --git a/run.sh b/run.sh index e42c38753af62fcadf5b338dac66de68550a8658..d99c3395294356fac7a81b696461e7a2ca64c89b 100755 --- a/run.sh +++ b/run.sh @@ -4,12 +4,15 @@ task="$1" input="$2" output="$3" +# recolic: I edited class FuncDef so place target/assignment.jar before chocopy-ref.jar! +classPath="target/assignment.jar:chocopy-ref.jar" + if [[ "$task" = parse ]]; then - java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy --pass=r --out "$output" "$input" + java -cp "$classPath" chocopy.ChocoPy --pass=r --out "$output" "$input" elif [[ "$task" = type ]]; then - java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy --pass=.s --out "$output" "$input" + java -cp "$classPath" chocopy.ChocoPy --pass=.s --out "$output" "$input" elif [[ "$task" = ass ]]; then - java -cp "chocopy-ref.jar:target/assignment.jar" chocopy.ChocoPy --pass=.s --dir src/test/data/pa2/sample --test + java -cp "$classPath" chocopy.ChocoPy --pass=.s --dir src/test/data/pa2/sample --test fi exit $? diff --git a/src/main/java/chocopy/common/analysis/SymbolTable.java b/src/main/java/chocopy/common/analysis/SymbolTable.java index da10666416d6bf6b4afe0298346c21cb7d65fd2e..930ea9da597d163b60dccee3317d89c7144c773b 100644 --- a/src/main/java/chocopy/common/analysis/SymbolTable.java +++ b/src/main/java/chocopy/common/analysis/SymbolTable.java @@ -62,4 +62,8 @@ public class SymbolTable<T> { return this.parent; } + public boolean isEmpty() { + return tab.isEmpty(); + } + } diff --git a/src/main/java/chocopy/common/astnodes/FuncDef.java b/src/main/java/chocopy/common/astnodes/FuncDef.java index 35070d32f27bbbd61d720b89b641bedf9b16e8ef..8913791e3889754bad12dca6a6bf4465b08bcc4f 100644 --- a/src/main/java/chocopy/common/astnodes/FuncDef.java +++ b/src/main/java/chocopy/common/astnodes/FuncDef.java @@ -21,7 +21,7 @@ public class FuncDef extends Declaration { /** Other statements. */ public final List<Stmt> statements; - // Recolic + // recolic public SymbolTable<SymbolType> symTable = null; /** The AST for diff --git a/src/main/java/chocopy/pa2/DeclarationAnalyzer.java b/src/main/java/chocopy/pa2/DeclarationAnalyzer.java index 1130fe7626dfa10b5394ba1e4a2155fef51387aa..839bf960b6013de6f9d49bddab13c254eaa4a4d6 100644 --- a/src/main/java/chocopy/pa2/DeclarationAnalyzer.java +++ b/src/main/java/chocopy/pa2/DeclarationAnalyzer.java @@ -66,9 +66,9 @@ public class DeclarationAnalyzer extends AbstractNodeAnalyzer<SymbolType> { @Override public SymbolType analyze(FuncDef funcDef) { - System.out.println("debug: start funcDef"); + System.out.println("debug: start funcDef: " + funcDef.getClass().getName()); assert funcDef.symTable == null; - sym = funcDef.symTable = new SymbolTable<>(sym); + sym = funcDef.symTable = new SymbolTable<SymbolType>(sym); // Func parameter list for(TypedVar param : funcDef.params) { diff --git a/src/main/java/chocopy/pa2/TypeChecker.java b/src/main/java/chocopy/pa2/TypeChecker.java index 7f3f77c16a973c5621de82471fd9f86f6821a88d..3aeb45c44ad88bb26a7220bf9d1b9c64ec6516bf 100644 --- a/src/main/java/chocopy/pa2/TypeChecker.java +++ b/src/main/java/chocopy/pa2/TypeChecker.java @@ -65,26 +65,85 @@ public class TypeChecker extends AbstractNodeAnalyzer<SymbolType> { } @Override - public SymbolType analyze(BinaryExpr e) { - SymbolType t1 = e.left.dispatch(this); - SymbolType t2 = e.right.dispatch(this); - - switch (e.operator) { - case "-": - case "*": - case "//": - case "%": - if (INT_TYPE.equals(t1) && INT_TYPE.equals(t2)) { - return e.setInferredType(INT_TYPE); - } else { - err(e, "Cannot apply operator `%s` on types `%s` and `%s`", - e.operator, t1, t2); - return e.setInferredType(INT_TYPE); - } - default: - return e.setInferredType(OBJECT_TYPE); + public SymbolType analyze(BinaryExpr node) { + String op = node.operator; + SymbolType left_type = node.left.dispatch(this); + SymbolType right_type = node.right.dispatch(this); + + //switch (e.operator) { + //case "-": + //case "*": + //case "//": + //case "%": + // if (INT_TYPE.equals(t1) && INT_TYPE.equals(t2)) { + // return e.setInferredType(INT_TYPE); + // } else { + // err(e, "Cannot apply operator `%s` on types `%s` and `%s`", + // e.operator, t1, t2); + // return e.setInferredType(INT_TYPE); + // } + //default: + // return e.setInferredType(OBJECT_TYPE); + //} + + + switch(op) { + case "-": + case "*": + case "//": + case "%": + case ">": + case "<": + case ">=": + case "<=": + if(left_type != ValueType.INT_TYPE || right_type != ValueType.INT_TYPE) + err(node, "Syntax Error: operand should be INT"); + break; + case "and": + case "or": + if(left_type != ValueType.BOOL_TYPE || right_type != ValueType.BOOL_TYPE) + err(node, "Syntax Error: operand should be BOOL"); + break; + case "+": + 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 + case "==": + case "!=": + case "is": + if(node.left.getInferredType() != node.right.getInferredType()) + err(node, "Syntax Error: binary operator operand type mismatch"); + break; + default: + err(node, "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 node.setInferredType(result_type); } @Override