Permalink
Browse files

Removed dependency from typelevel compiler (#49)

* Removed dependency from typelevel compiler
* Fixed 2.11.x compilation
* Readme and improved build
  • Loading branch information...
barambani committed Oct 29, 2018
1 parent d6323fb commit 542adabf680066bf4c8629a96abc1db821d1b21c
View
@@ -2,7 +2,7 @@ sudo: false
dist: trusty
language: scala
scala:
- 2.12.4-bin-typelevel-4
- 2.12.7
- 2.11.11-bin-typelevel-4
jdk:
- oraclejdk8
View
@@ -16,9 +16,8 @@ LaserDisc is a(nother) Scala driver for [Redis](https://redis.io/), written in S
It differentiates itself from the others for having a core layer, which is made up of all the supported Redis commands
and the Redis Serialization Protocol ([RESP](https://redis.io/topics/protocol)), that is strongly typed and which makes
heavy use of [shapeless](https://github.com/milessabin/shapeless) and [refined](https://github.com/fthomas/refined) to
achieve this. It's also worth noting that the core - in order to be built - makes use of
[Typelevel's Scala 2.12](https://typelevel.org/scala) fork, since it requires the enhancements on implicit heuristics
and the surfacing of literal types. Finally, it also provides an implementation of RESP built using
achieve this. It's also worth noting that the core - in order to be built on scala 2.11.x - makes use of
[Typelevel's Scala 2.11](https://typelevel.org/scala) fork, since it requires the enhancements on implicit heuristics. Finally, it also provides an implementation of RESP built using
[scodec](http://scodec.org/).
On top of this, one or more clients can be implemented. The only one currently available out of the box is built using
View
@@ -1,10 +1,15 @@
import sbtcrossproject.{CrossType, crossProject}
import sbtcrossproject.CrossPlugin.autoImport.crossProject
import sbtcrossproject.CrossType
val `scala 211` = "2.11.11-bin-typelevel-4"
val `scala 212` = "2.12.7"
val V = new {
val fs2 = "1.0.0"
val `kind-projector` = "0.9.8"
val kittens = "1.2.0"
val refined = "0.8.7" //FIXME can't upgrade see https://gist.github.com/sirocchj/64a00a28f5cc5776140c776c7db4e2e3
val refined = "0.9.2"
val refined211 = "0.8.7"
val scalacheck = "1.13.5"
val scalatest = "3.0.5"
val `scodec-bits` = "1.1.6"
@@ -17,14 +22,20 @@ val V = new {
val `fs2-core` = Def.setting("co.fs2" %%% "fs2-core" % V.fs2)
val `fs2-io` = Def.setting("co.fs2" %% "fs2-io" % V.fs2)
val kittens = Def.setting("org.typelevel" %%% "kittens" % V.kittens)
val refined = Def.setting("eu.timepit" %%% "refined" % V.refined)
val `scodec-bits` = Def.setting("org.scodec" %%% "scodec-bits" % V.`scodec-bits`)
val `scodec-core` = Def.setting("org.scodec" %%% "scodec-core" % V.`scodec-core`)
val `scodec-stream` = Def.setting("org.scodec" %%% "scodec-stream" % V.`scodec-stream`)
val shapeless = Def.setting("com.chuusai" %%% "shapeless" % V.shapeless)
val `log-effect-fs2` = Def.setting("io.laserdisc" %%% "log-effect-fs2" % V.`log-effect-fs2`)
val scalacheck = Def.setting("org.scalacheck" %%% "scalacheck" % V.scalacheck % Test)
val scalatest = Def.setting("org.scalatest" %%% "scalatest" % V.scalatest % Test)
val refined = Def.setting {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 11)) => "eu.timepit" %%% "refined" % V.refined211
case _ => "eu.timepit" %%% "refined" % V.refined
}
}
val `kind-projector-compiler-plugin` = Def.setting {
compilerPlugin("org.spire-math" % "kind-projector" % V.`kind-projector` cross CrossVersion.binary)
@@ -34,7 +45,15 @@ val `scalajs-compiler-plugin` = Def.setting {
}
val coreDeps = Def.Initialize.join {
Seq(`kind-projector-compiler-plugin`, refined, `scodec-bits`, `scodec-core`, shapeless, scalacheck, scalatest)
Seq(
`kind-projector-compiler-plugin`,
`scodec-bits`,
`scodec-core`,
shapeless,
refined,
scalacheck,
scalatest
)
}
val fs2Deps = Def.Initialize.join {
@@ -81,23 +100,24 @@ val externalApiMappings = Def.task {
}
val versionDependantScalacOptions = Def.setting {
def versionDependent(scalaVersion: String, flags: Seq[String]) = CrossVersion.partialVersion(scalaVersion) match {
case Some((2, major)) if major >= 12 =>
flags ++ Seq(
"-Xlint:constant", // Evaluation of a constant arithmetic expression results in an error.
"-Ywarn-extra-implicit", // Warn when more than one implicit parameter section is defined.
"-Ywarn-unused:explicits", // Warn if a parameter is unused.
"-Ywarn-unused:imports", // Warn if an import selector is not referenced.
"-Ywarn-unused:locals", // Warn if a local definition is unused.
"-Ywarn-unused:patvars", // Warn if a variable bound in a pattern is unused.
"-Ywarn-unused:privates", // Warn if a private member is unused.
"-Ywarn-value-discard" // Warn when non-Unit expression results are unused.
)
case _ =>
flags
.filterNot(_ == "-Xlint:missing-interpolator") //@implicitNotFound uses ${A} syntax w/o need for s interpolator
}
def versionDependent(scalaVersion: String, flags: Seq[String]) =
CrossVersion.partialVersion(scalaVersion) match {
case Some((2, major)) if major >= 12 =>
flags ++ Seq(
"-Xlint:constant", // Evaluation of a constant arithmetic expression results in an error.
"-Ywarn-extra-implicit", // Warn when more than one implicit parameter section is defined.
"-Ywarn-unused:explicits", // Warn if a parameter is unused.
"-Ywarn-unused:imports", // Warn if an import selector is not referenced.
"-Ywarn-unused:locals", // Warn if a local definition is unused.
"-Ywarn-unused:patvars", // Warn if a variable bound in a pattern is unused.
"-Ywarn-unused:privates", // Warn if a private member is unused.
"-Ywarn-value-discard" // Warn when non-Unit expression results are unused.
)
case _ =>
(flags ++ Seq("-Yinduction-heuristics", "-Yliteral-types"))
.filterNot(_ == "-Xlint:missing-interpolator") //@implicitNotFound uses ${A} syntax w/o need for s interpolator
}
val flags = Seq(
"-deprecation", // Emit warning and location for usages of deprecated APIs.
"-encoding",
@@ -136,8 +156,6 @@ val versionDependantScalacOptions = Def.setting {
"-Ywarn-nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
"-Ywarn-nullary-unit", // Warn when nullary methods return Unit.
"-Ywarn-numeric-widen", // Warn when numerics are widened.
"-Yinduction-heuristics", // Nobody wants recursive implicit searches that last forever, we need TLS for this
"-Yliteral-types" // Allow inferring singleton types, we need TLS for this in 2.12
)
versionDependent(scalaVersion.value, flags)
@@ -146,13 +164,17 @@ val versionDependantScalacOptions = Def.setting {
inThisBuild {
Def.settings(
organization := "io.laserdisc",
scalaOrganization := "org.typelevel",
scalaVersion := "2.12.4-bin-typelevel-4"
scalaVersion := `scala 212`
)
}
lazy val commonSettings = Seq(
crossScalaVersions := Seq("2.11.11-bin-typelevel-4", "2.12.4-bin-typelevel-4"),
scalaOrganization :=
(CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 11)) => "org.typelevel"
case _ => "org.scala-lang"
}),
crossScalaVersions := Seq(`scala 211`, `scala 212`),
scalacOptions ++= versionDependantScalacOptions.value,
Compile / console / scalacOptions --= Seq("-Ywarn-unused:imports", "-Xfatal-warnings"),
Test / console / scalacOptions := (Compile / console / scalacOptions).value
@@ -23,7 +23,7 @@ trait HashPExtra { this: HashP =>
]
//HMSET
[..21#final def hmset[[#A1 <: XString, B1: Show#]](key: Key, [#field1: SingletonKey[A1], value1: B1#]): Protocol.Aux["OK"] = {
[..21#final def hmset[[#A1 <: XString, B1: Show#]](key: Key, [#field1: SingletonKey[A1], value1: B1#]): Protocol.Aux[OK] = {
[#val tagged1 = tag[A1](Symbol(field1.value))#
]
hmset(key, [#labelled.field[tagged1.type](value1)# :: ] :: HNil)
@@ -13,7 +13,7 @@ trait HyperLogLogPExtra { this: HyperLogLogP =>
]
//PFMERGE
[..20#final def pfmerge(sourceKey##1: Key, [#sourceKey2: Key#], destinationKey: Key): Protocol.Aux["OK"] =
[..20#final def pfmerge(sourceKey##1: Key, [#sourceKey2: Key#], destinationKey: Key): Protocol.Aux[OK] =
pfmerge(TwoOrMoreKeys.unsafeFrom(sourceKey##1 :: [#sourceKey2# :: ] :: Nil), destinationKey)#
]
}
@@ -19,7 +19,7 @@ trait StringPExtra { this: StringP =>
]
//MSET
[#final def mset[[#A1 <: XString, B1: Show#]]([#key1: SingletonKey[A1], value1: B1#]): Protocol.Aux["OK"] = {
[#final def mset[[#A1 <: XString, B1: Show#]]([#key1: SingletonKey[A1], value1: B1#]): Protocol.Aux[OK] = {
[#val tagged1 = tag[A1](Symbol(key1.value))#
]
mset([#labelled.field[tagged1.type](value1)# :: ] :: HNil)
@@ -1,7 +1,9 @@
package laserdisc
package object protocol {
implicit def eitherSyntaxBase[A, B](aOrB: A | B): EitherSyntaxBaseOps[A, B] = new EitherSyntaxBaseOps(aOrB)
implicit def eitherSyntaxBase[A, B](aOrB: A | B): EitherSyntaxBaseOps[A, B] =
new EitherSyntaxBaseOps(aOrB)
}
final private[laserdisc] class EitherSyntaxBaseOps[A, B](private val aOrB: A | B) extends AnyVal {
@@ -1,6 +1,7 @@
import java.{lang => j}
import eu.timepit.refined.W
import eu.timepit.refined.auto._
import eu.timepit.refined.api._
import eu.timepit.refined.boolean.{And, Not, Or, True}
import eu.timepit.refined.char.Whitespace
@@ -23,6 +24,12 @@ package object laserdisc {
final type RESP = protocol.RESP
final type Show[A] = protocol.Show[A]
final type OK = String Refined Equal[W.`"OK"`.T]
final type PONG = String Refined Equal[W.`"PONG"`.T]
final val OK: OK = "OK"
final val PONG: PONG = "PONG"
//object forwarders
final val Protocol = protocol.Protocol
final val Read = protocol.Read
@@ -4,22 +4,22 @@ package protocol
trait ConnectionP {
import Read.==>
private[this] implicit final val pongRead: SimpleString ==> "PONG" = Read.instancePF {
case SimpleString("PONG") => "PONG"
private[this] implicit final val pongRead: SimpleString ==> PONG = Read.instancePF {
case SimpleString("PONG") => PONG
}
final def auth(password: Key): Protocol.Aux["OK"] = Protocol("AUTH", password).as[SimpleString, "OK"]
final def auth(password: Key): Protocol.Aux[OK] = Protocol("AUTH", password).as[SimpleString, OK]
final def echo(message: Key): Protocol.Aux[Key] = Protocol("ECHO", message).as[NonNullBulkString, Key]
final val ping: Protocol.Aux["PONG"] = Protocol("PING", Nil).as[SimpleString, "PONG"]
final val ping: Protocol.Aux[PONG] = Protocol("PING", Nil).as[SimpleString, PONG]
final def ping(message: Key): Protocol.Aux[Key] = Protocol("PING", message).as[NonNullBulkString, Key]
final val quit: Protocol.Aux["OK"] = Protocol("QUIT", Nil).as[SimpleString, "OK"]
final val quit: Protocol.Aux[OK] = Protocol("QUIT", Nil).as[SimpleString, OK]
final def select(index: DbIndex): Protocol.Aux["OK"] = Protocol("SELECT", index).as[SimpleString, "OK"]
final def select(index: DbIndex): Protocol.Aux[OK] = Protocol("SELECT", index).as[SimpleString, OK]
final def swapdb(index1: DbIndex, index2: DbIndex): Protocol.Aux["OK"] =
Protocol("SWAPDB", index1 :: index2 :: Nil).as[SimpleString, "OK"]
final def swapdb(index1: DbIndex, index2: DbIndex): Protocol.Aux[OK] =
Protocol("SWAPDB", index1 :: index2 :: Nil).as[SimpleString, OK]
}
@@ -42,15 +42,15 @@ trait HashP {
implicit ev0: Length.Aux[L, N],
ev1: N >= _1,
ev2: LUBConstraint[L, FieldType[_, _]]
): Protocol.Aux["OK"] = Protocol("HMSET", key :: l).as[SimpleString, "OK"]
): Protocol.Aux[OK] = Protocol("HMSET", key :: l).as[SimpleString, OK]
final def hmset[P <: Product, L <: HList, N <: Nat](key: Key, product: P)(
implicit gen: LabelledGeneric.Aux[P, L],
ev0: Length.Aux[L, N],
ev1: N >= _1,
ev2: LUBConstraint[L, FieldType[_, _]],
ev3: RESPParamWrite[L]
): Protocol.Aux["OK"] = Protocol("HMSET", key :: gen.to(product)).as[SimpleString, "OK"]
): Protocol.Aux[OK] = Protocol("HMSET", key :: gen.to(product)).as[SimpleString, OK]
final def hscan(key: Key, cursor: NonNegLong): Protocol.Aux[ScanKV] =
Protocol("HSCAN", key :: cursor :: HNil).as[NonNilArray, ScanKV]
@@ -8,8 +8,8 @@ trait HyperLogLogP {
final def pfcount(keys: OneOrMoreKeys): Protocol.Aux[NonNegInt] =
Protocol("PFCOUNT", keys.value).as[Integer, NonNegInt]
final def pfmerge(sourceKeys: TwoOrMoreKeys, destinationKey: Key): Protocol.Aux["OK"] =
Protocol("PFMERGE", destinationKey :: sourceKeys.value).as[SimpleString, "OK"]
final def pfmerge(sourceKeys: TwoOrMoreKeys, destinationKey: Key): Protocol.Aux[OK] =
Protocol("PFMERGE", destinationKey :: sourceKeys.value).as[SimpleString, OK]
}
trait AllHyperLogLogP extends HyperLogLogP with HyperLogLogPExtra
@@ -135,11 +135,11 @@ trait KeyP {
final def renamenx(key: Key, newKey: Key): Protocol.Aux[Boolean] =
Protocol("RENAMENX", key :: newKey :: Nil).as[Integer, Boolean]
final def restore(key: Key, ttl: NonNegLong, serializedValue: NonNullBulkString): Protocol.Aux["OK"] =
Protocol("RESTORE", key :: ttl :: serializedValue :: HNil).as[SimpleString, "OK"]
final def restore(key: Key, ttl: NonNegLong, serializedValue: NonNullBulkString): Protocol.Aux[OK] =
Protocol("RESTORE", key :: ttl :: serializedValue :: HNil).as[SimpleString, OK]
final def restorereplace(key: Key, ttl: NonNegLong, serializedValue: NonNullBulkString): Protocol.Aux["OK"] =
Protocol("RESTORE", key :: ttl :: serializedValue :: "REPLACE" :: HNil).as[SimpleString, "OK"]
final def restorereplace(key: Key, ttl: NonNegLong, serializedValue: NonNullBulkString): Protocol.Aux[OK] =
Protocol("RESTORE", key :: ttl :: serializedValue :: "REPLACE" :: HNil).as[SimpleString, OK]
final def scan(cursor: NonNegLong): Protocol.Aux[Scan[Key]] = Protocol("SCAN", cursor).as[NonNilArray, Scan[Key]]
@@ -53,11 +53,11 @@ trait ListP {
final def lrem[A: Show](key: Key, count: Index, value: A): Protocol.Aux[NonNegInt] =
Protocol("LREM", key :: count :: value :: HNil).as[Integer, NonNegInt]
final def lset[A: Show](key: Key, index: Index, value: A): Protocol.Aux["OK"] =
Protocol("LSET", key :: index :: value :: HNil).as[SimpleString, "OK"]
final def lset[A: Show](key: Key, index: Index, value: A): Protocol.Aux[OK] =
Protocol("LSET", key :: index :: value :: HNil).as[SimpleString, OK]
final def ltrim(key: Key, start: Index, stop: Index): Protocol.Aux["OK"] =
Protocol("LTRIM", key :: start :: stop :: HNil).as[SimpleString, "OK"]
final def ltrim(key: Key, start: Index, stop: Index): Protocol.Aux[OK] =
Protocol("LTRIM", key :: start :: stop :: HNil).as[SimpleString, OK]
final def rpop[A](key: Key)(
implicit ev: NonNullBulkString ==> A
@@ -72,8 +72,8 @@ trait LowPriorityReadInstances extends LowerPriorityReadInstances {
implicit final val simpleString2StringRead: SimpleString ==> String = Read.instance {
case SimpleString(s) => Some(s)
}
implicit final val simpleString2OKRead: SimpleString ==> "OK" = Read.instancePF {
case SimpleString("OK") => "OK"
implicit final val simpleString2OKRead: SimpleString ==> OK = Read.instancePF {
case SimpleString("OK") => OK
}
implicit final val simpleString2KeyRead: SimpleString ==> Key = Read.instancePF {
case SimpleString(Key(s)) => s
@@ -165,7 +165,7 @@ trait LowPriorityReadInstances extends LowerPriorityReadInstances {
implicit final def nonNilArray2Tuple2Read[A, B](
implicit RA: NonNullBulkString ==> A,
RB: NonNullBulkString ==> B,
RB: NonNullBulkString ==> B
): NonNilArray ==> (A, B) = Read.instancePF {
case NonNilArray(RA(key) +: RB(value) +: Seq()) => key -> value
}
@@ -243,9 +243,10 @@ trait LowPriorityReadInstances extends LowerPriorityReadInstances {
}
implicit final def nonNilArray2HCons[H, T <: HList](
implicit ev: H <:!< FieldType[_, _],
RH: NonNullBulkString ==> H,
RT: NonNilArray ==> T
implicit
ev: H <:!< FieldType[_, _],
RH: NonNullBulkString ==> H,
RT: NonNilArray ==> T
): NonNilArray ==> (H :: T) = Read.instance {
case NonNilArray(RH(h) +: rest) => RT.read(RESP.arr(rest)).map(h :: _)
}
Oops, something went wrong.

0 comments on commit 542adab

Please sign in to comment.