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.Arrays; 014import java.util.List; 015import gololang.Tuple; 016import org.eclipse.golo.runtime.InvalidDestructuringException; 017 018public final class WhenClause<T extends GoloElement<?>> extends GoloElement<WhenClause<T>> { 019 private ExpressionStatement<?> condition; 020 private T action; 021 022 WhenClause(ExpressionStatement<?> condition, T action) { 023 this.condition = makeParentOf(condition); 024 setAction(action); 025 } 026 027 protected WhenClause<T> self() { return this; } 028 029 public ExpressionStatement<?> condition() { return this.condition; } 030 031 public T action() { return this.action; } 032 033 private void setAction(T a) { 034 this.action = makeParentOf(a); 035 } 036 037 public WhenClause<T> then(T action) { 038 setAction(action); 039 return this; 040 } 041 042 @Override 043 public String toString() { 044 return String.format("when %s then %s", condition, action); 045 } 046 047 /** 048 * {@inheritDoc} 049 */ 050 @Override 051 protected void replaceElement(GoloElement<?> original, GoloElement<?> newElement) { 052 if (this.condition.equals(original)) { 053 if (!(newElement instanceof ExpressionStatement)) { 054 throw cantConvert("ExpressionStatement", newElement); 055 } 056 this.condition = makeParentOf(ExpressionStatement.of(newElement)); 057 } else if (this.action.equals(original)) { 058 @SuppressWarnings("unchecked") 059 T element = (T) newElement; 060 setAction(element); 061 } else { 062 throw doesNotContain(original); 063 } 064 } 065 066 /** 067 * {@inheritDoc} 068 */ 069 @Override 070 public void accept(GoloIrVisitor visitor) { 071 visitor.visitWhenClause(this); 072 } 073 074 /** 075 * {@inheritDoc} 076 */ 077 @Override 078 public List<GoloElement<?>> children() { 079 return Arrays.asList(condition, action); 080 } 081 082 /** 083 * Destructuring helper. 084 * @deprecated This method should not be called directly and is no more used by new style destructuring. 085 */ 086 @Deprecated 087 public Tuple destruct() { 088 return new Tuple(condition, action); 089 } 090 091 /** 092 * New style destructuring helper. 093 * 094 * <p>The destructuring must be to exactly two values. No remainer syntax is allowed. 095 * <p>The destructured values are the condition and the action. 096 * 097 * @param number number of variable that will be affected. 098 * @param substruct whether the destructuring is complete or should contains a sub structure. 099 * @param toSkip a boolean array indicating the elements to skip. 100 * @return an array containing the values to assign. 101 */ 102 public Object[] __$$_destruct(int number, boolean substruct, Object[] toSkip) { 103 if (number == 2 && !substruct) { 104 return new Object[]{condition, action}; 105 } 106 throw new InvalidDestructuringException("A WhenClause must destructure to exactly two values"); 107 } 108} 109 110