Example #1
0
void
Interpreter::loadModuleRecursive (const string &moduleName)
{
    debug ("Interpreter::loadModuleRecursive "
	   "(moduleName = " << moduleName << ")");

    if (moduleIsLoadedInternal (moduleName))
    {
	debug ("\talready loaded");
	return;
    }

    //
    // Using the module search path, locate the file that contains the
    // source code for the module.  Open the file.
    //

    string fileName = findModule (moduleName);
    ifstream file (fileName.c_str());

    if (!file)
    {
	THROW_ERRNO ("Cannot load CTL module \"" << moduleName << "\". "
		     "Opening file \"" << fileName << "\" for reading "
		     "failed (%T).");
    }

    debug ("\tloading from file \"" << fileName << "\"");

    Module *module = 0;
    LContext *lcontext = 0;

    try
    {
	//
	// Create a Module, an Lcontext and a Parser
	//

	module = newModule (moduleName, fileName);	
	_data->moduleSet.addModule (module);
	lcontext = newLContext (file, module, _data->symtab);
	Parser parser (*lcontext, *this);

	//
	// Parse the source code and generate executable code
	// for the module
	//

	debug ("\tparsing input");
	SyntaxNodePtr syntaxTree = parser.parseInput ();

	if (syntaxTree && lcontext->numErrors() == 0)
	{
	    debug ("\tgenerating code");
	    syntaxTree->generateCode (*lcontext);
	}

	if (lcontext->numErrors() > 0)
	{
	    lcontext->printDeclaredErrors();
	    THROW (LoadModuleExc,
		   "Failed to load CTL module \"" << moduleName << "\".");
	}

	//
	// Run the module's initialization code
	//

	debug ("\trunning module initialization code");
	module->runInitCode();

	//
	// Cleanup: the LContext and the module's local symbols
	// are no longer needed, but we keep the global symbols.
	//

	debug ("\tcleanup");
	delete lcontext;
	_data->symtab.deleteAllLocalSymbols (module);
    }
    catch (...)
    {
	//
	// Something went wrong while loading the module, clean up
	//

	delete lcontext;
	_data->symtab.deleteAllSymbols (module);
	_data->moduleSet.removeModule (moduleName);
	throw;
    }
}