*** empty log message ***
[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 RelationExpr(Expr expr, RelationDescriptor relation, boolean inverse) {
12         this.expr = expr;
13         this.relation = relation;
14         this.inverse = inverse;
15     }
16
17     public Set freeVars() {
18         return expr.freeVars();
19     }
20
21     public String name() {
22         String name=expr.name()+".";
23         if (inverse)
24             name+="~";
25         name+=relation.toString();
26         return name;
27     }
28
29     public Expr getExpr() {
30         return expr;
31     }
32
33     public boolean equals(Map remap, Expr e) {
34         if (e==null||!(e instanceof RelationExpr))
35             return false;
36         RelationExpr re=(RelationExpr)e;
37         if (re.relation!=relation)
38             return false;
39         if (!expr.equals(remap,re.expr))
40             return false;
41         if (inverse!=re.inverse)
42             return false;
43         return true;
44     }
45
46     public boolean usesDescriptor(Descriptor rd) {
47         if (rd==relation)
48             return true;
49         else
50             return expr.usesDescriptor(rd);
51     }
52     
53     public RelationDescriptor getRelation() {
54         return relation;
55     }
56
57     public Descriptor getDescriptor() {
58         return relation;
59     }
60
61     public boolean inverted() {
62         return inverse;
63     }
64
65     public Set getInversedRelations() {
66         Set set = expr.getInversedRelations();
67         if (inverse) {
68             set.add(relation);
69         }
70         return set;
71     }
72
73     public Set getRequiredDescriptors() {
74         Set v = expr.getRequiredDescriptors();        
75         v.add(relation);
76         return v;
77     }
78
79     public void generate(CodeWriter writer, VarDescriptor dest) {
80         VarDescriptor domain = VarDescriptor.makeNew("domain");
81         String strinverse = inverse ? "inv" : "";
82         String found = (VarDescriptor.makeNew("found")).getSafeSymbol();
83         expr.generate(writer, domain);
84         writer.outputline(relation.getRange().getType().getGenerateType().getSafeSymbol() + " " + dest.getSafeSymbol() + ";");
85         writer.outputline("int " + found + " = " + relation.getSafeSymbol() + "_hash" + strinverse + "->get(" + domain.getSafeSymbol() + ", " + dest.getSafeSymbol() + ");");
86         writer.outputline("if (!" + found + ") { maybe = 1; }");
87     }
88
89     // #TBD#: don't think this method is needed (or even called/referenced)
90     /*
91       public void generate_set(CodeWriter writer, VarDescriptor dest) {
92       VarDescriptor domain = VarDescriptor.makeNew("domain");
93       expr.generate(writer, domain);
94       writer.outputline(relation.getRange().getType().getGenerateType().getSafeSymbol() + " " + dest.getSafeSymbol() + " = " + relation.getSafeSymbol() + "_hash->get(" + domain.getSafeSymbol() + ");");
95       }
96     */
97
98     public void prettyPrint(PrettyPrinter pp) {
99         expr.prettyPrint(pp);
100         pp.output(".");
101         
102         if (inverse) {
103             pp.output("~");
104         }
105
106         pp.output(relation.getSafeSymbol());
107     }
108
109     public TypeDescriptor typecheck(SemanticAnalyzer sa) {
110
111         TypeDescriptor type = expr.typecheck(sa);
112         
113         if (type == null) {
114             return null;
115         }
116
117         /* check to make sure that the types of the relation match up */
118         if (inverse) {
119             TypeDescriptor rangetype = relation.getRange().getType();
120             
121             if (rangetype != type) {
122                 sa.getErrorReporter().report(null, "Type of left side of relation operator '.' is '" + type.getSymbol() + 
123                                     "' but must be '" + rangetype.getSymbol() + 
124                                     "', the type of the range of the relation '" + relation.getSymbol() + "'");
125                 return null;
126             }
127             
128             this.td = relation.getDomain().getType();
129             return this.td;
130         } else { /* not inverse */
131             TypeDescriptor domaintype = relation.getDomain().getType();
132             
133             if (domaintype != type) {
134                 sa.getErrorReporter().report(null, "Type of left side of relation operator '.' is '" + type.getSymbol() + 
135                                     "' but must be '" + domaintype.getSymbol() + 
136                                     "', the type of the domain of the relation '" + relation.getSymbol() + "'");
137                 return null;
138             }
139
140             this.td = relation.getRange().getType();
141             return this.td;
142         }
143     }
144
145 }