<commit_before>/*
 * Copyright © 2014 <NAME> (<EMAIL>)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.emmalanguage
package compiler.lang.core

import compiler.Common

/** Dead code elimination (DCE) for the Core language. */
private[core] trait DCE extends Common {
  self: Core =>

  import UniverseImplicits._
  import Core.{Lang => core}

  private[core] object DCE {

    /**
     * Eliminates unused value definitions (dead code) from a tree.
     *
     * == Preconditions ==
     * - The input tree is in LNF (see [[Core.lnf]]).
     *
     * == Postconditions ==
     * - All unused value definitions are pruned.
     */
    lazy val transform: u.Tree => u.Tree =
      api.BottomUp.withValUses.transformWithSyn {
        case Attr(let @ core.Let(vals, defs, expr), _, _, syn) =>
          def refs(tree: u.Tree) = syn(tree).head.keySet
          val liveRefs = vals.foldRight(refs(expr)) {
            case (core.ValDef(lhs, rhs, _), live) =>
              if (live(lhs)) live | refs(rhs) else live
          }

          val liveVals = vals.filter(liveRefs compose api.TermSym.of)
          if (liveVals.size == vals.size) let
          else core.Let(liveVals: _*)(defs: _*)(expr)
      }.andThen(_.tree)
  }
}<commit_msg>[IR] Fixed DCE to also look in DefDefs.<commit_after>/*
 * Copyright © 2014 <NAME> (em<EMAIL>)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.emmalanguage
package compiler.lang.core

import compiler.Common

import scala.collection.breakOut

/** Dead code elimination (DCE) for the Core language. */
private[core] trait DCE extends Common {
  self: Core =>

  import UniverseImplicits._
  import Core.{Lang => core}

  private[core] object DCE {

    /**
     * Eliminates unused value definitions (dead code) from a tree.
     *
     * == Preconditions ==
     * - The input tree is in LNF (see [[Core.lnf]]).
     *
     * == Postconditions ==
     * - All unused value definitions are pruned.
     */
    lazy val transform: u.Tree => u.Tree =
      api.BottomUp.withValUses.transformWithSyn {
        case Attr(let @ core.Let(vals, defs, expr), _, _, syn) =>
          def refs(tree: u.Tree) = syn(tree).head.keySet

          // Gather refs in DefDefs.
          val refsInDefs: Set[u.TermSymbol] = defs.flatMap(refs)(breakOut)

          // Decide for each ValDef whether it is needed.
          // Start with the refs in the expr and refs in the DefDefs, then go through the ValDefs backwards.
          val liveRefs = vals.foldRight(refs(expr) | refsInDefs) {
            case (core.ValDef(lhs, rhs, _), live) =>
              if (live(lhs)) live | refs(rhs) else live
          }

          // Retain only those ValDefs which are referenced.
          val liveVals = vals.filter(liveRefs compose api.TermSym.of)
          if (liveVals.size == vals.size) let
          else core.Let(liveVals: _*)(defs: _*)(expr)
      }.andThen(_.tree)
  }
}
{'fraction_non_alphanumeric': 0.1085133418043202, 'fraction_numerical': 0.004066073697585769, 'mean_word_length': 2.6785046728971964, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 17, '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': '4443666', 'n_tokens_mistral': 1201, 'n_tokens_neox': 1166, 'n_words': 413}