<commit_before>package d_m

import scala.tools.nsc
import nsc.Global
import nsc.Phase
import nsc.plugins.Plugin
import nsc.plugins.PluginComponent
import nsc.transform.Transform
import nsc.transform.InfoTransform
import nsc.transform.TypingTransformers
import nsc.symtab.Flags._
import nsc.ast.TreeDSL
import nsc.typechecker

class KindProjector(val global: Global) extends Plugin {
  val name = "kind-projector"
  val description = "Expand type lambda syntax"
  val components = new KindRewriter(this, global) :: Nil
}

class KindRewriter(plugin: Plugin, val global: Global)
    extends PluginComponent with Transform with TypingTransformers with TreeDSL {

  import global._

  val runsAfter = "parser" :: Nil
  val phaseName = "kind-projector"

  def newTransformer(unit: CompilationUnit) = new MyTransformer(unit)

  class MyTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {

    // reserve some names
    val TypeLambda1 = newTypeName("Lambda")
    val TypeLambda2 = newTypeName("λ")
    val Placeholder = newTypeName("$qmark")
    val CoPlaceholder = newTypeName("$plus$qmark")
    val ContraPlaceholder = newTypeName("$minus$qmark")

    // these will be used for matching but aren't reserved
    val Plus = newTypeName("$plus")
    val Minus = newTypeName("$minus")

    val UpperBound = """^(.+?)(?:\$u0020)+\$less\$colon(?:\$u0020)+(.+?)$""".r
    val LowerBound = """^(.+?)(?:\$u0020)+\$greater\$colon(?:\$u0020)+(.+?)$""".r
    val LowerAndUpperBounds = """^(.+?)(?:\$u0020)+\$greater\$colon(?:\$u0020)+(.+?)(?:\$u0020)+\$less\$colon(?:\$u0020)+(.+?)$""".r

    def rssi(b: String, c: String) =
      Select(Select(Ident("_root_"), b), newTypeName(c))

    val NothingLower = rssi("scala", "Nothing")
    val AnyUpper = rssi("scala", "Any")
    val DefaultBounds = TypeBoundsTree(NothingLower, AnyUpper)

    def parseBoundString(s: String): Tree = {
      def parseDotted(curr: Tree, parts: List[String]): Tree =
        parts match {
          case Nil => curr
          case h :: Nil => Select(curr, newTypeName(h))
          case h :: ts => parseDotted(Select(curr, h), ts)
        }
      s.split("\\$u002E").toList match {
        case Nil => sys.error("unpossible")
        case h :: Nil => Ident(newTypeName(h))
        case h :: ts => parseDotted(Ident(h), ts)
      }
    }

    override def transform(tree: Tree): Tree = {

      // Handy way to make a TypeName from a Name.
      def makeTypeName(name: Name) =
        newTypeName(name.toString)

      // We use this to create type parameters inside our type project, e.g.
      // the A in: ({type L[A] = (A, Int) => A})#L.
      def makeTypeParam(name: Name, bounds: TypeBoundsTree = DefaultBounds) =
        TypeDef(Modifiers(PARAM), makeTypeName(name), Nil, bounds)

      // Like makeTypeParam but with covariance, e.g.
      // ({type L[+A] = ... })#L.
      def makeTypeParamCo(name: Name, bounds: TypeBoundsTree = DefaultBounds) =
        TypeDef(Modifiers(PARAM | COVARIANT), makeTypeName(name), Nil, bounds)

      // Like makeTypeParam but with contravariance, e.g.
      // ({type L[-A] = ... })#L.
      def makeTypeParamContra(name: Name, bounds: TypeBoundsTree = DefaultBounds) =
        TypeDef(Modifiers(PARAM | CONTRAVARIANT), makeTypeName(name), Nil, bounds)

      // Detects which makeTypeParam method to call based on name,
      // as well as what bounds (if any) to apply
      def makeTypeParamFromName(name: Name) = {
        val (n, bs) = name.toString match {
          case LowerAndUpperBounds(name, lower, upper) =>
            (newTermName(name), TypeBoundsTree(parseBoundString(lower), parseBoundString(upper)))
          case LowerBound(name, lower) =>
            (newTermName(name), TypeBoundsTree(parseBoundString(lower), AnyUpper))
          case UpperBound(name, upper) =>
            val u = parseBoundString(upper)
            println(u)
            (newTermName(name), TypeBoundsTree(NothingLower, u))
          case _ =>
            (name, DefaultBounds)
        }
        makeTypeParamFromName0(n, bs)
      }

      // Detects which makeTypeParam* method to call based on name.
      // Names like +A are covariant, names like -A are contravariant,
      // all others are invariant.
      def makeTypeParamFromName0(name: Name, bounds: TypeBoundsTree = DefaultBounds) =
        if (name.startsWith("$plus")) {
          makeTypeParamCo(newTypeName(name.toString.substring(5)), bounds)
        } else if (name.startsWith("$minus")) {
          makeTypeParamContra(newTypeName(name.toString.substring(6)), bounds)
        } else {
          makeTypeParam(name, bounds)
        }<commit_msg>Use NameTransformer to "de-mangle" strings.<commit_after>package d_m

import scala.tools.nsc
import nsc.Global
import nsc.Phase
import nsc.plugins.Plugin
import nsc.plugins.PluginComponent
import nsc.transform.Transform
import nsc.transform.InfoTransform
import nsc.transform.TypingTransformers
import nsc.symtab.Flags._
import nsc.ast.TreeDSL
import nsc.typechecker

import scala.reflect.NameTransformer

class KindProjector(val global: Global) extends Plugin {
  val name = "kind-projector"
  val description = "Expand type lambda syntax"
  val components = new KindRewriter(this, global) :: Nil
}

class KindRewriter(plugin: Plugin, val global: Global)
    extends PluginComponent with Transform with TypingTransformers with TreeDSL {

  import global._

  val runsAfter = "parser" :: Nil
  val phaseName = "kind-projector"

  def newTransformer(unit: CompilationUnit) = new MyTransformer(unit)

  class MyTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {

    // reserve some names
    val TypeLambda1 = newTypeName("Lambda")
    val TypeLambda2 = newTypeName("λ")
    val Placeholder = newTypeName("$qmark")
    val CoPlaceholder = newTypeName("$plus$qmark")
    val ContraPlaceholder = newTypeName("$minus$qmark")

    // these will be used for matching but aren't reserved
    val Plus = newTypeName("$plus")
    val Minus = newTypeName("$minus")

    val UpperBound = """^(.+?) +<: +(.+?)$""".r
    val LowerBound = """^(.+?) +>: +(.+?)$""".r
    val LowerAndUpperBounds = """^(.+?) +>: +(.+?) +<: +(.+?)$""".r

    def rssi(b: String, c: String) =
      Select(Select(Ident("_root_"), b), newTypeName(c))

    val NothingLower = rssi("scala", "Nothing")
    val AnyUpper = rssi("scala", "Any")
    val DefaultBounds = TypeBoundsTree(NothingLower, AnyUpper)

    def parseBoundString(s: String): Tree = {
      def parseDotted(curr: Tree, parts: List[String]): Tree =
        parts match {
          case Nil => curr
          case h :: Nil => Select(curr, newTypeName(h))
          case h :: ts => parseDotted(Select(curr, h), ts)
        }
      s.split('.').toList match {
        case Nil => sys.error("unpossible")
        case h :: Nil => Ident(newTypeName(h))
        case h :: ts => parseDotted(Ident(h), ts)
      }
    }

    override def transform(tree: Tree): Tree = {

      // Handy way to make a TypeName from a Name.
      def makeTypeName(name: Name) =
        newTypeName(name.toString)

      // We use this to create type parameters inside our type project, e.g.
      // the A in: ({type L[A] = (A, Int) => A})#L.
      def makeTypeParam(name: Name, bounds: TypeBoundsTree = DefaultBounds) =
        TypeDef(Modifiers(PARAM), makeTypeName(name), Nil, bounds)

      // Like makeTypeParam but with covariance, e.g.
      // ({type L[+A] = ... })#L.
      def makeTypeParamCo(name: Name, bounds: TypeBoundsTree = DefaultBounds) =
        TypeDef(Modifiers(PARAM | COVARIANT), makeTypeName(name), Nil, bounds)

      // Like makeTypeParam but with contravariance, e.g.
      // ({type L[-A] = ... })#L.
      def makeTypeParamContra(name: Name, bounds: TypeBoundsTree = DefaultBounds) =
        TypeDef(Modifiers(PARAM | CONTRAVARIANT), makeTypeName(name), Nil, bounds)

      // Detects which makeTypeParam method to call based on name,
      // as well as what bounds (if any) to apply
      def makeTypeParamFromName(name: Name) = {
        val (n, bs) = NameTransformer.decode(name.toString) match {
          case LowerAndUpperBounds(name, lower, upper) =>
            (newTermName(name), TypeBoundsTree(parseBoundString(lower), parseBoundString(upper)))
          case LowerBound(name, lower) =>
            (newTermName(name), TypeBoundsTree(parseBoundString(lower), AnyUpper))
          case UpperBound(name, upper) =>
            val u = parseBoundString(upper)
            println(u)
            (newTermName(name), TypeBoundsTree(NothingLower, u))
          case _ =>
            (name, DefaultBounds)
        }
        makeTypeParamFromName0(n, bs)
      }

      // Detects which makeTypeParam* method to call based on name.
      // Names like +A are covariant, names like -A are contravariant,
      // all others are invariant.
      def makeTypeParamFromName0(name: Name, bounds: TypeBoundsTree = DefaultBounds) =
        if (name.startsWith("+")) {
          makeTypeParamCo(newTypeName(name.toString.substring(5)), bounds)
        } else if (name.startsWith("-")) {
          makeTypeParamContra(newTypeName(name.toString.substring(6)), bounds)
        } else {
          makeTypeParam(name, bounds)
        }
{'fraction_non_alphanumeric': 0.13271739130434781, 'fraction_numerical': 0.005108695652173913, 'mean_word_length': 3.0947930574098796, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5696985', 'n_tokens_mistral': 2915, 'n_tokens_neox': 2774, 'n_words': 732}