001/*
002 * Copyright (c) 2012-2018 Institut National des Sciences Appliquées de Lyon (INSA Lyon) and others
003 *
004 * This program and the accompanying materials are made available under the
005 * terms of the Eclipse Public License 2.0 which is available at
006 * http://www.eclipse.org/legal/epl-2.0.
007 *
008 * SPDX-License-Identifier: EPL-2.0
009 */
010
011package gololang.ir;
012
013import java.util.List;
014import java.util.LinkedList;
015import java.util.Collections;
016
017import gololang.ir.CollectionLiteral.Type;
018
019/**
020 * Represents a collection literal.
021 *
022 * <p>For instance code such as:
023 * <pre class="listing"><code class="lang-golo" data-lang="golo">
024 * list[1, 2, 3]
025 * </code></pre>
026 * @see Type
027 */
028public final class CollectionLiteral extends ExpressionStatement<CollectionLiteral> {
029
030  public enum Type {
031    array, list, set, map, tuple, vector, range
032  }
033
034  private final Type type;
035  private final List<ExpressionStatement<?>> expressions = new LinkedList<>();
036
037  private CollectionLiteral(Type type) {
038    super();
039    this.type = type;
040  }
041
042  /**
043   * Creates a collection literal of the given type.
044   *
045   * <p>For instance:
046   * <pre class="listing"><code class="lang-java" data-lang="java">
047   * collection(CollectionLiteral.Type.array, constant(1), constant(2), constant(3))
048   * </code></pre>
049   * creates
050   * <pre class="listing"><code class="lang-golo" data-lang="golo">
051   * array[1, 2, 3]
052   * </code></pre>
053   *
054   * @param type the type
055   * @param values expressions to add to the collection
056   */
057  public static CollectionLiteral create(Object type, Object... values) {
058    CollectionLiteral col = new CollectionLiteral(
059        type instanceof CollectionLiteral.Type
060          ? (CollectionLiteral.Type) type
061          : CollectionLiteral.Type.valueOf(type.toString()));
062    for (Object v : values) {
063      col.add(v);
064    }
065    return col;
066  }
067
068
069  protected CollectionLiteral self() { return this; }
070
071  /**
072   * Adds an expression to the collection.
073   *
074   * @param expression the expression to add.
075   * @return the collection literal.
076   */
077  public CollectionLiteral add(Object expression) {
078    this.expressions.add(makeParentOf(ExpressionStatement.of(expression)));
079    return this;
080  }
081
082  public Type getType() {
083    return type;
084  }
085
086  public List<ExpressionStatement<?>> getExpressions() {
087    return expressions;
088  }
089
090  @Override
091  public String toString() {
092    return this.type.toString() + this.expressions.toString();
093  }
094
095  /**
096   * {@inheritDoc}
097   */
098  @Override
099  public void accept(GoloIrVisitor visitor) {
100    visitor.visitCollectionLiteral(this);
101  }
102
103  /**
104   * {@inheritDoc}
105   */
106  @Override
107  public List<GoloElement<?>> children() {
108    return Collections.unmodifiableList(expressions);
109  }
110
111  /**
112   * {@inheritDoc}
113   */
114  @Override
115  protected void replaceElement(GoloElement<?> original, GoloElement<?> newElement) {
116    if (expressions.contains(original) && newElement instanceof ExpressionStatement) {
117      expressions.set(expressions.indexOf(original), ExpressionStatement.of(newElement));
118    } else {
119      throw cantReplace(original, newElement);
120    }
121  }
122}