/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.compiler.assembler; import java.util.Arrays; import java.util.BitSet; import java.util.Iterator; import java.util.NoSuchElementException; /** * */ public final class VariablesSnapshot implements Iterable<Variable<?>> { private final int startSlot; private final BitSet variables; private final BitSet active; private final Type[] types; VariablesSnapshot(int startSlot, BitSet variables, BitSet active, Type[] types) { this.startSlot = startSlot; this.variables = variables; this.active = active; this.types = types; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj == null || obj.getClass() != VariablesSnapshot.class) { return false; } VariablesSnapshot other = (VariablesSnapshot) obj; return startSlot == other.startSlot && variables.equals(other.variables) && active.equals(other.active) && Arrays.equals(types, other.types); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + startSlot; result = prime * result + variables.hashCode(); result = prime * result + active.hashCode(); result = prime * result + Arrays.hashCode(types); return result; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(getClass().getSimpleName()); sb.append("\n\tstartSlot=").append(startSlot); sb.append("\n\tvariables=").append(variables); sb.append("\n\tactive=").append(active); sb.append("\n\ttypes=").append(Arrays.toString(types)); return sb.toString(); } int getStartSlot() { return startSlot; } BitSet getVariables() { return variables; } BitSet getActive() { return active; } Type[] getTypes() { return types; } private Variable<?> getVariable(int slot) { assert 0 <= slot && slot <= types.length : String.format("slot=%d not in [%d, %d]", slot, 0, types.length); assert variables.get(slot) && types[slot] != null && types[slot] != Type.RESERVED : String .format("slot=%d, used=%b, type=%s", slot, variables.get(slot), types[slot]); return new Variable<>(null, types[slot], slot); } private int getNextInitializedSlot(int slot) { assert 0 <= slot && slot <= types.length : String.format("slot=%d not in [%d, %d]", slot, 0, types.length); assert variables.get(slot) && active.get(slot) && types[slot] != null && types[slot] != Type.RESERVED : String .format("slot=%d, used=%b, active=%b, type=%s", slot, variables.get(slot), active.get(slot), types[slot]); return active.nextSetBit(slot + types[slot].getSize()); } /** * Returns the number of initialized variables. * * @return the total variable count */ public int getSize() { return active.cardinality(); } @Override public Iterator<Variable<?>> iterator() { return new SnapshotIterator(); } private final class SnapshotIterator implements Iterator<Variable<?>> { private int slot = active.nextSetBit(startSlot); @Override public boolean hasNext() { return slot != -1; } @Override public Variable<?> next() { if (slot == -1) { throw new NoSuchElementException(); } Variable<?> v = getVariable(slot); slot = getNextInitializedSlot(slot); return v; } } }