// // Copyright (C) 2010 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.vm; import java.util.Arrays; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; import cmu.conditional.ChoiceFactory; import cmu.conditional.Conditional; import cmu.conditional.One; import de.fosd.typechef.featureexpr.FeatureExpr; import de.fosd.typechef.featureexpr.FeatureExprFactory; import gov.nasa.jpf.util.HashData; import gov.nasa.jpf.util.IntVector; /** * value container for non-array classes */ public class NamedFields extends Fields { private static final One<Integer> nullValue = One.valueOf(0); /** * this is where we store the instance data. Since field types are * heterogenous, we have to map everything into int */ protected Conditional<Integer>[] values; @SuppressWarnings("unchecked") public NamedFields(int dataSize) { values = new Conditional[dataSize]; Arrays.fill(values, nullValue); } @Override public int[] asFieldSlots() { int[] array = new int[values.length]; int i = 0; for (Conditional<Integer> v : values) { array[i++] = v.getValue(true); } return array; } /** * give an approximation of the heap size in bytes - we assume fields are word * aligned, hence the number of values*4 should be good. Note that this is * overridden by ArrayFields (arrays would be packed) */ public int getHeapSize() { return values.length * 4; } @Override public Conditional<Integer> getIntValue(int index) { return values[index]; } public boolean isEqual(Fields o, int off, int len, int otherOff) { if (o instanceof NamedFields) { NamedFields other = (NamedFields) o; int iEnd = off + len; int jEnd = otherOff + len; Conditional<Integer>[] v = other.values; if ((iEnd > values.length) || (jEnd > v.length)) { return false; } for (int i = off, j = otherOff; i < iEnd; i++, j++) { if (values[i] != v[j]) { return false; } } return true; } else { return false; } } @Override public Conditional<Integer> getReferenceValue(int index) { return values[index]; } @Override public Conditional<Long> getLongValue(final int index) { return values[index + 1].mapr(new Function<Integer, Conditional<Long>>() { @Override public Conditional<Long> apply(final Integer l) { return values[index].mapr(new Function<Integer, Conditional<Long>>() { @Override public Conditional<Long> apply(final Integer h) { return new One<>(Types.intsToLong(l, h)); } }); } }); } @Override public Conditional<Boolean> getBooleanValue(int index) { return values[index].mapr(new Function<Integer, Conditional<Boolean>>() { @Override public Conditional<Boolean> apply(Integer v) { return One.valueOf(Types.intToBoolean(v)); } }); } @Override public Conditional<Byte> getByteValue(int index) { return values[index].mapr(new Function<Integer, Conditional<Byte>>() { @Override public Conditional<Byte> apply(Integer x) { return One.valueOf(x.byteValue()); } }).simplify(); } @Override public Conditional<Character> getCharValue(int index) { return values[index].map(GetCharValue); } private static final Function<Integer, Character> GetCharValue = new Function<Integer, Character>() { @Override public Character apply(final Integer x) { return (char) x.intValue(); } }; @Override public Conditional<Short> getShortValue(int index) { return values[index].map(new Function<Integer, Short>() { @Override public Short apply(Integer v) { return (short)v.intValue(); } }); } // <2do> get rid of it!! this is only for internal use, to increase efficiency public int[] getValues() { return asFieldSlots(); } @Override public void setReferenceValue(FeatureExpr ctx, int index, Conditional<Integer> newValue) { if (Conditional.isTautology(ctx)) { values[index] = newValue; } else { values[index] = ChoiceFactory.create(ctx, newValue, values[index]).simplify(); } } @Override public void setBooleanValue(FeatureExpr ctx, int index, Conditional<Boolean> newValue) { if (Conditional.isTautology(ctx)) { values[index] = One.valueOf(newValue.getValue() ? 1 : 0); } else { values[index] = ChoiceFactory.create(ctx, newValue.mapr(new Function<Boolean, Conditional<Integer>>() { @Override public Conditional<Integer> apply(Boolean v) { return One.valueOf(v ? 1 : 0); } }), values[index]).simplify(); } } @Override public void setByteValue(FeatureExpr ctx, int index, Conditional<Byte> newValue) { if (Conditional.isTautology(ctx)) { values[index] = One.valueOf((int)newValue.getValue()); } else { values[index] = ChoiceFactory.create(ctx, newValue.mapr(new Function<Byte, Conditional<Integer>>() { @Override public Conditional<Integer> apply(Byte x) { return One.valueOf((int) x); } }), values[index]).simplify(); } } @Override public void setCharValue(FeatureExpr ctx, int index, Conditional<Character> newValue) { values[index] = ChoiceFactory.create(ctx, newValue.mapr(SetCharValue), values[index]).simplify(); } private static final Function<Character, Conditional<Integer>> SetCharValue = new Function<Character, Conditional<Integer>>() { @Override public Conditional<Integer> apply(final Character newValue) { return new One<>((int) newValue.charValue()); } }; @Override public void setShortValue(FeatureExpr ctx, int index, Conditional<Short> newValue) { if (Conditional.isTautology(ctx)) { values[index] = new One<>((int)(newValue.getValue())); } else { values[index] = ChoiceFactory.create(ctx, newValue.mapr(new Function<Short, Conditional<Integer>>() { @Override public Conditional<Integer> apply(Short v) { return new One<>((int)v); } }), values[index]).simplify(); } } @Override public void setFloatValue(FeatureExpr ctx, int index, Conditional<Float> newValue) { if (Conditional.isTautology(ctx)) { values[index] = new One<>(Types.floatToInt(newValue.getValue())); } else { values[index] = ChoiceFactory.create(ctx, newValue.map(new Function<Float, Integer>() { @Override public Integer apply(Float v) { return Types.floatToInt(v); } }), values[index]).simplify(); } } @Override public void setIntValue(FeatureExpr ctx, int pos, Conditional<Integer> newValue) { if (Conditional.isTautology(ctx)) { values[pos] = newValue; } else { values[pos] = ChoiceFactory.create(ctx, newValue, values[pos]).simplify(); } } @Override public void setLongValue(FeatureExpr ctx, final int index, Conditional<Long> newValue) { newValue.mapf(ctx, new BiConsumer<FeatureExpr, Long>() { @Override public void accept(FeatureExpr ctx, Long newValue) { if (Conditional.isTautology(ctx)) { values[index] = new One<>(Types.hiLong(newValue)); values[index + 1] = new One<>(Types.loLong(newValue)); } else if (!Conditional.isContradiction(ctx)) { values[index] = ChoiceFactory.create(ctx, new One<>(Types.hiLong(newValue)), values[index]); values[index + 1] = ChoiceFactory.create(ctx, new One<>(Types.loLong(newValue)), values[index + 1]); } } }); values[index] = values[index].simplify(); values[index + 1] = values[index + 1].simplify(); } @Override public void setDoubleValue(FeatureExpr ctx, final int index, Conditional<Double> newValue) { newValue.mapf(ctx, new BiConsumer<FeatureExpr, Double>() { @Override public void accept(FeatureExpr ctx, Double newValue) { if (Conditional.isTautology(ctx)) { values[index] = new One<>(Types.hiDouble(newValue)); values[index + 1] = new One<>(Types.loDouble(newValue)); } else if (!Conditional.isContradiction(ctx)) { values[index] = ChoiceFactory.create(ctx, new One<>(Types.hiDouble(newValue)), values[index]); values[index + 1] = ChoiceFactory.create(ctx, new One<>(Types.loDouble(newValue)), values[index + 1]); } } }); values[index] = values[index].simplify(); values[index + 1] = values[index + 1].simplify(); } @Override public Conditional<Float> getFloatValue(int index) { return values[index].map(new Function<Integer, Float>() { @Override public Float apply(Integer v) { return Types.intToFloat(v); } }); } @Override public Conditional<Double> getDoubleValue(final int index) { return values[index + 1].mapf(FeatureExprFactory.True(), new BiFunction<FeatureExpr, Integer, Conditional<Double>>() { @Override public Conditional<Double> apply(FeatureExpr ctx, final Integer y) { return values[index].mapf(FeatureExprFactory.True(), new BiFunction<FeatureExpr, Integer, Conditional<Double>>() { @Override public Conditional<Double> apply(FeatureExpr ctx, final Integer x) { return new One<>(Types.intsToDouble(y, x)); } }); } }).simplify(); } /** * Creates a clone. */ public NamedFields clone() { NamedFields f = (NamedFields) cloneFields(); f.values = values.clone(); return f; } /** * Checks for equality. */ public boolean equals(Object o) { if (o instanceof NamedFields) { NamedFields other = (NamedFields) o; // --- check values Conditional<Integer>[] v1 = values; Conditional<Integer>[] v2 = other.values; int l = v1.length; if (l != v2.length) { return false; } for (int i = 0; i < l; i++) { if (!v1[i].equals(v2[i])) { return false; } } return super.compareAttrs(other); } else { return false; } } public int hashCode() { throw new RuntimeException("hashCode not designed"); } // serialization interface public void appendTo(IntVector v) { v.append(getValues()); // v.append(values); } /** * Adds some data to the computation of an hashcode. */ public void hash(HashData hd) { int[] v = getValues(); for (int i = 0, l = v.length; i < l; i++) { hd.add(v[i]); } } /** * Size of the fields. */ public int size() { return values.length; } public String toString() { StringBuilder sb = new StringBuilder("NamedFields["); sb.append("values="); sb.append('['); for (int i = 0; i < values.length; i++) { if (i != 0) { sb.append(','); } sb.append(values[i]); } sb.append(']'); sb.append(','); sb.append(']'); return sb.toString(); } // <2do> replace with copyTo() !! public int[] getRawValues() {// TODO jens return getValues(); } public void copyFrom(Fields other) { System.arraycopy(((NamedFields) other).values, 0, this.values, 0, values.length); super.copyAttrs(other); } }