1) Added useDescriptor method to Expr's.
[repair.git] / Repair / RepairCompiler / MCC / IR / RelationExpr.java
1 package MCC.IR;
2
3 import java.util.*;
4
5 public class RelationExpr extends Expr {
6
7     Expr expr;
8     RelationDescriptor relation;
9     boolean inverse;
10
11     public Set getfunctions() {
12         HashSet functions=new HashSet();
13         Set exprfunctions=expr.getfunctions();
14         if (exprfunctions!=null)
15             functions.addAll(exprfunctions);
16         functions.add(new ConstraintDependence.Function(relation,expr.getSet(),inverse));
17         
18         return functions;
19     }
20
21     public SetDescriptor getSet() {
22         if (inverse)
23             return relation.domain;
24         else
25             return relation.range;
26     }
27
28     public RelationExpr(Expr expr, RelationDescriptor relation, boolean inverse) {
29         this.expr = expr;
30         this.relation = relation;
31         this.inverse = inverse;
32     }
33
34     public Set freeVars() {
35         return expr.freeVars();
36     }
37
38     public String name() {
39         String name=expr.name()+".";
40         if (inverse)
41             name+="~";
42         name+=relation.toString();
43         return name;
44     }
45
46     public Expr getExpr() {
47         return expr;
48     }
49
50     public boolean equals(Map remap, Expr e) {
51         if (e==null||!(e instanceof RelationExpr))
52             return false;
53         RelationExpr re=(RelationExpr)e;
54         if (re.relation!=relation)
55             return false;
56         if (!expr.equals(remap,re.expr))
57             return false;
58         if (inverse!=re.inverse)
59             return false;
60         return true;
61     }
62
63     public boolean usesDescriptor(Descriptor rd) {
64         if (rd==relation)
65             return true;
66         else
67             return expr.usesDescriptor(rd);
68     }
69
70     public Set useDescriptor(Descriptor rd) {
71         HashSet newset=new HashSet();
72         if (rd==relation)
73             newset.add(this);
74         newset.addAll(expr.useDescriptor(rd));
75         return newset;
76     }
77     
78     public RelationDescriptor getRelation() {
79         return relation;
80     }
81
82     public Descriptor getDescriptor() {
83         return relation;
84     }
85
86     public boolean inverted() {
87         return inverse;
88     }
89
90     public Set getInversedRelations() {
91         Set set = expr.getInversedRelations();
92         if (inverse) {
93             set.add(relation);
94         }
95         return set;
96     }
97
98     public Set getRequiredDescriptors() {
99         Set v = expr.getRequiredDescriptors();        
100         v.add(relation);
101         return v;
102     }
103
104     public void generate(CodeWriter writer, VarDescriptor dest) {
105         VarDescriptor domain = VarDescriptor.makeNew("domain");
106         String strinverse = inverse ? "inv" : "";
107         String found = (VarDescriptor.makeNew("found")).getSafeSymbol();
108         expr.generate(writer, domain);
109         writer.outputline(relation.getRange().getType().getGenerateType().getSafeSymbol() + " " + dest.getSafeSymbol() + ";");
110         writer.outputline("int " + found + " = " + relation.getSafeSymbol() + "_hash" + strinverse + "->get(" + domain.getSafeSymbol() + ", " + dest.getSafeSymbol() + ");");
111         writer.outputline("if (!" + found + ") { maybe = 1; }");
112     }
113
114     // #TBD#: don't think this method is needed (or even called/referenced)
115     /*
116       public void generate_set(CodeWriter writer, VarDescriptor dest) {
117       VarDescriptor domain = VarDescriptor.makeNew("domain");
118       expr.generate(writer, domain);
119       writer.outputline(relation.getRange().getType().getGenerateType().getSafeSymbol() + " " + dest.getSafeSymbol() + " = " + relation.getSafeSymbol() + "_hash->get(" + domain.getSafeSymbol() + ");");
120       }
121     */
122
123     public void prettyPrint(PrettyPrinter pp) {
124         expr.prettyPrint(pp);
125         pp.output(".");
126         
127         if (inverse) {
128             pp.output("~");
129         }
130
131         pp.output(relation.getSafeSymbol());
132     }
133
134     public TypeDescriptor typecheck(SemanticAnalyzer sa) {
135
136         TypeDescriptor type = expr.typecheck(sa);
137         
138         if (type == null) {
139             return null;
140         }
141
142         /* check to make sure that the types of the relation match up */
143         if (inverse) {
144             TypeDescriptor rangetype = relation.getRange().getType();
145             
146             if (rangetype != type) {
147                 sa.getErrorReporter().report(null, "Type of left side of relation operator '.' is '" + type.getSymbol() + 
148                                     "' but must be '" + rangetype.getSymbol() + 
149                                     "', the type of the range of the relation '" + relation.getSymbol() + "'");
150                 return null;
151             }
152             
153             this.td = relation.getDomain().getType();
154             return this.td;
155         } else { /* not inverse */
156             TypeDescriptor domaintype = relation.getDomain().getType();
157             
158             if (domaintype != type) {
159                 sa.getErrorReporter().report(null, "Type of left side of relation operator '.' is '" + type.getSymbol() + 
160                                     "' but must be '" + domaintype.getSymbol() + 
161                                     "', the type of the domain of the relation '" + relation.getSymbol() + "'");
162                 return null;
163             }
164
165             this.td = relation.getRange().getType();
166             return this.td;
167         }
168     }
169
170 }