From 0eaaa81d605f3e7b585eb8712759ebe76c0310c1 Mon Sep 17 00:00:00 2001 From: Recolic Keghart <root@recolic.net> Date: Tue, 2 Apr 2019 02:56:12 -0700 Subject: [PATCH] working on decl analyser --- run.sh | 9 +- .../chocopy/common/analysis/SymbolTable.java | 4 + .../java/chocopy/common/astnodes/FuncDef.java | 2 +- .../java/chocopy/pa2/DeclarationAnalyzer.java | 4 +- src/main/java/chocopy/pa2/TypeChecker.java | 95 +++++++++++++++---- 5 files changed, 90 insertions(+), 24 deletions(-) diff --git a/run.sh b/run.sh index e42c387..d99c339 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 da10666..930ea9d 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 35070d3..8913791 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 1130fe7..839bf96 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 7f3f77c..3aeb45c 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 -- GitLab