//===-- SourceLanguage-Unknown.cpp - Implement itf for unknown languages --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// If the LLVM debugger does not have a module for a particular language, it
// falls back on using this one to perform the source-language interface.  This
// interface is not wonderful, but it gets the job done.
//
//===----------------------------------------------------------------------===//

#include "llvm/Debugger/SourceLanguage.h"
#include "llvm/Debugger/ProgramInfo.h"
#include "llvm/Support/Streams.h"
#include <cassert>
#include <ostream>
using namespace llvm;

//===----------------------------------------------------------------------===//
// Implement the SourceLanguage cache for the Unknown language.
//

namespace {
  /// SLUCache - This cache allows for efficient lookup of source functions by
  /// name.
  ///
  struct SLUCache : public SourceLanguageCache {
    ProgramInfo &PI;
    std::multimap<std::string, SourceFunctionInfo*> FunctionMap;
  public:
    SLUCache(ProgramInfo &pi);

    typedef std::multimap<std::string, SourceFunctionInfo*>::const_iterator
       fm_iterator;

    std::pair<fm_iterator, fm_iterator>
    getFunction(const std::string &Name) const {
      return FunctionMap.equal_range(Name);
    }

    SourceFunctionInfo *addSourceFunction(SourceFunctionInfo *SF) {
      FunctionMap.insert(std::make_pair(SF->getSymbolicName(), SF));
      return SF;
    }
  };
}

SLUCache::SLUCache(ProgramInfo &pi) : PI(pi) {
}


//===----------------------------------------------------------------------===//
// Implement SourceLanguageUnknown class, which is used to handle unrecognized
// languages.
//

namespace {
  struct SLU : public SourceLanguage {
    //===------------------------------------------------------------------===//
    // Implement the miscellaneous methods...
    //
    virtual const char *getSourceLanguageName() const {
      return "unknown";
    }

    /// lookupFunction - Given a textual function name, return the
    /// SourceFunctionInfo descriptor for that function, or null if it cannot be
    /// found.  If the program is currently running, the RuntimeInfo object
    /// provides information about the current evaluation context, otherwise it
    /// will be null.
    ///
    virtual SourceFunctionInfo *lookupFunction(const std::string &FunctionName,
                                               ProgramInfo &PI,
                                               RuntimeInfo *RI = 0) const;

    //===------------------------------------------------------------------===//
    // We do use a cache for information...
    //
    typedef SLUCache CacheType;
    SLUCache *createSourceLanguageCache(ProgramInfo &PI) const {
      return new SLUCache(PI);
    }

    /// createSourceFunctionInfo - Create the new object and inform the cache of
    /// the new function.
    virtual SourceFunctionInfo *
    createSourceFunctionInfo(const GlobalVariable *Desc, ProgramInfo &PI) const;

  } TheUnknownSourceLanguageInstance;
}

const SourceLanguage &SourceLanguage::getUnknownLanguageInstance() {
  return TheUnknownSourceLanguageInstance;
}


SourceFunctionInfo *
SLU::createSourceFunctionInfo(const GlobalVariable *Desc,
                              ProgramInfo &PI) const {
  SourceFunctionInfo *Result = new SourceFunctionInfo(PI, Desc);
  return PI.getLanguageCache(this).addSourceFunction(Result);
}


/// lookupFunction - Given a textual function name, return the
/// SourceFunctionInfo descriptor for that function, or null if it cannot be
/// found.  If the program is currently running, the RuntimeInfo object
/// provides information about the current evaluation context, otherwise it will
/// be null.
///
SourceFunctionInfo *SLU::lookupFunction(const std::string &FunctionName,
                                        ProgramInfo &PI, RuntimeInfo *RI) const{
  SLUCache &Cache = PI.getLanguageCache(this);
  std::pair<SLUCache::fm_iterator, SLUCache::fm_iterator> IP
    = Cache.getFunction(FunctionName);

  if (IP.first == IP.second) {
    if (PI.allSourceFunctionsRead())
      return 0;  // Nothing found

    // Otherwise, we might be able to find the function if we read all of them
    // in.  Do so now.
    PI.getSourceFunctions();
    assert(PI.allSourceFunctionsRead() && "Didn't read in all functions?");
    return lookupFunction(FunctionName, PI, RI);
  }

  SourceFunctionInfo *Found = IP.first->second;
  ++IP.first;
  if (IP.first != IP.second)
    cout << "Whoa, found multiple functions with the same name.  I should"
         << " ask the user which one to use: FIXME!\n";
  return Found;
}
