package de.renew.expression;

import de.renew.unify.ICalculationChecker;
import de.renew.unify.IStateRecorder;
import de.renew.unify.Impossible;
import de.renew.unify.Variable;


/**
 * An {@code Expression} whose value is the result of a {@link NoArgFunction}.
 */
public class NoArgExpression extends ExpressionWithTypeField {
    /**
     * The function that is evaluated to obtain the value of the expression.
     */
    private final NoArgFunction _function;

    /**
     * Constructs a new {@code NoArgExpression} based on a {@code Class} and a {@code NoArgFunction}.
     *
     * @param targetType the class that the result value of the {@code NoArgExpression} should have
     * @param function the {@code NoArgFunction} that determines the value of this expression
     */
    public NoArgExpression(Class<?> targetType, NoArgFunction function) {
        super(targetType);
        _function = function;
    }

    @Override
    public boolean isInvertible() {
        // Because there is only one value that this expression
        // can take, there is really no use in starting a search
        // process.
        return false;
    }

    @Override
    public Object startEvaluation(
        VariableMapper mapper, IStateRecorder recorder, ICalculationChecker checker)
        throws Impossible
    {
        return _function.function();
    }

    @Override
    public Object registerCalculation(
        VariableMapper mapper, IStateRecorder recorder, ICalculationChecker checker)
        throws Impossible
    {
        Variable target = new Variable();
        checker.addCalculated(getType(), target, null, recorder);
        return target.getValue();
    }

    @Override
    public String toString() {
        return "NoArgExpr(" + de.renew.util.Types.typeToString(getType()) + ": " + _function + ")";
    }
}