001/*
002 * Copyright (c) 2012-2021 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.*;
014import org.eclipse.golo.compiler.PackageAndClass;
015import static gololang.Messages.message;
016
017/**
018 * Named augmentation definition.
019 */
020public final class NamedAugmentation extends GoloElement<NamedAugmentation> implements FunctionContainer, ToplevelGoloElement, NamedElement {
021  private final PackageAndClass name;
022  private final Set<GoloFunction> functions = new LinkedHashSet<>();
023  private final Set<MacroInvocation> macroCalls = new LinkedHashSet<>();
024
025  private NamedAugmentation(PackageAndClass name) {
026    super();
027    this.name = name;
028  }
029
030  /**
031   * Creates a named augmentation.
032   *
033   * @param name the name of the augmentation (compatible with {@link PackageAndClass#of(Object)})
034   */
035  public static NamedAugmentation of(Object name) {
036    return new NamedAugmentation(PackageAndClass.of(name));
037  }
038
039  @Override
040  public String getName() {
041    return this.name.toString();
042  }
043
044  public PackageAndClass getPackageAndClass() {
045    return this.name;
046  }
047
048  protected NamedAugmentation self() { return this; }
049
050  /**
051   * {@inheritDoc}
052   */
053  @Override
054  public List<GoloFunction> getFunctions() {
055    return new ArrayList<>(functions);
056  }
057
058  /**
059   * {@inheritDoc}
060   */
061  @Override
062  public void addFunction(GoloFunction func) {
063    if (func.getArity() == 0) {
064      throw new IllegalArgumentException(message("augment_function_no_args", func.getName(), this.getPackageAndClass()));
065    }
066    functions.add(makeParentOf(func));
067  }
068
069  /**
070   * {@inheritDoc}
071   */
072  @Override
073  public void addMacroInvocation(MacroInvocation macroCall) {
074    macroCalls.add(macroCall);
075    makeParentOf(macroCall);
076  }
077
078  /**
079   * {@inheritDoc}
080   */
081  @Override
082  public boolean hasFunctions() {
083    return !functions.isEmpty();
084  }
085
086  /**
087   * Adds the elements to this augmentation.
088   *
089   * <p>This is a builder method.
090   *
091   * @see FunctionContainer#addElement(Object)
092   */
093  public NamedAugmentation add(Object... elts) {
094    for (Object elt : elts) {
095      addElement(elt);
096    }
097    return this;
098  }
099
100  /**
101   * {@inheritDoc}
102   */
103  @Override
104  public void accept(GoloIrVisitor visitor) {
105    visitor.visitNamedAugmentation(this);
106  }
107
108  /**
109   * {@inheritDoc}
110   */
111  @Override
112  public List<GoloElement<?>> children() {
113    LinkedList<GoloElement<?>> children = new LinkedList<>(functions);
114    children.addAll(macroCalls);
115    return children;
116  }
117
118  /**
119   * {@inheritDoc}
120   */
121  @Override
122  protected void replaceElement(GoloElement<?> original, GoloElement<?> newElement) {
123    if (functions.contains(original)) {
124      functions.remove(original);
125    } else if (macroCalls.contains(original)) {
126      macroCalls.remove(original);
127    } else {
128      throw cantReplace(original, newElement);
129    }
130    addElement(newElement);
131  }
132}