<commit_before>/**
 * User: <NAME>
 * Date: 11/17/13
 */
package scalan.meta

import scala.language.implicitConversions
import scala.tools.nsc.Global
import scala.reflect.internal.util.RangePosition
import scala.reflect.internal.util.OffsetPosition
import scalan.meta.ScalanAst._
import java.util.regex.Pattern

trait ScalanParsers {

  type Compiler = Global
  val compiler: Compiler
  import compiler._

  implicit def nameToString(name: Name): String = name.toString

  implicit class OptionListOps[A](opt: Option[List[A]]) {
    def flatList: List[A] = opt.toList.flatten
  }

  private def positionString(tree: Tree) = {
    tree.pos match {
      case pos: RangePosition =>
        val path = pos.source.file.canonicalPath
        s"file $path at ${pos.line}:${pos.column} (start ${pos.point - pos.start} before, end ${pos.end - pos.point} after)"
      case pos: OffsetPosition =>
        val path = pos.source.file.canonicalPath
        s"file $path at ${pos.line}:${pos.column}"
      case pos => pos.toString
    }
  }

  def !!!(msg: String, tree: Tree) = {
    val fullMsg = s"$msg at ${positionString(tree)}"
    throw new IllegalStateException(fullMsg)
  }

  def !!!(msg: String) = Base.!!!(msg)

  def ???(tree: Tree) = {
    val pos = tree.pos
    val msg = s"Unhandled case in ${positionString(tree)}:\nAST: ${showRaw(tree)}\n\nCode for AST: $tree"
    throw new IllegalStateException(msg)
  }

  def parse(name: String, tree: Tree) = tree match {
    case pd: PackageDef =>
      entityModule(pd)
    case tree =>
      throw new Exception(s"Unexpected tree in $name:\n\n$tree")
  }

  def config: CodegenConfig

  def parseDeclaredImplementations(entities: List[STraitOrClassDef], moduleDefOpt: Option[ClassDef]) = {
    val decls = for {
      dslModule <- moduleDefOpt.toList
      t <- entities
      stdOpsTrait <- findClassDefByName(dslModule.impl.body, t.name + "Decls")
    } yield {
      (t.name, stdOpsTrait)
    }
    val m = decls.map { case (name, decl) =>
      val methods = decl.impl.body.collect { case item: DefDef => item }
      (name, SDeclaredImplementation(methods.map(methodDef(_))))
    }.toMap
    SDeclaredImplementations(m)
  }

  def findClassDefByName(trees: List[Tree], name: String) =
    trees.collectFirst {
      case cd: ClassDef if cd.name.toString == name => cd
    }

  def entityModule(fileTree: PackageDef) = {
    val packageName = fileTree.pid.toString
    val statements = fileTree.stats
    val imports = statements.collect {
      case i: Import => importStat(i)
    }
    val moduleTraitTree = statements.collect {
      case cd: ClassDef if cd.mods.isTrait && !cd.name.contains("Dsl") => cd
    } match {
      case Seq(only) => only
      case seq => !!!(s"There must be exactly one module trait in file, found ${seq.length}")
    }
    val moduleTrait = traitDef(moduleTraitTree, Some(moduleTraitTree))
    val moduleName = moduleTrait.name

    val hasDsl =
      findClassDefByName(fileTree.stats, moduleName + "Dsl").isDefined

    val dslStdModuleOpt = findClassDefByName(fileTree.stats, moduleName + "DslStd")
    val dslExpModuleOpt = findClassDefByName(fileTree.stats, moduleName + "DslExp")
    val hasDslStdModule = dslStdModuleOpt.isDefined
    val hasDslExpModule = dslExpModuleOpt.isDefined

    val defs = moduleTrait.body

    val entityRepSynonym = defs.collectFirst { case t: STpeDef => t }

    val traits = defs.collect {
      case t: STraitDef if !(t.name.endsWith("Companion") || t.hasAnnotation("InternalType")) => t
    }
    val entity = traits.headOption.getOrElse {
      throw new IllegalStateException(s"Invalid syntax of entity module trait $moduleName. First member trait must define the entity, but no member traits found.")
    }

    val classes = entity.optBaseType match {
      case Some(bt) =>
        val entityName = entity.name
        val entityImplName = entityName + "Impl"
        val wrappedValueArg = SClassArg(false, false, true, "wrappedValue", STraitCall("Rep", List(bt)), None)
        val parent = STraitCall(entity.name, entity.tpeArgs.map(_.toTraitCall))
        val defaultBTImpl = SClassDef(
          name = entityImplName,
          tpeArgs = entity.tpeArgs,
          args = SClassArgs(List(wrappedValueArg)),
          implicitArgs = entity.implicitArgs,
          ancestors = List(parent),
          body = List(

          ),
          selfType = None,
          companion = None,
          //            companion = defs.collectFirst {
          //              case c: STraitOrClassDef if c.name.toString == entityImplName + "Companion" => c
          //            },
          true, Nil

        )
        defaultBTImpl :: moduleTrait.getConcreteClasses
      case None => moduleTrait.getConcreteClasses
    }
    val methods = defs.collect { case md: SMethodDef => md }

    val declaredStdImplementations = parseDeclaredImplementations(traits ++ classes, dslStdModuleOpt)
    val declaredExpImplementations = parseDeclaredImplementations(traits ++ classes, dslExpModuleOpt)

    SEntityModuleDef(packageName, imports, moduleName,
      entityRepSynonym, entity, traits, classes, methods,
      moduleTrait.selfType, Nil,
      Some(declaredStdImplementations),
      Some(declaredExpImplementations),
      hasDsl, hasDslStdModule, hasDslExpModule, moduleTrait.ancestors)
  }

  def importStat(i: Import): SImportStat = {
    SImportStat(i.toString.stripPrefix("import "))
  }

  def isEvidenceParam(vd: ValDef) = vd.name.toString.startsWith("evidence$")

  def tpeArgs(typeParams: List[TypeDef], possibleImplicits: List[ValDef]): List[STpeArg] = {
    val evidenceTypes = possibleImplicits.filter(isEvidenceParam(_)).map(_.tpt)

    def tpeArg(tdTree: TypeDef): STpeArg = {
      val bound = tdTree.rhs match {
        case TypeBoundsTree(low, high) =><commit_msg>fixup! Fixes needed by scalanizer to create boilerplate code for wrappers (Romanov)<commit_after>/**
 * User: <NAME>
 * Date: 11/17/13
 */
package scalan.meta

import scala.language.implicitConversions
import scala.tools.nsc.Global
import scala.reflect.internal.util.RangePosition
import scala.reflect.internal.util.OffsetPosition
import scalan.meta.ScalanAst._
import java.util.regex.Pattern

trait ScalanParsers {

  type Compiler = Global
  val compiler: Compiler
  import compiler._

  implicit def nameToString(name: Name): String = name.toString

  implicit class OptionListOps[A](opt: Option[List[A]]) {
    def flatList: List[A] = opt.toList.flatten
  }

  private def positionString(tree: Tree) = {
    tree.pos match {
      case pos: RangePosition =>
        val path = pos.source.file.canonicalPath
        s"file $path at ${pos.line}:${pos.column} (start ${pos.point - pos.start} before, end ${pos.end - pos.point} after)"
      case pos: OffsetPosition =>
        val path = pos.source.file.canonicalPath
        s"file $path at ${pos.line}:${pos.column}"
      case pos => pos.toString
    }
  }

  def !!!(msg: String, tree: Tree) = {
    val fullMsg = s"$msg at ${positionString(tree)}"
    throw new IllegalStateException(fullMsg)
  }

  def !!!(msg: String) = Base.!!!(msg)

  def ???(tree: Tree) = {
    val pos = tree.pos
    val msg = s"Unhandled case in ${positionString(tree)}:\nAST: ${showRaw(tree)}\n\nCode for AST: $tree"
    throw new IllegalStateException(msg)
  }

  def parse(name: String, tree: Tree) = tree match {
    case pd: PackageDef =>
      entityModule(pd)
    case tree =>
      throw new Exception(s"Unexpected tree in $name:\n\n$tree")
  }

  def config: CodegenConfig

  def parseDeclaredImplementations(entities: List[STraitOrClassDef], moduleDefOpt: Option[ClassDef]) = {
    val decls = for {
      dslModule <- moduleDefOpt.toList
      t <- entities
      stdOpsTrait <- findClassDefByName(dslModule.impl.body, t.name + "Decls")
    } yield {
      (t.name, stdOpsTrait)
    }
    val m = decls.map { case (name, decl) =>
      val methods = decl.impl.body.collect { case item: DefDef => item }
      (name, SDeclaredImplementation(methods.map(methodDef(_))))
    }.toMap
    SDeclaredImplementations(m)
  }

  def findClassDefByName(trees: List[Tree], name: String) =
    trees.collectFirst {
      case cd: ClassDef if cd.name.toString == name => cd
    }

  def tpeUseExpr(arg: STpeArg): STpeExpr = STraitCall(arg.name, arg.tparams.map(tpeUseExpr))

  def wrapperImpl(entity: STraitDef, bt: STpeExpr): SClassDef = {
    val entityName = entity.name
    val entityImplName = entityName + "Impl"
    val typeUseExprs = entity.tpeArgs.map(tpeUseExpr)
    SClassDef(
      name = entityImplName,
      tpeArgs = entity.tpeArgs,
      args = SClassArgs(List(SClassArg(false, false, true, "wrappedValue", STraitCall("Rep", List(bt)), None))),
      implicitArgs = entity.implicitArgs,
      ancestors = List(STraitCall(entity.name, typeUseExprs)),
      body = List(),
      selfType = None,
      companion = None,
      //            companion = defs.collectFirst {
      //              case c: STraitOrClassDef if c.name.toString == entityImplName + "Companion" => c
      //            },
      true, Nil
    )
  }

  def entityModule(fileTree: PackageDef) = {
    val packageName = fileTree.pid.toString
    val statements = fileTree.stats
    val imports = statements.collect {
      case i: Import => importStat(i)
    }
    val moduleTraitTree = statements.collect {
      case cd: ClassDef if cd.mods.isTrait && !cd.name.contains("Dsl") => cd
    } match {
      case Seq(only) => only
      case seq => !!!(s"There must be exactly one module trait in file, found ${seq.length}")
    }
    val moduleTrait = traitDef(moduleTraitTree, Some(moduleTraitTree))
    val moduleName = moduleTrait.name

    val hasDsl =
      findClassDefByName(fileTree.stats, moduleName + "Dsl").isDefined

    val dslStdModuleOpt = findClassDefByName(fileTree.stats, moduleName + "DslStd")
    val dslExpModuleOpt = findClassDefByName(fileTree.stats, moduleName + "DslExp")
    val hasDslStdModule = dslStdModuleOpt.isDefined
    val hasDslExpModule = dslExpModuleOpt.isDefined

    val defs = moduleTrait.body

    val entityRepSynonym = defs.collectFirst { case t: STpeDef => t }

    val traits = defs.collect {
      case t: STraitDef if !(t.name.endsWith("Companion") || t.hasAnnotation("InternalType")) => t
    }
    val entity = traits.headOption.getOrElse {
      throw new IllegalStateException(s"Invalid syntax of entity module trait $moduleName. First member trait must define the entity, but no member traits found.")
    }

    val classes = entity.optBaseType match {
      case Some(bt) =>
        wrapperImpl(entity, bt) :: moduleTrait.getConcreteClasses
      case None =>
        moduleTrait.getConcreteClasses
    }
    val methods = defs.collect { case md: SMethodDef => md }

    val declaredStdImplementations = parseDeclaredImplementations(traits ++ classes, dslStdModuleOpt)
    val declaredExpImplementations = parseDeclaredImplementations(traits ++ classes, dslExpModuleOpt)

    SEntityModuleDef(packageName, imports, moduleName,
      entityRepSynonym, entity, traits, classes, methods,
      moduleTrait.selfType, Nil,
      Some(declaredStdImplementations),
      Some(declaredExpImplementations),
      hasDsl, hasDslStdModule, hasDslExpModule, moduleTrait.ancestors)
  }

  def importStat(i: Import): SImportStat = {
    SImportStat(i.toString.stripPrefix("import "))
  }

  def isEvidenceParam(vd: ValDef) = vd.name.toString.startsWith("evidence$")

  def tpeArgs(typeParams: List[TypeDef], possibleImplicits: List[ValDef]): List[STpeArg] = {
    val evidenceTypes = possibleImplicits.filter(isEvidenceParam(_)).map(_.tpt)

    def tpeArg(tdTree: TypeDef): STpeArg = {
      val bound = tdTree.rhs match {
        case TypeBoundsTree(low, high) =>
{'fraction_non_alphanumeric': 0.11340558068094547, 'fraction_numerical': 0.0010239781551326906, 'mean_word_length': 3.2664725154714236, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 43, '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': '5758522', 'n_tokens_mistral': 3715, 'n_tokens_neox': 3658, 'n_words': 871}