<commit_before>package scala.tools.nsc.matching

import compat.StringBuilder
import scala.tools.nsc.util.Position

/** utility methods (not just for ParallelMatching) */
trait ParallelMatching requires (transform.ExplicitOuter with PatternMatchers with CodeFactory) {

  import global._

  def DEBUG(x:String) = {if (settings.debug.value) Console.println(x)}
  // ----------------------------------   data

  trait RuleApplication
  case class ErrorRule    extends RuleApplication
  case class VariableRule(subst:List[Pair[Symbol,Symbol]], guard: Tree, body: Tree) extends RuleApplication
  case class MixtureRule(scrutinee:Symbol, column:List[Tree], rest:Rep) extends RuleApplication {

    var parent: Rep = null
    def setParent(rep:Rep) = { parent = rep; this }
    var casted: Symbol = null
    var moreSpecific:   List[Tree]        = Nil
    var subsumed:  List[(Int,List[Tree])] = Nil // row index and subpatterns
    var remaining: List[(Int,Tree)]       = Nil // row index and pattern

    val isExhaustive = !scrutinee.tpe.symbol.hasFlag(symtab.Flags.SEALED) || {
      //DEBUG("check exha for column "+column)
      val tpes = column.map (.tpe.symbol)
      scrutinee.tpe.symbol.children.forall { sym => tpes.contains(sym) }
    }

    //DEBUG("Mixture, is exhaustive? "+isExhaustive)
    //if(!isExhaustive)
    //  cunit.warning(column.head.pos, "match is not exhaustive, I think (first approx)")
    private val patternType     = column.head match {
      case p@(_:Ident | _:Select) => singleType(p.symbol.tpe.prefix, p.symbol)  //ConstantType(p.tpe.singleton)
      //case p@Apply(_,_) if !p.tpe.symbol.hasFlag(symtab.Flags.CASE) => ConstantType(new NamedConstant(p))
      case _ => column.head.tpe
    }
    private val isCaseScrutinee = patternType.symbol.hasFlag(symtab.Flags.CASE)
    private val dummies = if(!isCaseScrutinee) Nil else patternType.symbol.caseFieldAccessors.map { x => EmptyTree }
    private def subpatterns(pat:Tree): List[Tree] = pat match {
      case Bind(_,p)                                                          => subpatterns(p)
      case app @ Apply(fn, pats) if app.tpe.symbol.hasFlag(symtab.Flags.CASE) => pats
      case _: UnApply                                                         => throw CantHandleUnapply
      case pat                                                                => /*DEBUG("dummy patterns for "+pat+" of class "+pat.getClass);*/dummies
    }
      // more specific patterns, subpatterns, remaining patterns
    private var sr = column.zipWithIndex.foldLeft (moreSpecific,subsumed,remaining) {
      (p,patAndIndex) =>
        val (ms,ss,rs) = p
        val (pat,j)    = patAndIndex
      //Console.println("pat.tpe = "+pat.tpe)
      //Console.println("patternType = "+patternType)
      pat match {
        case Literal(Constant(null)) if !(patternType =:= pat.tpe) => //special case for constant null pattern
          (ms,ss,(j,pat)::rs)
        case _ if (pat.symbol ne null) && (patternType =:= singleType(pat.symbol.tpe.prefix, pat.symbol))=>
          (EmptyTree::ms, (j,dummies)::ss, rs);                                                 // matching an object
        case _ if pat.tpe <:< patternType =>
          ({if(pat.tpe =:= patternType) EmptyTree else pat}::ms, (j,subpatterns(pat))::ss, rs); // subsumed (same or more specific) pattern;
        case _ if patternType <:< pat.tpe  =>
          (EmptyTree::ms, (j,dummies)::ss, (j,pat)::rs);                                        // subsuming (matched *and* remaining pattern)
        case _ =>
          (ms,ss,(j,pat)::rs)
      }
    }
    this.moreSpecific = sr._1.reverse
    this.subsumed     = sr._2.reverse
    this.remaining    = sr._3.reverse
    sr = null
    override def toString = {
      "MixtureRule("+scrutinee+":"+scrutinee.tpe+") {\n  moreSpecific:"+moreSpecific+"\n  subsumed:"+subsumed+"\n  remaining"+remaining+"\n}"
    }

    def getTransition(implicit theOwner: Symbol): (Symbol, Rep, Option[Rep]) = {
      // the following works for type tests... what fudge is necessary for value comparisons?
      // type test
      casted = if(scrutinee.tpe =:= patternType) scrutinee else newVar(scrutinee.pos, patternType)
      if(scrutinee.hasFlag(symtab.Flags.CAPTURED))
        casted.setFlag(symtab.Flags.CAPTURED)
      // succeeding => transition to translate(subsumed) (taking into account more specific)
      val nmatrix = {
        var ntemps   = casted.caseFieldAccessors map {
          meth =>
            val ctemp = newVar(scrutinee.pos, casted.tpe.memberType(meth).resultType)
            if(scrutinee.hasFlag(symtab.Flags.CAPTURED))
              ctemp.setFlag(symtab.Flags.CAPTURED)
            ctemp
        } // (***)
        var subtests = subsumed

        if(moreSpecific.exists { x => x != EmptyTree }) {
          ntemps   = casted::ntemps                                                                                 // (***)<commit_msg>fixed bug related to default patterns<commit_after>package scala.tools.nsc.matching

import compat.StringBuilder
import scala.tools.nsc.util.Position

/** utility methods (not just for ParallelMatching) */
trait ParallelMatching requires (transform.ExplicitOuter with PatternMatchers with CodeFactory) {

  import global._

  def DEBUG(x:String) = {if (settings.debug.value) Console.println(x)}
  // ----------------------------------   data

  trait RuleApplication
  case class ErrorRule    extends RuleApplication
  case class VariableRule(subst:List[Pair[Symbol,Symbol]], guard: Tree, body: Tree) extends RuleApplication
  case class MixtureRule(scrutinee:Symbol, column:List[Tree], rest:Rep) extends RuleApplication {

    var parent: Rep = null
    def setParent(rep:Rep) = { parent = rep; this }
    var casted: Symbol = null
    var moreSpecific:   List[Tree]        = Nil
    var subsumed:  List[(Int,List[Tree])] = Nil // row index and subpatterns
    var remaining: List[(Int,Tree)]       = Nil // row index and pattern

    val isExhaustive = !scrutinee.tpe.symbol.hasFlag(symtab.Flags.SEALED) || {
      //DEBUG("check exha for column "+column)
      val tpes = column.map (.tpe.symbol)
      scrutinee.tpe.symbol.children.forall { sym => tpes.contains(sym) }
    }

    //DEBUG("Mixture, is exhaustive? "+isExhaustive)
    //if(!isExhaustive)
    //  cunit.warning(column.head.pos, "match is not exhaustive, I think (first approx)")
    private val patternType     = column.head match {
      case p@(_:Ident | _:Select) => singleType(p.symbol.tpe.prefix, p.symbol)  //ConstantType(p.tpe.singleton)
      //case p@Apply(_,_) if !p.tpe.symbol.hasFlag(symtab.Flags.CASE) => ConstantType(new NamedConstant(p))
      case _ => column.head.tpe
    }
    private val isCaseScrutinee = patternType.symbol.hasFlag(symtab.Flags.CASE)
    private val dummies = if(!isCaseScrutinee) Nil else patternType.symbol.caseFieldAccessors.map { x => EmptyTree }
    private def subpatterns(pat:Tree): List[Tree] = pat match {
      case Bind(_,p)                                                          => subpatterns(p)
      case app @ Apply(fn, pats) if app.tpe.symbol.hasFlag(symtab.Flags.CASE) => pats
      case _: UnApply                                                         => throw CantHandleUnapply
      case pat                                                                => /*DEBUG("dummy patterns for "+pat+" of class "+pat.getClass);*/dummies
    }
      // more specific patterns, subpatterns, remaining patterns
    private var sr = column.zipWithIndex.foldLeft (moreSpecific,subsumed,remaining) {
      (p,patAndIndex) =>
        val (ms,ss,rs) = p
        val (pat,j)    = patAndIndex
      //Console.println("pat.tpe = "+pat.tpe)
      //Console.println("patternType = "+patternType)
      pat match {
        case Literal(Constant(null)) if !(patternType =:= pat.tpe) => //special case for constant null pattern
          (ms,ss,(j,pat)::rs)
        case _ if (pat.symbol ne null) && (patternType =:= singleType(pat.symbol.tpe.prefix, pat.symbol))=>
          (EmptyTree::ms, (j,dummies)::ss, rs);                                                 // matching an object
        case _ if (pat.tpe <:< patternType) =>
          ({if(pat.tpe =:= patternType) EmptyTree else pat}::ms, (j,subpatterns(pat))::ss, rs); // subsumed (same or more specific) pattern;
        case _ if (patternType <:< pat.tpe) || isDefaultPattern(pat) =>
          (EmptyTree::ms, (j,dummies)::ss, (j,pat)::rs);                                        // subsuming (matched *and* remaining pattern)
        case _ =>
          (ms,ss,(j,pat)::rs)
      }
    }
    this.moreSpecific = sr._1.reverse
    this.subsumed     = sr._2.reverse
    this.remaining    = sr._3.reverse
    sr = null
    override def toString = {
      "MixtureRule("+scrutinee+":"+scrutinee.tpe+") {\n  moreSpecific:"+moreSpecific+"\n  subsumed:"+subsumed+"\n  remaining"+remaining+"\n}"
    }

    def getTransition(implicit theOwner: Symbol): (Symbol, Rep, Option[Rep]) = {
      DEBUG("*** getTransition! of "+this.toString)
      // the following works for type tests... what fudge is necessary for value comparisons?
      // type test
      casted = if(scrutinee.tpe =:= patternType) scrutinee else newVar(scrutinee.pos, patternType)
      if(scrutinee.hasFlag(symtab.Flags.CAPTURED))
        casted.setFlag(symtab.Flags.CAPTURED)
      // succeeding => transition to translate(subsumed) (taking into account more specific)
      val nmatrix = {
        var ntemps   = casted.caseFieldAccessors map {
          meth =>
            val ctemp = newVar(scrutinee.pos, casted.tpe.memberType(meth).resultType)
            if(scrutinee.hasFlag(symtab.Flags.CAPTURED))
              ctemp.setFlag(symtab.Flags.CAPTURED)
            ctemp
        } // (***)
        var subtests = subsumed

        if(moreSpecific.exists { x => x != EmptyTree }) {
          ntemps   = casted::ntemps                                                                                 // (***)
{'fraction_non_alphanumeric': 0.13176895306859207, 'fraction_numerical': 0.0006016847172081829, 'mean_word_length': 2.302317880794702, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '136144', 'n_tokens_mistral': 3046, 'n_tokens_neox': 2951, 'n_words': 678}