/**
 * @author Merijn de Jonge (mdjonge@cwi.nl)
 */
module stratego/gpp/Instantiate
rules

  gpp-instantiate =
    ?(template, args)
    ; <gpp-instantiate(|args)> template

  gpp-instantiate(|args) =
    bottomup(
      try(
        ?Arg(_); gpp-Instantiate(|args)
      + ?Arg2(_, _); gpp-Instantiate(|args)
      + ?[_|_]; gpp-flat-list
      )
    )
   
  gpp-Instantiate(|args) =
    gpp-FastInstantiate(|args) <+ gpp-SlowInstantiate(|args)
    
  gpp-FastInstantiate(|args) :
    Arg(1) -> a
    where
      !args => [a | _]
      
  gpp-FastInstantiate(|args) :
    Arg(2) -> a
    where
      !args => [_, a | _]
      
  gpp-FastInstantiate(|args) :
    Arg(3) -> a
    where
      !args => [_, _, a | _]

  gpp-SlowInstantiate(|args) :
    Arg(n) -> <index(|n)> args

  gpp-SlowInstantiate(|args) :
    Arg2(n, m) -> <index(|m)> list
    where
      <index(|n)> args => list

strategies

  gpp-instantiate-list(|pp-entry) =
    rec rec(
      {sym,xs:
         []
      <+ ?[sym|xs]
         ; [<gpp-instantiate(|[sym])> pp-entry | <rec> xs ]
      }
    )
  
  gpp-instantiate-sep-list(|pp-entry) =
    rec rec(
      {sym,sep,xs:
         []
      <+ ?[_]
      <+ ?[sym, sep | xs]
         ; [<gpp-instantiate(|[sym, sep])> pp-entry | <rec> xs ]
      }
    )