Exemple #1
0
Parser::Parser(std::unique_ptr<Lexer> Lex, SourceFile &SF,
               SILParserState *SIL, PersistentParserState *PersistentState)
  : SourceMgr(SF.getASTContext().SourceMgr),
    Diags(SF.getASTContext().Diags),
    SF(SF),
    L(Lex.release()),
    SIL(SIL),
    CurDeclContext(&SF),
    Context(SF.getASTContext()) {

  State = PersistentState;
  if (!State) {
    OwnedState.reset(new PersistentParserState());
    State = OwnedState.get();
  }

  // Set the token to a sentinel so that we know the lexer isn't primed yet.
  // This cannot be tok::unknown, since that is a token the lexer could produce.
  Tok.setKind(tok::NUM_TOKENS);

  auto ParserPos = State->takeParserPosition();
  if (ParserPos.isValid() &&
      SourceMgr.findBufferContainingLoc(ParserPos.Loc) == L->getBufferID()) {
    auto BeginParserPosition = getParserPosition(ParserPos);
    restoreParserPosition(BeginParserPosition);
    InPoundLineEnvironment = State->InPoundLineEnvironment;
  }
}
Exemple #2
0
bool KJSDebugWin::sourceUnused(KJS::ExecState *exec, int sourceId)
{
    // Verify that there aren't any contexts on the stack using the given sourceId
    // This should never be the case because this function is only called when
    // the interpreter has deleted all Node objects for the source.
    for(int e = 0; e < m_execsCount; e++)
        assert(m_execs[e]->context().sourceId() != sourceId);

    // Now remove the fragment (and the SourceFile, if it was the last fragment in that file)
    SourceFragment *fragment = m_sourceFragments[sourceId];
    if(fragment)
    {
        m_sourceFragments.erase(sourceId);

        SourceFile *sourceFile = fragment->sourceFile;
        if(sourceFile->hasOneRef())
        {
            for(int i = 0; i < m_sourceSel->count(); i++)
            {
                if(m_sourceSelFiles.at(i) == sourceFile)
                {
                    m_sourceSel->removeItem(i);
                    m_sourceSelFiles.remove(i);
                    break;
                }
            }
            removeSourceFile(exec->interpreter(), sourceFile->url);
        }
        delete fragment;
    }

    return (m_mode != Stop);
}
Exemple #3
0
Parser::Parser(std::unique_ptr<Lexer> Lex, SourceFile &SF,
               SILParserTUStateBase *SIL,
               PersistentParserState *PersistentState)
  : SourceMgr(SF.getASTContext().SourceMgr),
    Diags(SF.getASTContext().Diags),
    SF(SF),
    L(Lex.release()),
    SIL(SIL),
    CurDeclContext(&SF),
    Context(SF.getASTContext()),
    TokReceiver(SF.shouldKeepSyntaxInfo() ?
                new TokenRecorder(SF) :
                new ConsumeTokenReceiver()),
    SyntaxContext(new SyntaxParsingContext(SyntaxContext, SF, Diags, SourceMgr,
                                           L->getBufferID())) {
  State = PersistentState;
  if (!State) {
    OwnedState.reset(new PersistentParserState());
    State = OwnedState.get();
  }

  // Set the token to a sentinel so that we know the lexer isn't primed yet.
  // This cannot be tok::unknown, since that is a token the lexer could produce.
  Tok.setKind(tok::NUM_TOKENS);

  auto ParserPos = State->takeParserPosition();
  if (ParserPos.isValid() &&
      L->isStateForCurrentBuffer(ParserPos.LS)) {
    restoreParserPosition(ParserPos);
    InPoundLineEnvironment = State->InPoundLineEnvironment;
  }
}
Exemple #4
0
bool MainWindow::memoryOpen(const QByteArray& ba, const QString& assocPath)
{
	QFileInfo fileInfo(assocPath);

	if(!fileInfo.isFile() || !fileInfo.isReadable()) return false;

	for(int i = 0; i < ui_tabWidget->count(); ++i) {
		SourceFile* sourceFile = dynamic_cast<SourceFile*>(ui_tabWidget->widget(i));
		if(sourceFile && sourceFile->associatedFile() == assocPath) {
			ui_tabWidget->setCurrentIndex(i);
			on_ui_tabWidget_currentChanged(i);
			return true;
		}
	}
	
	/* Attempt to open the selected file */
	SourceFile *sourceFile = new SourceFile(this);
	if(!sourceFile->memoryOpen(ba, assocPath)) {
		MessageDialog::showError(this, "simple_error", QStringList() <<
			tr("Could not open ") + sourceFile->associatedFileName() <<
			tr("Unable to open file from memory."));
		delete sourceFile;
		return false;
	}	

	addTab(sourceFile);
	
	UiEventManager::ref().sendEvent(UI_EVENT_OPEN_FILE);

	hideProjectDock();

	return true;
}
/// getInfixData - If the specified expression is an infix binary
/// operator, return its infix operator attributes.
static InfixData getInfixData(TypeChecker &TC, DeclContext *DC, Expr *E) {
  if (auto *ifExpr = dyn_cast<IfExpr>(E)) {
    // Ternary has fixed precedence.
    assert(!ifExpr->isFolded() && "already folded if expr in sequence?!");
    (void)ifExpr;
    return InfixData(IntrinsicPrecedences::IfExpr,
                     Associativity::Right,
                     /*assignment*/ false);

  }

  if (auto *assign = dyn_cast<AssignExpr>(E)) {
    // Assignment has fixed precedence.
    assert(!assign->isFolded() && "already folded assign expr in sequence?!");
    (void)assign;
    return InfixData(IntrinsicPrecedences::AssignExpr,
                     Associativity::Right,
                     /*assignment*/ true);

  }

  if (auto *as = dyn_cast<ExplicitCastExpr>(E)) {
    // 'as' and 'is' casts have fixed precedence.
    assert(!as->isFolded() && "already folded 'as' expr in sequence?!");
    (void)as;
    return InfixData(IntrinsicPrecedences::ExplicitCastExpr,
                     Associativity::None,
                     /*assignment*/ false);

  }

  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
    SourceFile *SF = DC->getParentSourceFile();
    Identifier name = DRE->getDecl()->getName();
    bool isCascading = DC->isCascadingContextForLookup(true);
    if (InfixOperatorDecl *op = SF->lookupInfixOperator(name, isCascading,
                                                        E->getLoc()))
      return op->getInfixData();

  }

  if (OverloadedDeclRefExpr *OO = dyn_cast<OverloadedDeclRefExpr>(E)) {
    SourceFile *SF = DC->getParentSourceFile();
    Identifier name = OO->getDecls()[0]->getName();
    bool isCascading = DC->isCascadingContextForLookup(true);
    if (InfixOperatorDecl *op = SF->lookupInfixOperator(name, isCascading,
                                                        E->getLoc()))
      return op->getInfixData();
  }

  // If E is already an ErrorExpr, then we've diagnosed it as invalid already,
  // otherwise emit an error.
  if (!isa<ErrorExpr>(E))
    TC.diagnose(E->getLoc(), diag::unknown_binop);

  // Recover with an infinite-precedence left-associative operator.
  return InfixData((unsigned char)~0U, Associativity::Left,
                   /*assignment*/ false);
}
Exemple #6
0
Parser::Parser(unsigned BufferID, SourceFile &SF, SILParserState *SIL,
               PersistentParserState *PersistentState)
  : Parser(std::unique_ptr<Lexer>(
             new Lexer(SF.getASTContext().LangOpts, SF.getASTContext().SourceMgr,
                   BufferID, &SF.getASTContext().Diags,
                   /*InSILMode=*/SIL != nullptr,
                   SF.getASTContext().LangOpts.AttachCommentsToDecls
                   ? CommentRetentionMode::AttachToNextToken
                   : CommentRetentionMode::None)), SF, SIL, PersistentState) {
}
Exemple #7
0
static PrecedenceGroupDecl *
lookupPrecedenceGroupForOperator(TypeChecker &TC, DeclContext *DC,
                                 Identifier name, SourceLoc loc) {
  SourceFile *SF = DC->getParentSourceFile();
  bool isCascading = DC->isCascadingContextForLookup(true);
  if (auto op = SF->lookupInfixOperator(name, isCascading, loc)) {
    TC.validateDecl(op);
    return op->getPrecedenceGroup();
  } else {
    TC.diagnose(loc, diag::unknown_binop);
  }
  return nullptr;
}
Exemple #8
0
bool
Project::HasLibrary(const char *path)
{
	if (!path)
		return false;
	
	for (int32 i = 0; i < fLibraryList.CountItems(); i++)
	{
		SourceFile *file = (SourceFile*)fLibraryList.ItemAt(i);
		if (file && strcmp(file->GetPath().GetFullPath(),path) == 0)
			return true;
	}
	return false;
}
Exemple #9
0
Parser::Parser(unsigned BufferID, SourceFile &SF, SILParserTUStateBase *SIL,
               PersistentParserState *PersistentState)
    : Parser(
          std::unique_ptr<Lexer>(new Lexer(
              SF.getASTContext().LangOpts, SF.getASTContext().SourceMgr,
              BufferID, &SF.getASTContext().Diags,
              /*InSILMode=*/SIL != nullptr,
              SF.getASTContext().LangOpts.AttachCommentsToDecls
                  ? CommentRetentionMode::AttachToNextToken
                  : CommentRetentionMode::None,
              SF.shouldKeepSyntaxInfo()
                  ? TriviaRetentionMode::WithTrivia
                  : TriviaRetentionMode::WithoutTrivia)),
          SF, SIL, PersistentState) {}
Exemple #10
0
void DesignerProjectImpl::breakPoints( QMap<QString, QValueList<uint> > &bps ) const
{
    MainWindow::self->saveAllBreakPoints();
    for ( QPtrListIterator<SourceFile> sources = project->sourceFiles();
	  sources.current(); ++sources ) {
	SourceFile* f = sources.current();
	bps.insert( project->makeRelative( f->fileName() ) + " <Source-File>", MetaDataBase::breakPoints( f ) );
    }
    for ( QPtrListIterator<FormFile> forms = project->formFiles();
	  forms.current(); ++forms ) {
	if ( forms.current()->formWindow() )
	    bps.insert( QString( forms.current()->formWindow()->name() ) + " <Form>", MetaDataBase::breakPoints( forms.current()->formWindow() ) );
    }
}
Exemple #11
0
status_t
FileManager::LoadSourceFile(LocatableFile* file, SourceFile*& _sourceFile)
{
	AutoLocker<FileManager> locker(this);

	// get the path
	BString path;
	BString originalPath;
	file->GetPath(originalPath);
	if (!file->GetLocatedPath(path)) {
		// see if this is a file we have a lazy mapping for.
		if (!_LocateFileIfMapped(originalPath, file)
			|| !file->GetLocatedPath(path)) {
			return B_ENTRY_NOT_FOUND;
		}
	}

	// we might already know the source file
	SourceFileEntry* entry = _LookupSourceFile(originalPath);
	if (entry != NULL) {
		entry->file->AcquireReference();
		_sourceFile = entry->file;
		return B_OK;
	}

	// create the hash table entry
	entry = new(std::nothrow) SourceFileEntry(this, originalPath);
	if (entry == NULL)
		return B_NO_MEMORY;

	// load the file
	SourceFile* sourceFile = new(std::nothrow) SourceFile(entry);
	if (sourceFile == NULL) {
		delete entry;
		return B_NO_MEMORY;
	}
	ObjectDeleter<SourceFile> sourceFileDeleter(sourceFile);

	entry->file = sourceFile;

	status_t error = sourceFile->Init(path);
	if (error != B_OK)
		return error;

	fSourceFiles->Insert(entry);

	_sourceFile = sourceFileDeleter.Detach();
	return B_OK;
}
Exemple #12
0
void MainWindow::on_ui_addFile_clicked()
{
	Project* project = activeProject();
	if(!project) {
		MessageDialog::showError(this, "simple_error", QStringList() << 
			tr("Unable to determine active project.") <<
			tr("Please make sure that you have a project open."));
		return;
	} 
	
	SourceFile* source = new SourceFile(this);
	source->setAssociatedProject(project);
	addTab(source);
	// ui_projects->expandAll();
}
static void printUntilFirstDeclStarts(SourceFile &File, ASTPrinter &Printer) {
  if (!File.getBufferID().hasValue())
    return;
  auto BufferID = *File.getBufferID();

  auto &SM = File.getASTContext().SourceMgr;
  CharSourceRange TextRange = SM.getRangeForBuffer(BufferID);

  auto DeclStartLoc = getDeclStartPosition(File);
  if (DeclStartLoc.isValid()) {
    TextRange = CharSourceRange(SM, TextRange.getStart(), DeclStartLoc);
  }

  Printer << SM.extractText(TextRange, BufferID);
}
static SourceLoc getDeclStartPosition(SourceFile &File) {
  SourceManager &SM = File.getASTContext().SourceMgr;
  SourceLoc Winner;

  auto tryUpdateStart = [&](SourceLoc Loc) -> bool {
    if (Loc.isInvalid())
      return false;
    if (Winner.isInvalid()) {
      Winner = Loc;
      return true;
    }
    if (SM.isBeforeInBuffer(Loc, Winner)) {
      Winner = Loc;
      return true;
    }
    return false;
  };

  for (auto D : File.Decls) {
    if (tryUpdateStart(D->getStartLoc())) {
      tryUpdateStart(D->getAttrs().getStartLoc());
      auto RawComment = D->getRawComment();
      if (!RawComment.isEmpty())
        tryUpdateStart(RawComment.Comments.front().Range.getStart());
    }
  }

  return Winner;
}
Exemple #15
0
void
Project::ForceRebuild(void)
{
	STRACE(1,("%s: Force rebuild\n",GetName()));
	for (int32 i = 0; i < CountGroups(); i++)
	{
		SourceGroup *group = GroupAt(i);
		
		for (int32 j = 0; j < group->filelist.CountItems(); j++)
		{
			SourceFile *file = group->filelist.ItemAt(j);
			file->RemoveObjects(fBuildInfo);
		}
	}
	
}
Exemple #16
0
void swift::performWholeModuleTypeChecking(SourceFile &SF) {
  auto &Ctx = SF.getASTContext();
  Ctx.diagnoseAttrsRequiringFoundation(SF);
  Ctx.diagnoseObjCMethodConflicts(SF);
  Ctx.diagnoseObjCUnsatisfiedOptReqConflicts(SF);
  Ctx.diagnoseUnintendedObjCMethodOverrides(SF);
}
Exemple #17
0
void swift::finishTypeChecking(SourceFile &SF) {
  auto &Ctx = SF.getASTContext();
  TypeChecker TC(Ctx);

  for (auto D : SF.Decls)
    if (auto PD = dyn_cast<ProtocolDecl>(D))
      TC.inferDefaultWitnesses(PD);
}
void swift::ide::printSwiftSourceInterface(SourceFile &File,
                                           ASTPrinter &Printer,
                                           const PrintOptions &Options) {

  // We print all comments before the first line of Swift code.
  printUntilFirstDeclStarts(File, Printer);
  File.print(Printer, Options);
}
QString Project::locationOfObject( QObject *o )
{
    if ( !o )
	return QString::null;

    if ( MainWindow::self ) {
	QWidgetList windows = MainWindow::self->qWorkspace()->windowList();
	for ( QWidget *w = windows.first(); w; w = windows.next() ) {
	    FormWindow *fw = ::qt_cast<FormWindow*>(w);
	    SourceEditor *se = ::qt_cast<SourceEditor*>(w);
	    if ( fw ) {
		if ( fw->isFake() )
		    return objectForFakeForm( fw )->name() + QString( " [Source]" );
		else
		    return fw->name() + QString( " [Source]" );
	    } else if ( se ) {
		if ( !se->object() )
		    continue;
		if ( se->formWindow() )
		    return se->formWindow()->name() + QString( " [Source]" );
		else
		    return makeRelative( se->sourceFile()->fileName() );
	    }
	}
    }

    if ( ::qt_cast<SourceFile*>(o) ) {
	for ( QPtrListIterator<SourceFile> sources = sourceFiles();
	      sources.current(); ++sources ) {
	    SourceFile* f = sources.current();
	    if ( f == o )
		return makeRelative( f->fileName() );
	}
    }

    extern QMap<QWidget*, QString> *qwf_forms;
    if ( !qwf_forms ) {
	qWarning( "Project::locationOfObject: qwf_forms is NULL!" );
	return QString::null;
    }

    QString s = makeRelative( *qwf_forms->find( (QWidget*)o ) );
    s += " [Source]";
    return s;
}
Exemple #20
0
void
Project::RemoveLibrary(const char *path)
{
	if (!path)
		return;
	
	STRACE(1,("%s: Attempting to remove %s\n",GetName(),path));
	for (int32 i = 0; i < fLibraryList.CountItems(); i++)
	{
		SourceFile *file = (SourceFile*)fLibraryList.ItemAt(i);
		if (file && strcmp(file->GetPath().GetFullPath(),path) == 0)
		{
			STRACE(1,("%s: Removed %s\n",GetName(),path));
			fLibraryList.RemoveItemAt(i);
			delete file;
			return;
		}
	}
}
Exemple #21
0
SyntaxParsingContext::SyntaxParsingContext(SyntaxParsingContext *&CtxtHolder,
                                           SourceFile &SF,
                                           DiagnosticEngine &Diags,
                                           SourceManager &SourceMgr,
                                           unsigned BufferID)
    : RootDataOrParent(new RootContextData(SF, Diags, SourceMgr, BufferID)),
      CtxtHolder(CtxtHolder), Storage(getRootData().Storage), Offset(0),
      Mode(AccumulationMode::Root), Enabled(SF.shouldKeepSyntaxInfo()) {
  CtxtHolder = this;
}
Exemple #22
0
SourceFile *
Project::FindFile(const char *path)
{
	if (!path)
		return NULL;
	
	for (int32 i = 0; i < CountGroups(); i++)
	{
		SourceGroup *group = GroupAt(i);
		
		for (int32 j = 0; j < group->filelist.CountItems(); j++)
		{
			SourceFile *src = group->filelist.ItemAt(j);
			if (src && strcmp(src->GetPath().GetFullPath(),path) == 0)
				return src;
		}
	}
	return NULL;
}
Exemple #23
0
void
Project::UpdateResources(void)
{
	DPath targetpath(fPath.GetFolder());
	targetpath.Append(GetTargetName());
	
	BString resFileString;
	int32 resCount = 0;

	for (int32 i = 0; i < CountGroups(); i++)
	{
		SourceGroup *group = GroupAt(i);
		
		for (int32 j = 0; j < group->filelist.CountItems(); j++)
		{
			SourceFile *file = group->filelist.ItemAt(j);
			
			if (file->GetResourcePath(fBuildInfo).GetFullPath())
			{
				resFileString << "'" << file->GetResourcePath(fBuildInfo).GetFullPath() << "' ";
				resCount++;
			}
		}
	}
	
	if (resCount > 0)
	{
		BString resString = "xres -o ";
		resString << "'" << targetpath.GetFullPath() << "' " << resFileString;		
		BString errmsg;
		PipeCommand(resString.String(),errmsg);
		
		STRACE(1,("Resources for %s:\n%s\nErrors:%s\n",GetName(),resString.String(),errmsg.String()));
		
		if (errmsg.CountChars() > 0)
			printf("Resource errors: %s\n",errmsg.String());
	}
	else
	{
		STRACE(1,("Resources for %s: No resource files to add\n",GetName()));
	}
}
void GD_API CodeCompilationHelpers::CreateExternalSourceFileCompilationTask(gd::Project & game, SourceFile & file, gd::Layout * scene)
{
    CodeCompilerTask task;

    wxFileName inputFile(file.GetFileName());
    inputFile.MakeAbsolute(wxFileName::FileName(game.GetProjectFile()).GetPath());
    task.compilerCall.inputFile = ToString(inputFile.GetFullPath());
    task.compilerCall.outputFile = string(CodeCompiler::Get()->GetOutputDirectory()+"GD"+ToString(&file)+"ObjectFile.o");
    task.compilerCall.compilationForRuntime = false;
    task.compilerCall.optimize = false;
    task.compilerCall.eventsGeneratedCode = false;
    task.compilerCall.extraHeaderDirectories.push_back(ToString(wxFileName::FileName(game.GetProjectFile()).GetPath()));

    task.scene = scene;
    if ( scene ) task.postWork = std::shared_ptr<CodeCompilerExtraWork>(new SourceFileCodeCompilerPostWork(scene));

    task.userFriendlyName = "Compilation of file "+file.GetFileName();

    CodeCompiler::Get()->AddTask(task);
}
Exemple #25
0
bool
Project::HasFileName(const char *name)
{
	if (!name)
		return false;
	
	DPath newfile(name);
	
	for (int32 i = 0; i < CountGroups(); i++)
	{
		SourceGroup *group = GroupAt(i);
		
		for (int32 j = 0; j < group->filelist.CountItems(); j++)
		{
			SourceFile *src = group->filelist.ItemAt(j);
			if (src && strcmp(src->GetPath().GetFileName(),newfile.GetFileName()) == 0)
				return true;
		}
	}
	return false;
}
unsigned
SourceManager::getCol(const LREntry &range, const SourceLocation &loc, unsigned line)
{
  if (!line) {
    if ((line = getLine(range, loc)) == 0)
      return 0;
  }

  SourceFile *file = range.getFile();

  // Cached and returned lines are + 1, but the line cache starts at 0.
  line = line - 1;
  assert(line < file->lineCache()->length());

  uint32_t pos = loc.offset() - range.id;
  uint32_t line_start = file->lineCache()->at(line);

#if !defined(NDEBUG)
  uint32_t line_end = (line < file->lineCache()->length() - 1)
                      ? file->lineCache()->at(line + 1)
                      : file->length() + 1;
  assert(pos >= line_start && pos < line_end);
#endif

  return pos - line_start + 1;
}
Exemple #27
0
void MainWindow::projectClicked(const QModelIndex& index)
{
	Project* project = m_projectsModel.indexToProject(index);
	qDebug() << "Type" << m_projectsModel.indexType(index);
	if(m_projectsModel.indexType(index) == ProjectsModel::ProjectType) {
		for(int i = 0; i < ui_tabWidget->count(); ++i) {
			ProjectSettingsTab* tab = dynamic_cast<ProjectSettingsTab*>(ui_tabWidget->widget(i));
			if(tab && tab->associatedProject() == project) {
				ui_tabWidget->setCurrentIndex(i);
				on_ui_tabWidget_currentChanged(i);
				return;
			}
		}
	
		ProjectSettingsTab* tab = new ProjectSettingsTab(project, this);
		addTab(tab);
	} else if(m_projectsModel.indexType(index) == ProjectsModel::FileType) {
		qDebug() << "File!!";
		const TinyNode* node = m_projectsModel.indexToNode(index);
		const QString& file = QString::fromStdString(node->path());
		if(!project) return;

		SourceFile* sourceFile = new SourceFile(this);
		for(int i = 0; i < ui_tabWidget->count(); ++i) {
			SourceFile* sourceFile = dynamic_cast<SourceFile*>(ui_tabWidget->widget(i));
			if(sourceFile && sourceFile->associatedFile() == file) {
				ui_tabWidget->setCurrentIndex(i);
				on_ui_tabWidget_currentChanged(i);
				return;
			}
		}

		if(!sourceFile->openProjectFile(project, node)) {
			delete sourceFile;
			return;
		}
		Log::ref().debug(QString("Opened %1 for editing").arg(node->name()));
		addTab(sourceFile);
	}
}
Exemple #28
0
Shader::Shader(GLenum type, const char* fileName) {
    m_shaderID = glCreateShader(type);
    SourceFile *sourceFile = SourceFileManager::getSource(fileName);
    const GLchar** source = sourceFile->getSource();
    
    glShaderSource(m_shaderID, sourceFile->getNumLines(), source, NULL);
    
    glCompileShader(m_shaderID);
    
    GLint status;
    glGetShaderiv(m_shaderID, GL_COMPILE_STATUS, &status);
    
    if(!status) {
        printf("Error compiling shader from file %s.\n", fileName);
    }
    
    char log[512];
        
    glGetShaderInfoLog(m_shaderID, 512, NULL, log);
    
    printf("Shader compile log:\n%s\n", log);
}
Exemple #29
0
/// performNameBinding - Once parsing is complete, this walks the AST to
/// resolve names and do other top-level validation.
///
/// At this parsing has been performed, but we still have UnresolvedDeclRefExpr
/// nodes for unresolved value names, and we may have unresolved type names as
/// well.  This handles import directives and forward references.
void swift::performNameBinding(SourceFile &SF, unsigned StartElem) {
    // Make sure we skip adding the standard library imports if the
    // source file is empty.
    if (SF.ASTStage == SourceFile::NameBound || SF.Decls.empty()) {
        SF.ASTStage = SourceFile::NameBound;
        return;
    }

    // Reset the name lookup cache so we find new decls.
    // FIXME: This is inefficient.
    SF.clearLookupCache();

    NameBinder Binder(SF);

    SmallVector<std::pair<ImportedModule, ImportOptions>, 8> ImportedModules;

    // Do a prepass over the declarations to find and load the imported modules
    // and map operator decls.
    for (auto D : llvm::makeArrayRef(SF.Decls).slice(StartElem)) {
        if (ImportDecl *ID = dyn_cast<ImportDecl>(D)) {
            Binder.addImport(ImportedModules, ID);
        } else if (auto *OD = dyn_cast<PrefixOperatorDecl>(D)) {
            insertOperatorDecl(Binder, SF.PrefixOperators, OD);
        } else if (auto *OD = dyn_cast<PostfixOperatorDecl>(D)) {
            insertOperatorDecl(Binder, SF.PostfixOperators, OD);
        } else if (auto *OD = dyn_cast<InfixOperatorDecl>(D)) {
            insertOperatorDecl(Binder, SF.InfixOperators, OD);
        }
    }

    SF.addImports(ImportedModules);

    // FIXME: This algorithm has quadratic memory usage.  (In practice,
    // import statements after the first "chunk" should be rare, though.)
    // FIXME: Can we make this more efficient?

    SF.ASTStage = SourceFile::NameBound;
    verify(SF);
}
//! \param sourceName Pointer to string containing the name of the source to look up.
//!		May be NULL, in which case the default source is used.
//! \param line The line number on which the source name was located.
//!
//! \result A source file object that was previously created in the processSources()
//!		stage.
//!
//! \exception std::runtime_error Thrown if the source name is invalid, or if it
//!		was NULL and there is no default source (i.e., we're not inside a from
//!		statement).
SourceFile * ConversionController::getSourceFromName(std::string * sourceName, int line)
{
	SourceFile * sourceFile = NULL;
	if (sourceName)
	{
		// look up source in map
		source_map_t::iterator it = m_sources.find(*sourceName);
		if (it == m_sources.end())
		{
			source_name_vector_t::const_iterator findIt = std::find<source_name_vector_t::const_iterator, std::string>(m_failedSources.begin(), m_failedSources.end(), *sourceName);
			if (findIt != m_failedSources.end())
			{
				throw semantic_error(format_string("line %d: error opening source '%s'", line, sourceName->c_str()));
			}
			else
			{
				throw semantic_error(format_string("line %d: invalid source name '%s'", line, sourceName->c_str()));
			}
		}
		sourceFile = it->second;
	}
	else
	{
		// no name provided - use default source
		sourceFile = m_defaultSource;
		if (!sourceFile)
		{
			throw semantic_error(format_string("line %d: source required but no default source is available", line));
		}
	}
	
	// open the file if it hasn't already been
	if (!sourceFile->isOpen())
	{
		sourceFile->open();
	}
	return sourceFile;
}