Small changes to allow:
[repair.git] / Repair / RepairCompiler / MCC / IR / LogicStatement.java
1 package MCC.IR;
2
3 import java.util.*;
4
5 public class LogicStatement {
6
7     public static final Operation AND = new Operation("AND");
8     public static final Operation OR = new Operation("OR");
9     public static final Operation NOT = new Operation("NOT");
10
11     public String name() {
12         if (op==NOT)
13             return "!("+left.name()+")";
14         String name=left.name();
15         name+=" "+op.toString()+" ";
16         if (right!=null)
17             name+=right.name();
18         return name;
19     }
20
21     public Set getInversedRelations() {
22         if (left == null) {
23             throw new IRException();
24         }
25         Set set = left.getInversedRelations();
26         if (right != null) {
27             set.addAll(right.getInversedRelations());
28         }
29         return set;
30     }
31
32     public TypeDescriptor typecheck(SemanticAnalyzer sa) {
33         TypeDescriptor lt=left.typecheck(sa);
34         if (lt!=ReservedTypeDescriptor.INT)
35             return null;
36         TypeDescriptor rt;
37         if (op!=NOT) {
38             rt=right.typecheck(sa);
39             if (rt!=ReservedTypeDescriptor.INT)
40                 return null;
41         }
42         return ReservedTypeDescriptor.INT;
43     }
44
45     public DNFConstraint constructDNF() {
46         if (op==AND) {
47             DNFConstraint leftd=left.constructDNF();
48             DNFConstraint rightd=right.constructDNF();
49             return leftd.and(rightd);
50         } else if (op==OR) {
51             DNFConstraint leftd=left.constructDNF();
52             DNFConstraint rightd=right.constructDNF();
53             return leftd.or(rightd);
54         } else if (op==NOT) {
55             DNFConstraint leftd=left.constructDNF();
56             return leftd.not();
57         } else throw new Error();
58     }
59
60     public static class Operation {
61         private final String name;
62         private Operation(String opname) { name = opname; }
63         public String toString() { return name; }
64     }
65
66     Operation op;
67     LogicStatement left;
68     LogicStatement right;
69
70     public LogicStatement(Operation op, LogicStatement left, LogicStatement right) {
71         if (op == NOT) {
72             throw new IllegalArgumentException("Must be a AND or OR expression.");
73         }
74
75         this.op = op;
76         this.left = left;
77         this.right = right;
78     }
79
80     public LogicStatement(Operation op, LogicStatement left) {
81         if (op != NOT) {
82             throw new IllegalArgumentException("Must be a NOT expression.");
83         }
84
85         this.op = op;
86         this.left = left;
87         this.right = null;
88     }
89
90     protected LogicStatement() {
91         this.op = null;
92         this.left = null;
93         this.right = null;
94     }
95
96     public Set getRequiredDescriptors() {
97         Set v = left.getRequiredDescriptors();
98         if (right != null) {
99             v.addAll(right.getRequiredDescriptors());
100         }
101         return v;
102     }
103
104     public void generate(CodeWriter writer, VarDescriptor dest) {
105
106         writer.addDeclaration("int", dest.getSafeSymbol());
107
108         if (op == NOT) {
109
110             VarDescriptor leftd = VarDescriptor.makeNew("leftboolean");
111             left.generate(writer, leftd);
112
113             writer.outputline("/* 3-valued NOT*/");
114             //            writer.outputline("if (!maybe)"); //this isn't really necessary
115             writer.startblock();
116             writer.outputline(dest.getSafeSymbol() + " =  !" + leftd.getSafeSymbol() + ";");
117             writer.endblock();
118
119         } else { // two operands
120
121             VarDescriptor leftd = VarDescriptor.makeNew("leftboolean");
122             String lm = (VarDescriptor.makeNew("leftmaybe")).getSafeSymbol();
123             left.generate(writer, leftd);
124             writer.addDeclaration("int", lm);
125             writer.outputline(lm + " = maybe;");
126             writer.outputline("maybe=0;");
127             VarDescriptor rightd = VarDescriptor.makeNew("rightboolean");
128             String rm = (VarDescriptor.makeNew("rightmaybe")).getSafeSymbol();
129             assert right != null;
130             right.generate(writer, rightd);
131             writer.addDeclaration("int", rm);
132             writer.outputline(rm + " = maybe;");
133
134             String l = leftd.getSafeSymbol();
135             String r = rightd.getSafeSymbol();
136
137             if (op == AND) {
138
139                 /*
140                  * 3-value AND LOGIC
141                  *
142                  * LRLR
143                  * MM    M O
144                  * ----  ---
145                  * 0000  0 0
146                  * 0001  0 0
147                  * 0010  0 0
148                  * 0011  0 1
149                  * 0100  0 0
150                  * 0101  0 0
151                  * 0110  1 X
152                  * 0111  1 X
153                  * 1000  0 0
154                  * 1001  1 X
155                  * 1010  0 0
156                  * 1011  1 X
157                  * 1100  1 X
158                  * 1101  1 X
159                  * 1110  1 X
160                  * 1111  1 X
161                  *
162                  * M = (L*RM) + (R*LM) + (LM*RM)
163                  * O = (L*R)
164                  */
165
166                 // maybe = (l && rm) || (r && lm) || (lm && rm)
167                 writer.outputline("maybe = (" + l + " && " + rm + ") || (" + r + " && " + lm + ") || (" + lm + " && " + rm + ");");
168                 writer.outputline(dest.getSafeSymbol() + " = " + l + " && " + r + ";");
169
170             } else if (op == OR) {
171
172                 /*
173                  * 3-value OR LOGIC
174                  *
175                  * LRLR
176                  * MM    M O
177                  * ----  ---
178                  * 0000  0 0
179                  * 0001  0 1
180                  * 0010  0 1
181                  * 0011  0 1
182                  * 0100  1 X
183                  * 0101  1 X
184                  * 0110  0 1
185                  * 0111  0 1
186                  * 1000  1 X
187                  * 1001  0 1
188                  * 1010  1 X
189                  * 1011  0 1
190                  * 1100  1 X
191                  * 1101  1 X
192                  * 1110  1 X
193                  * 1111  1 X
194                  *
195                  * M = (!L*RM) + (!R*LM) + (LM*RM)
196                  * O = L+R
197                  */
198
199                 // maybe = (!l && rm) || (!r && lm) || (lm && rm)
200                 writer.outputline("maybe = (!" + l + " && " + rm + ") || (!" + r + " && " + lm + ") || (" + lm + " && " + rm + ");");
201                 writer.outputline(dest.getSafeSymbol() + " = " + l + " || " + r + ";");
202             } else {
203                 throw new IRException();
204             }
205         }
206     }
207 }