of static method

LogicValue of(
  1. dynamic val,
  2. {bool fill = false,
  3. int? width}
)

Constructs a LogicValue from val which could be of a variety of types.

Supported types include String, bool, int, BigInt, LogicValue, and Iterable<LogicValue>.

If fill is set, then all bits of the returned value will be set to val. If the val is not representable as a single bit of information, then setting fill will throw an Exception.

If the width can be inferred from the type (e.g. String, LogicValue, Iterable<LogicValue>), then width does not need to be provided. If width is provided and does not match an inferred width, then width is used. If a width cannot be inferred, then it is required, or else it will throw an Exception. If val does not fit in a specified width, then the returned value will be truncated. bools will infer a default width of 1, but it can be overridden. Invalid 1-bit vals will always be filled even if fill is false, but will default to a width of 1 unless width is specified.

Implementation

static LogicValue of(dynamic val, {bool fill = false, int? width}) {
  if (val is int) {
    if (width == null) {
      throw LogicValueConstructionException(
          '`width` must be provided for `int`.');
    }

    if (fill) {
      return LogicValue.filled(
          width,
          val == 0
              ? LogicValue.zero
              : val == 1
                  ? LogicValue.one
                  : throw LogicValueConstructionException(
                      '`int` can only can fill 0 or 1, but saw $val.'));
    } else {
      return LogicValue.ofInt(val, width);
    }
  } else if (val is BigInt) {
    if (width == null) {
      throw LogicValueConstructionException(
          '`width` must be provided for `BigInt`.');
    }

    if (fill) {
      return LogicValue.filled(
          width,
          val == BigInt.zero
              ? LogicValue.zero
              : val == BigInt.one
                  ? LogicValue.one
                  : throw LogicValueConstructionException(
                      '`BigInt` can only fill 0 or 1, but saw $val.'));
    } else {
      return LogicValue.ofBigInt(val, width);
    }
  } else if (val is bool) {
    width ??= 1;

    if (fill) {
      return LogicValue.filled(width, val ? LogicValue.one : LogicValue.zero);
    }
    return LogicValue.ofInt(val ? 1 : 0, width);
  } else if (val is LogicValue) {
    if (fill && val.width != 1) {
      throw LogicValueConstructionException(
          'Only 1-bit `LogicValue`s can be filled');
    }

    if (val.width == 1 && (!val.isValid || fill)) {
      if (!val.isValid) {
        // ignore: parameter_assignments
        width ??= 1;
      }
      if (width == null) {
        throw LogicValueConstructionException(
            'Filled `LogicValue` $val must have provided a width.');
      }
      return LogicValue.filled(width, val);
    } else {
      if (val.width == width || width == null) {
        return val;
      } else if (width < val.width) {
        return val.getRange(0, width);
      } else {
        return val.zeroExtend(width);
      }
    }
  } else if (val is String) {
    if (fill && val.length != 1) {
      throw LogicValueConstructionException(
          'Only 1-bit values can be filled');
    }

    if (val.length == 1 && (val == 'x' || val == 'z' || fill)) {
      if (val == 'x' || val == 'z') {
        // ignore: parameter_assignments
        width ??= 1;
      }
      if (width == null) {
        throw LogicValueConstructionException(
            'Filled `String` $val must have provided a width.');
      }
      return LogicValue.filled(width, LogicValue.ofString(val));
    } else {
      if (val.length == width || width == null) {
        return LogicValue.ofString(val);
      } else if (width < val.length) {
        return LogicValue.ofString(val.substring(0, width));
      } else {
        return LogicValue.ofString(val).zeroExtend(width);
      }
    }
  } else if (val is Iterable<LogicValue>) {
    if (fill && val.length != 1) {
      throw LogicValueConstructionException(
          'Only 1-bit values can be filled');
    }

    if (val.length == 1 &&
        (val.first == LogicValue.x || val.first == LogicValue.z || fill)) {
      if (!val.first.isValid) {
        // ignore: parameter_assignments
        width ??= 1;
      }
      if (width == null) {
        throw LogicValueConstructionException(
            'Filled `Iterable<LogicValue>` $val must have provided a width.');
      }
      return LogicValue.filled(width, val.first);
    } else {
      if (val.length == width || width == null) {
        return LogicValue.ofIterable(val);
      } else if (width < val.length) {
        return LogicValue.ofIterable(val).getRange(0, width);
      } else {
        return LogicValue.ofIterable(val).zeroExtend(width);
      }
    }
  } else if (val == null) {
    throw LogicValueConstructionException('Cannot construct from `null`.');
  } else {
    throw UnsupportedTypeException(val,
        const [LogicValue, int, BigInt, bool, String, Iterable<LogicValue>]);
  }
}