optimized works
[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 = false;
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 Expr getLeftExpr() {
21         return leftelementexpr;
22     }
23     
24     public Expr getRightExpr() {
25         return rightelementexpr;
26     }
27
28     public RelationDescriptor getRelation() {
29         return relation;
30     }
31
32     public Set getTargetDescriptors() {
33         HashSet v = new HashSet();
34         v.add(relation);
35         return v;
36     }
37
38     public Set getRequiredDescriptors() {
39         Set v = leftelementexpr.getRequiredDescriptors();
40         v.addAll(rightelementexpr.getRequiredDescriptors());
41
42         if (!typesafe) { /* if not typesafe then domain and range are needed to make typesafety checks! */
43             v.add(relation.getDomain());
44             v.add(relation.getRange());
45         }
46
47         return v;
48     }
49
50     public void generate(CodeWriter writer) {
51         VarDescriptor ld = VarDescriptor.makeNew("leftele");
52         leftelementexpr.generate(writer, ld);
53         VarDescriptor rd = VarDescriptor.makeNew("rightele");
54         rightelementexpr.generate(writer, rd);
55
56         /* typesafe checks! */
57         String typesafecheck = (VarDescriptor.makeNew("typesafecheck")).getSafeSymbol();
58
59         if (!typesafe) {
60             String check = "int " + typesafecheck + " = " ;
61             
62             if (!(relation.getDomain() instanceof ReservedSetDescriptor)) {
63                 check += relation.getDomain().getSafeSymbol() + "_hash->contains(" + ld.getSafeSymbol() + ") && ";
64             }
65
66             if (!(relation.getRange() instanceof ReservedSetDescriptor)) {
67                 check += relation.getRange().getSafeSymbol() + "_hash->contains(" + rd.getSafeSymbol() + ") && ";
68             }
69         
70             check += "1;"; // terminate boolean expression
71
72             writer.outputline(check);
73             writer.outputline("if (" + typesafecheck + ")");
74             writer.startblock();
75         }
76
77         String addeditem = (VarDescriptor.makeNew("addeditem")).getSafeSymbol();
78         writer.outputline("int " + addeditem + ";");
79
80         if (relation.testUsage(RelationDescriptor.IMAGE)) {
81             writer.outputline(addeditem + " = " + relation.getSafeSymbol() + "_hash->add((int)" + ld.getSafeSymbol() + ", (int)" + rd.getSafeSymbol() + ");");
82         } 
83         
84         if (relation.testUsage(RelationDescriptor.INVIMAGE)) {
85             writer.outputline(addeditem + " = " + relation.getSafeSymbol() + "_hashinv->add((int)" + rd.getSafeSymbol() + ", (int)" + ld.getSafeSymbol() + ");");
86         }
87         
88         if (RelationInclusion.worklist) {
89             writer.outputline("if (" + addeditem + ")");
90             writer.startblock(); {                
91                 WorkList.generate_dispatch(writer, relation, rd.getSafeSymbol(), ld.getSafeSymbol());
92             }
93             writer.endblock();
94         }
95
96         if (!typesafe) {
97             writer.endblock();
98         }            
99
100         //writer.outputline("printf(\"" + relation.getSafeSymbol() + " (add): <%d, %d>\\n\", " + ld.getSafeSymbol() + ", " + rd.getSafeSymbol() + ");");
101     }
102
103     public boolean typecheck(SemanticAnalyzer sa) {
104         TypeDescriptor ld = leftelementexpr.typecheck(sa);
105         TypeDescriptor rd = rightelementexpr.typecheck(sa);
106         
107         if (ld == null || rd == null) {
108             return false;
109         }
110
111         boolean ok = true;
112
113         /* #ATTN#: this check makes sure that the types match up, 
114            a runtime check needs to made that the set relationships 
115            are correct */
116
117         if (ld != relation.getDomain().getType()) { 
118             sa.getErrorReporter().report(null, "Type of left element '" + ld.getSymbol() + "' must match domain type '" + relation.getDomain().getType().getSymbol() + "'");
119             ok = false;
120         }
121
122         if (rd != relation.getRange().getType()) {
123             assert rd.getSymbol() != null;
124             assert relation.getRange().getType() != null : relation.getRange().getSymbol();
125             sa.getErrorReporter().report(null, "Type of right element '" + rd.getSymbol() + "' must match range type '" + relation.getRange().getType().getSymbol() + "'");
126             ok = false;
127         }
128
129         return ok;
130     }
131
132 }