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