Package joust.optimisers.translators

Source Code of joust.optimisers.translators.ConstFoldTranslator

package joust.optimisers.translators;

import joust.tree.annotatedtree.AJCComparableExpressionTree;
import joust.tree.annotatedtree.AJCForest;
import joust.tree.annotatedtree.AJCTree;
import joust.utils.logging.LogUtils;
import lombok.experimental.ExtensionMethod;
import lombok.extern.java.Log;
import joust.utils.tree.evaluation.Value;

import java.util.NoSuchElementException;
import java.util.logging.Logger;

import static com.sun.tools.javac.tree.JCTree.Tag;
import static joust.tree.annotatedtree.AJCTree.*;
/**
* Implementation of constant folding. Unfortunately, javac does its constant folding after we are
* invoked, and it does so, perhaps understandably, at a lower level than the AST.
* The objective here is to get constant folding done at the AST level so other, actually
* interesting optimisations are not hindered by the non-foldedness of constants when they
* subsequently are run.
* Unfortunately, doing things at this level means we have to deal with issues like brackets.
* TODO: Lambdas might be able to make this less soul-destroyingly awful to look at.
*/
@Log
@ExtensionMethod({Logger.class, LogUtils.LogExtensions.class})
public class ConstFoldTranslator extends BaseTranslator {
    @Override
    public void visitUnary(AJCUnary tree) {
        super.visitUnary(tree);
        // Determine the type of this unary operation.
        final Tag nodeTag = tree.getTag();
        final AJCExpressionTree expr = tree.arg;

        // Replace each unary operation on a literal with a literal of the new value.
        if (!(expr instanceof AJCLiteral)) {
            return;
        }

        mHasMadeAChange = true;

        // To Values...
        Value operand = Value.of(((AJCLiteral) expr).getValue());
        AJCLiteral replacement = Value.unary(nodeTag, operand).toLiteral();

        try {
            tree.swapFor(replacement);
        } catch (NoSuchElementException e) {
            // The way javac constructs literal arrays wil lcause us to get here. No matter.
        }

        AJCForest.getInstance().increment("Constants Folded: ");
        log.info("{}:{} -> {}:{}", tree, tree.getClass().getCanonicalName(), replacement, replacement.getClass().getCanonicalName());
    }

    @Override
    public void visitBinary(AJCBinary tree) {
        super.visitBinary(tree);
        // Determine the type of this unary operation.
        final Tag nodeTag = tree.getTag();
        AJCExpressionTree leftOperand = tree.lhs;
        AJCExpressionTree rightOperand = tree.rhs;

        // Ensure this is an operation on literals before proceeding.
        if (!(leftOperand instanceof AJCLiteral && rightOperand instanceof AJCLiteral)) {
            return;
        }

        mHasMadeAChange = true;

        // To Values...
        Value lValue = Value.of(((AJCLiteral) leftOperand).getValue());
        Value rValue = Value.of(((AJCLiteral) rightOperand).getValue());

        AJCLiteral replacement = Value.binary(nodeTag, lValue, rValue).toLiteral();

        try {
            tree.swapFor(replacement);
        } catch (NoSuchElementException e) {
            // The way javac constructs literal arrays wil lcause us to get here. No matter.
        }

        AJCForest.getInstance().increment("Constants Folded: ");
        log.info("{} {} {} -> {}", leftOperand, nodeTag, rightOperand, replacement);
    }

    @Override
    protected void visitConditional(AJCConditional that) {
        // Fold the subtrees of the conditional...
        super.visitConditional(that);

        if (that.cond instanceof AJCLiteral) {
            AJCLiteral cast = (AJCLiteral) that.cond;
            Object val = cast.getValue();
            if (!(val instanceof Boolean)) {
                log.fatal("Non-boolean boolean literal detected: {}", that.cond);
                return;
            }

            boolean realValue = (Boolean) val;
            if (realValue) {
                that.swapFor(that.truepart);
            } else {
                that.swapFor(that.falsepart);
            }
            AJCForest.getInstance().increment("Conditionals Folded: ");
        }
    }

    @Override
    protected void visitIf(AJCIf that) {
        super.visitIf(that);

        if (that.cond instanceof AJCLiteral) {
            AJCLiteral cast = (AJCLiteral) that.cond;
            Object val = cast.getValue();
            if (!(val instanceof Boolean)) {
                log.fatal("Non-boolean boolean literal detected: {}", that.cond);
                return;
            }

            boolean realValue = (Boolean) val;
            if (realValue) {
                that.swapFor(that.thenpart);
            } else {
                that.swapFor(that.elsepart);
            }
            AJCForest.getInstance().increment("Conditionals Folded: ");
        }
    }
}
TOP

Related Classes of joust.optimisers.translators.ConstFoldTranslator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.