001package de.monochromata.anaphors.cog.transform;
002
003import de.monochromata.anaphors.ast.ASTBasedAnaphora;
004import de.monochromata.anaphors.ast.relatedexp.RelatedExpression;
005import de.monochromata.anaphors.ast.spi.TransformationsSpi;
006import de.monochromata.anaphors.ast.transform.ASTTransformation;
007import de.monochromata.anaphors.cog.memory.Chunk;
008
009/**
010 * If the given definite expression is reachable via the call chain from the
011 * invocable containing the potential related expression, add a parameter for it
012 * to propagate it to the invocable containing the definite expression.
013 *
014 * @param <N>  The node type in the AST
015 * @param <E>  The expression type
016 * @param <T>  The type type
017 * @param <B>  The binding type
018 * @param <TB> The type binding type
019 * @param <S>  The scope type (optional)
020 * @param <I>  The type used to represent identifiers
021 * @param <QI> The type used to represent qualified identifiers
022 * @param <R>  The sub-type of related expression to use
023 * @param <A>  The sub-type of AST-based anaphora to use
024 */
025public class AddParameterToCallChain<N, E, T, B, TB extends B, S, I, QI, R extends RelatedExpression<N, T, B, TB, S, QI, R>, A extends ASTBasedAnaphora<N, E, T, B, TB, S, I, QI, R, A>>
026        extends AbstractPreparatoryTransformation<N, E, T, B, TB, S, I, QI, R, A> {
027
028    /**
029     * Used in contract testing.
030     */
031    @SuppressWarnings("unused")
032    protected AddParameterToCallChain() {
033    }
034
035    public AddParameterToCallChain(final TransformationsSpi<N, E, T, B, TB, S, I, QI, R, A> transformationsSpi) {
036        super(transformationsSpi);
037    }
038
039    @Override
040    public String getKind() {
041        return "AddParam";
042    }
043
044    @Override
045    public CheckResult<N, E, S> canPerform(final Chunk<N> chunk, final E definiteExpression, final S scope) {
046        final ASTTransformation<N, E, T, B, TB, S, I, QI, R, A> astTransformation = transformationsSpi
047                .passAlongCallChain(chunk.getRepresented(), definiteExpression, scope);
048        return new AddParamCheckResult(chunk, definiteExpression, scope, astTransformation);
049    }
050
051    @Override
052    @SuppressWarnings("unchecked")
053    public A perform(final CheckResult<N, E, S> result, final A preliminaryAnaphora) {
054        requireSuccessfulCheck(result);
055        requireInstanceOf(result, AddParamCheckResult.class);
056        return ((AddParamCheckResult) result).astTransformation.perform(preliminaryAnaphora);
057    }
058
059    private class AddParamCheckResult extends AbstractCheckResult<N, E, S> {
060
061        private final ASTTransformation<N, E, T, B, TB, S, I, QI, R, A> astTransformation;
062
063        /**
064         * Used in contract testing.
065         */
066        @SuppressWarnings("unused")
067        protected AddParamCheckResult() {
068            astTransformation = null;
069        }
070
071        public AddParamCheckResult(final Chunk<N> chunk, final E definiteExpression, final S scope,
072                final ASTTransformation<N, E, T, B, TB, S, I, QI, R, A> astTransformation) {
073            super(chunk, definiteExpression, scope, astTransformation != null);
074            this.astTransformation = astTransformation;
075        }
076
077    }
078
079}