From 5c7f8b770860f77d01d0be321c61e2ef699e5b87 Mon Sep 17 00:00:00 2001
From: Recolic Keghart <root@recolic.net>
Date: Mon, 1 Apr 2019 12:42:19 -0700
Subject: [PATCH] type: BinaryExpr

---
 .gitignore                                    |  4 +
 .../java/chocopy/pa2/DeclarationAnalyzer.java | 81 +++++++++++++++++--
 2 files changed, 79 insertions(+), 6 deletions(-)

diff --git a/.gitignore b/.gitignore
index 21cc758..6fb050f 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 24eebdc..92f0203 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;
     }
 
 
-- 
GitLab