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