Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rm cats from engine #226

Merged
merged 12 commits into from
Feb 8, 2022
12 changes: 4 additions & 8 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import java.io.FileInputStream
import java.util.Properties

ThisBuild / name := "inkuire"
ThisBuild / organization := "org.virtuslab"

Expand Down Expand Up @@ -28,7 +25,7 @@ ThisBuild / developers := List(
)

publish / skip := true
ThisBuild / scalaVersion := "2.13.4"
ThisBuild / scalaVersion := "2.13.8"


ThisBuild / scalafixDependencies += "com.github.liancheng" %% "organize-imports" % "0.5.0"
Expand All @@ -37,11 +34,12 @@ ThisBuild / semanticdbVersion := scalafixSemanticdb.revision
ThisBuild / scalafixScalaBinaryVersion := CrossVersion.binaryScalaVersion(scalaVersion.value)
ThisBuild / scalacOptions ++= Seq(
"-Yrangepos",
"-Ywarn-unused"
"-Ywarn-unused",
"-deprecation",
"-feature"
)

val http4sVersion = "0.21.0"
val catsVersion = "2.2.0"
val circeVersion = "0.13.0"

lazy val inkuireEngine = crossProject(JSPlatform, JVMPlatform)
Expand All @@ -51,8 +49,6 @@ lazy val inkuireEngine = crossProject(JSPlatform, JVMPlatform)
libraryDependencies ++= Seq(
"com.softwaremill.quicklens" %%% "quicklens" % "1.7.2",
"org.scala-lang.modules" %%% "scala-parser-combinators" % "1.1.2",
"org.typelevel" %%% "cats-core" % catsVersion,
"org.typelevel" %%% "cats-effect" % catsVersion,
"io.circe" %%% "circe-core" % circeVersion,
"io.circe" %%% "circe-parser" % circeVersion,
"io.circe" %%% "circe-generic" % circeVersion,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package org.virtuslab.inkuire.engine.common.api

import cats.data.EitherT
import cats.effect.IO
import org.virtuslab.inkuire.engine.common.api.FutureExcept
import org.virtuslab.inkuire.engine.common.model.AppConfig

import scala.concurrent.ExecutionContext

trait ConfigReader {
def readConfig(args: Seq[String]): EitherT[IO, String, AppConfig]
def readConfig(args: Seq[String])(implicit ec: ExecutionContext): FutureExcept[AppConfig]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.virtuslab.inkuire.engine.common.api

import scala.concurrent.ExecutionContext
import scala.concurrent.Future

case class FutureExcept[A](value: Future[Either[String, A]]) {
def map[B](f: A => B)(implicit ec: ExecutionContext): FutureExcept[B] =
new FutureExcept(value.map(_.map(f)))

def flatMap[B](f: A => FutureExcept[B])(implicit ec: ExecutionContext): FutureExcept[B] =
new FutureExcept(
value.flatMap {
case Left(value) => Future(Left(value))
case Right(value) => f(value).value
}
)

def semiflatmap[B](f: A => Either[String, B])(implicit ec: ExecutionContext): FutureExcept[B] =
new FutureExcept(value.map(_.flatMap(f)))

def mapInner[B](f: Either[String, A] => Either[String, B])(implicit ec: ExecutionContext): FutureExcept[B] =
new FutureExcept(value.map(f))
}

object FutureExcept {
def pure[A](a: A)(implicit ec: ExecutionContext): FutureExcept[A] =
FutureExcept(Future(Right(a)))

def fromExcept[A](e: Either[String, A])(implicit ec: ExecutionContext): FutureExcept[A] =
FutureExcept(Future(e))

def fromFuture[A](f: Future[A])(implicit ec: ExecutionContext): FutureExcept[A] =
FutureExcept(f.map(Right.apply[String, A]))
}
Original file line number Diff line number Diff line change
@@ -1,39 +1,48 @@
package org.virtuslab.inkuire.engine.common.api

import cats.effect.IO
import org.virtuslab.inkuire.engine.common.model._
import org.virtuslab.inkuire.engine.common.parser.ScalaSignatureParserService
import org.virtuslab.inkuire.engine.common.service.DefaultSignatureResolver
import org.virtuslab.inkuire.engine.common.service.ScalaExternalSignaturePrettifier
import org.virtuslab.inkuire.engine.common.service.SubstitutionMatchService
import org.virtuslab.inkuire.engine.common.service.TopLevelMatchQualityService

import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.util.chaining._

class InkuireRunner(
configReader: ConfigReader,
inputHandler: InputHandler,
outputHandler: OutputHandler,
parser: BaseSignatureParserService,
resolver: InkuireDb => BaseSignatureResolver,
matchService: InkuireDb => BaseMatchService,
matchQualityService: InkuireDb => BaseMatchQualityService,
prettifier: BaseSignaturePrettifier
val configReader: ConfigReader,
val inputHandler: InputHandler,
val outputHandler: OutputHandler,
val parser: BaseSignatureParserService,
val resolver: InkuireDb => BaseSignatureResolver,
val matchService: InkuireDb => BaseMatchService,
val matchQualityService: InkuireDb => BaseMatchQualityService,
val prettifier: BaseSignaturePrettifier
) {

def run(args: Seq[String]): IO[Unit] =
def run(args: Seq[String])(implicit ec: ExecutionContext): Future[Unit] =
configReader
.readConfig(args)
.flatMap { config: AppConfig =>
inputHandler
.readInput(config)
.semiflatMap { db: InkuireDb =>
.flatMap { db: InkuireDb =>
outputHandler
.serveOutput()
.runA(
Engine.Env(db, matchService(db), matchQualityService(db), prettifier, parser, resolver(db), config)
.serveOutput(
Env(db, matchService(db), matchQualityService(db), prettifier, parser, resolver(db), config)
)
.pipe(FutureExcept.fromFuture)
}
}
.fold(str => println(s"Oooooh man, bad luck. Inkuire encountered an unexpected error. Caused by $str"), identity)
.value
.map(
_.fold(
str => println(s"Oooooh man, bad luck. Inkuire encountered an unexpected error. Caused by $str"),
identity
)
)

}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package org.virtuslab.inkuire.engine.common.api

import cats.data.EitherT
import cats.effect.IO
import org.virtuslab.inkuire.engine.common.api.FutureExcept
import org.virtuslab.inkuire.engine.common.model.AppConfig
import org.virtuslab.inkuire.engine.common.model.InkuireDb

import scala.concurrent.ExecutionContext

trait InputHandler {
def readInput(appConfig: AppConfig): EitherT[IO, String, InkuireDb]
def readInput(appConfig: AppConfig)(implicit ec: ExecutionContext): FutureExcept[InkuireDb]
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
package org.virtuslab.inkuire.engine.common.api

import cats.data.StateT
import cats.effect.IO
import cats.implicits._
import org.virtuslab.inkuire.engine.common.model.Engine.Env
import org.virtuslab.inkuire.engine.common.model.Engine._
import org.virtuslab.inkuire.engine.common.model.Env

import scala.concurrent.ExecutionContext
import scala.concurrent.Future

trait OutputHandler {
def serveOutput(env: Env): IO[Unit] =
serveOutput().runA(env)

def serveOutput(): Engine[Unit] = {
StateT.get[IO, Env] >>= { env =>
this.serveOutput(env).liftApp
}
}
def serveOutput(env: Env)(implicit ec: ExecutionContext): Future[Unit]

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
package org.virtuslab.inkuire.engine.common.model

import cats.kernel.Monoid
import org.virtuslab.inkuire.engine.common.utils.Monoid

case class AppConfig(
address: Option[String],
port: Option[Int],
inkuirePaths: Seq[String]
address: Option[String] = None,
port: Option[Int] = None,
inkuirePaths: Seq[String] = Seq.empty
) {
def getAddress: String = address.getOrElse("0.0.0.0")
def getPort: Int = port.getOrElse(8080)
}

object AppConfig {
def empty: AppConfig = AppConfig(
address = None,
port = None,
inkuirePaths = Seq.empty
)

implicit val appConfigMonoid: Monoid[AppConfig] = new Monoid[AppConfig] {
def empty: AppConfig = AppConfig(
address = None,
port = None,
inkuirePaths = Seq.empty
)
def combine(x: AppConfig, y: AppConfig): AppConfig =
def empty: AppConfig = AppConfig.empty
def mappend(x: AppConfig, y: AppConfig): AppConfig =
AppConfig(
address = x.address.orElse(y.address),
port = x.port.orElse(y.port),
Expand All @@ -28,11 +30,11 @@ object AppConfig {

def parseCliOption(opt: String, v: String): AppConfig =
opt match {
case "-a" | "--address" => Monoid.empty[AppConfig].copy(address = Some(v))
case "-p" | "--port" => Monoid.empty[AppConfig].copy(port = Some(v.toInt))
case "-i" | "--inkuire" => Monoid.empty[AppConfig].copy(inkuirePaths = Seq(v))
case "-a" | "--address" => AppConfig(address = Some(v))
case "-p" | "--port" => AppConfig(port = Some(v.toInt))
case "-i" | "--inkuire" => AppConfig(inkuirePaths = Seq(v))
case o =>
println(s"Inkuire ignored wrong option: $o")
Monoid.empty[AppConfig]
AppConfig.empty
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.virtuslab.inkuire.engine.common.model

import org.virtuslab.inkuire.engine.common.api._

case class Env(
db: InkuireDb,
matcher: BaseMatchService,
matchQualityService: BaseMatchQualityService,
prettifier: BaseSignaturePrettifier,
parser: BaseSignatureParserService,
resolver: BaseSignatureResolver,
appConfig: AppConfig
)
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.virtuslab.inkuire.engine.common.model

import cats.kernel.Monoid
import org.virtuslab.inkuire.engine.common.utils.Monoid

//TODO technically it would be better to have a different type for type declarations -> types: Map[ITID, (Declaration, Seq[Type])]
// TODO(kπ) technically it would be better to have a different type for type declarations -> types: Map[ITID, (Declaration, Seq[Type])]
case class InkuireDb(
functions: Seq[ExternalSignature],
types: Map[ITID, (Type, Seq[Type])],
Expand All @@ -12,7 +12,7 @@ case class InkuireDb(

object InkuireDb {
implicit val inkuireDbMonoid: Monoid[InkuireDb] = new Monoid[InkuireDb] {
override def combine(x: InkuireDb, y: InkuireDb): InkuireDb =
override def mappend(x: InkuireDb, y: InkuireDb): InkuireDb =
InkuireDb(
functions = (x.functions ++ y.functions).distinct,
types = (x.types.toSeq ++ y.types.toSeq).distinct
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.virtuslab.inkuire.engine.common.model

import cats.kernel.Monoid
import org.virtuslab.inkuire.engine.common.utils.Monoid

case class SignatureContext(
vars: Set[String],
Expand All @@ -20,7 +20,7 @@ object SignatureContext {
implicit val signatureContextMonoid: Monoid[SignatureContext] = new Monoid[SignatureContext] {
override def empty: SignatureContext = SignatureContext(Set.empty, Map.empty)

override def combine(x: SignatureContext, y: SignatureContext): SignatureContext = {
override def mappend(x: SignatureContext, y: SignatureContext): SignatureContext = {
SignatureContext(
x.vars ++ y.vars,
x.constraints ++ y.constraints
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.virtuslab.inkuire.engine.common.model

import scala.language.implicitConversions

case class TypeName(name: String) {
override def hashCode(): Int = name.toLowerCase.hashCode

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.virtuslab.inkuire.engine.common.parser

import cats.Monoid
import org.virtuslab.inkuire.engine.common.model.Type
import org.virtuslab.inkuire.engine.common.model._

Expand All @@ -16,7 +15,7 @@ abstract class BaseSignatureParser extends RegexParsers {
(typ <~ ",") ~ list(typ) ^^ { case head ~ tail => head +: tail } |
typ ^^ (Seq(_))

def empty[T](implicit monoid: Monoid[T]): Parser[T] = "" ^^^ monoid.empty
def empty[A]: Parser[List[A]] = "" ^^^ List.empty

def genericType: Parser[Type]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.virtuslab.inkuire.engine.common.parser

import cats.instances.all._
import cats.syntax.all._
import com.softwaremill.quicklens._
import org.virtuslab.inkuire.engine.common.api._
import org.virtuslab.inkuire.engine.common.model._
Expand Down Expand Up @@ -76,9 +74,9 @@ class ScalaSignatureParser extends BaseSignatureParser {
case baseType ~ types => Type(baseType, types.map(UnresolvedVariance))
}

def types: Parser[Seq[TypeLike]] = list(typeLike) | empty[List[TypeLike]]
def types: Parser[Seq[TypeLike]] = list(typeLike) | empty[TypeLike]

def typeArguments: Parser[Seq[TypeLike]] = list(typeLike) | empty[List[TypeLike]]
def typeArguments: Parser[Seq[TypeLike]] = list(typeLike) | empty[TypeLike]

def typeVariable: Parser[(String, Seq[Type])] =
(identifier <~ "<:") ~ singleType ^^ { case typeVar ~ constraint => (typeVar, Seq(constraint)) } |
Expand Down Expand Up @@ -144,7 +142,10 @@ class ScalaSignatureParserService extends BaseSignatureParserService {
private val scalaSignatureParser = new ScalaSignatureParser

override def parse(str: String): Either[String, ParsedSignature] =
doParse(str) map convert map (s => curry(s)) >>= validate
doParse(str)
.map(convert)
.map(curry)
.flatMap(validate)

val parsingErrorGenericMessage =
"Could not parse provided signature. Example signature looks like this: List[Int] => (Int => Boolean) => Int"
Expand Down