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