001package daikon;
002
003import daikon.inv.DummyInvariant;
004import daikon.split.Splitter;
005import org.checkerframework.checker.initialization.qual.Initialized;
006import org.checkerframework.checker.nullness.qual.Nullable;
007
008// Information about a disjunctive program point that represents just part
009// of the data.
010// This doesn't do any direct computation, instead deferring that to its
011// views that are slices.
012
013// This perhaps shouldn't extend PptTopLevel; fix that in the future.
014// For now, it's convenient to take advantage of its functionality.
015// And they're so similar that maybe this is the right thing after all.
016public final class PptConditional extends PptTopLevel {
017  // We are Serializable, so we specify a version to allow changes to
018  // method signatures without breaking serialization.  If you add or
019  // remove fields, you should change this number to the current date.
020  static final long serialVersionUID = 20041216L;
021
022  public PptTopLevel parent;
023  public transient Splitter splitter;
024  // indicates whether we're on the true side or the false side of the Splitter
025  public boolean splitter_inverse;
026
027  // This does not install the variable values.  The reason is that it's
028  // more efficient to do that for two PptConditional objects at once.
029
030  public PptConditional(PptTopLevel parent, Splitter splitter, boolean splitter_inverse) {
031
032    super(ctor_name_helper(parent, splitter, splitter_inverse), ctor_vis_helper(parent));
033    // assert splitter.instantiated() == false;
034    this.parent = parent;
035    @SuppressWarnings({"nullness"}) // won't be used until it's fully initialized
036    @Initialized PptConditional thisNonRaw = this;
037    this.splitter = splitter.instantiateSplitter(thisNonRaw);
038    this.splitter_inverse = splitter_inverse;
039    // assert splitter.instantiated() == false;
040    // assert this.splitter.instantiated() == true;
041    // jhp this.invflow_ppts = new PptTopLevel[0];
042    // jhp this.invflow_transforms = new int[0][];
043  }
044
045  private static String ctor_name_helper(
046      PptTopLevel parent, Splitter splitter, boolean splitter_inverse) {
047    if (splitter_inverse) {
048      return parent.name + ";condition=\"not(" + splitter.condition() + ")\"";
049    } else {
050      return parent.name + ";condition=\"" + splitter.condition() + "\"";
051    }
052  }
053
054  private static VarInfo[] ctor_vis_helper(PptTopLevel parent) {
055    return VarInfo.arrayclone_simple(parent.var_infos);
056  }
057
058  // This is tested after constructing a PptConditional but before
059  // installing it on any lists.  It should perhaps be checked earlier, but
060  // it's convenient (for the Splitter writer) to do so after instantiating.
061  public boolean splitter_valid() {
062    return splitter.valid();
063  }
064
065  public @Nullable DummyInvariant dummyInvariant() {
066    return splitter.getDummyInvariant();
067  }
068}