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