<commit_before>/* NSC -- new Scala compiler
 *
 * Copyright 2011-2013 LAMP/EPFL
 * @author <NAME>
 */

package scala
package tools.nsc.transform.patmat

import scala.language.postfixOps
import scala.collection.mutable
import scala.reflect.internal.util.Statistics
import scala.reflect.internal.util.HashSet

trait Logic extends Debugging  {
  import PatternMatchingStats._

  private def max(xs: Seq[Int]) = if (xs isEmpty) 0 else xs max
  private def alignedColumns(cols: Seq[Any]): Seq[String] = {
    def toString(x: Any) = if (x == null) "" else x.toString
    if (cols.isEmpty || cols.tails.isEmpty) cols map toString
    else {
      val colLens = cols map (c => toString(c).length)
      val maxLen = max(colLens)
      val avgLen = colLens.sum/colLens.length
      val goalLen = maxLen min avgLen*2
      def pad(s: String) = {
        val toAdd = ((goalLen - s.length) max 0) + 2
        (" " * (toAdd/2)) + s + (" " * (toAdd/2 + (toAdd%2)))
      }
      cols map (x => pad(toString(x)))
    }
  }

  def alignAcrossRows(xss: List[List[Any]], sep: String, lineSep: String = "\n"): String = {
    val maxLen = max(xss map (_.length))
    val padded = xss map (xs => xs ++ List.fill(maxLen - xs.length)(null))
    padded.transpose.map(alignedColumns).transpose map (_.mkString(sep)) mkString(lineSep)
  }

  // http://www.cis.upenn.edu/~cis510/tcl/chap3.pdf
  // http://users.encs.concordia.ca/~ta_ahmed/ms_thesis.pdf
  // propositional logic with constants and equality
  trait PropositionalLogic {
    type Type
    type Tree

    class Prop
    final case class Eq(p: Var, q: Const) extends Prop

    type Const

    type TypeConst <: Const
    def TypeConst: TypeConstExtractor
    trait TypeConstExtractor {
      def apply(tp: Type): Const
    }

    type ValueConst <: Const
    def ValueConst: ValueConstExtractor
    trait ValueConstExtractor {
      def apply(p: Tree): Const
    }

    val NullConst: Const

    type Var <: AbsVar
    val Var: VarExtractor
    trait VarExtractor {
      def apply(x: Tree): Var
      def unapply(v: Var): Some[Tree]
    }

    def reportWarning(message: String): Unit

    // resets hash consing -- only supposed to be called by TreeMakersToProps
    def prepareNewAnalysis(): Unit

    trait AbsVar {
      // indicate we may later require a prop for V = C
      def registerEquality(c: Const): Unit

      // call this to indicate null is part of the domain
      def registerNull(): Unit

      // can this variable be null?
      def mayBeNull: Boolean

      // compute the domain and return it (call registerNull first!)
      def domainSyms: Option[Set[Sym]]

      // the symbol for this variable being equal to its statically known type
      // (only available if registerEquality has been called for that type before)
      def symForStaticTp: Option[Sym]

      // for this var, call it V, turn V = C into the equivalent proposition in boolean logic
      // registerEquality(c) must have been called prior to this call
      // in fact, all equalities relevant to this variable must have been registered
      def propForEqualsTo(c: Const): Prop

      // populated by registerEquality
      // once implications has been called, must not call registerEquality anymore
      def implications: List[(Sym, List[Sym], List[Sym])]
    }

    // would be nice to statically check whether a prop is equational or pure,
    // but that requires typing relations like And(x: Tx, y: Ty) : (if(Tx == PureProp && Ty == PureProp) PureProp else Prop)
    final case class And(ops: Set[Prop]) extends Prop
    object And {
      def apply(ops: Prop*) = new And(ops.toSet)
    }

    final case class Or(ops: Set[Prop]) extends Prop
    object Or {
      def apply(ops: Prop*) = new Or(ops.toSet)
    }

    final case class Not(a: Prop) extends Prop

    case object True extends Prop
    case object False extends Prop

    // symbols are propositions
    final class Sym private[PropositionalLogic] (val variable: Var, val const: Const) extends Prop {
      private val id: Int = Sym.nextSymId

      override def toString = variable + "=" + const + "#" + id
    }

    object Sym {
      private val uniques: HashSet[Sym] = new HashSet("uniques", 512)
      def apply(variable: Var, const: Const): Sym = {<commit_msg>Bugfix: Implement missing `equals` method for `Sym`.<commit_after>/* NSC -- new Scala compiler
 *
 * Copyright 2011-2013 LAMP/EPFL
 * @author <NAME>
 */

package scala
package tools.nsc.transform.patmat

import scala.language.postfixOps
import scala.collection.mutable
import scala.reflect.internal.util.Statistics
import scala.reflect.internal.util.HashSet

trait Logic extends Debugging  {
  import PatternMatchingStats._

  private def max(xs: Seq[Int]) = if (xs isEmpty) 0 else xs max
  private def alignedColumns(cols: Seq[Any]): Seq[String] = {
    def toString(x: Any) = if (x == null) "" else x.toString
    if (cols.isEmpty || cols.tails.isEmpty) cols map toString
    else {
      val colLens = cols map (c => toString(c).length)
      val maxLen = max(colLens)
      val avgLen = colLens.sum/colLens.length
      val goalLen = maxLen min avgLen*2
      def pad(s: String) = {
        val toAdd = ((goalLen - s.length) max 0) + 2
        (" " * (toAdd/2)) + s + (" " * (toAdd/2 + (toAdd%2)))
      }
      cols map (x => pad(toString(x)))
    }
  }

  def alignAcrossRows(xss: List[List[Any]], sep: String, lineSep: String = "\n"): String = {
    val maxLen = max(xss map (_.length))
    val padded = xss map (xs => xs ++ List.fill(maxLen - xs.length)(null))
    padded.transpose.map(alignedColumns).transpose map (_.mkString(sep)) mkString(lineSep)
  }

  // http://www.cis.upenn.edu/~cis510/tcl/chap3.pdf
  // http://users.encs.concordia.ca/~ta_ahmed/ms_thesis.pdf
  // propositional logic with constants and equality
  trait PropositionalLogic {
    type Type
    type Tree

    class Prop
    final case class Eq(p: Var, q: Const) extends Prop

    type Const

    type TypeConst <: Const
    def TypeConst: TypeConstExtractor
    trait TypeConstExtractor {
      def apply(tp: Type): Const
    }

    type ValueConst <: Const
    def ValueConst: ValueConstExtractor
    trait ValueConstExtractor {
      def apply(p: Tree): Const
    }

    val NullConst: Const

    type Var <: AbsVar
    val Var: VarExtractor
    trait VarExtractor {
      def apply(x: Tree): Var
      def unapply(v: Var): Some[Tree]
    }

    def reportWarning(message: String): Unit

    // resets hash consing -- only supposed to be called by TreeMakersToProps
    def prepareNewAnalysis(): Unit

    trait AbsVar {
      // indicate we may later require a prop for V = C
      def registerEquality(c: Const): Unit

      // call this to indicate null is part of the domain
      def registerNull(): Unit

      // can this variable be null?
      def mayBeNull: Boolean

      // compute the domain and return it (call registerNull first!)
      def domainSyms: Option[Set[Sym]]

      // the symbol for this variable being equal to its statically known type
      // (only available if registerEquality has been called for that type before)
      def symForStaticTp: Option[Sym]

      // for this var, call it V, turn V = C into the equivalent proposition in boolean logic
      // registerEquality(c) must have been called prior to this call
      // in fact, all equalities relevant to this variable must have been registered
      def propForEqualsTo(c: Const): Prop

      // populated by registerEquality
      // once implications has been called, must not call registerEquality anymore
      def implications: List[(Sym, List[Sym], List[Sym])]
    }

    // would be nice to statically check whether a prop is equational or pure,
    // but that requires typing relations like And(x: Tx, y: Ty) : (if(Tx == PureProp && Ty == PureProp) PureProp else Prop)
    final case class And(ops: Set[Prop]) extends Prop
    object And {
      def apply(ops: Prop*) = new And(ops.toSet)
    }

    final case class Or(ops: Set[Prop]) extends Prop
    object Or {
      def apply(ops: Prop*) = new Or(ops.toSet)
    }

    final case class Not(a: Prop) extends Prop

    case object True extends Prop
    case object False extends Prop

    // symbols are propositions
    final class Sym private[PropositionalLogic] (val variable: Var, val const: Const) extends Prop {

      override def equals(other: scala.Any): Boolean = other match {
        case that: Sym => this.variable == that.variable &&
          this.const == that.const
        case _         => false
      }

      override def hashCode(): Int = {
        variable.hashCode * 41 + const.hashCode
      }

      private val id: Int = Sym.nextSymId

      override def toString = s"$variable=$const#$id"
    }

    object Sym {
      private val uniques: HashSet[Sym] = new HashSet("uniques", 512)
      def apply(variable: Var, const: Const): Sym = {
{'fraction_non_alphanumeric': 0.10073239436619719, 'fraction_numerical': 0.005183098591549295, 'mean_word_length': 2.7754147171416417, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '3312330', 'n_tokens_mistral': 2740, 'n_tokens_neox': 2638, 'n_words': 941}