Skip to content

Commit

Permalink
Address compile warnings
Browse files Browse the repository at this point in the history
Many remaining warnings relate to exhaustivity of DataType (#304)
and Data matches (#305).
  • Loading branch information
dlindhol committed Jun 29, 2021
1 parent b003101 commit 5f3fead
Show file tree
Hide file tree
Showing 30 changed files with 83 additions and 55 deletions.
6 changes: 3 additions & 3 deletions core/src/main/scala/latis/data/SamplePosition.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ package latis.data
* Positions in the range can point to a nested SampledFunction so we need a
* SamplePath (Seq[SamplePosition]) to locate a variable in the model.
*/
trait SamplePosition
sealed trait SamplePosition

//TODO: enforce no negative values
case class DomainPosition(i: Int) extends SamplePosition
final case class DomainPosition(i: Int) extends SamplePosition

case class RangePosition(i: Int) extends SamplePosition
final case class RangePosition(i: Int) extends SamplePosition
2 changes: 1 addition & 1 deletion core/src/main/scala/latis/data/StreamFunction.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ case class StreamFunction(samples: Stream[IO, Sample]) extends SampledFunction {
val ord: PartialOrdering[DomainData] = ordering.getOrElse(DefaultDomainOrdering)
//TODO: avoid unsafe run
StreamUtils.unsafeStreamToSeq(samples.find(s => ord.equiv(s.domain, data))).headOption match {
case Some(Sample(_, rd)) => Right(rd)
case Some(sample) => Right(sample.range)
case None =>
val msg = s"No sample found matching $data"
Left(LatisException(msg))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ case class ComputationalDataset(
*/
override def toString: String = model match {
case Function(domain, range) => s"$id: $domain => $range"
case _ => throw LatisException("ComputationalDataset model must be a Function")
}

//TODO: need SampledDataset to do things this can't
Expand Down
5 changes: 3 additions & 2 deletions core/src/main/scala/latis/input/Adapter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package latis.input

import java.net.URI

import scala.annotation.nowarn

import latis.data.Data
import latis.ops.Operation

Expand All @@ -13,8 +15,7 @@ trait Adapter {
//TODO: add SmartAdapter that takes ops?
//TODO: require UnaryOperations

@annotation.nowarn("msg=never used")
def canHandleOperation(op: Operation): Boolean = false
def canHandleOperation(@nowarn("cat=unused") op: Operation): Boolean = false

def getData(baseUri: URI, ops: Seq[Operation] = Seq.empty): Data
}
7 changes: 5 additions & 2 deletions core/src/main/scala/latis/input/DatasetReader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package latis.input
import java.net.URI
import java.util.ServiceLoader

import scala.annotation.nowarn
import scala.jdk.CollectionConverters._

import latis.dataset.Dataset
Expand All @@ -18,9 +19,11 @@ import latis.util.LatisException
* the ServiceProvider mechanism (with an entry in META-INF/services).
*/
trait DatasetReader {

def model: DataType
@annotation.nowarn("msg=never used")
def canRead(uri: URI): Boolean = false

def canRead(@nowarn("cat=unused") uri: URI): Boolean = false

def read(uri: URI): Dataset
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package latis.input

import java.net.URI

import scala.annotation.nowarn

import cats.implicits._
import cats.effect.IO
import fs2.Stream
Expand Down Expand Up @@ -29,8 +31,7 @@ final class GranuleListAppendAdapter(granules: Dataset, template: URI => Dataset

/** Gets data using this adapter. */
def getData(
@annotation.nowarn("msg=never used")
ops: Seq[Operation]
@nowarn("cat=unused") ops: Seq[Operation]
): SampledFunction = {
val samples: Stream[IO, Sample] = for {
sample <- granules.samples
Expand Down
4 changes: 3 additions & 1 deletion core/src/main/scala/latis/model/valueType.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package latis.model

import scala.annotation.nowarn

import cats.syntax.all._
import scala.util.Try

Expand Down Expand Up @@ -33,7 +35,7 @@ sealed trait ValueType extends Serializable {
*
* NaN will be converted to 0 for many value types.
*/
def convertDouble(value: Double): Option[Datum] = None
def convertDouble(@nowarn("cat=unused") value: Double): Option[Datum] = None
//TODO: beware silent truncation for overflow
// e.g. Double.MaxValue.toShort = -1
// Int, Long will yield their max value
Expand Down
1 change: 1 addition & 0 deletions core/src/main/scala/latis/ops/Composition.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ case class Composition(dataset: Dataset) extends MapRangeOperation {
case mds: MemoizedDataset => DomainData.fromData(data).flatMap { dd =>
mds.data.eval(dd).map(Data.fromSeq(_))
}
case _ => throw LatisException("Invalid dataset for composition")
}
(input: Data) =>
f(input) match {
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/latis/ops/ConvertTime.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ case class ConvertTime(scale: TimeScale) extends TimeOperation {
(d : Datum) => d match {
case Text(s) =>
format.parse(s)
.map(converter.convert(_))
.map(t => converter.convert(t.toDouble))
.flatMap(Data.fromValue(_))
.fold(throw _, identity)
case _ => throw new LatisException(s"Data does not match string value type: $d")
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/scala/latis/ops/Curry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ case class Curry(arity: Int = 1) extends GroupOperation {
case ss => Tuple(ss)
}
//case Function(Tuple(es @ _*), _) => Tuple(es.take(arity))
case _ => throw LatisException("Invalid DataType for Curry")
}

def aggregation: Aggregation = {
val mapOp = new MapOperation {
override def mapFunction(model: DataType): Sample => Sample = {
case Sample(d, r) => Sample(d.drop(arity), r)
}
override def mapFunction(model: DataType): Sample => Sample =
(sample: Sample) => Sample(sample.domain.drop(arity), sample.range)

// takes the model for the dataset and returns the range of the curried dataset
override def applyToModel(model: DataType): Either[LatisException, DataType] = model match {
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/scala/latis/ops/HeadAggregation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ case class HeadAggregation() extends Aggregation {
def aggregateFunction(model: DataType): Iterable[Sample] => Data =
(samples: Iterable[Sample]) =>
if (samples.isEmpty) applyToModel(model).fold(throw _, identity) match {
case f: Function => SeqFunction(Seq.empty) //can't fill Function, use empty
//can't fill Function, use empty //TODO: NullData? not for outer function?
case _: Function => SeqFunction(Seq.empty)
case dt => dt.fillData
}
else Data.fromSeq(samples.head.range)
Expand Down
7 changes: 3 additions & 4 deletions core/src/main/scala/latis/ops/MapRangeOperation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ trait MapRangeOperation extends StreamOperation {
* Implements a Pipe in terms of the mapFunction.
*/
def pipe(model: DataType): Pipe[IO, Sample, Sample] =
(stream: Stream[IO, Sample]) => stream.map {
case Sample(d, r) =>
val range = RangeData(mapFunction(model)(Data.fromSeq(r)))
Sample(d, range)
(stream: Stream[IO, Sample]) => stream.map { sample =>
val range = RangeData(mapFunction(model)(Data.fromSeq(sample.range)))
Sample(sample.domain, range)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ case class NearestNeighborAggregation(domain: DomainData) extends Aggregation {
case Function(_, r) => r.fillData
case _ => ??? //TODO: error, model must be a Function
} else {
val sample = samples.minBy {
case Sample(dd, _) => DomainData.distance(domain, dd)
val sample = samples.minBy { sample =>
DomainData.distance(domain, sample.domain)
}
Data.fromSeq(sample.range)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ case class PartiallyAppliedBinaryOperation(
(dataset match {
case ad: AdaptedDataset => ad.tap().map(_.data)
case td: TappedDataset => td.data.asRight
case _ => throw LatisException("Invalid dataset for PartiallyAppliedBinaryOperation")
}).flatMap(binOp.applyToData(_, data))
}
}
2 changes: 2 additions & 0 deletions core/src/main/scala/latis/ops/Pivot.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ case class Pivot(values: Seq[String], vids: Seq[String]) extends MapOperation {
case Sample(domain, RangeData(mf: MemoizedFunction)) =>
val scalar = model match {
case Function(_, Function(s: Scalar, _)) => s
case _ => throw LatisException("Invalid DataType for Pivot")
}
// Eval nested Function at each requested value.
val range = values.flatMap { value =>
Expand All @@ -64,6 +65,7 @@ case class Pivot(values: Seq[String], vids: Seq[String]) extends MapOperation {
rangeValues.fold(throw _, identity)
}
Sample(domain, RangeData(range))
case _ => throw LatisException("Invalid Sample for Pivot")
//TODO: deal with errors?
//TODO: use Fill interpolation? or nearest-neighbor so users don't need to know exact values
}
Expand Down
25 changes: 16 additions & 9 deletions core/src/main/scala/latis/ops/Projection.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ case class Projection(ids: Identifier*) extends MapOperation {

/** Recursive method to apply the projection. */
private def applyToVariable(v: DataType): Option[DataType] = v match {
//TODO: make exhaustive (https://github.com/latis-data/latis3/issues/304)
case s: Scalar =>
if (s.id.exists(id => ids.contains(id))) Some(s) else None
case Tuple(vars @ _*) =>
Expand All @@ -47,7 +48,7 @@ case class Projection(ids: Identifier*) extends MapOperation {
case None => Some(Function(makeIndex(domain), domain))
}
// Not all domain variables projected.
case Some(d) =>
case Some(_) =>
//TODO: Move remaining vars to range and replace domain with single index.
throw LatisException("Partial domain projection not yet supported.")
// No domain variable projected
Expand All @@ -64,7 +65,7 @@ case class Projection(ids: Identifier*) extends MapOperation {
// Get the sample positions of the projected variables.
// Assumes Scalar projection only, for now.
// Does not support nested Function, for now.
val (dpos, rpos): (List[SamplePosition], List[SamplePosition]) = model
val positions = model
.getScalars //start here so we preserve variable order
.map(_.id.get)
.filter(ids.contains(_)) //keep the projected ids
Expand All @@ -73,7 +74,15 @@ case class Projection(ids: Identifier*) extends MapOperation {
case p :: Nil => p
case _ :: _ => throw LatisException("Can't project within nested Function.")
case _ => ??? //shouldn't happen
}.partition(_.isInstanceOf[DomainPosition])
}
// Separate domain and range positions
val (dpos, rpos): (List[DomainPosition], List[RangePosition]) =
positions.foldLeft((List[DomainPosition](), List[RangePosition]())) {
(p, pos) => pos match {
case dp: DomainPosition => ((p._1 :+ dp), p._2)
case rp: RangePosition => (p._1, (p._2 :+ rp))
}
}

val domainIndices: List[Int] = dpos.map {
case DomainPosition(i) => i
Expand All @@ -83,13 +92,11 @@ case class Projection(ids: Identifier*) extends MapOperation {
}

if (rangeIndices.isEmpty) {
(sample: Sample) => sample match {
case Sample(ds, rs) => Sample(DomainData(), domainIndices.map(ds))
}
(sample: Sample) =>
Sample(DomainData(), domainIndices.map(sample.domain))
} else {
(sample: Sample) => sample match {
case Sample(ds, rs) => Sample(domainIndices.map(ds), rangeIndices.map(rs))
}
(sample: Sample) =>
Sample(domainIndices.map(sample.domain), rangeIndices.map(sample.range))
}
}

Expand Down
1 change: 1 addition & 0 deletions core/src/main/scala/latis/ops/Selection.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ case class Selection(id: Identifier, operator: ast.SelectionOp, value: String) e

(sample: Sample) =>
sample.getValue(pos) match {
//TODO: not exhaustive: Some(Data) See https://github.com/latis-data/latis3/issues/305
case Some(d: Datum) =>
ordering
.tryCompare(d, cdata)
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/latis/ops/Stride.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ case class Stride(stride: Seq[Int]) extends Filter {

def predicate(model: DataType): Sample => Boolean = {
var count = -1
(sample: Sample) => {
(_: Sample) => {
count = count + 1
if (count % stride.head == 0) true
else false
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/scala/latis/ops/Substitution.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ case class Substitution(dataset: Dataset) extends MapOperation {
case Right(rd) =>
// Make sure these range data can be used for a domain, i.e. all Datum, no SF
rd match {
//TODO: not exhaustive: Some(Data) See https://github.com/latis-data/latis3/issues/305
case d: Datum => List(d)
case TupleData(ds @ _*) => ds.toList.map {
case d: Datum => d
Expand All @@ -75,6 +76,7 @@ case class Substitution(dataset: Dataset) extends MapOperation {
val vals: List[Data] = sample.range
// Extract the values to be replaced; can't include Function
val slice: List[Datum] = vals.slice(i, i + domainVariableIDs.length).map {
//TODO: not exhaustive: Some(Data) See https://github.com/latis-data/latis3/issues/305
case d: Datum => d
// Note, there should be no TupleData in a Sample
case _: TupleData =>
Expand All @@ -84,6 +86,7 @@ case class Substitution(dataset: Dataset) extends MapOperation {
}
// Evaluate the substitution Dataset with the values to be replaced
val sub: List[Data] = f(Data.fromSeq(slice)) match {
//TODO: not exhaustive: Some(Data) See https://github.com/latis-data/latis3/issues/305
case Right(d: Datum) => List(d)
case Right(TupleData(ds @ _*)) => ds.toList
case Left(le) => throw le
Expand Down Expand Up @@ -118,6 +121,7 @@ case class Substitution(dataset: Dataset) extends MapOperation {
// substitution Dataset's domain with the types from its range.
// Recursive helper function
def go(dt: DataType): DataType = dt match {
//TODO: not exhaustive: Some(Data) See https://github.com/latis-data/latis3/issues/304
case s: Scalar =>
if ((domainVariableIDs.length == 1) && s.id.contains(domainVariableIDs.head)) subScalars.head
else s
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/latis/ops/Take.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import latis.util.LatisException

class Take private (val n: Int) extends StreamOperation {

def pipe(model: DataType): Pipe[IO, Sample, Sample] = in => in.take(n)
def pipe(model: DataType): Pipe[IO, Sample, Sample] = in => in.take(n.toLong)

def applyToModel(model: DataType): Either[LatisException, DataType] =
model.asRight
Expand Down
12 changes: 7 additions & 5 deletions core/src/main/scala/latis/ops/Uncurry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ case class Uncurry() extends FlatMapOperation {

// Recursive helper function to restructure the model
def go(dt: DataType): Unit = dt match {
//TODO: not exhaustive: See https://github.com/latis-data/latis3/issues/304
case dt: Scalar => rs += dt
case Tuple(es @ _*) => es.foreach(go)
case Function(d, r) =>
//flatten tuples, instead of recursing on domain (no nested functions)
d match {
//TODO: not exhaustive: See https://github.com/latis-data/latis3/issues/304
case Tuple(es @ _*) => ds ++= es
case _: Scalar => ds += d
}
Expand Down Expand Up @@ -66,16 +68,16 @@ case class Uncurry() extends FlatMapOperation {
* Functions are not within a Tuple.
*/
def flatMapFunction(model: DataType): Sample => MemoizedFunction = {
case s @ Sample(ds, rs) =>
(sample: Sample) =>
//TODO: recurse for deeper nested functions
//TODO: allow function in tuple
rs match {
sample.range match {
case ((sf: MemoizedFunction) :: Nil) => //one function in range
val samples = sf.sampleSeq.map {
case Sample(ds2, rs2) => Sample(ds ++ ds2, rs2)
val samples = sf.sampleSeq.map { s =>
Sample(sample.domain ++ s.domain, s.range)
}
SampledFunction(samples)
case _ => SampledFunction(Seq(s)) //no-op if range is not a Function
case _ => SampledFunction(Seq(sample)) //no-op if range is not a Function
}
}

Expand Down
2 changes: 0 additions & 2 deletions core/src/main/scala/latis/ops/parser/ast.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package latis.ops.parser

import latis.util.Identifier

object ast {

}
4 changes: 3 additions & 1 deletion core/src/main/scala/latis/output/BinaryEncoder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import scodec.{Encoder => SEncoder, _}
import scodec.Codec
import scodec.bits._
import scodec.stream.StreamEncoder
import latis.data.Data._

import latis.data._
import latis.data.Data._
import latis.dataset._
import latis.model._
import latis.ops.Uncurry
Expand All @@ -32,6 +33,7 @@ class BinaryEncoder extends Encoder[IO, BitVector] {
def sampleEncoder(model: DataType): SEncoder[Sample] = new SEncoder[(DomainData, RangeData)] {
def encode(sample: (DomainData, RangeData)): Attempt[BitVector] =
(model, sample) match {
//TODO: not exhaustive: See https://github.com/latis-data/latis3/issues/304
case (Function(domain, range), Sample(ds, rs)) =>
val scalars = (domain.getScalars ++ range.getScalars).filterNot(_.isInstanceOf[Index])
val datas = ds ++ rs
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/scala/latis/output/CsvEncoder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class CsvEncoder(header: Dataset => Stream[IO, String]) extends Encoder[IO, Stri
*/
def encodeSample(model: DataType, sample: Sample): String =
(model, sample) match {
//TODO: not exhaustive: See https://github.com/latis-data/latis3/issues/304
case (Function(domain, range), Sample(ds, rs)) =>
val scalars = (domain.getScalars ++ range.getScalars).filterNot(_.isInstanceOf[Index])
val datas = ds ++ rs
Expand Down Expand Up @@ -61,6 +62,7 @@ object CsvEncoder {

def withColumnName: CsvEncoder = {
def header(dataset: Dataset): String = dataset.model match {
//TODO: not exhaustive: See https://github.com/latis-data/latis3/issues/304
case Function(domain, range) =>
(domain.getScalars ++ range.getScalars)
.filterNot(_.isInstanceOf[Index])
Expand Down
Loading

0 comments on commit 5f3fead

Please sign in to comment.