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.Collection; 014import java.util.List; 015 016/** 017 * A closure reference. 018 * <p> 019 * A closure reference is a wrapper around a golo function, to represent a closure or a lambda. 020 * For instance, the golo code: 021 * <pre class="listing"><code class="lang-golo" data-lang="golo"> 022 * foo(|x| -> x + 1) 023 * </code></pre> 024 * The argument of the call to {@code foo} is a {@code ClosureReference} wrapping the actual {@link GoloFunction} 025 * 026 * <p>To ease manipulating this node, it delegate most of its methods to the wrapped target function. 027 * 028 * @see GoloFunction#asClosure() 029 * @see GoloFunction#asClosureReference() 030 */ 031public class ClosureReference extends ExpressionStatement<ClosureReference> implements BlockContainer<ClosureReference> { 032 033 private GoloFunction target; 034 035 ClosureReference(GoloFunction target) { 036 super(); 037 setTarget(target); 038 } 039 040 protected ClosureReference self() { return this; } 041 042 public GoloFunction getTarget() { 043 return target; 044 } 045 046 private void setTarget(GoloFunction target) { 047 this.target = makeParentOf(target); 048 this.positionInSourceCode(target.positionInSourceCode()); 049 this.documentation(target.documentation()); 050 } 051 052 /** 053 * Delegates on the wrapped target. 054 * @see GoloFunction#getSyntheticParameterNames() 055 */ 056 public Collection<String> getCapturedReferenceNames() { 057 return target.getSyntheticParameterNames(); 058 } 059 060 /** 061 * Checks if this reference has closed variables. 062 */ 063 public boolean hasCapturedReferences() { 064 return target.getSyntheticParameterCount() > 0; 065 } 066 067 /** 068 * Delegates on the wrapped target. 069 * @see GoloFunction#body(Object...) 070 */ 071 @Override 072 public ClosureReference body(Object... statements) { 073 this.target.body(statements); 074 return this; 075 } 076 077 /** 078 * Delegates on the wrapped target. 079 * @see GoloFunction#block(Object) 080 */ 081 @Override 082 public ClosureReference block(Object block) { 083 this.target.block(block); 084 return this; 085 } 086 087 /** 088 * Delegates on the wrapped target. 089 * @see GoloFunction#getBlock() 090 */ 091 @Override 092 public Block getBlock() { 093 return this.target.getBlock(); 094 } 095 096 /** 097 * Delegates on the wrapped target. 098 * @see GoloFunction#returns(Object) 099 */ 100 public ClosureReference returns(Object expression) { 101 this.target.returns(expression); 102 return this; 103 } 104 105 /** 106 * Delegates on the wrapped target. 107 * @see GoloFunction#varargs() 108 */ 109 public ClosureReference varargs() { 110 this.target.varargs(); 111 return this; 112 } 113 114 public ClosureReference varargs(boolean v) { 115 this.target.varargs(v); 116 return this; 117 } 118 119 /** 120 * Delegates on the wrapped target. 121 * @see GoloFunction#isVarargs() 122 */ 123 public boolean isVarargs() { 124 return this.target.isVarargs(); 125 } 126 127 /** 128 * Delegates on the wrapped target. 129 * @see GoloFunction#withParameters(Collection) 130 */ 131 public ClosureReference withParameters(Collection<String> paramNames) { 132 this.target.withParameters(paramNames); 133 return this; 134 } 135 136 /** 137 * {@inheritDoc} 138 */ 139 @Override 140 public void accept(GoloIrVisitor visitor) { 141 visitor.visitClosureReference(this); 142 } 143 144 /** 145 * {@inheritDoc} 146 */ 147 @Override 148 public void walk(GoloIrVisitor visitor) { 149 target.accept(visitor); 150 } 151 152 /** 153 * {@inheritDoc} 154 */ 155 @Override 156 public List<GoloElement<?>> children() { 157 return target.children(); 158 } 159 160 161 /** 162 * {@inheritDoc} 163 */ 164 @Override 165 protected void replaceElement(GoloElement<?> original, GoloElement<?> newElement) { 166 if (newElement instanceof GoloFunction && target.equals(original)) { 167 setTarget((GoloFunction) newElement); 168 } else { 169 throw cantReplace(original, newElement); 170 } 171 } 172 173 @Override 174 public String toString() { 175 return String.format("ClosureReference{target=%s, captured=%s}", target, getCapturedReferenceNames()); 176 } 177}