worklist version
[repair.git] / Repair / RepairCompiler / MCC / IR / RelationInclusion.java
1 package MCC.IR;
2
3 import java.util.*;
4
5 public class RelationInclusion extends Inclusion {
6     
7     Expr leftelementexpr, rightelementexpr;
8     RelationDescriptor relation;
9
10     // #TBD#: this flag needs to be set by some static analysis
11     boolean typesafe = true;
12     static boolean worklist = true;
13
14     public RelationInclusion(Expr leftelementexpr, Expr rightelementexpr, RelationDescriptor relation) {
15         this.leftelementexpr = leftelementexpr;
16         this.rightelementexpr = rightelementexpr;
17         this.relation = relation;
18     }
19
20     public Set getTargetDescriptors() {
21         HashSet v = new HashSet();
22         v.add(relation);
23         return v;
24     }
25
26     public Set getRequiredDescriptors() {
27         Set v = leftelementexpr.getRequiredDescriptors();
28         v.addAll(rightelementexpr.getRequiredDescriptors());
29
30         if (!typesafe) { /* if not typesafe then domain and range are needed to make typesafety checks! */
31             v.add(relation.getDomain());
32             v.add(relation.getRange());
33         }
34
35         return v;
36     }
37
38     public void generate(CodeWriter writer) {
39         VarDescriptor ld = VarDescriptor.makeNew("leftele");
40         leftelementexpr.generate(writer, ld);
41         VarDescriptor rd = VarDescriptor.makeNew("rightele");
42         rightelementexpr.generate(writer, rd);
43
44         /* typesafe checks! */
45         String typesafecheck = (VarDescriptor.makeNew("typesafecheck")).getSafeSymbol();
46
47         if (!typesafe) {
48             String check = "int " + typesafecheck + " = " ;
49             
50             if (!(relation.getDomain() instanceof ReservedSetDescriptor)) {
51                 check += relation.getDomain().getSafeSymbol() + "_hash->contains(" + ld.getSafeSymbol() + ") && ";
52             }
53
54             if (!(relation.getRange() instanceof ReservedSetDescriptor)) {
55                 check += relation.getRange().getSafeSymbol() + "_hash->contains(" + rd.getSafeSymbol() + ") && ";
56             }
57         
58             check += "1;"; // terminate boolean expression
59
60             writer.outputline(check);
61             writer.outputline("if (" + typesafecheck + ")");
62             writer.startblock();
63         }
64
65         String addeditem = (VarDescriptor.makeNew("addeditem")).getSafeSymbol();
66         writer.outputline("int " + addeditem + ";");
67
68         if (relation.testUsage(RelationDescriptor.IMAGE)) {
69             writer.outputline(addeditem + " = " + relation.getSafeSymbol() + "_hash->add((int)" + ld.getSafeSymbol() + ", (int)" + rd.getSafeSymbol() + ");");
70         } 
71         
72         if (relation.testUsage(RelationDescriptor.INVIMAGE)) {
73             writer.outputline(addeditem + " = " + relation.getSafeSymbol() + "_hashinv->add((int)" + rd.getSafeSymbol() + ", (int)" + ld.getSafeSymbol() + ");");
74         }
75         
76         if (RelationInclusion.worklist) {
77             writer.outputline("if (" + addeditem + ")");
78             writer.startblock(); {                
79                 WorkList.generate_dispatch(writer, relation, rd.getSafeSymbol(), ld.getSafeSymbol());
80             }
81             writer.endblock();
82         }
83
84         if (!typesafe) {
85             writer.endblock();
86         }            
87
88         //writer.outputline("printf(\"" + relation.getSafeSymbol() + " (add): <%d, %d>\\n\", " + ld.getSafeSymbol() + ", " + rd.getSafeSymbol() + ");");
89     }
90
91     public boolean typecheck(SemanticAnalyzer sa) {
92         TypeDescriptor ld = leftelementexpr.typecheck(sa);
93         TypeDescriptor rd = rightelementexpr.typecheck(sa);
94         
95         if (ld == null || rd == null) {
96             return false;
97         }
98
99         boolean ok = true;
100
101         /* #ATTN#: this check makes sure that the types match up, 
102            a runtime check needs to made that the set relationships 
103            are correct */
104
105         if (ld != relation.getDomain().getType()) { 
106             sa.getErrorReporter().report(null, "Type of left element '" + ld.getSymbol() + "' must match domain type '" + relation.getDomain().getType().getSymbol() + "'");
107             ok = false;
108         }
109
110         if (rd != relation.getRange().getType()) {
111             assert rd.getSymbol() != null;
112             assert relation.getRange().getType() != null : relation.getRange().getSymbol();
113             sa.getErrorReporter().report(null, "Type of right element '" + rd.getSymbol() + "' must match range type '" + relation.getRange().getType().getSymbol() + "'");
114             ok = false;
115         }
116
117         return ok;
118     }
119
120 }