diff --git a/chimney-macro-commons/src/main/scala-2/io/scalaland/chimney/internal/compiletime/datatypes/ProductTypesPlatform.scala b/chimney-macro-commons/src/main/scala-2/io/scalaland/chimney/internal/compiletime/datatypes/ProductTypesPlatform.scala index 94d4b9090..0b01fcf5e 100644 --- a/chimney-macro-commons/src/main/scala-2/io/scalaland/chimney/internal/compiletime/datatypes/ProductTypesPlatform.scala +++ b/chimney-macro-commons/src/main/scala-2/io/scalaland/chimney/internal/compiletime/datatypes/ProductTypesPlatform.scala @@ -233,11 +233,10 @@ trait ProductTypesPlatform extends ProductTypes { this: DefinitionsPlatform => val methodType: ?? = args.foldRight[??](Type[A].as_??) { (paramList, resultType) => val paramTypes = paramList.view.values.map(_.Underlying.tpe).toList + // tq returns c.Tree, to turn it to c.Type we need .tpe, which without a .typecheck is null fromUntyped(c.typecheck(tq"(..$paramTypes) => ${resultType.Underlying.tpe}", mode = c.TYPEmode).tpe).as_?? } - println(methodType.Underlying) - import methodType.Underlying as MethodType val tree = expr.asInstanceOfExpr[MethodType].tree c.Expr[A](q"$tree(...${(args.map(_.map { case (paramName, _) => diff --git a/chimney-macro-commons/src/main/scala-3/io/scalaland/chimney/internal/compiletime/datatypes/ProductTypesPlatform.scala b/chimney-macro-commons/src/main/scala-3/io/scalaland/chimney/internal/compiletime/datatypes/ProductTypesPlatform.scala index 5b5e7d070..3f51e9bb4 100644 --- a/chimney-macro-commons/src/main/scala-3/io/scalaland/chimney/internal/compiletime/datatypes/ProductTypesPlatform.scala +++ b/chimney-macro-commons/src/main/scala-3/io/scalaland/chimney/internal/compiletime/datatypes/ProductTypesPlatform.scala @@ -243,6 +243,10 @@ trait ProductTypesPlatform extends ProductTypes { this: DefinitionsPlatform => } else None def exprAsInstanceOfMethod[A: Type](args: List[ListMap[String, ??]])(expr: Expr[Any]): Product.Constructor[A] = { + + println("\n\n\n\nWTF\n\n\n") + println(s"Arguments: $args") + val parameters: Product.Parameters = ListMap.from(for { list <- args pair <- list.toList @@ -255,25 +259,84 @@ trait ProductTypesPlatform extends ProductTypes { this: DefinitionsPlatform => }) val constructor: Product.Arguments => Expr[A] = arguments => { + + println("\n\n\n\nWTF\n\n\n") + println(s"Arguments: $args") + println(s"Arguments: $arguments") + val (constructorArguments, _) = checkArguments[A](parameters, arguments) - val methodType: ?? = null.asInstanceOf[??] // TODO: figure out the type + + val methodType: ?? = args.foldRight[??](Type[A].as_??) { (paramList, resultType) => + val fnType = fnTypeByArity.getOrElse( + paramList.size, + assertionFailed(s"Expected arity between 1 and 22 into ${Type.prettyPrint[A]}, got: ${paramList.size}") + ) + val paramTypes = paramList.view.values.map(p => TypeRepr.of(using p.Underlying)).toVector + + println( + s"Constructing: ${fnType.show(using Printer.TypeReprAnsiCode)} -> ${paramTypes + .map(_.show(using Printer.TypeReprAnsiCode))} + ${TypeRepr.of(using resultType.Underlying).show(using Printer.TypeReprAnsiCode)}" + ) + + fromUntyped( + fnType.appliedTo((paramTypes :+ TypeRepr.of(using resultType.Underlying)).toList).dealias.simplified + ).as_?? + // fromUntyped(AppliedType(fnType, (paramTypes :+ TypeRepr.of(using resultType.Underlying)).toList)).as_?? + } + import methodType.Underlying as MethodType - val tree = expr - .asInstanceOfExpr[MethodType] - .asTerm - tree - .appliedToArgss( - args - .map(_.map { case (paramName, _) => + println(s"Constructed: ${Type.prettyPrint[MethodType]}") + println(s"Expr: ${Expr.prettyPrint(expr.asInstanceOfExpr[MethodType])}") + val tree = expr.asInstanceOfExpr[MethodType].asTerm + val a = args + .foldLeft(tree) { (result, list) => + val method: Symbol = result.tpe.typeSymbol.methodMember("apply").head + result + .select(method) + .appliedToArgs(list.map { (paramName, _) => constructorArguments(paramName).value.asTerm }.toList) - ) + } .asExprOf[A] + + println(s"Final result: ${Expr.prettyPrint(a)}") + + a +// tree +// .appliedToArgss(args.map(_.map { case (paramName, _) => +// constructorArguments(paramName).value.asTerm +// }.toList)) +// .asExprOf[A] } Product.Constructor[A](parameters, constructor) } + private lazy val fnTypeByArity = Map( + 1 -> TypeRepr.of[scala.Function1], + 2 -> TypeRepr.of[scala.Function2], + 3 -> TypeRepr.of[scala.Function3], + 4 -> TypeRepr.of[scala.Function4], + 5 -> TypeRepr.of[scala.Function5], + 6 -> TypeRepr.of[scala.Function6], + 7 -> TypeRepr.of[scala.Function7], + 8 -> TypeRepr.of[scala.Function8], + 9 -> TypeRepr.of[scala.Function9], + 10 -> TypeRepr.of[scala.Function10], + 11 -> TypeRepr.of[scala.Function11], + 12 -> TypeRepr.of[scala.Function12], + 13 -> TypeRepr.of[scala.Function13], + 14 -> TypeRepr.of[scala.Function14], + 15 -> TypeRepr.of[scala.Function15], + 16 -> TypeRepr.of[scala.Function16], + 17 -> TypeRepr.of[scala.Function17], + 18 -> TypeRepr.of[scala.Function18], + 19 -> TypeRepr.of[scala.Function19], + 20 -> TypeRepr.of[scala.Function20], + 21 -> TypeRepr.of[scala.Function21], + 22 -> TypeRepr.of[scala.Function22] + ) + private val isGarbageSymbol = ((s: Symbol) => s.name) andThen isGarbage } } diff --git a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/utils/DslMacroUtils.scala b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/utils/DslMacroUtils.scala index a51195198..05f71e65e 100644 --- a/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/utils/DslMacroUtils.scala +++ b/chimney/src/main/scala-2/io/scalaland/chimney/internal/compiletime/dsl/utils/DslMacroUtils.scala @@ -78,6 +78,81 @@ private[chimney] trait DslMacroUtils { s"Invalid selector expression - only input value can be extracted from: $selectorTree" } + private trait ExistentialCtor { + type Underlying <: runtime.Path + implicit val Underlying: Type[Underlying] + } + private object ExistentialCtor { + + def parse(t: Tree): Either[String, ExistentialCtor] = t match { + // TODO: add support for multiple parameter lists + case Function(params, _) => + val t = paramsToType(List(params)) + // TODO: remove once everything works + println(s"""Expression: + |${Console.MAGENTA}${show(f)}${Console.RESET} + |defined as: + |${Console.MAGENTA}${showRaw(f)}${Console.RESET} + |of type: + |${Console.MAGENTA}${f.tpe}${Console.RESET} + |of type: + |${Console.MAGENTA}${showRaw(f.tpe)}${Console.RESET} + |resolved as: + |${Console.MAGENTA}$t${Console.RESET} + |""".stripMargin) + Right(new ExistentialCtor { + type Underlying = runtime.ArgumentLists + val Underlying: WeakTypeTag[runtime.ArgumentLists] = t + }) + case _ => + Left(invalidConstructor(f)) + } + + private def paramsToType(paramsLists: List[List[ValDef]]): WeakTypeTag[runtime.ArgumentLists] = + paramsLists + .map { paramList => + paramList.foldRight[WeakTypeTag[? <: runtime.ArgumentList]](weakTypeTag[runtime.ArgumentList.Empty])( + constructArgumentListType + ) + } + .foldRight[WeakTypeTag[? <: runtime.ArgumentLists]](weakTypeTag[runtime.ArgumentLists.Empty])( + constructArgumentListsType + ) + + private def constructArgumentListsType( + head: WeakTypeTag[? <: runtime.ArgumentList], + tail: WeakTypeTag[? <: runtime.ArgumentLists] + ): WeakTypeTag[? <: runtime.ArgumentLists] = { + object ApplyParams { + def apply[Head <: runtime.ArgumentList: WeakTypeTag, Tail <: runtime.ArgumentLists: WeakTypeTag] + : WeakTypeTag[runtime.ArgumentLists.List[Head, Tail]] = + weakTypeTag[runtime.ArgumentLists.List[Head, Tail]] + } + + ApplyParams(head, tail) + } + + private def constructArgumentListType( + t: ValDef, + args: WeakTypeTag[? <: runtime.ArgumentList] + ): WeakTypeTag[? <: runtime.ArgumentList] = { + object ApplyParam { + def apply[ParamName <: String: WeakTypeTag, ParamType: WeakTypeTag, Args <: runtime.ArgumentList: WeakTypeTag] + : WeakTypeTag[runtime.ArgumentList.Argument[ParamName, ParamType, Args]] = + weakTypeTag[runtime.ArgumentList.Argument[ParamName, ParamType, Args]] + } + + ApplyParam( + c.WeakTypeTag(c.internal.constantType(Constant(t.name.decodedName.toString))), + c.WeakTypeTag(t.tpt.tpe), + args + ) + } + + private def invalidConstructor(t: Tree): String = + s"Expected function, instead got: ${Console.MAGENTA}$t${Console.RESET}: ${Console.MAGENTA}${t.tpe}${Console.RESET}" + } + // If we try to do: // // implicit val fieldNameT = fieldName.Underlying @@ -158,68 +233,14 @@ private[chimney] trait DslMacroUtils { def apply[Ctor <: runtime.ArgumentLists: WeakTypeTag]: Tree - final def applyFromBody(f: Tree): Tree = f match { - case Function(params, _) => - val t = paramsToType(List(params)) - // TODO: remove once everything works - println(s"""Expression: - |${Console.MAGENTA}${show(f)}${Console.RESET} - |defined as: - |${Console.MAGENTA}${showRaw(f)}${Console.RESET} - |of type: - |${Console.MAGENTA}${f.tpe}${Console.RESET} - |of type: - |${Console.MAGENTA}${showRaw(f.tpe)}${Console.RESET} - |resolved as: - |${Console.MAGENTA}$t${Console.RESET} - |""".stripMargin) - apply(t) - case _ => - c.abort(c.enclosingPosition, invalidConstructor(f)) - } - - private def paramsToType(paramsLists: List[List[ValDef]]): WeakTypeTag[? <: runtime.ArgumentLists] = - paramsLists - .map { paramList => - paramList.foldRight[WeakTypeTag[? <: runtime.ArgumentList]](weakTypeTag[runtime.ArgumentList.Empty])( - constructArgumentListType - ) - } - .foldRight[WeakTypeTag[? <: runtime.ArgumentLists]](weakTypeTag[runtime.ArgumentLists.Empty])( - constructArgumentListsType - ) - - private def constructArgumentListsType( - head: WeakTypeTag[? <: runtime.ArgumentList], - tail: WeakTypeTag[? <: runtime.ArgumentLists] - ): WeakTypeTag[? <: runtime.ArgumentLists] = { - object ApplyParams { - def apply[Head <: runtime.ArgumentList: WeakTypeTag, Tail <: runtime.ArgumentLists: WeakTypeTag] - : WeakTypeTag[runtime.ArgumentLists.List[Head, Tail]] = - weakTypeTag[runtime.ArgumentLists.List[Head, Tail]] - } - - ApplyParams(head, tail) + final def applyFromBody(f: Tree): Tree = { + val ctorType = extractCtorType(f) + ctorType.Underlying } - private def constructArgumentListType( - t: ValDef, - args: WeakTypeTag[? <: runtime.ArgumentList] - ): WeakTypeTag[? <: runtime.ArgumentList] = { - object ApplyParam { - def apply[ParamName <: String: WeakTypeTag, ParamType: WeakTypeTag, Args <: runtime.ArgumentList: WeakTypeTag] - : WeakTypeTag[runtime.ArgumentList.Argument[ParamName, ParamType, Args]] = - weakTypeTag[runtime.ArgumentList.Argument[ParamName, ParamType, Args]] - } - - ApplyParam( - c.WeakTypeTag(c.internal.constantType(Constant(t.name.decodedName.toString))), - c.WeakTypeTag(t.tpt.tpe), - args - ) + private def extractCtorType(f: Tree): ExistentialCtor = ExistentialCtor.parse(f) match { + case Right(ctor) => ctor + case Left(error) => c.abort(c.enclosingPosition, error) } - - private def invalidConstructor(t: Tree): String = - s"Expected function, instead got: ${Console.MAGENTA}$t${Console.RESET}: ${Console.MAGENTA}${t.tpe}${Console.RESET}" } } diff --git a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/utils/DslMacroUtils.scala b/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/utils/DslMacroUtils.scala index 5307ef181..e4e0c057a 100644 --- a/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/utils/DslMacroUtils.scala +++ b/chimney/src/main/scala-3/io/scalaland/chimney/internal/compiletime/dsl/utils/DslMacroUtils.scala @@ -66,7 +66,6 @@ private[chimney] class DslMacroUtils()(using quotes: Quotes) { case Inlined(_, _, block) => parse(block) case _ => Left(invalidSelectorErrorMessage(t)) } - List(1 -> 2).fol private def invalidSelectorErrorMessage(t: Tree): String = s"Invalid selector expression: ${t.show(using Printer.TreeAnsiCode)}" @@ -78,6 +77,111 @@ private[chimney] class DslMacroUtils()(using quotes: Quotes) { s"Invalid selector expression - only input value can be extracted from: ${t.show(using Printer.TreeAnsiCode)}" } + private trait ExistentialCtor { + type Underlying <: runtime.ArgumentLists + implicit val Underlying: Type[Underlying] + } + private object ExistentialCtor { + + def parse(t: Tree): Either[String, ExistentialCtor] = { + def extractParams(t: Tree): Either[String, List[List[ValDef]]] = t match { + case DefDef(_, params, _, bodyOpt) => + val head = params.map(_.params.asInstanceOf[List[ValDef]]) + + // TODO: sprawdzić czy to faktycznie działa + + bodyOpt match { + case Some(body) => + extractParams(body) match { + case Left(_) => + println(s"Skipped: $body") + Right(head) + case Right(tail) => + println(s"Prepended: $head to $tail") + Right(head ++ tail) + } + case None => + println(s"No body") + Right(head) + } + case Block(List(defdef), Closure(_, _)) => + println("Unwrapping single element block") + extractParams(defdef) + case Block(Nil, singleTerm) => + println("Unwrapping single element block") + extractParams(singleTerm) + case Inlined(_, _, block) => + println("Unwrapping inlined") + extractParams(block) + case _ => + println(s"""Expression: + |${t.show(using Printer.TreeAnsiCode)} + |defined as: + |${t.show(using Printer.TreeStructure)} + |of type: + |${t.asInstanceOf[Term].tpe.show(using Printer.TypeReprAnsiCode)} + |of type: + |${t.asInstanceOf[Term].tpe.show(using Printer.TypeReprStructure)} + |""".stripMargin) + Left(invalidConstructor(t)) + } + + extractParams(t).map(params => + new ExistentialCtor { + type Underlying = runtime.ArgumentLists + implicit val Underlying: Type[runtime.ArgumentLists] = paramsToType(params) + } + ) + } + + private def paramsToType(paramsLists: List[List[ValDef]]): Type[runtime.ArgumentLists] = + paramsLists + .map { paramList => + paramList.foldRight[Type[? <: runtime.ArgumentList]](Type.of[runtime.ArgumentList.Empty])( + constructArgumentListType + ) + } + .foldRight[Type[? <: runtime.ArgumentLists]](Type.of[runtime.ArgumentLists.Empty])( + constructArgumentListsType + ) + .asInstanceOf[Type[runtime.ArgumentLists]] + + private def constructArgumentListsType( + head: Type[? <: runtime.ArgumentList], + tail: Type[? <: runtime.ArgumentLists] + ): Type[? <: runtime.ArgumentLists] = { + object ApplyParams { + def apply[Head <: runtime.ArgumentList: Type, Tail <: runtime.ArgumentLists: Type] + : Type[runtime.ArgumentLists.List[Head, Tail]] = + Type.of[runtime.ArgumentLists.List[Head, Tail]] + } + + ApplyParams(head, tail) + } + + private def constructArgumentListType( + t: ValDef, + args: Type[? <: runtime.ArgumentList] + ): Type[? <: runtime.ArgumentList] = { + val ValDef(name, tpe, _) = t + + object ApplyParam { + def apply[ParamName <: String: Type, ParamType: Type, Args <: runtime.ArgumentList: Type] + : Type[runtime.ArgumentList.Argument[ParamName, ParamType, Args]] = + Type.of[runtime.ArgumentList.Argument[ParamName, ParamType, Args]] + } + + ApplyParam( + ConstantType(StringConstant(name)).asType.asInstanceOf[Type[String]], + tpe.tpe.asType.asInstanceOf[Type[Any]], + args + ) + } + + private def invalidConstructor(t: Tree): String = + s"Expected function, instead got: ${t.show(using Printer.TreeAnsiCode)}: ${t.asInstanceOf[Term].tpe.show(using Printer.TypeReprAnsiCode)}" + } + def applyFieldNameType[Out](f: [A <: runtime.Path] => Type[A] ?=> Out)(selector: Expr[?]): Out = ExistentialPath .parse(selector.asTerm) @@ -96,9 +200,21 @@ private[chimney] class DslMacroUtils()(using quotes: Quotes) { def applyConstructorType[Out]( f: [Ctor <: runtime.ArgumentLists] => Type[Ctor] ?=> Out - )(ctor: Expr[?]): Out = { - // TODO: analyze f and implement the type - val _ = ctor - f[runtime.ArgumentLists.Empty] - } + )(ctor: Expr[?]): Out = + ExistentialCtor.parse(ctor.asTerm) match { + case Right(ctorType) => + println(s"""Expression: + |${ctor.asTerm.show(using Printer.TreeAnsiCode)} + |defined as: + |${ctor.asTerm.show(using Printer.TreeStructure)} + |of type: + |${ctor.asTerm.tpe.show(using Printer.TypeReprAnsiCode)} + |of type: + |${ctor.asTerm.tpe.show(using Printer.TypeReprStructure)} + |resolved as: + |${TypeRepr.of(using ctorType.Underlying).show(using Printer.TypeReprAnsiCode)} + |""".stripMargin) + f(using ctorType.Underlying) + case Left(error) => report.errorAndAbort(error, Position.ofMacroExpansion) + } } diff --git a/chimney/src/main/scala/io/scalaland/chimney/internal/compiletime/DerivationError.scala b/chimney/src/main/scala/io/scalaland/chimney/internal/compiletime/DerivationError.scala index 5786c6e4d..ee04d8aed 100644 --- a/chimney/src/main/scala/io/scalaland/chimney/internal/compiletime/DerivationError.scala +++ b/chimney/src/main/scala/io/scalaland/chimney/internal/compiletime/DerivationError.scala @@ -14,7 +14,7 @@ object DerivationError { .collectFirst { case MacroException(exception) => val stackTrace = - exception.getStackTrace.view.take(100).map(ste => s" \t${Console.RED}$ste${Console.RESET}").mkString("\n") + exception.getStackTrace.view.take(10).map(ste => s" \t${Console.RED}$ste${Console.RESET}").mkString("\n") s" macro expansion thrown exception!: $exception:\n$stackTrace\n \t${Console.RED}...${Console.RESET}" case NotYetImplemented(what) => s" derivation failed because functionality $what is not yet implemented!" diff --git a/chimney/src/main/scala/io/scalaland/chimney/internal/runtime/IsFunction.scala b/chimney/src/main/scala/io/scalaland/chimney/internal/runtime/IsFunction.scala index d6e8c2d6d..0e5a22d48 100644 --- a/chimney/src/main/scala/io/scalaland/chimney/internal/runtime/IsFunction.scala +++ b/chimney/src/main/scala/io/scalaland/chimney/internal/runtime/IsFunction.scala @@ -9,48 +9,108 @@ import scala.annotation.implicitNotFound sealed trait IsFunction[Fn] { type Out } -object IsFunction { +object IsFunction extends IsFunctionLowPriorityImplicits { type Of[Fn, Out0] = IsFunction[Fn] { type Out = Out0 } + private def cast[A, Out](of: Of[?, Out]): Of[A, Out] = of.asInstanceOf[Of[A, Out]] + + implicit def curriedFunction1[A, Mid, Out](implicit ev: Of[Mid, Out]): Of[A => Mid, Out] = cast(ev) + implicit def curriedFunction2[A, B, Mid, Out](implicit ev: Of[Mid, Out]): Of[(A, B) => Mid, Out] = cast(ev) + implicit def curriedFunction3[A, B, C, Mid, Out](implicit ev: Of[Mid, Out]): Of[(A, B, C) => Mid, Out] = cast(ev) + implicit def curriedFunction4[A, B, C, D, Mid, Out](implicit ev: Of[Mid, Out]): Of[(A, B, C, D) => Mid, Out] = cast( + ev + ) + implicit def curriedFunction5[A, B, C, D, E, Mid, Out](implicit ev: Of[Mid, Out]): Of[(A, B, C, D, E) => Mid, Out] = + cast(ev) + implicit def curriedFunction6[A, B, C, D, E, F, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F) => Mid, Out] = cast(ev) + implicit def curriedFunction7[A, B, C, D, E, F, G, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G) => Mid, Out] = cast(ev) + implicit def curriedFunction8[A, B, C, D, E, F, G, H, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H) => Mid, Out] = cast(ev) + implicit def curriedFunction9[A, B, C, D, E, F, G, H, I, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I) => Mid, Out] = cast(ev) + implicit def curriedFunction10[A, B, C, D, E, F, G, H, I, J, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J) => Mid, Out] = cast(ev) + implicit def curriedFunction11[A, B, C, D, E, F, G, H, I, J, K, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K) => Mid, Out] = cast(ev) + implicit def curriedFunction12[A, B, C, D, E, F, G, H, I, J, K, L, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K, L) => Mid, Out] = cast(ev) + implicit def curriedFunction13[A, B, C, D, E, F, G, H, I, J, K, L, M, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K, L, M) => Mid, Out] = cast(ev) + implicit def curriedFunction14[A, B, C, D, E, F, G, H, I, J, K, L, M, N, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N) => Mid, Out] = cast(ev) + implicit def curriedFunction15[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => Mid, Out] = cast(ev) + implicit def curriedFunction16[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => Mid, Out] = cast(ev) + implicit def curriedFunction17[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => Mid, Out] = cast(ev) + implicit def curriedFunction18[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => Mid, Out] = cast(ev) + implicit def curriedFunction19[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => Mid, Out] = cast(ev) + implicit def curriedFunction20[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => Mid, Out] = cast(ev) + implicit def curriedFunction21[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => Mid, Out] = cast(ev) + implicit def curriedFunction22[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, Mid, Out](implicit + ev: Of[Mid, Out] + ): Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => Mid, Out] = cast(ev) +} +private trait IsFunctionLowPriorityImplicits { this: IsFunction.type => + private val impl = new IsFunction[Any] {} - private def cast[Fn, Out]: IsFunction.Of[Fn, Out] = impl.asInstanceOf[IsFunction.Of[Fn, Out]] + private def cast[Fn, Out]: Of[Fn, Out] = impl.asInstanceOf[Of[Fn, Out]] - implicit def function0[Out]: IsFunction.Of[() => Out, Out] = cast // TODO: is it needed or is it Function1? - implicit def function1[A, Out]: IsFunction.Of[A => Out, Out] = cast - implicit def function2[A, B, Out]: IsFunction.Of[(A, B) => Out, Out] = cast - implicit def function3[A, B, C, Out]: IsFunction.Of[(A, B, C) => Out, Out] = cast - implicit def function4[A, B, C, D, Out]: IsFunction.Of[(A, B, C, D) => Out, Out] = cast - implicit def function5[A, B, C, D, E, Out]: IsFunction.Of[(A, B, C, D, E) => Out, Out] = cast - implicit def function6[A, B, C, D, E, F, Out]: IsFunction.Of[(A, B, C, D, E, F) => Out, Out] = cast - implicit def function7[A, B, C, D, E, F, G, Out]: IsFunction.Of[(A, B, C, D, E, F, G) => Out, Out] = cast - implicit def function8[A, B, C, D, E, F, G, H, Out]: IsFunction.Of[(A, B, C, D, E, F, G, H) => Out, Out] = cast - implicit def function9[A, B, C, D, E, F, G, H, I, Out]: IsFunction.Of[(A, B, C, D, E, F, G, H, I) => Out, Out] = cast - implicit def function10[A, B, C, D, E, F, G, H, I, J, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J) => Out, Out] = cast - implicit def function11[A, B, C, D, E, F, G, H, I, J, K, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K) => Out, Out] = cast + implicit def function1[A, Out]: Of[A => Out, Out] = cast + implicit def function2[A, B, Out]: Of[(A, B) => Out, Out] = cast + implicit def function3[A, B, C, Out]: Of[(A, B, C) => Out, Out] = cast + implicit def function4[A, B, C, D, Out]: Of[(A, B, C, D) => Out, Out] = cast + implicit def function5[A, B, C, D, E, Out]: Of[(A, B, C, D, E) => Out, Out] = cast + implicit def function6[A, B, C, D, E, F, Out]: Of[(A, B, C, D, E, F) => Out, Out] = cast + implicit def function7[A, B, C, D, E, F, G, Out]: Of[(A, B, C, D, E, F, G) => Out, Out] = cast + implicit def function8[A, B, C, D, E, F, G, H, Out]: Of[(A, B, C, D, E, F, G, H) => Out, Out] = cast + implicit def function9[A, B, C, D, E, F, G, H, I, Out]: Of[(A, B, C, D, E, F, G, H, I) => Out, Out] = cast + implicit def function10[A, B, C, D, E, F, G, H, I, J, Out]: Of[(A, B, C, D, E, F, G, H, I, J) => Out, Out] = cast + implicit def function11[A, B, C, D, E, F, G, H, I, J, K, Out]: Of[(A, B, C, D, E, F, G, H, I, J, K) => Out, Out] = + cast implicit def function12[A, B, C, D, E, F, G, H, I, J, K, L, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K, L) => Out, Out] = cast + : Of[(A, B, C, D, E, F, G, H, I, J, K, L) => Out, Out] = cast implicit def function13[A, B, C, D, E, F, G, H, I, J, K, L, M, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K, L, M) => Out, Out] = cast + : Of[(A, B, C, D, E, F, G, H, I, J, K, L, M) => Out, Out] = cast implicit def function14[A, B, C, D, E, F, G, H, I, J, K, L, M, N, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N) => Out, Out] = cast + : Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N) => Out, Out] = cast implicit def function15[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => Out, Out] = cast + : Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => Out, Out] = cast implicit def function16[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => Out, Out] = cast + : Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => Out, Out] = cast implicit def function17[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => Out, Out] = cast + : Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => Out, Out] = cast implicit def function18[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => Out, Out] = cast + : Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => Out, Out] = cast implicit def function19[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => Out, Out] = cast + : Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => Out, Out] = cast implicit def function20[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => Out, Out] = cast + : Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => Out, Out] = cast implicit def function21[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => Out, Out] = cast + : Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => Out, Out] = cast implicit def function22[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, Out] - : IsFunction.Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => Out, Out] = cast - - // TODO: multiple parameter lists + : Of[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => Out, Out] = cast } diff --git a/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerCustomConstructorSpec.scala b/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerCustomConstructorSpec.scala index 778443797..78aa69fcf 100644 --- a/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerCustomConstructorSpec.scala +++ b/chimney/src/test/scala/io/scalaland/chimney/TotalTransformerCustomConstructorSpec.scala @@ -31,5 +31,11 @@ class TotalTransformerCustomConstructorSpec extends ChimneySpec { customConstructor(x, z) }) .transform ==> Bar(6, (6.28, 6.28)) + Foo(3, "pi", (3.14, 3.14)) + .into[Bar] + .withConstructor({ (x: Int) => (z: (Double, Double)) => + customConstructor(x, z) + }) + .transform ==> Bar(6, (6.28, 6.28)) } }