001package org.clafer.ast;
002
003import org.clafer.ast.AstQuantify.Quantifier;
004
005/**
006 * Import this class to access all AST building functions.
007 * <pre>
008 * import static org.clafer.ast.Asts.*;
009 * </pre>
010 *
011 * @author jimmy
012 */
013public class Asts {
014
015    private Asts() {
016    }
017    public static final AstIntClafer IntType = AstIntClafer.Singleton;
018    public static final AstBoolClafer BoolType = AstBoolClafer.Singleton;
019    // Cardinality keywords
020    public static final Card Any = new Card();
021    public static final Card Optional = new Card(0, 1);
022    public static final Card Mandatory = new Card(1, 1);
023    public static final Card Many = new Card(1);
024    // Not going to define group cardinality key words since they are confusing
025    // and they don't work like they do in the Clafer compiler. For example:
026    //   opt A
027    //       B
028    //       C
029    // is desugarred in the Clafer compiler to
030    //   opt A
031    //       B ?
032    //       C ?
033    // So the keywords implicitly affect the cardinalities of the children. If
034    // these keywords were defined in the API as below, they do not desugar the
035    // children and the behaviour is unexpected. Hence leave them undefined.
036    // public static final Card Opt = new Card();
037    // public static final Card Mux = new Card(0, 1);
038    // public static final Card Xor = new Card(1, 1);
039    // public static final Card Or = new Card(1);
040
041    public static AstModel newModel() {
042        return new AstModel();
043    }
044
045    public static AstThis $this() {
046        return new AstThis();
047    }
048
049    public static AstGlobal global(AstClafer type) {
050        return new AstGlobal(type);
051    }
052
053    public static AstConstant constant(int value) {
054        return constant(IntType, value);
055    }
056
057    public static AstConstant constant(AstClafer type, int... value) {
058        return new AstConstant(type, value);
059    }
060
061    public static AstSetExpr join(AstSetExpr left, AstConcreteClafer right) {
062        return new AstJoin(left, right);
063    }
064
065    public static AstSetExpr joinParent(AstSetExpr children) {
066        return new AstJoinParent(children);
067    }
068
069    public static AstSetExpr joinRef(AstSetExpr deref) {
070        return new AstJoinRef(deref);
071    }
072
073    public static AstBoolExpr not(AstBoolExpr expr) {
074        return new AstNot(expr);
075    }
076
077    public static AstSetExpr minus(AstSetExpr expr) {
078        return new AstMinus(expr);
079    }
080
081    public static AstSetExpr card(AstSetExpr set) {
082        return new AstCard(set);
083    }
084
085    public static AstBoolExpr test(AstSetExpr left, AstSetTest.Op op, AstSetExpr right) {
086        return new AstSetTest(left, op, right);
087    }
088
089    public static AstBoolExpr equal(AstSetExpr left, AstSetExpr right) {
090        return test(left, AstSetTest.Op.Equal, right);
091    }
092
093    public static AstBoolExpr notEqual(AstSetExpr left, AstSetExpr right) {
094        return test(left, AstSetTest.Op.NotEqual, right);
095    }
096
097    public static AstBoolExpr compare(AstSetExpr left, AstCompare.Op op, AstSetExpr right) {
098        return new AstCompare(left, op, right);
099    }
100
101    public static AstBoolExpr lessThan(AstSetExpr left, AstSetExpr right) {
102        return compare(left, AstCompare.Op.LessThan, right);
103    }
104
105    public static AstBoolExpr lessThanEqual(AstSetExpr left, AstSetExpr right) {
106        return compare(left, AstCompare.Op.LessThanEqual, right);
107    }
108
109    public static AstBoolExpr greaterThan(AstSetExpr left, AstSetExpr right) {
110        return compare(left, AstCompare.Op.GreaterThan, right);
111    }
112
113    public static AstBoolExpr greaterThanEqual(AstSetExpr left, AstSetExpr right) {
114        return compare(left, AstCompare.Op.GreaterThanEqual, right);
115    }
116
117    public static AstSetExpr arithm(AstArithm.Op op, AstSetExpr... operands) {
118        if (operands.length == 1) {
119            return operands[0];
120        }
121        return new AstArithm(op, operands);
122    }
123
124    public static AstSetExpr add(AstSetExpr... addends) {
125        return arithm(AstArithm.Op.Add, addends);
126    }
127
128    public static AstSetExpr sub(AstSetExpr... subtrahends) {
129        return arithm(AstArithm.Op.Sub, subtrahends);
130    }
131
132    public static AstSetExpr mul(AstSetExpr... multipliers) {
133        return arithm(AstArithm.Op.Mul, multipliers);
134    }
135
136    public static AstSetExpr div(AstSetExpr... divisors) {
137        return arithm(AstArithm.Op.Div, divisors);
138    }
139
140    public static AstSetExpr sum(AstSetExpr set) {
141        return new AstSum(set);
142    }
143
144    public static AstBoolExpr arithm(AstBoolArithm.Op op, AstBoolExpr... operands) {
145        if (operands.length == 1) {
146            return operands[0];
147        }
148        return new AstBoolArithm(op, operands);
149    }
150
151    public static AstBoolExpr and(AstBoolExpr... operands) {
152        return arithm(AstBoolArithm.Op.And, operands);
153    }
154
155    public static AstBoolExpr ifOnlyIf(AstBoolExpr... operands) {
156        return arithm(AstBoolArithm.Op.IfOnlyIf, operands);
157    }
158
159    public static AstBoolExpr implies(AstBoolExpr... operands) {
160        return arithm(AstBoolArithm.Op.Implies, operands);
161    }
162
163    public static AstBoolExpr or(AstBoolExpr... operands) {
164        return arithm(AstBoolArithm.Op.Or, operands);
165    }
166
167    public static AstBoolExpr xor(AstBoolExpr... operands) {
168        return arithm(AstBoolArithm.Op.Xor, operands);
169    }
170
171    public static AstSetExpr diff(AstSetExpr left, AstSetExpr right) {
172        return new AstDifference(left, right);
173    }
174
175    public static AstSetExpr inter(AstSetExpr left, AstSetExpr right) {
176        return new AstIntersection(left, right);
177    }
178
179    public static AstSetExpr union(AstSetExpr left, AstSetExpr right) {
180        return new AstUnion(left, right);
181    }
182
183    public static AstBoolExpr membership(AstSetExpr member, AstMembership.Op op, AstSetExpr set) {
184        return new AstMembership(member, op, set);
185    }
186
187    public static AstBoolExpr in(AstSetExpr member, AstSetExpr set) {
188        return membership(member, AstMembership.Op.In, set);
189    }
190
191    public static AstBoolExpr notIn(AstSetExpr member, AstSetExpr set) {
192        return membership(member, AstMembership.Op.NotIn, set);
193    }
194
195    public static AstSetExpr ifThenElse(AstBoolExpr antecedent, AstSetExpr consequent, AstSetExpr alternative) {
196        return new AstTernary(antecedent, consequent, alternative);
197    }
198
199    public static AstBoolExpr ifThenElse(AstBoolExpr antecedent, AstBoolExpr consequent, AstBoolExpr alternative) {
200        return new AstIfThenElse(antecedent, consequent, alternative);
201    }
202
203    /**
204     * Downcast an expression. Highly unlikely you will ever need to call this
205     * method since the compiler will automatically insert casts where
206     * necessary.
207     *
208     * @param base the set expression
209     * @param target the casted type
210     * @return {@code base} downcasted to type {@code target}
211     */
212    public static AstSetExpr downcast(AstSetExpr base, AstClafer target) {
213        return new AstDowncast(base, target);
214    }
215
216    /**
217     * Upcast an expression. Highly unlikely you will ever need to call this
218     * method since the compiler will automatically insert casts where
219     * necessary.
220     *
221     * @param base the set expression
222     * @param target the casted type
223     * @return {@code base} upcasted to type {@code target}
224     */
225    public static AstSetExpr upcast(AstSetExpr base, AstAbstractClafer target) {
226        return new AstUpcast(base, target);
227    }
228
229    public static AstBoolExpr lone(AstClafer clafer) {
230        // Syntactic sugar.
231        return lone(global(clafer));
232    }
233
234    public static AstBoolExpr lone(AstSetExpr set) {
235        // Syntactic sugar.
236        return lessThanEqual(card(set), constant(1));
237    }
238
239    public static AstBoolExpr none(AstClafer clafer) {
240        // Syntactic sugar.
241        return none(global(clafer));
242    }
243
244    public static AstBoolExpr none(AstSetExpr set) {
245        // Syntactic sugar.
246        return equal(card(set), constant(0));
247    }
248
249    public static AstBoolExpr one(AstClafer clafer) {
250        // Syntactic sugar.
251        return one(global(clafer));
252    }
253
254    public static AstBoolExpr one(AstSetExpr set) {
255        // Syntactic sugar.
256        return equal(card(set), constant(1));
257    }
258
259    public static AstBoolExpr some(AstClafer clafer) {
260        // Syntactic sugar.
261        return some(global(clafer));
262    }
263
264    public static AstBoolExpr some(AstSetExpr set) {
265        // Syntactic sugar.
266        return greaterThanEqual(card(set), constant(1));
267    }
268
269    public static AstLocal local(String name) {
270        return new AstLocal(name);
271    }
272
273    public static AstDecl decl(boolean disjoint, AstLocal[] locals, AstSetExpr body) {
274        return new AstDecl(disjoint, locals, body);
275    }
276
277    public static AstDecl decl(AstLocal[] locals, AstSetExpr body) {
278        return decl(false, locals, body);
279    }
280
281    public static AstDecl decl(AstLocal local, AstSetExpr body) {
282        return decl(new AstLocal[]{local}, body);
283    }
284
285    public static AstDecl disjDecl(AstLocal[] locals, AstSetExpr body) {
286        return decl(true, locals, body);
287    }
288
289    public static AstBoolExpr quantify(Quantifier quantifier, AstDecl[] decls, AstBoolExpr body) {
290        return new AstQuantify(quantifier, decls, body);
291    }
292
293    public static AstBoolExpr quantify(Quantifier quantifier, AstDecl decl, AstBoolExpr body) {
294        return quantify(quantifier, new AstDecl[]{decl}, body);
295    }
296
297    public static AstBoolExpr all(AstDecl[] decls, AstBoolExpr body) {
298        return quantify(Quantifier.All, decls, body);
299    }
300
301    public static AstBoolExpr all(AstDecl decl, AstBoolExpr body) {
302        return quantify(Quantifier.All, decl, body);
303    }
304
305    public static AstBoolExpr lone(AstDecl[] decls, AstBoolExpr body) {
306        return quantify(Quantifier.Lone, decls, body);
307    }
308
309    public static AstBoolExpr lone(AstDecl decl, AstBoolExpr body) {
310        return quantify(Quantifier.Lone, decl, body);
311    }
312
313    public static AstBoolExpr none(AstDecl[] decls, AstBoolExpr body) {
314        return quantify(Quantifier.None, decls, body);
315    }
316
317    public static AstBoolExpr none(AstDecl decl, AstBoolExpr body) {
318        return quantify(Quantifier.None, decl, body);
319    }
320
321    public static AstBoolExpr one(AstDecl[] decls, AstBoolExpr body) {
322        return quantify(Quantifier.One, decls, body);
323    }
324
325    public static AstBoolExpr one(AstDecl decl, AstBoolExpr body) {
326        return quantify(Quantifier.One, decl, body);
327    }
328
329    public static AstBoolExpr some(AstDecl[] decls, AstBoolExpr body) {
330        return quantify(Quantifier.Some, decls, body);
331    }
332
333    public static AstBoolExpr some(AstDecl decl, AstBoolExpr body) {
334        return quantify(Quantifier.Some, decl, body);
335    }
336}