/*******************************************************************************
* Copyright (c) 2013, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package dtool.ast.definitions;
import dtool.ast.expressions.Expression;
import dtool.ast.statements.IFunctionBody;
import dtool.parser.common.Token;
import melnorme.lang.tooling.ast.IASTNode;
import melnorme.lang.tooling.ast.IASTVisitor;
import melnorme.lang.tooling.ast.util.ASTCodePrinter;
import melnorme.lang.tooling.ast.util.NodeVector;
import melnorme.lang.tooling.ast_actual.ASTNode;
import melnorme.lang.tooling.engine.scoping.IScopeElement;
import melnorme.lang.tooling.engine.scoping.ScopeTraverser;
import melnorme.utilbox.collections.ArrayView;
import melnorme.utilbox.core.CoreUtil;
import melnorme.utilbox.misc.IteratorUtil;
public abstract class AbstractFunctionDefinition extends CommonDefinition
implements ICallableElement, IScopeElement, ITemplatableElement
{
public final NodeVector<ITemplateParameter> tplParams;
public final NodeVector<IFunctionParameter> fnParams;
public final NodeVector<IFunctionAttribute> fnAttributes;
public final Expression tplConstraint;
public final IFunctionBody fnBody;
public AbstractFunctionDefinition(Token[] comments, DefSymbol defId, NodeVector<ITemplateParameter> tplParams,
NodeVector<IFunctionParameter> fnParams, NodeVector<IFunctionAttribute> fnAttributes,
Expression tplConstraint,
IFunctionBody fnBody) {
super(comments, defId);
this.tplParams = parentize(tplParams);
this.fnParams = parentize(fnParams);
this.fnAttributes = parentize(fnAttributes);
this.tplConstraint = parentize(tplConstraint);
this.fnBody = parentize(fnBody);
}
public final ArrayView<ASTNode> getParams_asNodes() {
return CoreUtil.blindCast(fnParams);
}
public static ArrayView<IFunctionParameter> NO_PARAMS = ArrayView.create(new IFunctionParameter[0]);
protected void visitChildren_common(IASTVisitor visitor) {
acceptVisitor(visitor, defName);
acceptVisitor(visitor, tplParams);
acceptVisitor(visitor, fnParams);
acceptVisitor(visitor, fnAttributes);
acceptVisitor(visitor, tplConstraint);
acceptVisitor(visitor, fnBody);
}
@Override
public ArrayView<IFunctionParameter> getParameters() {
return fnParams == null ? NO_PARAMS : fnParams;
}
public void toStringAsCode_fromDefId(ASTCodePrinter cp) {
cp.append(defName);
cp.appendList("(", tplParams, ",", ") ");
cp.appendList("(", getParams_asNodes(), ",", ") ");
cp.appendList(fnAttributes, " ", true);
DefinitionTemplate.tplConstraintToStringAsCode(cp, tplConstraint);
cp.appendNodeOrNullAlt(fnBody, " ");
}
@Override
public boolean isTemplated() {
return tplParams != null;
}
@Override
public NodeVector<ITemplateParameter> getTemplateParameters() {
return tplParams;
}
@Override
public String getExtendedName() {
return getExtendedName(false, true); // XXX: maybe includeTemplateParams should be true?
}
public String getExtendedName(boolean includeTemplateParams, boolean includeParamNames) {
ASTCodePrinter cp = new ASTCodePrinter();
cp.append(getName());
if(includeTemplateParams) {
cp.appendList("(", tplParams, ",", ") ");
}
cp.append(toStringParametersForSignature(fnParams, includeParamNames));
return cp.toString();
}
public String toStringParametersForSignature() {
return toStringParametersForSignature(fnParams, true);
}
protected static String toStringParametersForSignature(ArrayView<IFunctionParameter> params, boolean includeName) {
if(params == null)
return "";
String strParams = "(";
for (int i = 0; i < params.size(); i++) {
if(i != 0)
strParams += ", ";
strParams += params.get(i).toStringForFunctionSignature(includeName);
}
return strParams + ")";
}
/* ----------------- ----------------- */
@Override
public ScopeTraverser getScopeTraverser() {
// TODO: technically not correct, these are two separte scopes
Iterable<? extends IASTNode> iterable = IteratorUtil.<IASTNode>chainedIterable(tplParams, fnParams);
return new ScopeTraverser(iterable, false);
}
}