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 016/** 017 * A destructuring assignment. 018 * 019 * <p>For instance: 020 * <pre class="listing"><code class="lang-golo" data-lang="golo"> 021 * let a, b = [1, 2] 022 * </code></pre> 023 */ 024public final class DestructuringAssignment extends GoloAssignment<DestructuringAssignment> { 025 026 private final List<LocalReference> references = new LinkedList<>(); 027 private boolean isVarargs = false; 028 029 private DestructuringAssignment() { 030 super(); 031 } 032 033 /** 034 * Create a destructuring assignment. 035 * 036 * <p>Typical usage: 037 * <pre class="listing"><code class="lang-java" data-lang="java"> 038 * destruct(tuple(1, 2)).to("a", "b").declaring(true) 039 * </code></pre> 040 * creates 041 * <pre class="listing"><code class="lang-golo" data-lang="golo"> 042 * let a, b = [1, 2] 043 * </code></pre> 044 * 045 * @param expr the expression to destructure 046 * @see #as(Object) 047 */ 048 public static DestructuringAssignment destruct(Object expr) { 049 return new DestructuringAssignment().as(expr); 050 } 051 052 /** 053 * Creates a uninitialized destructuring assignment. 054 */ 055 public static DestructuringAssignment create() { 056 return new DestructuringAssignment(); 057 } 058 059 protected DestructuringAssignment self() { return this; } 060 061 /** 062 * Checks if this destructuring is a varargs one. 063 * 064 * @see #varargs(boolean) 065 */ 066 public boolean isVarargs() { 067 return this.isVarargs; 068 } 069 070 /** 071 * Defines if this destructuring is a varargs one. 072 * 073 * <p>For instance: 074 * <pre class="listing"><code class="lang-golo" data-lang="golo"> 075 * let a, b... = list[1, 2, 3, 4] 076 * </code></pre> 077 * <p>This is a builder method. 078 */ 079 public DestructuringAssignment varargs(boolean varargs) { 080 this.isVarargs = varargs; 081 return this; 082 } 083 084 /** 085 * Defines this destructuring as a varargs one. 086 * 087 * <p>Same as {@code varargs(true)}. 088 */ 089 public DestructuringAssignment varargs() { 090 return varargs(true); 091 } 092 093 /** 094 * {@inheritDoc} 095 */ 096 @Override 097 public DestructuringAssignment variable() { 098 for (LocalReference ref : references) { 099 ref.variable(); 100 } 101 return this; 102 } 103 104 /** 105 * {@inheritDoc} 106 */ 107 @Override 108 public boolean isConstant() { 109 if (!references.isEmpty()) { 110 return references.get(0).isConstant(); 111 } 112 return false; 113 } 114 115 /** 116 * {@inheritDoc} 117 */ 118 @Override 119 public LocalReference[] getReferences() { 120 return this.references.toArray(new LocalReference[references.size()]); 121 } 122 123 /** 124 * {@inheritDoc} 125 */ 126 @Override 127 public int getReferencesCount() { 128 return this.references.size(); 129 } 130 131 /** 132 * @inheritDoc 133 */ 134 @Override 135 public DestructuringAssignment to(Object... refs) { 136 for (Object o : refs) { 137 references.add(LocalReference.of(o)); 138 } 139 return this; 140 } 141 142 @Override 143 public String toString() { 144 List<String> names = new LinkedList<>(); 145 for (LocalReference r : getReferences()) { 146 names.add(r.toString()); 147 } 148 return String.join(", ", names) + " = " + expression().toString(); 149 } 150 151 /** 152 * {@inheritDoc} 153 */ 154 @Override 155 public void accept(GoloIrVisitor visitor) { 156 visitor.visitDestructuringAssignment(this); 157 } 158 159 /** 160 * {@inheritDoc} 161 */ 162 @Override 163 public void walk(GoloIrVisitor visitor) { 164 for (LocalReference ref : references) { 165 ref.accept(visitor); 166 } 167 super.walk(visitor); 168 } 169}