Skip to content

Commit

Permalink
sprinkle in logs
Browse files Browse the repository at this point in the history
  • Loading branch information
arainko committed Oct 15, 2023
1 parent a9b3c56 commit a9ed920
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 106 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
metals.sbt
target/
ast.*
sbt-launch.jar
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.github.arainko.ducktape
import scala.quoted.*
import io.github.arainko.ducktape.internal.modules.*
import io.github.arainko.ducktape.internal.*
import io.github.arainko.ducktape.internal.Debug

opaque type Path = Vector[Path.Segment]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.github.arainko.ducktape

import scala.quoted.*
import io.github.arainko.ducktape.internal.macros.DebugMacros
import io.github.arainko.ducktape.internal.Logger
import scala.collection.mutable.ListBuffer
import scala.annotation.tailrec

Expand All @@ -15,24 +16,37 @@ object PathSelector {

term match {
case Inlined(_, _, tree) =>
Logger.debug("Matched 'Inlined', recursing...")
recurse(acc, tree)
case Lambda(_, tree) =>
Logger.debug("Matched 'Lambda', recursing...")
recurse(acc, tree)
case Block(_, tree) =>
Logger.debug("Matched 'Block', recursing...")
recurse(acc, tree)
case select @ Select(tree, name) =>
Logger.debug(s"Matched 'Select' (matching field access) with name = $name")
recurse(acc.prepended(Path.Segment.Field(select.tpe.asType, name)), tree)
case TypeApply(Apply(TypeApply(Select(Ident(_), "at"), _), tree :: Nil), tpe :: Nil) =>
Logger.debug(s"Matched 'TypeApply' (matching '.at')", tpe.tpe.asType)
recurse(acc.prepended(Path.Segment.Case(tpe.tpe.asType)), tree)
// Function arg selection can only happen as the first selection (aka the last one to be parsed) so this not being recursive is fine (?)
case TypeApply(Select(Apply(Select(Ident(_), "selectDynamic"), Literal(StringConstant(argName)) :: Nil), "$asInstanceOf$"), argTpe :: Nil) =>
case TypeApply(
Select(Apply(Select(Ident(_), "selectDynamic"), Literal(StringConstant(argName)) :: Nil), "$asInstanceOf$"),
argTpe :: Nil
) =>
Logger.debug(s"Matched 'selectDynamic' (matching a function arg selector) with name = $argName")
acc.prepended(Path.Segment.Field(argTpe.tpe.asType, argName))
case Ident(_) => acc
case other => report.errorAndAbort(other.show(using Printer.TreeShortCode))
case Ident(_) =>
Logger.debug(s"Matched 'Ident', returning...")
acc
case other =>
Logger.debug(s"Matched an unexpected term")
report.errorAndAbort(other.show(using Printer.TreeShortCode))
}
}

Some(recurse(Path.empty, expr))
Some(Logger.loggedInfo("Parsed path")(recurse(Path.empty, expr)))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ object Plan {

def unapply[E <: Plan.Error](plan: Plan[E]): (Type[?], Type[?]) = (plan.sourceTpe, plan.destTpe)

given debug: Debug[Plan[?]] = Debug.derived
given debug[E <: Plan.Error]: Debug[Plan[E]] = Debug.derived

final case class Context(root: Type[?], path: Path) derives Debug {
def add(segment: Path.Segment): Context = copy(path = path.appended(segment))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,14 @@ object PlanInterpreter {
)(using Quotes): Expr[B] = {
import quotes.reflect.*

// Logger.info("Creating transformation")

val plan = Planner.betweenTypes[A, B]
val config = Configuration.parse(configs)
val reconfiguredPlan = config.foldLeft(plan) { (plan, config) => plan.configure(config) }
// println(s"OG PLAN: ${plan.show}")
// println()
// println(s"CONFIG: ${Debug.show(config)}")
// println()
// println(s"CONF PLAN: ${reconfiguredPlan.show}")
// println()
Logger.debug("Original plan", plan)
Logger.debug("Config", config)
Logger.debug("Reconfigured plan", reconfiguredPlan)
reconfiguredPlan.refine match {
case Left(errors) =>
val rendered = errors.map(err => s"${err.message} @ ${err.sourceContext.render}").mkString("\n")
Expand Down
109 changes: 55 additions & 54 deletions ducktapeNext/src/main/scala/io/github/arainko/ducktape/Planner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package io.github.arainko.ducktape

import io.github.arainko.ducktape.Plan.Context
import io.github.arainko.ducktape.internal.modules.*
import io.github.arainko.ducktape.internal.Debug
import io.github.arainko.ducktape.internal.{Debug, Logger}

import scala.quoted.*

Expand Down Expand Up @@ -35,71 +35,72 @@ object Planner {
)(using Quotes): Plan[Plan.Error] = {
import quotes.reflect.*

(source.force -> dest.force) match {
case (source: Product, dest: Function) =>
planProductFunctionTransformation(source, dest, sourceContext, destContext)
Logger.loggedInfo("Plan"):
(source.force -> dest.force) match {
case (source: Product, dest: Function) =>
planProductFunctionTransformation(source, dest, sourceContext, destContext)

case UserDefinedTransformation(transformer) =>
Plan.UserDefined(source.tpe, dest.tpe, sourceContext, destContext, transformer)
case UserDefinedTransformation(transformer) =>
Plan.UserDefined(source.tpe, dest.tpe, sourceContext, destContext, transformer)

case (source, dest) if source.tpe.repr <:< dest.tpe.repr =>
Plan.Upcast(source.tpe, dest.tpe, sourceContext, destContext)
case (source, dest) if source.tpe.repr <:< dest.tpe.repr =>
Plan.Upcast(source.tpe, dest.tpe, sourceContext, destContext)

case Structure('[Option[srcTpe]], srcName) -> Structure('[Option[destTpe]], destName) =>
Plan.BetweenOptions(
Type[srcTpe],
Type[destTpe],
sourceContext,
destContext,
recurseAndCreatePlan[srcTpe, destTpe](sourceContext, destContext)
)
case Structure('[Option[srcTpe]], srcName) -> Structure('[Option[destTpe]], destName) =>
Plan.BetweenOptions(
Type[srcTpe],
Type[destTpe],
sourceContext,
destContext,
recurseAndCreatePlan[srcTpe, destTpe](sourceContext, destContext)
)

case Structure('[a], _) -> Structure('[Option[destTpe]], destName) =>
Plan.BetweenNonOptionOption(
Type[a],
Type[destTpe],
sourceContext,
destContext,
recurseAndCreatePlan[a, destTpe](sourceContext, destContext)
)
case Structure('[a], _) -> Structure('[Option[destTpe]], destName) =>
Plan.BetweenNonOptionOption(
Type[a],
Type[destTpe],
sourceContext,
destContext,
recurseAndCreatePlan[a, destTpe](sourceContext, destContext)
)

case Structure(source @ '[Iterable[srcTpe]], srcName) -> Structure(dest @ '[Iterable[destTpe]], destName) =>
Plan.BetweenCollections(
dest,
Type[srcTpe],
Type[destTpe],
sourceContext,
destContext,
recurseAndCreatePlan[srcTpe, destTpe](sourceContext, destContext)
)
case Structure(source @ '[Iterable[srcTpe]], srcName) -> Structure(dest @ '[Iterable[destTpe]], destName) =>
Plan.BetweenCollections(
dest,
Type[srcTpe],
Type[destTpe],
sourceContext,
destContext,
recurseAndCreatePlan[srcTpe, destTpe](sourceContext, destContext)
)

case (source: Product, dest: Product) =>
planProductTransformation(source, dest, sourceContext, destContext)
case (source: Product, dest: Product) =>
planProductTransformation(source, dest, sourceContext, destContext)

case (source: Coproduct, dest: Coproduct) =>
planCoproductTransformation(source, dest, sourceContext, destContext)
case (source: Coproduct, dest: Coproduct) =>
planCoproductTransformation(source, dest, sourceContext, destContext)

case (source: Structure.Singleton, dest: Structure.Singleton) if source.name == dest.name =>
Plan.BetweenSingletons(source.tpe, dest.tpe, sourceContext, destContext, dest.value)
case (source: Structure.Singleton, dest: Structure.Singleton) if source.name == dest.name =>
Plan.BetweenSingletons(source.tpe, dest.tpe, sourceContext, destContext, dest.value)

case (source: ValueClass, dest) if source.paramTpe.repr <:< dest.tpe.repr =>
Plan.BetweenWrappedUnwrapped(source.tpe, dest.tpe, sourceContext, destContext, source.paramFieldName)
case (source: ValueClass, dest) if source.paramTpe.repr <:< dest.tpe.repr =>
Plan.BetweenWrappedUnwrapped(source.tpe, dest.tpe, sourceContext, destContext, source.paramFieldName)

case (source, dest: ValueClass) if source.tpe.repr <:< dest.paramTpe.repr =>
Plan.BetweenUnwrappedWrapped(source.tpe, dest.tpe, sourceContext, destContext)
case (source, dest: ValueClass) if source.tpe.repr <:< dest.paramTpe.repr =>
Plan.BetweenUnwrappedWrapped(source.tpe, dest.tpe, sourceContext, destContext)

case DerivedTransformation(transformer) =>
Plan.Derived(source.tpe, dest.tpe, sourceContext, destContext, transformer)
case DerivedTransformation(transformer) =>
Plan.Derived(source.tpe, dest.tpe, sourceContext, destContext, transformer)

case (source, dest) =>
Plan.Error(
source.tpe,
dest.tpe,
sourceContext,
destContext,
s"Couldn't build a transformation plan between ${source.tpe.repr.show} and ${dest.tpe.repr.show}"
)
}
case (source, dest) =>
Plan.Error(
source.tpe,
dest.tpe,
sourceContext,
destContext,
s"Couldn't build a transformation plan between ${source.tpe.repr.show} and ${dest.tpe.repr.show}"
)
}
}

private def planProductTransformation(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package io.github.arainko.ducktape

import io.github.arainko.ducktape.internal.macros.DebugMacros
import io.github.arainko.ducktape.internal.Debug
import scala.annotation.nowarn
import scala.deriving.Mirror
import io.github.arainko.ducktape.Transformer.Debug
import scala.reflect.TypeTest
import scala.reflect.ClassTag
import scala.quoted.Quotes

final case class Value(int: Int) extends AnyVal
final case class ValueGen[A](int: A) extends AnyVal
Expand Down Expand Up @@ -100,11 +102,11 @@ final case class ProdTest2(test: Test2)
case class PersonFields2(int: Int, str: String, extra: Int)

val fields: PersonFields2 = ???
Debug.showCode {
// Debug.showCode {
PlanInterpreter.transformBetween[PersonCostamCostam, PersonCostamCostam2](
???, Field2.allMatching(a => a.p.p, fields)
)
}
// }


def costam(int: Int, str: String): Int = ???
Expand Down
Original file line number Diff line number Diff line change
@@ -1,67 +1,80 @@
package io.github.arainko.ducktape.internal

import io.github.arainko.ducktape.Transformer
import io.github.arainko.ducktape.internal.{ Debug, Metainformation }

import scala.compiletime.*
import scala.quoted.*
import io.github.arainko.ducktape.Transformer
import io.github.arainko.tooling.FullName
import scala.Ordering.Implicits.*

private[ducktape] object Logger {

transparent inline given Level = Level.Info
given Output = Output.StdOut
// Logger Config
private transparent inline def level = Level.Off
private val output = Output.StdOut
private def filter(msg: String, meta: Metainformation) = true

enum Level {
case Debug, Info, Off
case Off, Debug, Info
}

object Level {
given Ordering[Level] = Ordering.by(_.ordinal)
}

enum Output {
case StdOut, Report

final def print(msg: String)(using Quotes) =
final def print(msg: String, level: Level, meta: Metainformation)(using Quotes) = {
def colored(color: String & Singleton)(msg: String) = s"$color$msg${Console.RESET}"
def blue(msg: String) = colored(Console.BLUE)(msg)
def green(msg: String) = colored(Console.GREEN)(msg)
val formatted = s"${green(s"[${level.toString().toUpperCase()}]")} $msg ${blue(s"[$meta]")}"
this match {
case StdOut => println(msg)
case Report => quotes.reflect.report.info(msg)
case StdOut => if (filter(msg, meta)) println(formatted)
case Report => if (filter(msg, meta)) quotes.reflect.report.info(formatted)
}
}
}

private val infoTag = s"${Console.GREEN}[INFO]${Console.RESET}"
private val debugTag = s"${Console.GREEN}[DEBUG]${Console.RESET}"
private def blue(msg: String) = s"${Console.BLUE}$msg${Console.RESET}"

inline def loggedInfo[A](using Level, Output, FullName, Debug[A], Quotes)(
inline def loggedInfo[A](using Metainformation, Quotes)(
inline msg: String
)(value: A) = {
)(value: A)(using Debug[A]) = {
info(msg, value)
value
}

inline def info(inline msg: String)(using level: Level, output: Output, name: FullName, quotes: Quotes): Unit =
inline def info(inline msg: String)(using name: Metainformation, quotes: Quotes): Unit =
inline level match {
case Level.Debug => ()
case Level.Info => output.print(s"$infoTag $msg ${blue(s"[$name]")}")
case Level.Debug => if (level <= Level.Info) output.print(msg, Level.Info, name)
case Level.Info => if (level <= Level.Info) output.print(msg, Level.Info, name)
case Level.Off => ()
}

inline def info[A](
inline msg: String,
value: A
)(using Level, Output, FullName, Debug[A], Quotes): Unit =
)(using Metainformation, Debug[A], Quotes): Unit =
info(s"$msg: ${Debug.show(value)}")

inline def loggedDebug[A](using Level, Output, FullName, Debug[A], Quotes)(
inline def loggedDebug[A](using Level, Output, Metainformation, Quotes)(
inline msg: String
)(value: A) = {
)(value: A)(using Debug[A]) = {
debug(msg, value)
value
}

inline def debug(inline msg: String)(using level: Level, output: Output, name: FullName, quotes: Quotes): Unit =
inline def debug(inline msg: String)(using name: Metainformation, quotes: Quotes): Unit =
inline level match {
case Level.Debug => output.print(s"$debugTag $msg ${blue(s"[$name]")}")
case Level.Info => output.print(s"$infoTag $msg ${blue(s"[$name]")}")
case Level.Debug => if (level <= Level.Debug) output.print(msg, Level.Debug, name)
case Level.Info => if (level <= Level.Debug) output.print(msg, Level.Debug, name)
case Level.Off => ()
}

inline def debug[A](inline msg: String, value: A)(using level: Level, name: FullName, _debug: Debug[A], quotes: Quotes): Unit =
inline def debug[A](inline msg: String, value: A)(using
name: Metainformation,
_debug: Debug[A],
quotes: Quotes
): Unit =
debug(s"$msg: ${Debug.show(value)}")
}
Loading

0 comments on commit a9ed920

Please sign in to comment.