//
// 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
}