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.Objects;
014import java.util.Collections;
015import java.util.List;
016
017public final class ReturnStatement extends GoloStatement<ReturnStatement> {
018
019  private GoloStatement<?> expressionStatement;
020  private boolean returningVoid;
021  private boolean synthetic;
022
023  private ReturnStatement(ExpressionStatement<?> expression) {
024    super();
025    setExpressionStatement(expression);
026    this.returningVoid = false;
027    this.synthetic = false;
028  }
029
030  /**
031   * Creates a {@code return} statement.
032   *
033   * @param value an object interpreted as an {@link ExpressionStatement}
034   * @see ExpressionStatement#of(Object)
035   */
036  public static ReturnStatement of(Object value) {
037    return new ReturnStatement(ExpressionStatement.of(value));
038  }
039
040  /**
041   * Creates a {@code void} return statement.
042   */
043  public static ReturnStatement empty() {
044    return new ReturnStatement(null).returningVoid();
045  }
046
047  protected ReturnStatement self() { return this; }
048
049  public GoloStatement<?> expression() {
050    return expressionStatement;
051  }
052
053  private void setExpressionStatement(GoloStatement<?> stat) {
054    if (stat != null) {
055      this.expressionStatement = makeParentOf(stat);
056    } else {
057      this.expressionStatement = null;
058    }
059  }
060
061  public boolean isReturningVoid() {
062    return returningVoid;
063  }
064
065  public ReturnStatement returningVoid() {
066    this.returningVoid = true;
067    return this;
068  }
069
070  public ReturnStatement synthetic() {
071    this.synthetic = true;
072    return this;
073  }
074
075  public boolean isSynthetic() {
076    return this.synthetic;
077  }
078
079  @Override
080  public String toString() {
081    return "return " + (
082        returningVoid || expressionStatement == null
083        ? ""
084        : expressionStatement.toString());
085  }
086
087  /**
088   * {@inheritDoc}
089   */
090  @Override
091  public void accept(GoloIrVisitor visitor) {
092    visitor.visitReturnStatement(this);
093  }
094
095  /**
096   * {@inheritDoc}
097   */
098  @Override
099  public List<GoloElement<?>> children() {
100    if (expressionStatement != null) {
101      return Collections.singletonList(expressionStatement);
102    }
103    return Collections.emptyList();
104  }
105
106  /**
107   * {@inheritDoc}
108   */
109  @Override
110  protected void replaceElement(GoloElement<?> original, GoloElement<?> newElement) {
111    if (Objects.equals(original, expressionStatement) && newElement instanceof ExpressionStatement) {
112      setExpressionStatement(ExpressionStatement.of(newElement));
113    } else {
114      throw cantReplace(original, newElement);
115    }
116  }
117}