/*
* Copyright 2015 S. Webber
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.oakgp.function;
import org.oakgp.Arguments;
import org.oakgp.Assignments;
import org.oakgp.Type;
import org.oakgp.node.Node;
/** Represents an operation. */
public interface Function {
/**
* Returns the result of applying this operation to the specified {@code Arguments} and {@code Assignments}.
*
* @param arguments
* represents the arguments to apply to the operation
* @param assignments
* represents values assigned to variables belonging to {@code arguments}
* @return the result of applying this operation to the {@code arguments} and {@code assignments}
*/
Object evaluate(Arguments arguments, Assignments assignments);
/** Returns the return type and argument types associated with this function. */
Signature getSignature();
/**
* Attempts to find a simplified alternative to applying this function to the specified arguments.
* <p>
* Simplification can occur by replacing expressions with constant values (e.g. replacing {@code (+ 1 1)} with {@code 2}) or removing redundant branches
* (e.g. replacing {@code (if (< 2 3) (+ v0 v1) (* v0 v1))} with {@code (+ v0 v1)}.
*
* @param arguments
* the arguments to be applied to (i.e. evaluated by) this function
* @return a simplified version of applying this function to the specified arguments, or {@code null} if unable to simplify.
* @see org.oakgp.NodeSimplifier
*/
default Node simplify(Arguments arguments) {
return null;
}
/** Returns the {@code String} value to use in the textual representation of this function. */
default String getDisplayName() {
String className = getClass().getName();
int packagePos = className.lastIndexOf('.');
String lowerCaseNameMinusPackage = className.substring(packagePos + 1).toLowerCase();
if (lowerCaseNameMinusPackage.startsWith("is") && getSignature().getReturnType() == Type.booleanType()) {
return lowerCaseNameMinusPackage.substring(2) + "?";
} else {
return lowerCaseNameMinusPackage;
}
}
/**
* Returns {@code true} if this function is pure, else returns {@code false}.
* <p>
* A function is a pure function if it conforms to the following criteria:
* <ol>
* <li><i>Always</i> returns the same result when given the <i>same</i> arguments.</li>
* <li>Doesn't cause any <i>observable</i> side effects.</li>
* </ol>
* </p>
* <p>
* If a function is pure then it is <i>referentially transparent</i>. This means that if a function node contains a pure function, and all its arguments are
* constants, then the function node can be replaced with the result of evaluating it. This avoids unnecessary computation and reduces bloat.
* </p>
* <p>
* Default implementation always returns {@code true}.
*
* @see ImpureFunction
*/
default boolean isPure() {
return true;
}
}