<commit_before>package scala.scalanative
package nscplugin

import scala.collection.mutable
import scala.tools.nsc.{util => _, _}
import scala.tools.nsc.plugins._
import scala.util.{Either, Left, Right}
import scala.reflect.internal.Flags._
import util._, util.ScopedVar.scoped
import nir.Focus, Focus.sequenced
import nir._, Shows._
import NirPrimitives._

abstract class NirCodeGen
    extends PluginComponent
    with NirFiles
    with NirTypeEncoding
    with NirNameEncoding {
  val nirAddons: NirGlobalAddons {
    val global: NirCodeGen.this.global.type
  }

  import global._
  import definitions._
  import treeInfo.hasSynthCaseSymbol
  import nirAddons._
  import nirDefinitions._

  val phaseName = "nir"

  override def newPhase(prev: Phase): StdPhase =
    new SaltyCodePhase(prev)

  case class ValTree(val value: nir.Val) extends Tree

  class Env(val fresh: Fresh) {
    private val env = mutable.Map.empty[Symbol, Val]

    def enter(sym: Symbol, value: Val): Unit =
      env += ((sym, value))

    def enterLabel(ld: LabelDef): Local = {
      val local = fresh()
      enter(ld.symbol, Val.Local(local, Type.Ptr))
      local
    }

    def resolve(sym: Symbol): Val = env(sym)

    def resolveLabel(ld: LabelDef): Local = {
      val Val.Local(n, Type.Ptr) = resolve(ld.symbol)
      n
    }
  }

  class CollectLocalInfo extends Traverser {
    var mutableVars = Set.empty[Symbol]
    var labels      = Set.empty[LabelDef]

    override def traverse(tree: Tree) = {
      tree match {
        case label: LabelDef =>
          labels += label
        case Assign(id @ Ident(_), _) =>
          mutableVars += id.symbol
        case _ =>
          ()
      }
      super.traverse(tree)
    }

    def collect(tree: Tree) = {
      traverse(tree)
      this
    }
  }

  class SaltyCodePhase(prev: Phase) extends StdPhase(prev) {
    val curLocalInfo = new util.ScopedVar[CollectLocalInfo]
    val curClassSym  = new util.ScopedVar[Symbol]
    val curMethodSym = new util.ScopedVar[Symbol]
    val curEnv       = new util.ScopedVar[Env]
    val curThis      = new util.ScopedVar[Val]

    override def run(): Unit = {
      scalaPrimitives.init()
      nirPrimitives.init()
      super.run()
    }

    override def apply(cunit: CompilationUnit): Unit = {
      def collectClassDefs(tree: Tree): List[ClassDef] = {
        tree match {
          case EmptyTree            => Nil
          case PackageDef(_, stats) => stats flatMap collectClassDefs
          case cd: ClassDef         => cd :: Nil
        }
      }
      val classDefs = collectClassDefs(cunit.body)

      classDefs.foreach { cd =>
        val sym = cd.symbol
        if (isPrimitiveValueClass(sym) || (sym == ArrayClass)) ()
        else {
          val defn =
            if (isStruct(cd.symbol)) genStruct(cd)
            else genClass(cd)

          genIRFile(cunit, sym, defn)
        }
      }
    }

    def genStruct(cd: ClassDef): Seq[Defn] =
      scoped(
          curClassSym := cd.symbol
      ) {
        val sym = cd.symbol

        val attrs   = genStructAttrs(sym)<commit_msg>Add support for lazy anonymous definition to nscplugin<commit_after>package scala.scalanative
package nscplugin

import scala.collection.mutable
import scala.tools.nsc.{util => _, _}
import scala.tools.nsc.plugins._
import scala.util.{Either, Left, Right}
import scala.reflect.internal.Flags._
import util._, util.ScopedVar.scoped
import nir.Focus, Focus.sequenced
import nir._, Shows._
import NirPrimitives._

abstract class NirCodeGen
    extends PluginComponent
    with NirFiles
    with NirTypeEncoding
    with NirNameEncoding {
  val nirAddons: NirGlobalAddons {
    val global: NirCodeGen.this.global.type
  }

  import global._
  import definitions._
  import treeInfo.hasSynthCaseSymbol
  import nirAddons._
  import nirDefinitions._

  val phaseName = "nir"

  override def newPhase(prev: Phase): StdPhase =
    new SaltyCodePhase(prev)

  case class ValTree(val value: nir.Val) extends Tree

  class Env(val fresh: Fresh) {
    private val env = mutable.Map.empty[Symbol, Val]

    def enter(sym: Symbol, value: Val): Unit =
      env += ((sym, value))

    def enterLabel(ld: LabelDef): Local = {
      val local = fresh()
      enter(ld.symbol, Val.Local(local, Type.Ptr))
      local
    }

    def resolve(sym: Symbol): Val = env(sym)

    def resolveLabel(ld: LabelDef): Local = {
      val Val.Local(n, Type.Ptr) = resolve(ld.symbol)
      n
    }
  }

  class CollectLocalInfo extends Traverser {
    var mutableVars = Set.empty[Symbol]
    var labels      = Set.empty[LabelDef]

    override def traverse(tree: Tree) = {
      tree match {
        case label: LabelDef =>
          labels += label
        case Assign(id @ Ident(_), _) =>
          mutableVars += id.symbol
        case _ =>
          ()
      }
      super.traverse(tree)
    }

    def collect(tree: Tree) = {
      traverse(tree)
      this
    }
  }

  class SaltyCodePhase(prev: Phase) extends StdPhase(prev) {
    private val curLocalInfo = new util.ScopedVar[CollectLocalInfo]
    private val curClassSym  = new util.ScopedVar[Symbol]
    private val curMethodSym = new util.ScopedVar[Symbol]
    private val curEnv       = new util.ScopedVar[Env]
    private val curThis      = new util.ScopedVar[Val]

    private val lazyAnonDefs = mutable.Map.empty[Symbol, ClassDef]

    private def consumeLazyAnonDef(sym: Symbol) = {
      lazyAnonDefs
        .get(sym)
        .fold {
          sys.error(s"Couldn't find anon def for $sym")
        } { cd =>
          lazyAnonDefs.remove(cd.symbol)
          cd
        }
    }

    override def run(): Unit = {
      scalaPrimitives.init()
      nirPrimitives.init()
      super.run()
    }

    override def apply(cunit: CompilationUnit): Unit = {
      try {
        def collectClassDefs(tree: Tree): List[ClassDef] = {
          tree match {
            case EmptyTree            => Nil
            case PackageDef(_, stats) => stats flatMap collectClassDefs
            case cd: ClassDef         => cd :: Nil
          }
        }

        val (anonDefs, classDefs) = collectClassDefs(cunit.body).partition {
          cd =>
            cd.symbol.isAnonymousFunction
        }

        lazyAnonDefs ++= anonDefs.map(cd => cd.symbol -> cd)

        val nirDefns = mutable.UnrolledBuffer.empty[(Symbol, Seq[nir.Defn])]

        classDefs.foreach { cd =>
          val sym = cd.symbol

          if (isPrimitiveValueClass(sym) || (sym == ArrayClass)) {
            ()
          } else if (isStruct(cd.symbol)) {
            nirDefns += cd.symbol -> genStruct(cd)
          } else {
            nirDefns += cd.symbol -> genClass(cd)
          }
        }

        lazyAnonDefs.foreach {
          case (sym, cd) =>
            nirDefns += sym -> genClass(cd)
        }

        nirDefns.foreach {
          case (sym, defn) =>
            genIRFile(cunit, sym, defn)
        }
      } finally {
        lazyAnonDefs.clear()
      }
    }

    def genStruct(cd: ClassDef): Seq[Defn] =
      scoped(
          curClassSym := cd.symbol
      ) {
        val sym = cd.symbol

        val attrs   = genStructAttrs(sym)
{'fraction_non_alphanumeric': 0.10193494111048794, 'fraction_numerical': 0.0, 'mean_word_length': 2.229062924400181, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 28, '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': '6440985', 'n_tokens_mistral': 2289, 'n_tokens_neox': 2233, 'n_words': 539}