/**
 * Implosion of AsFix injections.
 *
 * Injections are nodes in a tree with a single child. Such nodes
 * can be ignored if they only relate syntactic information
 * instead of structural information. For instance, bracket nodes
 * are only necessary for syntactic purposes.
 */
module stratego/asfix/implode/injection
rules

  ImplodeInjection : 
    appl(p, [t]) -> t
    where
      <is-injection> p

  /**
   * Injection of a literal to a sort.
   */
  ImplodeInjection : 
    appl(prod([lit(x)], sym, attrs), []) -> x
    where
      <asfix-is-sort + cf(asfix-is-sort)> sym
      ; <not(oncetd(cons(id)))> attrs

  /**
   * Injection of a case insensitive literal to a sort.
   */
  ImplodeInjection : 
    appl(prod([cilit(x)], sym, attrs), []) -> x
    where
      <asfix-is-sort + cf(asfix-is-sort)> sym
      ; <not(oncetd(cons(id)))> attrs

strategies

  is-injection = 
    ?prod(_, sort(""), _)

  /**
   * @todo Improve the bracket detection.
   */
  is-injection = 
    prod(id, id, oncetd("bracket" + bracket))

  is-injection = 
    ?prod([cf(iter(x))],cf(iter-star(x)), attrs)
    ; where(<not(oncetd(cons(id)))> attrs)

  is-injection = 
    ?prod([cf(iter-sep(x,l))],cf(iter-star-sep(x,l)), attrs)
    ; where(<not(oncetd(cons(id)))> attrs)    

  is-injection = 
    prod([not(lit(id))]
	 ,rec x(asfix-is-sort + cf(x) + lex(x) 
		+ iter(x) + iter-star(x) 
		+ iter-sep(x,lit(id)) + iter-star-sep(x,lit(id)))
	, not(oncetd(cons(id))))

  is-injection =
    prod(
      [asfix-is-sort + cf(asfix-is-sort)]
    , is-injective-alt
    , not(oncetd(cons(id)))
    )

  is-injection = 
    prod([varsym(id)],id,not(oncetd(cons(id))))

  is-injective-alt = 
    rec x(asfix-is-sort + cf(x) + alt(x,x))

  asfix-is-sort =
    sort(id) + parameterized-sort(id, map(asfix-is-sort))