IR
[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     // #TBD#: right now i'm not sure if this is the best way to organize the relationexpr... it may be better
8     // to have one class represent each a.B.B'.B'' expression with a VarDescriptor for the a and a vector 
9     // for the list of B
10     RelationExpr subdomain;
11     VarDescriptor domain;
12
13     RelationDescriptor relation;
14     boolean inverse;
15
16     public RelationExpr() {
17         this.domain = null;
18         this.subdomain = null;
19         this.relation = null;
20         this.inverse = false;
21     }
22
23     public RelationExpr(RelationExpr subdomain) {
24         this.subdomain = subdomain;
25         this.domain = null;
26         this.relation = null;
27         this.inverse = false;
28     }
29
30     public void setRelation(RelationDescriptor rd, boolean inverse) {
31         this.relation = rd;
32         this.inverse = inverse;
33     }
34
35     public void setDomain(VarDescriptor vd) {
36         this.domain = vd;
37     }
38
39     public Set getRequiredDescriptors() {
40         HashSet v = new HashSet();
41         v.add(relation);
42         if (subdomain != null) {
43             v.addAll(subdomain.getRequiredDescriptors());
44         }
45         return v;
46     }
47
48     public void generate(CodeWriter writer, VarDescriptor dest) {
49         if (domain != null) { /* base case */
50             writer.outputline(relation.getRange().getType().getSafeSymbol() + " " + dest.getSymbol() + " = " + relation.getSafeSymbol() + "_hash.getFirst(" + domain.getSafeSymbol() + ");");
51         } else {
52             VarDescriptor ld = VarDescriptor.makeNew();
53             subdomain.generate(writer, ld);
54             writer.outputline(relation.getRange().getType().getSafeSymbol() + " " + dest.getSymbol() + " = " + relation.getSafeSymbol() + "_hash.getFirst(" + ld.getSafeSymbol() + ");");
55         }            
56
57     }
58
59     public void generate_set(CodeWriter writer, VarDescriptor dest) {
60         if (domain != null) { /* base case */
61             writer.outputline("Set " + dest.getSymbol() + " = " + relation.getSafeSymbol() + "_hash.get(" + domain.getSafeSymbol() + ");");
62         } else {
63             VarDescriptor ld = VarDescriptor.makeNew();
64             subdomain.generate(writer, ld);
65             writer.outputline("Set " + dest.getSymbol() + " = " + relation.getSafeSymbol() + "_hash.get(" + domain.getSafeSymbol() + ");");
66         }     
67     }
68
69     public void prettyPrint(PrettyPrinter pp) {
70         if (subdomain != null) {
71             subdomain.prettyPrint(pp);
72         } else {
73             pp.output(domain.getSafeSymbol());
74         }
75
76         pp.output(".");
77         
78         if (inverse) {
79             pp.output("~");
80         }
81
82         pp.output(relation.getSafeSymbol());
83     }
84
85     public TypeDescriptor typecheck(SemanticAnalyzer sa) {
86         TypeDescriptor type = null;
87         
88         if (domain != null) {
89             type = domain.getType();            
90         } else {
91             type = subdomain.typecheck(sa);
92         }
93
94         if (type == null) {
95             return null;
96         }
97
98         /* check to make sure that the types of the relation match up */
99         if (inverse) {
100             TypeDescriptor rangetype = relation.getRange().getType();
101             
102             if (rangetype != type) {
103                 sa.getErrorReporter().report(null, "Type of left side of relation operator '.' is '" + type.getSymbol() + 
104                                     "' but must be the '" + rangetype.getSymbol() + 
105                                     "', the type of the range of the relation '" + relation.getSymbol() + "'");
106                 return null;
107             }
108             
109             this.td = relation.getDomain().getType();
110             return this.td;
111         } else { /* not inverse */
112             TypeDescriptor domaintype = relation.getDomain().getType();
113             
114             if (domaintype != type) {
115                 sa.getErrorReporter().report(null, "Type of left side of relation operator '.' is '" + type.getSymbol() + 
116                                     "' but must be the '" + domaintype.getSymbol() + 
117                                     "', the type of the range of the relation '" + relation.getSymbol() + "'");
118                 return null;
119             }
120
121             this.td = relation.getRange().getType();
122             return this.td;
123         }
124     }
125
126 }