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