Package joust.tree.annotatedtree.treeinfo

Source Code of joust.tree.annotatedtree.treeinfo.EffectSet

package joust.tree.annotatedtree.treeinfo;

import static com.sun.tools.javac.code.Symbol.*;

import joust.utils.data.SymbolSet;
import joust.utils.tree.TreeUtils;
import lombok.extern.java.Log;

/**
* A class for representing the side effects of a particular tree node.
*/
@Log
public class EffectSet {
    public static final EffectSet NO_EFFECTS = new EffectSet(EffectType.NONE);
    public static final EffectSet ALL_EFFECTS = new EffectSet(EffectType.getAllEffects()) {
        {
            readInternal = SymbolSet.UNIVERSAL_SET;
            writeInternal = SymbolSet.UNIVERSAL_SET;
            readEscaping = SymbolSet.UNIVERSAL_SET;
            writeEscaping = SymbolSet.UNIVERSAL_SET;
        }
    };

    public static final int ESCAPING_ONLY = EffectType.READ_ESCAPING.maskValue
                                          | EffectType.WRITE_ESCAPING.maskValue
                                          | EffectType.EXCEPTION.maskValue
                                          | EffectType.IO.maskValue;

    // The summary of all effect types this EffectSet represents.
    public int effectTypes;

    // The symbols read/written to by this EffectSet.
    public SymbolSet readInternal = new SymbolSet();
    public SymbolSet writeInternal = new SymbolSet();

    public SymbolSet readEscaping = new SymbolSet();
    public SymbolSet writeEscaping = new SymbolSet();

    public enum EffectType {
        NONE(0),
        READ_INTERNAL(1),
        WRITE_INTERNAL(2),
        READ_ESCAPING(4),
        WRITE_ESCAPING(8),
        EXCEPTION(16),
        IO(32);

        private static int ALL_EFFECTS;

        public static int getAllEffects() {
            if (ALL_EFFECTS == 0) {
                for (EffectType e : values()) {
                    ALL_EFFECTS |= e.maskValue;
                }
            }

            return ALL_EFFECTS;
        }

        public final int maskValue;
        EffectType(int mask) {
            maskValue = mask;
        }
    }

    /**
     * Return the effect set representing the current effect set unioned with the given effect set.
     * Provided in addition to the varargs one for performance reasons.
     *
     * @param unionee An EffectSet to add to this one.
     * @return The effect set representing the union of the effects of this set with the argument.
     */
    public EffectSet union(EffectSet unionee) {
        if (unionee == null) {
            return this;
        }

        // Union the effect summary...
        EffectSet unioned = new EffectSet(effectTypes | unionee.effectTypes);

        unioned.readInternal = SymbolSet.union(readInternal, unionee.readInternal);
        unioned.writeInternal = SymbolSet.union(writeInternal, unionee.writeInternal);
        unioned.readEscaping = SymbolSet.union(readEscaping, unionee.readEscaping);
        unioned.writeEscaping = SymbolSet.union(writeEscaping, unionee.writeEscaping);

        return unioned;
    }

    /**
     * Creates a new EffectSet containing all the escaping/non escaping read/write effects of this, plus all
     * the escaping read/write effects of unionee, plus all other effects.
     */
    public EffectSet unionEscaping(EffectSet unionee) {
        if (unionee == null) {
            log.warning("Unionee was null.");
            return this;
        }

        EffectSet unioned = new EffectSet(effectTypes | (unionee.effectTypes & ESCAPING_ONLY));

        unioned.readInternal = new SymbolSet(readInternal);
        unioned.writeInternal = new SymbolSet(writeInternal);
        unioned.readEscaping = SymbolSet.union(readEscaping, unionee.readEscaping);
        unioned.writeEscaping = SymbolSet.union(writeEscaping, unionee.writeEscaping);

        return unioned;
    }

    public EffectSet dropUnescaping() {
        EffectSet unioned = new EffectSet(effectTypes & ESCAPING_ONLY);

        unioned.readInternal = new SymbolSet();
        unioned.writeInternal = new SymbolSet();
        unioned.readEscaping = new SymbolSet(readEscaping);
        unioned.writeEscaping = new SymbolSet(writeEscaping);

        return unioned;
    }

    /**
     * Convenience varargs method for unioning a collection of EffectSets together.
     *
     * @param effectSets Effect sets to union with this one.
     * @return The result of the union.
     */
    public EffectSet union(EffectSet... effectSets) {
        if (effectSets == null || effectSets.length == 0) {
            return this;
        }

        int newMask = effectTypes;
        SymbolSet riSyms = new SymbolSet(readInternal);
        SymbolSet wiSyms = new SymbolSet(writeInternal);
        SymbolSet reSyms = new SymbolSet(readEscaping);
        SymbolSet weSyms = new SymbolSet(writeEscaping);


        for (int i = 0; i < effectSets.length; i++) {
            EffectSet unionee = effectSets[i];

            newMask |= unionee.effectTypes;

            // Add the symbols from the new unionee...
            riSyms.addAll(unionee.readInternal);
            wiSyms.addAll(unionee.writeInternal);
            reSyms.addAll(unionee.readEscaping);
            weSyms.addAll(unionee.writeEscaping);
        }

        EffectSet unioned = new EffectSet(newMask);

        unioned.readInternal = riSyms;
        unioned.writeInternal = wiSyms;
        unioned.readEscaping = reSyms;
        unioned.writeEscaping = weSyms;

        return unioned;
    }

    /**
     * Return the effect set representing the current effect set plus the given summary fields.
     *
     * @param effect An effect to add to this EffectSet.
     * @return The effect set representing the effects of this EffectSet plus the given extra one.
     */
    public EffectSet union(EffectType effect) {
        if (effect == null) {
            return this;
        }

        EffectSet newEffectSet = new EffectSet(effectTypes | effect.maskValue);
        newEffectSet.readInternal = new SymbolSet(readInternal);
        newEffectSet.writeInternal = new SymbolSet(writeInternal);
        newEffectSet.readEscaping = new SymbolSet(readEscaping);
        newEffectSet.writeEscaping = new SymbolSet(writeEscaping);

        return newEffectSet;
    }

    public EffectSet(final int mask) {
        effectTypes = mask;
    }

    public EffectSet(final EffectType type) {
        effectTypes = type.maskValue;
    }

    public static EffectSet write(VarSymbol sym) {
        EffectSet ret;
        if (TreeUtils.isLocalVariable(sym)) {
            ret = new EffectSet(EffectType.WRITE_INTERNAL);
            ret.writeInternal.add(sym);
        } else {
            ret = new EffectSet(EffectType.WRITE_ESCAPING);
            ret.writeEscaping.add(sym);
        }

        return ret;
    }

    public static EffectSet read(VarSymbol sym) {
        EffectSet ret;
        if (TreeUtils.isLocalVariable(sym)) {
            ret = new EffectSet(EffectType.READ_INTERNAL);
            ret.readInternal.add(sym);
        } else {
            ret = new EffectSet(EffectType.READ_ESCAPING);
            ret.readEscaping.add(sym);
        }

        return ret;
    }

    @Override
    public String toString() {
        StringBuilder str = new StringBuilder(Integer.toString(effectTypes, 2));
        if (!readInternal.isEmpty()) {
            str.append(":RI(")
               .append(readInternal)
               .append(')');
        }

        if (!readEscaping.isEmpty()) {
            str.append(":RE(")
               .append(readEscaping)
               .append(')');
        }

        if (!writeInternal.isEmpty()) {
            str.append(":WI(")
               .append(writeInternal)
               .append(')');
        }

        if (!writeEscaping.isEmpty()) {
            str.append(":WE(")
               .append(writeEscaping)
               .append(')');
        }

        return str.toString();
    }

    /**
     * Returns true if this effect set contains every effect described by the input set, false otherwise.
     */
    public boolean contains(EffectSet effectSet) {
        // If any of the bits not set on both masks are set on effectSet.effectTypes, it contains an effect that
        // isn't present in this EffectSet, so we don't contain it.
        if (((effectSet.effectTypes | effectTypes) ^ effectTypes) != 0) {
            return false;
        }

        // Check appropriate symbol sets...
        if (effectSet.contains(EffectType.READ_ESCAPING)) {
            if (!effectSet.readEscaping.subsetOf(readEscaping)) {
                return false;
            }
        }

        if (effectSet.contains(EffectType.WRITE_ESCAPING)) {
            if (!effectSet.writeEscaping.subsetOf(writeEscaping)) {
                return false;
            }
        }

        if (effectSet.contains(EffectType.WRITE_INTERNAL)) {
            if (!effectSet.readInternal.subsetOf(readInternal)) {
                return false;
            }
        }

        if (effectSet.contains(EffectType.WRITE_INTERNAL)) {
            if (!effectSet.writeInternal.subsetOf(writeInternal)) {
                return false;
            }
        }

        return true;
    }

    public boolean contains(EffectType effect) {
        return (effectTypes & effect.maskValue) != 0;
    }

    public boolean contains(int effectMask) {
        return (effectTypes & effectMask) != 0;
    }

    public boolean containsAny(EffectType... effects) {
        int unifiedMask = 0;
        for (int i = 0; i < effects.length; i++) {
            unifiedMask |= effects[i].maskValue;
        }

        return (effectTypes & unifiedMask) != 0;
    }

    public boolean writesSymbol(VarSymbol sym) {
        if (writeInternal != null) {
            if (writeInternal.contains(sym)) {
                return true;
            }
        }

        if (writeEscaping != null) {
            return writeEscaping.contains(sym);
        }

        return false;
    }

    public boolean readsSymbol(VarSymbol sym) {
        if (readInternal != null) {
            if (readInternal.contains(sym)) {
                return true;
            }
        }

        if (readEscaping != null) {
            return readEscaping.contains(sym);
        }

        return false;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof EffectSet)) {
            return false;
        }

        EffectSet cast = (EffectSet) obj;

        return contains(cast) && cast.contains(this);
    }

    // Kryo constructor
    private EffectSet() {}
}
TOP

Related Classes of joust.tree.annotatedtree.treeinfo.EffectSet

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.