/**
 * 14.14.2: The enhanced for statement
 *
 * @author Lennart Kats <lennart add lclnet.nl>
 */
module dryad/type-check/stm/ForStatement
rules
      
  /**
   * Define the type of and conversions for a local variable declared in
   * an enhanced for loop.
   */      
  dryad-tc-foreach(rec) =
    ?ForEach(_, _, _)
  
    ; {| TypeOf :
        ForEach(id, rec, id)
        ; ForEach(dryad-tc-declare-param, id, rec)
      |}
    
    ; try(dryad-tc-foreach-add-conversion(rec))
  
  /**
   * The foreach is defined as a desugaring over the regular for;
   * do on-the-fly desugaring to determine the required conversion.
   */ 
  dryad-tc-foreach-add-conversion(rec) :
    ForEach(Param(mods, type, Id(x)),              list, body) ->
    ForEach(Param(mods, type, Id(x)) {conversion}, list, body)
    where
      rhs-type := <get-foreach-rhs-value; rec; type-attr>
      
    ; conversion := <assignment-conversion(|type)> rhs-type

/** @internal */
strategies

  get-foreach-rhs-value =
    ?ForEach(_, list, _)
    ; where(ArrayType(_) := <dryad-type-of> list)
    ; !ArrayAccess(list, Lit(Deci("0")))

  get-foreach-rhs-value =
    ?ForEach(_, list, _)
    ; where(
        <type-attr> list
      ; is-subtype(|TypeIterable())
      )
    
    ; !Invoke(Method(list, None(), Id("iterator")), [])
    ; !Invoke(Method(<id>, None(), Id("next")), [])