<commit_before>package exploration

import scala.collection.Seq
import ir._
import opencl.ir._

/*class Derivations(val f: Fun, val c: Constraints) {
  
  private def vfn(f: Fun, s: Seq[Seq[Fun]]): Seq[Seq[Fun]] = {
      val outDerivs = Rules.outerDerivations(f, c)
      s :+ outDerivs
    }
  private val derivs = Fun.visit(Seq(Seq[Fun]()))(f, vfn)
    
  def getAll() : Seq[Fun] {
    listPossiblities[T](oriList : Seq[T], optionsList : Seq[Seq[T]]) : Seq[Seq[T]]
  }
  
  def getRandom() : Fun {
    
  }
  
}*/

object Rules {
   
  
  /*private def derivsWithOneRule(fp: FPattern, c: Constraints): Seq[Fun] = {
    outerDerivations(fp,c) ++ Rules.innerDerivations(fp,c)
  }*/
  
  private def composedDerivations(cf: CompFun, c: Constraints, level: Int): Seq[Fun] = {

    val optionsList = cf.funs.map(f => derivsWithOneRule(f,c, level))
    Utils.listPossiblities(cf.funs, optionsList).map(funs => new CompFun(funs: _*))
    
    /*val pairs = cf.getFuns().zip(cf.getFuns.tail)
      val pairDerivs = pairs.map({case (x, y) => pairDeriv(x,y)})      
      val numPairDerivs = pairDerivs.foldLeft(0)((num,l) => num+l.length)*/
  }
   
   private def innerDerivations(fpat: FPattern, c: Constraints, level: Int): Seq[Fun] = {
     derivsWithOneRule(fpat.f, c,level).map((f) => fpat.getClass().getConstructor(classOf[Fun]).newInstance(f))        
  }
    
    
  /*
   * Return a list of all possible derivations using only one rule at a given level
   */
  def derivsWithOneRule(f: Fun, c: Constraints, level: Int): Seq[Fun] =  {
      f match {
        case cf: CompFun => composedDerivations(cf, c, level)
        case fp: FPattern if (level==0) => outerDerivations(fp,c)
        case fp: FPattern if (level>0) => innerDerivations(fp,c,level-1)
        case p: Pattern if (level==0)  => outerDerivations(p, c)
        case _ => List()
      }     
  } 


  private def validOSplitRange(t: Type) = {
    t match {
      case ArrayType(_, len) => RangeMul(Cst(1), len, Cst(2))
      case _ => RangeUnkown // Error
    }
  }
 

  def outerDerivations(f: Fun, c: Constraints): Seq[Fun] = {   
    
    f match {

      case Map(inF) => {
        var result = List[Fun]()
        
        // sequential
        if (!f.context.inSeq && (f.context.inMapGlb || f.context.inMapLcl))
        	result = result :+ MapSeq(inF.copy())
        	
        // global, workgroup
        if (f.context.mapDepth == 0 && !f.context.inMapGlb && !f.context.inMapWrg) {
          result = result :+ MapGlb(inF.copy())
          result = result :+ MapWrg(inF.copy())
        }
        
        // local
        if (f.context.mapDepth == 1 && f.context.inMapWrg && !f.context.inMapGlb && !f.context.inMapLcl) {
          result = result :+ MapLcl(inF.copy())
        }
        
        // split-join
        if (f.context.mapDepth+1 < c.maxMapDepth && !c.converge)          
          result = result :+ new CompFun(Join(), Map(Map(inF.copy())), Split(Var(validOSplitRange(f.inT))))
        
        result
      }     
      
      case Reduce(inF) => {
        var result = List[Fun]()
        if (!c.converge)
        	result = result :+ (Reduce(inF.copy()) o PartRed(inF.copy()))
        	
        if (/*!f.context.inSeq &&*/ (f.context.inMapGlb || f.context.inMapLcl))
        	result = result :+ ReduceSeq(inF.copy())

        if (!f.context.inMapGlb && !f.context.inMapLcl && !f.context.inMapWrg)
          result = result :+ ReduceHost(inF.copy())
        	
        result
      }
      <commit_msg>added constraint to avoid having reduce-seq inside map-seq<commit_after>package exploration

import scala.collection.Seq
import ir._
import opencl.ir._

/*class Derivations(val f: Fun, val c: Constraints) {
  
  private def vfn(f: Fun, s: Seq[Seq[Fun]]): Seq[Seq[Fun]] = {
      val outDerivs = Rules.outerDerivations(f, c)
      s :+ outDerivs
    }
  private val derivs = Fun.visit(Seq(Seq[Fun]()))(f, vfn)
    
  def getAll() : Seq[Fun] {
    listPossiblities[T](oriList : Seq[T], optionsList : Seq[Seq[T]]) : Seq[Seq[T]]
  }
  
  def getRandom() : Fun {
    
  }
  
}*/

object Rules {
   
  
  /*private def derivsWithOneRule(fp: FPattern, c: Constraints): Seq[Fun] = {
    outerDerivations(fp,c) ++ Rules.innerDerivations(fp,c)
  }*/
  
  private def composedDerivations(cf: CompFun, c: Constraints, level: Int): Seq[Fun] = {

    val optionsList = cf.funs.map(f => derivsWithOneRule(f,c, level))
    Utils.listPossiblities(cf.funs, optionsList).map(funs => new CompFun(funs: _*))
    
    /*val pairs = cf.getFuns().zip(cf.getFuns.tail)
      val pairDerivs = pairs.map({case (x, y) => pairDeriv(x,y)})      
      val numPairDerivs = pairDerivs.foldLeft(0)((num,l) => num+l.length)*/
  }
   
   private def innerDerivations(fpat: FPattern, c: Constraints, level: Int): Seq[Fun] = {
     derivsWithOneRule(fpat.f, c,level).map((f) => fpat.getClass().getConstructor(classOf[Fun]).newInstance(f))        
  }
    
    
  /*
   * Return a list of all possible derivations using only one rule at a given level
   */
  def derivsWithOneRule(f: Fun, c: Constraints, level: Int): Seq[Fun] =  {
      f match {
        case cf: CompFun => composedDerivations(cf, c, level)
        case fp: FPattern if (level==0) => outerDerivations(fp,c)
        case fp: FPattern if (level>0) => innerDerivations(fp,c,level-1)
        case p: Pattern if (level==0)  => outerDerivations(p, c)
        case _ => List()
      }     
  } 


  private def validOSplitRange(t: Type) = {
    t match {
      case ArrayType(_, len) => RangeMul(Cst(1), len, Cst(2))
      case _ => RangeUnkown // Error
    }
  }
 

  def outerDerivations(f: Fun, c: Constraints): Seq[Fun] = {   
    
    f match {

      case Map(inF) => {
        var result = List[Fun]()
        
        // sequential
        if (!f.context.inSeq && (f.context.inMapGlb || f.context.inMapLcl))
        	result = result :+ MapSeq(inF.copy())
        	
        // global, workgroup
        if (f.context.mapDepth == 0 && !f.context.inMapGlb && !f.context.inMapWrg) {
          result = result :+ MapGlb(inF.copy())
          result = result :+ MapWrg(inF.copy())
        }
        
        // local
        if (f.context.mapDepth == 1 && f.context.inMapWrg && !f.context.inMapGlb && !f.context.inMapLcl) {
          result = result :+ MapLcl(inF.copy())
        }
        
        // split-join
        if (f.context.mapDepth+1 < c.maxMapDepth && !c.converge)          
          result = result :+ new CompFun(Join(), Map(Map(inF.copy())), Split(Var(validOSplitRange(f.inT))))
        
        result
      }     
      
      case Reduce(inF) => {
        var result = List[Fun]()
        if (!c.converge)
        	result = result :+ (Reduce(inF.copy()) o PartRed(inF.copy()))
        	
        if (!f.context.inSeq && (f.context.inMapGlb || f.context.inMapLcl))
        	result = result :+ ReduceSeq(inF.copy())

        if (!f.context.inMapGlb && !f.context.inMapLcl && !f.context.inMapWrg)
          result = result :+ ReduceHost(inF.copy())
        	
        result
      }
      
{'fraction_non_alphanumeric': 0.15500783587405614, 'fraction_numerical': 0.0028494087476848553, 'mean_word_length': 2.34604385128694, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 33, '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': '6245929', 'n_tokens_mistral': 2570, 'n_tokens_neox': 2553, 'n_words': 503}