<commit_before>package scalan.meta

import scalan.util.{StringUtil, ScalaNameUtil}

trait ScalanCodegen extends ScalanParsers with SqlCompiler with ScalanAstExtensions { ctx: EntityManagement =>
  import PrintExtensions._

  abstract class TemplateData(val module: SEntityModuleDef, val entity: STraitOrClassDef) {
    val name = entity.name
    val tpeArgs = entity.tpeArgs
    val tpeArgDecls = tpeArgs.getTpeArgDecls
    val tpeArgUses = tpeArgs.getTpeArgUse
    val tpeArgDeclString = tpeArgs.getTpeArgDeclString
    val tpeArgUseString = tpeArgs.getTpeArgUseString
    val entityType = name + tpeArgUseString
    val typesDeclPref = tpeArgDecls.opt(_.rep() + ", ")
    val typesUsePref = tpeArgUses.opt(_.rep() + ", ")
    val implicitArgs = entity.implicitArgs.args
    val implicitArgsDecl = implicitArgs.opt(args => s"(implicit ${args.rep(a => s"${a.name}: ${a.tpe}")})")
    val implicitArgsUse = implicitArgs.opt(args => s"(${args.map(_.name).rep()})")
    val optBT = entity.optBaseType
    val firstAncestorType = entity.ancestors.head
    val entityRepSynonimOpt = module.entityRepSynonym

    def entityRepSynonim = entityRepSynonimOpt match {
      case Some(s) => s
      case None => STpeDef("Rep" + name, tpeArgs, STraitCall("Rep", List(STraitCall(name, tpeArgs.map(_.toTraitCall)))))
    }

    def emitEntityRepSynonim = {
      val td = entityRepSynonim
      td.emitTypeDecl
    }

    def isContainer1 = tpeArgs.length == 1 && entity.hasAnnotation(ContainerTypeAnnotation)

    def boundedTpeArgString(withTags: Boolean = false) = tpeArgs.getBoundedTpeArgString(withTags)

    def tpeArgsImplicitDecl(typeClass: String) = {
      tpeArgs.opt(args =>
        s"(implicit ${args.rep(t => s"ev${t.name}: $typeClass[${t.name}]")})")
    }
  }

  case class EntityTemplateData(m: SEntityModuleDef, t: STraitDef) extends TemplateData(m, t)

  case class ConcreteClassTemplateData(m: SEntityModuleDef, c: SClassDef) extends TemplateData(m, c) {
    val classType = name + tpeArgUseString
  }

  trait MatcherGenerator {

    object InternalFunctions {

      def whitespaces(title: String) = scala.Array.fill(title.length + 2)(" ").reduce(_ + _)
      def returnType(entity: STraitDef) = entity.tpeArgs.getTpeArgDecls.last.toString + "1"
      def typesNoBraces(entity: STraitDef) = entity.tpeArgs.getTpeArgDecls.opt(tyArgs => s"${tyArgs.rep(t => t)}")
      def title(entity: STraitDef) = s"def match${entity.name}[${typesNoBraces(entity)}, ${returnType(entity)}]"
      def lambdas(module: SEntityModuleDef, whitespace: String) = {
        val entity = module.entityOps
        val classes = module.concreteSClasses
        (1.to(classes.length).toList zip classes).map { case Pair(i, c) =>
          s"\n$whitespace(f$i: Rep[${c.name}[${typesNoBraces(entity)}]] => Rep[${returnType(entity)}])"
        }.opt(specs => s"${specs.rep(t => t, s"")}")
      }
      def declaration(module: SEntityModuleDef) = {
        val entity = module.entityOps
        val name = entity.name
        val types = typesNoBraces(entity)
        val titleDef = title(module.entityOps)
        s"""\n
          |  ${title(entity)}(x: Rep[$name[$types]])${lambdas(module, whitespaces(titleDef))}: Rep[${returnType(entity)}]
          |""".stripAndTrim
      }
    }
    import InternalFunctions._

    def entityMatcherAbs(module: SEntityModuleDef) = {
      declaration(module)
    }
    def entityMatcherSeq(module: SEntityModuleDef) = {
      val classes = module.concreteSClasses
      val cases = (1.to(classes.length).toList zip classes).map { case Pair(i, c) =>
        s"      case x$i: ${c.name}[_] => f$i(x$i)\n"
      }.opt(specs => s"${specs.rep(t => t, s"")}")
      val body = s""" = {
        |    x match {
        |$cases
        |    }
        |  }"""
      s"""\n
        |  ${declaration(module)}$body
        |""".stripAndTrim
    }
    def entityMatcherExp(module: SEntityModuleDef) = {
      val classes = module.concreteSClasses
      val types = module.entityOps.tpeArgs.getTpeArgDeclString
      val cases = (1.to(classes.length).toList zip classes).map { case Pair(i, c) =>
        s"      case _: ${c.name}Elem[_] => f$i(x.asRep[${c.name}$types])" }.opt(specs => s"${specs.rep(t => t, s"\n")}")
      val body = s""" = {
        |    x.elem.asInstanceOf[Elem[_]] match {
        |$cases
        |    }
        |  }"""
      s"""\n
        |  ${declaration(module)}$body
        |""".stripAndTrim
    }
  }

  class EntityFileGenerator(module: SEntityModuleDef, config: CodegenConfig) extends MatcherGenerator {

    def dataType(ts: List[STpeExpr]): String = ts match {
      case Nil => "Unit"
      case t :: Nil => t.toString
      case t :: ts => s"($t, ${dataType(ts)})"
    }

    def pairify(fs: List[String]): String = fs match {<commit_msg>Matchers with fallback case are auto-generated in meta, implemented for Vectors and Matrices.<commit_after>package scalan.meta

import scalan.util.{StringUtil, ScalaNameUtil}

trait ScalanCodegen extends ScalanParsers with SqlCompiler with ScalanAstExtensions { ctx: EntityManagement =>
  import PrintExtensions._

  abstract class TemplateData(val module: SEntityModuleDef, val entity: STraitOrClassDef) {
    val name = entity.name
    val tpeArgs = entity.tpeArgs
    val tpeArgDecls = tpeArgs.getTpeArgDecls
    val tpeArgUses = tpeArgs.getTpeArgUse
    val tpeArgDeclString = tpeArgs.getTpeArgDeclString
    val tpeArgUseString = tpeArgs.getTpeArgUseString
    val entityType = name + tpeArgUseString
    val typesDeclPref = tpeArgDecls.opt(_.rep() + ", ")
    val typesUsePref = tpeArgUses.opt(_.rep() + ", ")
    val implicitArgs = entity.implicitArgs.args
    val implicitArgsDecl = implicitArgs.opt(args => s"(implicit ${args.rep(a => s"${a.name}: ${a.tpe}")})")
    val implicitArgsUse = implicitArgs.opt(args => s"(${args.map(_.name).rep()})")
    val optBT = entity.optBaseType
    val firstAncestorType = entity.ancestors.head
    val entityRepSynonimOpt = module.entityRepSynonym

    def entityRepSynonim = entityRepSynonimOpt match {
      case Some(s) => s
      case None => STpeDef("Rep" + name, tpeArgs, STraitCall("Rep", List(STraitCall(name, tpeArgs.map(_.toTraitCall)))))
    }

    def emitEntityRepSynonim = {
      val td = entityRepSynonim
      td.emitTypeDecl
    }

    def isContainer1 = tpeArgs.length == 1 && entity.hasAnnotation(ContainerTypeAnnotation)

    def boundedTpeArgString(withTags: Boolean = false) = tpeArgs.getBoundedTpeArgString(withTags)

    def tpeArgsImplicitDecl(typeClass: String) = {
      tpeArgs.opt(args =>
        s"(implicit ${args.rep(t => s"ev${t.name}: $typeClass[${t.name}]")})")
    }
  }

  case class EntityTemplateData(m: SEntityModuleDef, t: STraitDef) extends TemplateData(m, t)

  case class ConcreteClassTemplateData(m: SEntityModuleDef, c: SClassDef) extends TemplateData(m, c) {
    val classType = name + tpeArgUseString
  }

  trait MatcherGenerator {

    object InternalFunctions {

      def whitespaces(title: String) = scala.Array.fill(title.length + 2)(" ").reduce(_ + _)
      def returnType(entity: STraitDef) = entity.tpeArgs.getTpeArgDecls.last.toString + "1"
      def typesNoBraces(entity: STraitDef) = entity.tpeArgs.getTpeArgDecls.opt(tyArgs => s"${tyArgs.rep(t => t)}")
      def title(entity: STraitDef) = s"def match${entity.name}[${typesNoBraces(entity)}, ${returnType(entity)}]"
      def lambdas(module: SEntityModuleDef, whitespace: String) = {
        val entity = module.entityOps
        val classes = module.concreteSClasses
        val types = typesNoBraces(entity)
        val retType = returnType(entity)
        (1.to(classes.length).toList zip classes).map { case Pair(i, c) =>
          s"\n$whitespace(f$i: Rep[${c.name}[$types]] => Rep[$retType])"
        }.opt(specs => s"${specs.rep(t => t, s"")}") + s"\n$whitespace(fb: Rep[${entity.name}[$types]] => Rep[$retType])"
      }
      def declaration(module: SEntityModuleDef) = {
        val entity = module.entityOps
        val name = entity.name
        val types = typesNoBraces(entity)
        val titleDef = title(module.entityOps)
        s"""\n
          |  ${title(entity)}(x: Rep[$name[$types]])${lambdas(module, whitespaces(titleDef))}: Rep[${returnType(entity)}]
          |""".stripAndTrim
      }
    }
    import InternalFunctions.declaration

    def entityMatcherAbs(module: SEntityModuleDef) = {
      declaration(module)
    }
    def entityMatcherSeq(module: SEntityModuleDef) = {
      val classes = module.concreteSClasses
      val cases = (1.to(classes.length).toList zip classes).map { case Pair(i, c) =>
        s"      case x$i: ${c.name}[_] => f$i(x$i)"
      }.opt(specs => s"${specs.rep(t => t, s"\n")}")
      val body = s""" = {
        |    x match {
        |$cases
        |      case xb: ${module.entityOps.name}[_] => fb(xb)
        |    }
        |  }"""
      s"""\n
        |  ${declaration(module)}$body
        |""".stripAndTrim
    }
    def entityMatcherExp(module: SEntityModuleDef) = {
      val classes = module.concreteSClasses
      val types = module.entityOps.tpeArgs.getTpeArgDeclString
      val cases = (1.to(classes.length).toList zip classes).map { case Pair(i, c) =>
        s"      case _: ${c.name}Elem[_] => f$i(x.asRep[${c.name}$types])"
      }.opt(specs => s"${specs.rep(t => t, s"\n")}")
      val body = s""" = {
        |    x.elem.asInstanceOf[Elem[_]] match {
        |$cases
        |      case _ => fb(x)
        |    }
        |  }"""
      s"""\n
        |  ${declaration(module)}$body
        |""".stripAndTrim
    }
  }

  class EntityFileGenerator(module: SEntityModuleDef, config: CodegenConfig) extends MatcherGenerator {

    def dataType(ts: List[STpeExpr]): String = ts match {
      case Nil => "Unit"
      case t :: Nil => t.toString
      case t :: ts => s"($t, ${dataType(ts)})"
    }

    def pairify(fs: List[String]): String = fs match {
{'fraction_non_alphanumeric': 0.1441468857780483, 'fraction_numerical': 0.0014201663623453033, 'mean_word_length': 3.161671591388772, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 56, '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': '2397283', 'n_tokens_mistral': 3353, 'n_tokens_neox': 3295, 'n_words': 651}