oops...freeVars can return null.
[repair.git] / Repair / RepairCompiler / MCC / IR / SemanticChecker.java
index a20c5a63f648fe23bc7480568256f4e2a1d6bed5..23e83f4b785377173e563a645e09735e3da66ac4 100755 (executable)
@@ -35,9 +35,6 @@ public class SemanticChecker {
        this.state = state;
        State.currentState = state;
 
-       // Don't clear the state!!  Do clear the IR-related state
-       this.state.stTypes = null;
-
        if (er == null) {
            throw new IRException("IRBuilder.build: Received null ErrorReporter");
        } else {
@@ -293,7 +290,7 @@ public class SemanticChecker {
                 } else {
                     rule.addQuantifier(quantifier);
                 }
-            }             
+            }
         }
         
         /* get guard expr */
@@ -382,7 +379,7 @@ public class SemanticChecker {
 
         boolean ok = true;
         ParseNodeVector constraints = pn.getChildren();
-        
+
         for (int i = 0; i < constraints.size(); i++) {
             ParseNode constraint = constraints.elementAt(i);
             assert constraint.getLabel().equals("constraint");
@@ -392,8 +389,30 @@ public class SemanticChecker {
         }
 
         /* do any post checks... (type constraints, etc?) */
-         
-        return ok;
+
+        Iterator consiterator = state.vConstraints.iterator();
+
+        while (consiterator.hasNext()) {
+            Constraint cons = (Constraint) consiterator.next();
+
+            final SymbolTable consst = cons.getSymbolTable();
+            SemanticAnalyzer sa = new SemanticAnalyzer() {
+                    public IRErrorReporter getErrorReporter() { return er; }
+                    public SymbolTable getSymbolTable() { return consst; }
+                };
+
+            TypeDescriptor constype = cons.getLogicStatement().typecheck(sa);
+
+            if (constype == null) {
+               System.out.println("Failed attempting to type constraint");
+                ok = false;
+            } else if (constype != ReservedTypeDescriptor.INT) {
+                er.report(null, "Type of guard must be 'int' not '" + constype.getSymbol() + "'");
+                ok = false;
+            }
+       }
+
+       return ok;
     }
 
     private boolean parse_constraint(ParseNode pn) {
@@ -421,17 +440,19 @@ public class SemanticChecker {
                 assert qn.getLabel().equals("quantifier");
                 Quantifier quantifier = parse_quantifier(qn);
                 if (quantifier == null) {
+                   System.out.println("Failed parsing quantifier");
                     ok = false;
                 } else {
                     constraint.addQuantifier(quantifier);
                 }
             }
         }
-                                                      
+
         /* get body */
         LogicStatement logicexpr = parse_body(pn.getChild("body"));
 
         if (logicexpr == null) {
+           System.out.println("Failed parsing logical expression");
             ok = false;
         } else {
             constraint.setLogicStatement(logicexpr);
@@ -445,7 +466,7 @@ public class SemanticChecker {
         assert sts.empty();
 
         /* add to vConstraints */
-        vConstraints.addElement(constraint);           
+        vConstraints.addElement(constraint);
 
         return ok;
     }
@@ -471,13 +492,14 @@ public class SemanticChecker {
             SetDescriptor set = parse_set(pn.getChild("set"));
             assert set != null;
             sq.setSet(set);
+           vd.setSet(set);
 
             vd.setType(set.getType());
 
             /* return to caller */
             return sq;
 
-        } else if (pn.getChild("relatiion") != null) { /* for < v1, v2 > in Relation */
+        } else if (pn.getChild("relation") != null) { /* for < v1, v2 > in Relation */
             RelationQuantifier rq = new RelationQuantifier();
 
             /* get vars */
@@ -501,18 +523,21 @@ public class SemanticChecker {
             
             rq.setRelation(rd);
             vd1.setType(rd.getDomain().getType());
+           vd1.setSet(rd.getDomain());
             vd2.setType(rd.getRange().getType());
+           vd2.setSet(rd.getRange());
             return rq;
         } else if (pn.getChild("for") != null) { /* for j = x to y */
             ForQuantifier fq = new ForQuantifier();
             
             /* grab var */
             VarDescriptor vd = reserveName(pn.getChild("var"));
-
+           
             if (vd == null) {
                 return null;
             }
 
+           vd.setSet(lookupSet("int", false));
             vd.setType(ReservedTypeDescriptor.INT);
             fq.setVar(vd);
 
@@ -520,17 +545,17 @@ public class SemanticChecker {
             Expr lower = parse_expr(pn.getChild("lower").getChild("expr"));
             Expr upper = parse_expr(pn.getChild("upper").getChild("expr"));
 
+
             if ((lower == null) || (upper == null)) {
                 return null;
             }
-
+           vd.setBounds(lower,upper);
             fq.setBounds(lower, upper);
 
             return fq;
         } else {
             throw new IRException("not supported yet");
         }
-
     }
 
     private LogicStatement parse_body(ParseNode pn) {
@@ -563,7 +588,7 @@ public class SemanticChecker {
             return new LogicStatement(LogicStatement.OR, left, right);
         } else if (pn.getChild("not") != null) {
             /* NOT body */
-            LogicStatement left = parse_body(pn.getChild("not").getChild("left").getChild("body"));
+            LogicStatement left = parse_body(pn.getChild("not").getChild("body"));
             
             if (left == null) {
                 return null;
@@ -585,10 +610,10 @@ public class SemanticChecker {
         if (pn.getChild("inclusion") != null) {
             ParseNode in = pn.getChild("inclusion");
             
-            /* get quantiifer var */
-            VarDescriptor vd = parse_quantifiervar(in.getChild("quantifiervar"));
+            /* Expr */
+            Expr expr = parse_expr(in.getChild("expr"));
            
-            if (vd == null) { 
+            if (expr == null) { 
                 return null;
             }
 
@@ -599,45 +624,15 @@ public class SemanticChecker {
                 return null;
             }
 
-            return new InclusionPredicate(vd, setexpr);
-        } else if (pn.getChild("sizeof") != null) {
-            ParseNode sizeof = pn.getChild("sizeof");
+            return new InclusionPredicate(expr, setexpr);
+        } else if (pn.getChild("expr") != null) {
+            Expr expr = parse_expr(pn.getChild("expr"));
             
-            /* get set expr */
-            SetExpr setexpr = parse_setexpr(sizeof.getChild("setexpr"));
-
-            if (setexpr == null) {
-                return null;
-            }
-
-            /* get comparison operator */
-            String compareop = sizeof.getChild("compare").getTerminal();
-            Opcode opcode = Opcode.decodeFromString(opname);
-
-            if (opcode == null) {
-                er.report(pn, "Unsupported operation: " + opname);
-                return null;
-            }
-
-
-
-            return new InclusionPredicate(vd, setexpr);
-        } else if (pn.getChild("comparison") != null) {
-            ParseNode cn = pn.getChild("comparison");
-            
-            /* get the expr's */
-            Expr left = parse_expr(cn.getChild("left").getChild("expr"));
-            Expr right = parse_expr(cn.getChild("right").getChild("expr"));
-
-            if ((left == null) || (right == null)) {
+            if (expr == null) {
                 return null;
             }
 
-            /* get comparison operator */
-            String comparison = cn.getChild("compare").getTerminal();
-            assert comparison != null;
-                         
-            return new ComparisonPredicate(comparison, left, right);
+            return new ExprPredicate(expr);
         } else {
             throw new IRException();
         }       
@@ -819,13 +814,17 @@ public class SemanticChecker {
         String rangesetname = pn.getChild("range").getChild("type").getTerminal();
         assert rangesetname != null;
 
-        /* get domain multiplicity */
-        String domainmult = pn.getChild("domain").getChild("mult").getTerminal();
-        assert domainmult != null;
+        /* get domain multiplicity */  
+       String domainmult;
+       if (pn.getChild("domain").getChild("domainmult") != null)
+           domainmult = pn.getChild("domain").getChild("domainmult").getChild("mult").getTerminal();
+        //assert domainmult != null;
 
         /* get range multiplicity */
-        String rangemult = pn.getChild("range").getChild("mult").getTerminal();
-        assert rangemult != null;
+       String rangemult;
+       if (pn.getChild("range").getChild("domainrange") != null)
+           rangemult = pn.getChild("range").getChild("domainrange").getChild("mult").getTerminal();
+        //assert rangemult != null;
 
         /* NOTE: it is assumed that the sets have been parsed already so that the 
            set namespace is fully populated. any missing setdescriptors for the set
@@ -893,7 +892,7 @@ public class SemanticChecker {
             } else if (t instanceof StructureTypeDescriptor) {
                 
                 StructureTypeDescriptor type = (StructureTypeDescriptor) t;
-                TypeDescriptor subtype = type.getSubType();
+                TypeDescriptor subtype = type.getSuperType();
 
                 // check that the subtype is valid
                 if (subtype instanceof MissingTypeDescriptor) {
@@ -904,7 +903,7 @@ public class SemanticChecker {
                         er.report(null, "Undefined subtype '" + subtype.getSymbol() + "'");
                         ok = false;
                     } else {
-                        type.setSubType(newtype);
+                        type.setSuperType(newtype);
                     }
                 }
 
@@ -922,13 +921,17 @@ public class SemanticChecker {
                         if (newtype == null) {
                             // type never defined
                             // #TBD#: replace new ParseNode with original parsenode
-                            er.report(null, "Undefined type '" + fieldtype.getSymbol() + "'");
-                            ok = false;
+                           
+                           if (!field.getPtr()) { 
+                               /* Pointer types don't have to be defined */
+                               er.report(null, "Undefined type '" + fieldtype.getSymbol() + "'");
+                               ok = false;
+                           }
                         } else {
                             assert newtype != null;
                             field.setType(newtype);
                         }
-                    }                        
+                    }
                 }
 
                 Iterator labels = type.getLabels();
@@ -973,7 +976,7 @@ public class SemanticChecker {
             } else if (t instanceof StructureTypeDescriptor) {
                 
                 StructureTypeDescriptor type = (StructureTypeDescriptor)t;
-                TypeDescriptor subtype = type.getSubType();
+                TypeDescriptor subtype = type.getSuperType();
                 Iterator fields = type.getFields();
 
                 while (fields.hasNext()) {
@@ -1014,11 +1017,9 @@ public class SemanticChecker {
                         }
                     }
                 }
-                
-            } else {
+           } else {
                 throw new IRException("shouldn't be any other typedescriptor classes");
             }
-
         }
 
         // #TBD#: need to make sure that no cycles exist in any of the declarations or subtypes
@@ -1048,7 +1049,7 @@ public class SemanticChecker {
             return false;
         }
 
-        stGlobals.add(new VarDescriptor(name, name, td));
+        stGlobals.add(new VarDescriptor(name, name, td,true));
         return true;
     }
 
@@ -1072,7 +1073,20 @@ public class SemanticChecker {
             }
 
             /* lookup the type to get the type descriptor */
-            type.setSubType(lookupType(subtype, CREATE_MISSING));
+            type.setSuperType(lookupType(subtype, CREATE_MISSING));
+        } else if (pn.getChild("subclass") != null) {
+            // has a subtype, lets try to resolve it
+            String subclass = pn.getChild("subclass").getTerminal();
+           
+            if (subclass.equals(typename)) {
+                // Semantic Error: cyclic inheritance
+                er.report(pn, "Cyclic inheritance prohibited");
+                ok = false;
+            }
+
+            /* lookup the type to get the type descriptor */
+            type.setSuperType(lookupType(subclass, CREATE_MISSING));
+            type.setSubClass(true);
         }
 
         // set the current type so that the recursive parses on the labels
@@ -1350,49 +1364,26 @@ public class SemanticChecker {
             return null;
         }
 
-        RelationExpr re = new RelationExpr();
+        String relname = pn.getChild("name").getTerminal();
+        boolean inverse = pn.getChild("inv") != null;
+        Expr expr = parse_expr(pn.getChild("expr"));        
 
-        /* get quantitifer var */
-        VarDescriptor vd = parse_quantifiervar(pn.getChild("quantifiervar"));
-        
-        if (vd == null) {
+        if (expr == null) {
             return null;
         }
-
-        // #TBD#: bad name
-        re.setDomain(vd);
-
-        /* grab list of relations */
-        ParseNodeVector relations = pn.getChild("relations").getChildren();
-        assert relations.size() >= 1;
-        
-        // #TBD#: verify that the relations are in the correct order and that the 
-        // first relation is getting the correct "inv" assigned from "expr"
-
-        /* lets verify that these relations are defined */
-        for (int i = 0; i < relations.size(); i++) {           
-            ParseNode rn = relations.elementAt(i);
-            String relname = rn.getLabel();
-            boolean inverse = rn.getChild("inv") != null;
-            
-            RelationDescriptor relation = lookupRelation(relname);
+                    
+        RelationDescriptor relation = lookupRelation(relname);
             
-            if (relation == null) {
-                /* Semantic Error: relation not definied" */
-                er.report(rn, "Undefined relation '" + relname + "'");
-                return null;
-            }                       
+        if (relation == null) {
+            /* Semantic Error: relation not definied" */
+            er.report(pn, "Undefined relation '" + relname + "'");
+            return null;
+        }                       
 
-            re.setRelation(relation, inverse);
+        /* add usage so correct sets are created */
+        relation.addUsage(inverse ? RelationDescriptor.INVIMAGE : RelationDescriptor.IMAGE);
             
-            /* if we are not at end of list then create new relation and 
-               replace it to chain the relations */
-            if (i + 1 < relations.size()) {
-                re = new RelationExpr(re);  // should create relation with domain as older 're'
-            } 
-        }
-
-        return re;                  
+        return new RelationExpr(expr, relation, inverse);
     }
 
     private SizeofExpr parse_sizeof(ParseNode pn) {
@@ -1457,11 +1448,23 @@ public class SemanticChecker {
         } else if (pn.getChild("dot") != null) {
             VarDescriptor vd = parse_quantifiervar(pn.getChild("dot").getChild("quantifiervar"));
             RelationDescriptor relation = lookupRelation(pn.getChild("dot").getChild("relation").getTerminal());
+            relation.addUsage(RelationDescriptor.IMAGE);
             return new ImageSetExpr(vd, relation);
         } else if (pn.getChild("dotinv") != null) {
             VarDescriptor vd = parse_quantifiervar(pn.getChild("dotinv").getChild("quantifiervar"));
             RelationDescriptor relation = lookupRelation(pn.getChild("dotinv").getChild("relation").getTerminal());
+            relation.addUsage(RelationDescriptor.INVIMAGE);
             return new ImageSetExpr(ImageSetExpr.INVERSE, vd, relation);
+        } else if (pn.getChild("dotset") != null) {
+            ImageSetExpr ise = (ImageSetExpr) parse_setexpr(pn.getChild("dotset").getChild("setexpr"));
+            RelationDescriptor relation = lookupRelation(pn.getChild("dotset").getChild("relation").getTerminal());
+            relation.addUsage(RelationDescriptor.IMAGE);
+            return new ImageSetExpr(ise, relation);
+        } else if (pn.getChild("dotinvset") != null) {
+            ImageSetExpr ise = (ImageSetExpr) parse_setexpr(pn.getChild("dotinvset").getChild("setexpr"));
+            RelationDescriptor relation = lookupRelation(pn.getChild("dotinvset").getChild("relation").getTerminal());
+            relation.addUsage(RelationDescriptor.INVIMAGE);
+            return new ImageSetExpr(ImageSetExpr.INVERSE, ise, relation);
         } else {
             throw new IRException();
         }
@@ -1487,7 +1490,14 @@ public class SemanticChecker {
         /* do semantic check and if valid, add it to symbol table
            and add it to the quantifier as well */
         if (sts.peek().contains(varname)) {
-            return new VarDescriptor(varname);
+           VarDescriptor vdold=(VarDescriptor)sts.peek().get(varname);
+           return vdold;
+           /*     Dan was creating a new VarDescriptor...This seems
+                  like the wrong thing to do.  We'll just lookup the
+                  other one.
+                  --------------------------------------------------
+                  VarDescriptor vd=new VarDescriptor(varname);
+                  vd.setSet(vdold.getSet()); return vd;*/
         } else {
             /* Semantic Error: undefined variable */
             er.report(pn, "Undefined variable '" + varname + "'");