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; 015 016import static java.util.Collections.unmodifiableList; 017 018/** 019 * A {@code match} node. 020 * <p> This node describe tree such as: 021 * <pre class="listing"><code class="lang-golo" data-lang="golo"> 022 * match { 023 * when condition_1 then expression_1 024 * when condition_2 then expression_2 025 * otherwise default_expression 026 * } 027 * </code></pre> 028 */ 029public final class MatchExpression extends ExpressionStatement<MatchExpression> implements Alternatives<ExpressionStatement<?>> { 030 031 private ExpressionStatement<?> otherwise; 032 private final LinkedList<WhenClause<ExpressionStatement<?>>> clauses = new LinkedList<>(); 033 034 MatchExpression() { 035 super(); 036 } 037 038 /** 039 * Creates an empty match expression. 040 */ 041 public static MatchExpression match() { 042 return new MatchExpression(); 043 } 044 045 protected MatchExpression self() { return this; } 046 047 /** 048 * {@inheritDoc} 049 */ 050 @Override 051 public MatchExpression when(Object cond) { 052 if (cond instanceof WhenClause) { 053 @SuppressWarnings("unchecked") 054 WhenClause<ExpressionStatement<?>> clause = (WhenClause<ExpressionStatement<?>>) cond; 055 this.clauses.add(makeParentOf(clause)); 056 } else { 057 this.clauses.add(makeParentOf(new WhenClause<ExpressionStatement<?>>(ExpressionStatement.of(cond), null))); 058 } 059 return this; 060 } 061 062 /** 063 * {@inheritDoc} 064 * 065 * @param action a {@link gololang.ir.ExpressionStatement} containing the expression to return. 066 */ 067 @Override 068 public MatchExpression then(Object action) { 069 this.clauses.getLast().then(ExpressionStatement.of(action)); 070 return this; 071 } 072 073 /** 074 * {@inheritDoc} 075 * 076 * @param action a {@link gololang.ir.ExpressionStatement} containing the expression to return. 077 */ 078 @Override 079 public MatchExpression otherwise(Object action) { 080 this.otherwise = makeParentOf(ExpressionStatement.of(action)); 081 return this; 082 } 083 084 public List<WhenClause<ExpressionStatement<?>>> getClauses() { 085 return unmodifiableList(this.clauses); 086 } 087 088 public ExpressionStatement<?> getOtherwise() { 089 return this.otherwise; 090 } 091 092 /** 093 * {@inheritDoc} 094 */ 095 @Override 096 public void accept(GoloIrVisitor visitor) { 097 visitor.visitMatchExpression(this); 098 } 099 100 /** 101 * {@inheritDoc} 102 */ 103 @Override 104 public List<GoloElement<?>> children() { 105 LinkedList<GoloElement<?>> children = new LinkedList<>(clauses); 106 children.add(otherwise); 107 return children; 108 } 109 110 /** 111 * {@inheritDoc} 112 */ 113 @Override 114 protected void replaceElement(GoloElement<?> original, GoloElement<?> newElement) { 115 if (!(newElement instanceof ExpressionStatement || newElement instanceof WhenClause)) { 116 throw cantConvert("ExpressionStatement or WhenClause", newElement); 117 } 118 if (otherwise.equals(original)) { 119 otherwise(newElement); 120 return; 121 } 122 if (clauses.contains(original)) { 123 @SuppressWarnings("unchecked") 124 WhenClause<ExpressionStatement<?>> when = (WhenClause<ExpressionStatement<?>>) newElement; 125 clauses.set(clauses.indexOf(original), makeParentOf(when)); 126 return; 127 } 128 throw doesNotContain(original); 129 } 130}