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.*; 014 015import static java.util.Collections.unmodifiableSet; 016 017/** 018 * Represents a {@code union} element. 019 * 020 * <p>For instance: 021 * <pre class="listing"><code class="lang-golo" data-lang="golo"> 022 * union ConsList = { 023 * Empty 024 * Cons = {head, tail} 025 * } 026 * </code></pre> 027 */ 028public final class Union extends GoloType<Union> implements ToplevelGoloElement { 029 030 private final Set<UnionValue> values = new LinkedHashSet<>(); 031 032 private Union(String name) { 033 super(name); 034 } 035 036 /** 037 * Creates a union type. 038 * 039 * <p>Typical usage: 040 * <pre class="listing"><code class="lang-java" data-lang="java"> 041 * union("ConsList") 042 * .value("Empty") 043 * .value("Cons", 044 * "head", 045 * "tail") 046 * </code></pre> 047 * creates 048 * <pre class="listing"><code class="lang-golo" data-lang="golo"> 049 * union ConsList = { 050 * Empty 051 * Cons = {head, tail} 052 * } 053 * </code></pre> 054 * 055 * @param name the name of the union. 056 */ 057 public static Union union(String name) { 058 return new Union(name); 059 } 060 061 protected Union self() { return this; } 062 063 /** 064 * Adds a new value to this union. 065 */ 066 public boolean addValue(UnionValue value) { 067 makeParentOf(value); 068 return values.add(value); 069 } 070 071 /** 072 * Adds a value according to the given argument. 073 * 074 * @see #addValue(UnionValue) 075 */ 076 public boolean addElement(GoloElement<?> elt) { 077 if (elt instanceof UnionValue) { 078 return addValue((UnionValue) elt); 079 } 080 throw cantConvert("UnionValue", elt); 081 } 082 083 public Collection<UnionValue> getValues() { 084 return unmodifiableSet(values); 085 } 086 087 /** 088 * Adds a new value to this union. 089 * 090 * <p>Convenient fluent method to add a new value. 091 * <p>This is a builder method. 092 * 093 * @see #addValue(UnionValue) 094 * @see UnionValue#members(Object...) 095 */ 096 public Union value(String name, Object... members) { 097 UnionValue value = new UnionValue(name); 098 value.members(members); 099 addValue(value); 100 return this; 101 } 102 103 /** 104 * {@inheritDoc} 105 */ 106 @Override 107 public void accept(GoloIrVisitor visitor) { 108 visitor.visitUnion(this); 109 } 110 111 /** 112 * {@inheritDoc} 113 */ 114 @Override 115 public List<GoloElement<?>> children() { 116 List<GoloElement<?>> children = new LinkedList<>(values); 117 return children; 118 } 119 120 /** 121 * {@inheritDoc} 122 */ 123 @Override 124 protected void replaceElement(GoloElement<?> original, GoloElement<?> newElement) { 125 if (values.contains(original)) { 126 values.remove(original); 127 } else { 128 throw cantReplace(original, newElement); 129 } 130 addElement(newElement); 131 } 132}