/* Copyright 2009-2016 David Hadka * * This file is part of the MOEA Framework. * * The MOEA Framework is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * The MOEA Framework is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the MOEA Framework. If not, see <http://www.gnu.org/licenses/>. */ package org.moeaframework.util.tree; /** * The node for calling a named function. * * @see Define */ public class Call extends Node { /** * The name of the function to call. */ private final String functionName; /** * The names of the variables to the function. */ private final String[] variableNames; /** * The types of the variables to the function. */ private final Class<?>[] variableTypes; /** * Constructs a new node for calling a function that takes no arguments. * * @param functionName the name of the function * @param returnType the return type of the function */ public Call(String functionName, Class<?> returnType) { this(functionName, returnType, new String[0], new Class<?>[0]); } /** * Constructs a new node for calling a function that takes one argument. * * @param functionName the name of the function * @param returnType the return type of the function * @param variableName the name of the argument * @param variableType the type of the argument */ public Call(String functionName, Class<?> returnType, String variableName, Class<?> variableType) { this(functionName, returnType, new String[] { variableName }, new Class<?>[] { variableType }); } /** * Constructs a new node for calling a function that takes two arguments. * * @param functionName the name of the function * @param returnType the return type of the function * @param name1 the name of the first argument * @param type1 the type of the first argument * @param name2 the name of the second argument * @param type2 the type of the second argument */ public Call(String functionName, Class<?> returnType, String name1, Class<?> type1, String name2, Class<?> type2) { this(functionName, returnType, new String[] { name1, name2 }, new Class<?>[] { type1, type2 }); } /** * Constructs a new node for calling the function as defined. * * @param function the function */ public Call(Define function) { this(function.getFunctionName(), function.getArgumentType(0), function.getVariableNames(), function.getVariableTypes()); } /** * Constructs a new node for calling a function that takes a * user-defined number of arguments. * * @param functionName the name of the function * @param returnType the return type of the function * @param variableNames the names of the arguments to the function * @param variableTypes the types of the arguments to the function */ public Call(String functionName, Class<?> returnType, String[] variableNames, Class<?>[] variableTypes) { super(returnType, variableTypes); this.functionName = functionName; this.variableNames = variableNames; this.variableTypes = variableTypes; } /** * Returns the name of this function. * * @return the name of this function */ public String getFunctionName() { return functionName; } /** * Returns the names of the arguments to this function. * * @return the names of the arguments to this function */ public String[] getVariableNames() { return variableNames; } /** * Returns the types of the arguments to this function. * * @return the types of the arguments to this function */ public Class<?>[] getVariableTypes() { return variableTypes; } @Override public Node copyNode() { return new Call(functionName, getReturnType(), variableNames, variableTypes); } @Override public Object evaluate(Environment environment) { Environment closure = new Environment(environment); for (int i = 0; i < getNumberOfArguments(); i++) { closure.set(variableNames[i], getArgument(i).evaluate(environment)); } Node functionBody = environment.get(Node.class, functionName); return functionBody.evaluate(closure); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append('('); sb.append(getClass().getSimpleName()); sb.append(' '); sb.append(getFunctionName()); for (int i = 0; i < getNumberOfArguments(); i++) { sb.append(' '); sb.append(getArgument(0).toString()); } sb.append(')'); return sb.toString(); } }