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.Collections; 014import java.util.List; 015import org.eclipse.golo.runtime.InvalidDestructuringException; 016 017import static gololang.Messages.message; 018 019/** 020 * A named argument in a function call. 021 * 022 * <p>Represents nodes such as: 023 * <pre class="listing"><code class="lang-golo" data-lang="golo"> 024 * foo(b=42, a=bar("answer")) 025 * </code></pre> 026 */ 027public final class NamedArgument extends ExpressionStatement<NamedArgument> { 028 029 private final String name; 030 private ExpressionStatement<?> expression; 031 032 private NamedArgument(String name, ExpressionStatement<?> expression) { 033 super(); 034 this.name = name; 035 this.setExpression(expression); 036 } 037 038 public static NamedArgument of(String name, Object value) { 039 return new NamedArgument(name, ExpressionStatement.of(value)); 040 } 041 042 protected NamedArgument self() { return this; } 043 044 public String getName() { 045 return this.name; 046 } 047 048 public ExpressionStatement<?> expression() { 049 return this.expression; 050 } 051 052 /** 053 * Defines the value of the named argument. 054 * 055 * <p>This is a builder method. 056 * 057 * @param value the {@link ExpressionStatement} to use as the value of the argument. 058 */ 059 private void setExpression(ExpressionStatement<?> value) { 060 this.expression = makeParentOf(value); 061 } 062 063 /** 064 * New style destructuring helper. 065 * 066 * <p>The destructuring must be to exactly two values. No remainer syntax is allowed. 067 * <p>The destructured values are the named and the expression. 068 * 069 * @param number number of variable that will be affected. 070 * @param substruct whether the destructuring is complete or should contains a sub structure. 071 * @param toSkip a boolean array indicating the elements to skip. 072 * @return an array containing the values to assign. 073 */ 074 public Object[] __$$_destruct(int number, boolean substruct, Object[] toSkip) { 075 if (number == 2 && !substruct) { 076 return new Object[]{name, expression}; 077 } 078 throw new InvalidDestructuringException("A NamedArgument must destructure to exactly two values"); 079 } 080 081 /** 082 * {@inheritDoc} 083 * 084 * <p>Always throws an exception since {@link NamedArgument} can't have a local declaration. 085 */ 086 @Override 087 public NamedArgument with(Object a) { 088 throw new UnsupportedOperationException(message("invalid_local_definition", this.getClass().getName())); 089 } 090 091 @Override 092 public boolean hasLocalDeclarations() { 093 return false; 094 } 095 096 /** 097 * {@inheritDoc} 098 */ 099 @Override 100 public void accept(GoloIrVisitor visitor) { 101 visitor.visitNamedArgument(this); 102 } 103 104 /** 105 * {@inheritDoc} 106 */ 107 @Override 108 public List<GoloElement<?>> children() { 109 return Collections.singletonList(expression); 110 } 111 112 /** 113 * {@inheritDoc} 114 */ 115 @Override 116 protected void replaceElement(GoloElement<?> original, GoloElement<?> newElement) { 117 if (this.expression != original) { 118 throw doesNotContain(original); 119 } 120 this.setExpression(ExpressionStatement.of(newElement)); 121 } 122}