//
// Copyright (c) 2006, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   26 Dec 05  Brian Frank  Creation
//    5 Jun 06  Brian Frank  Ported from Java to Fan
//

**
** ResolveDepends resolves each dependency to a CPod and
** checks the version.  We also set CNamespace.depends in
** this step.
**
class ResolveDepends : CompilerStep
{

//////////////////////////////////////////////////////////////////////////
// Construction
//////////////////////////////////////////////////////////////////////////

  **
  ** Constructor takes the associated Compiler
  **
  new make(Compiler compiler)
    : super(compiler)
  {
    loc = compiler.input.inputLoc
  }

//////////////////////////////////////////////////////////////////////////
// Methods
//////////////////////////////////////////////////////////////////////////

  **
  ** Run the step
  **
  override Void run()
  {
    log.debug("ResolveDepends")

    // if the input has no dependencies, then
    // assume a dependency on sys
    input := compiler.input
    myName := input.podName
    isSys := myName == "sys"
    if (compiler.depends.isEmpty && !isSys)
      compiler.depends.add(CDepend.fromStr("sys 0+"))

    // we initialize the CNamespace.depends map
    // as we process each dependency
    ns.depends = Str:CDepend[:]

    // process each dependency
    compiler.depends.each |cdepend|
    {
      ns.depends[cdepend.name] = cdepend
      cdepend.pod = resolveDepend(cdepend.depend)
    }

    // check that everything has a dependency on sys
    if (!ns.depends.containsKey("sys") && !isSys)
      err("All pods must have a dependency on 'sys'", loc)

    bombIfErr

    // now that we've resolved all depends, ensure there are no
    // cyclic dependencies; this means that none of my dependent
    // pods should have a cyclic dependency back on me
    ns.depends.each |myDepend|
    {
      if (myDepend.name == myName) err("Cyclic dependency on self '$myName'", loc)
      myDepend.pod.depends.each |podDepend|
      {
        if (podDepend.name == myName)
          err("Cyclic dependency on '$myDepend.name'", loc)
      }
    }

    bombIfErr
  }

  **
  ** Resolve the dependency via reflection using
  ** the pods the compiler is running against.
  **
  private CPod? resolveDepend(Depend depend)
  {
    CPod? pod
    try
    {
      pod = ns.resolvePod(depend.name, loc)
    }
    catch (CompilerErr e)
    {
      err("Cannot resolve depend: pod '$depend.name' not found", loc)
      return null
    }

    if (!depend.match(pod.version))
    {
      err("Cannot resolve depend: '$pod.name $pod.version' != '$depend'", loc)
    }

    return pod
  }

//////////////////////////////////////////////////////////////////////////
// Fields
//////////////////////////////////////////////////////////////////////////

  Loc loc

}