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