001/*
002 * Copyright (c) 2012-2017 Institut National des Sciences Appliquées de Lyon (INSA-Lyon)
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 */
009
010package org.eclipse.golo.compiler.ir;
011
012import org.eclipse.golo.runtime.OperatorType;
013import org.eclipse.golo.compiler.parser.GoloParser;
014import org.eclipse.golo.compiler.PackageAndClass;
015
016public final class Builders {
017  private Builders() {
018    // utility static class
019  }
020
021  public static NamedArgument namedArgument(String name) {
022    return new NamedArgument(name);
023  }
024
025  public static MethodInvocation invoke(String name) {
026    return new MethodInvocation(name);
027  }
028
029  public static Augmentation augment(String target) {
030    return new Augmentation(PackageAndClass.fromString(target));
031  }
032
033  public static Augmentation augment(PackageAndClass target) {
034    return new Augmentation(target);
035  }
036
037  public static NamedAugmentation augmentation(String name) {
038    return new NamedAugmentation(PackageAndClass.fromString(name));
039  }
040
041  public static NamedAugmentation augmentation(PackageAndClass name) {
042    return new NamedAugmentation(name);
043  }
044
045  public static LoopStatement loop() {
046    return new LoopStatement();
047  }
048
049  public static LoopStatement whileLoop(Object condition) {
050    return loop().condition(condition);
051  }
052
053  public static ForEachLoopStatement foreach() {
054    return new ForEachLoopStatement();
055  }
056
057  public static CaseStatement cases() {
058    return new CaseStatement();
059  }
060
061  public static MatchExpression match() {
062    return new MatchExpression();
063  }
064
065  public static AssignmentStatement assignment() {
066    return new AssignmentStatement();
067  }
068
069  /**
070   * Creates a assignment of the given expression.
071   */
072  public static AssignmentStatement assign(Object expression) {
073    return assignment().as(expression);
074  }
075
076  /**
077   * Creates a declaring assignment to a given reference.
078   */
079  public static AssignmentStatement define(Object reference) {
080    return assignment().to(reference).declaring();
081  }
082
083  public static DestructuringAssignment destruct() {
084    return new DestructuringAssignment();
085  }
086
087  public static UnaryOperation not(ExpressionStatement expression) {
088    return new UnaryOperation(OperatorType.NOT, expression);
089  }
090
091  public static BinaryOperation binaryOperation(OperatorType type, Object left, Object right) {
092    return binaryOperation(type).left(left).right(right);
093  }
094
095  public static BinaryOperation binaryOperation(Object type) {
096    return BinaryOperation.of(type);
097  }
098
099  public static Decorator decorator(Object expr) {
100    return new Decorator((ExpressionStatement) expr);
101  }
102
103  public static GoloFunction functionDeclaration() {
104    return new GoloFunction();
105  }
106
107  public static GoloFunction functionDeclaration(String name) {
108    return new GoloFunction().name(name);
109  }
110
111  public static ClosureReference lambda(String... parameters) {
112    return functionDeclaration()
113      .withParameters(parameters)
114      .synthetic()
115      .local()
116      .asClosure()
117      .asClosureReference();
118  }
119
120  public static FunctionInvocation functionInvocation() {
121    return new FunctionInvocation();
122  }
123
124  public static FunctionInvocation call(String name) {
125    return new FunctionInvocation(name);
126  }
127
128  public static BinaryOperation anonCall(Object receiver, Object invocation) {
129    return binaryOperation(
130        OperatorType.ANON_CALL,
131        (ExpressionStatement) receiver,
132        (FunctionInvocation) invocation);
133  }
134
135  public static Block block() {
136    return Block.emptyBlock();
137  }
138
139  public static Block block(Object... statements) {
140    Block block = Block.emptyBlock();
141    for (Object st : statements) {
142      block.add(st);
143    }
144    return block;
145  }
146
147  public static ReferenceLookup refLookup(String name) {
148    return new ReferenceLookup(name);
149  }
150
151  public static ConstantStatement constant(Object value) {
152    if (value instanceof Class) {
153      return classRef(value);
154    }
155    if (value instanceof ConstantStatement) {
156      return (ConstantStatement) value;
157    }
158    return new ConstantStatement(value);
159  }
160
161  public static ConstantStatement classRef(Object cls) {
162    if (cls instanceof String) {
163      return constant(toClassRef((String) cls));
164    }
165    if (cls instanceof Class) {
166      return constant(toClassRef((Class) cls));
167    }
168    if (cls instanceof GoloParser.ParserClassRef) {
169      return constant(cls);
170    }
171    if (cls instanceof PackageAndClass) {
172      return constant(toClassRef(cls.toString()));
173    }
174    throw new IllegalArgumentException("unknown type " + cls.getClass() + "to build a class reference");
175  }
176
177  public static ConstantStatement functionRef(Object funcName) {
178    return functionRef(null, funcName, -1);
179  }
180
181  public static ConstantStatement functionRef(Object moduleName, Object funcName) {
182    return functionRef(moduleName, funcName, -1);
183  }
184
185  public static ConstantStatement functionRef(Object moduleName, Object funcName, Object arity) {
186    return functionRef(moduleName, funcName, -1, false);
187  }
188
189  public static ConstantStatement functionRef(Object moduleName, Object funcName, Object arity, Object varargs) {
190    return constant(new GoloParser.FunctionRef(
191          (String) moduleName,
192          (String) funcName,
193          (Integer) arity,
194          (Boolean) varargs));
195  }
196
197  public static ReturnStatement returns(Object expr) {
198    return new ReturnStatement((ExpressionStatement) expr);
199  }
200
201  public static ThrowStatement raise(Object expression) {
202    return new ThrowStatement((ExpressionStatement) expression);
203  }
204
205  public static LocalReference localRef(Object name) {
206    return new LocalReference(name.toString());
207  }
208
209  public static GoloParser.ParserClassRef toClassRef(Class<?> cls) {
210    return toClassRef(cls.getCanonicalName());
211  }
212
213  public static GoloParser.ParserClassRef toClassRef(String clsName) {
214    return new GoloParser.ParserClassRef(clsName);
215  }
216
217  public static Struct structure(String name) {
218    return new Struct(name);
219  }
220
221  public static Union union(String name) {
222    return new Union(name);
223  }
224
225  public static CollectionLiteral collection(String type, Object... values) {
226    return collection(CollectionLiteral.Type.valueOf(type), values);
227  }
228
229  public static CollectionLiteral collection(CollectionLiteral.Type type, Object... values) {
230    CollectionLiteral col = new CollectionLiteral(type);
231    for (Object v : values) {
232      col.add(v);
233    }
234    return col;
235  }
236
237  public static CollectionLiteral list(Object... values) {
238    return collection(CollectionLiteral.Type.list, values);
239  }
240
241  public static CollectionLiteral array(Object... values) {
242    return collection(CollectionLiteral.Type.array, values);
243  }
244
245  public static CollectionLiteral set(Object... values) {
246    return collection(CollectionLiteral.Type.set, values);
247  }
248
249  public static CollectionLiteral map(Object... values) {
250    return collection(CollectionLiteral.Type.map, values);
251  }
252
253  public static CollectionLiteral tuple(Object... values) {
254    return collection(CollectionLiteral.Type.tuple, values);
255  }
256
257  public static CollectionLiteral vector(Object... values) {
258    return collection(CollectionLiteral.Type.vector, values);
259  }
260
261  public static CollectionLiteral range(Object... values) {
262    return collection(CollectionLiteral.Type.range, values);
263  }
264
265  public static CollectionComprehension collectionComprehension(CollectionLiteral.Type type) {
266    return new CollectionComprehension(type);
267  }
268
269  public static CollectionComprehension collectionComprehension(String typeName) {
270    return collectionComprehension(CollectionLiteral.Type.valueOf(typeName));
271  }
272
273  public static CollectionComprehension arrayComprehension() {
274    return new CollectionComprehension(CollectionLiteral.Type.array);
275  }
276
277  public static CollectionComprehension listComprehension() {
278    return new CollectionComprehension(CollectionLiteral.Type.list);
279  }
280
281  public static CollectionComprehension setComprehension() {
282    return new CollectionComprehension(CollectionLiteral.Type.set);
283  }
284
285  public static CollectionComprehension mapComprehension() {
286    return new CollectionComprehension(CollectionLiteral.Type.map);
287  }
288
289  public static CollectionComprehension tupleComprehension() {
290    return new CollectionComprehension(CollectionLiteral.Type.tuple);
291  }
292
293  public static CollectionComprehension vectorComprehension() {
294    return new CollectionComprehension(CollectionLiteral.Type.vector);
295  }
296
297  public static TryCatchFinally tryCatch(String exceptionId) {
298    return new TryCatchFinally(exceptionId);
299  }
300
301  public static GoloStatement toGoloStatement(Object statement) {
302    if (statement == null) { return null; }
303    if (statement instanceof GoloStatement) {
304      return (GoloStatement) statement;
305    }
306    throw cantConvert(statement, "GoloStatement");
307  }
308
309  public static Block toBlock(Object block) {
310    if (block == null) { return Block.emptyBlock(); }
311    if (block instanceof Block) {
312      return (Block) block;
313    }
314    throw cantConvert(block, "Block");
315  }
316
317  private static IllegalArgumentException cantConvert(Object value, String target) {
318    return new IllegalArgumentException(
319        String.format("%s is not a %s, but a %s",
320        value, target, value.getClass()));
321  }
322
323  public static GoloModule module(PackageAndClass name) {
324    return new GoloModule(name);
325  }
326
327  public static GoloModule module(String name) {
328    return new GoloModule(PackageAndClass.fromString(name));
329  }
330
331  public static ModuleImport moduleImport(Object name) {
332    if (name instanceof String) {
333      return new ModuleImport(PackageAndClass.fromString((String) name));
334    }
335    if (name instanceof PackageAndClass) {
336      return new ModuleImport((PackageAndClass) name);
337    }
338    throw cantConvert(name, "string or package");
339  }
340
341  public static ConditionalBranching branch() {
342    return new ConditionalBranching();
343  }
344
345  public static ConditionalBranching branch(Object condition,
346                                            Block trueBlock,
347                                            Block falseBlock,
348                                            ConditionalBranching elseBranch) {
349    return branch().condition(condition)
350      .whenTrue(trueBlock)
351      .whenFalse(falseBlock)
352      .elseBranch(elseBranch);
353  }
354
355  public static Member member(String name) {
356    return new Member(name);
357  }
358}