Beispiel #1
0
int Main::LoadFile(text file,
                   bool updateContext,
                   Context *importContext,
                   Symbols *importSymbols)
// ----------------------------------------------------------------------------
//   Load an individual file
// ----------------------------------------------------------------------------
{
    Tree_p tree = NULL;
    bool hadError = false;

    IFTRACE(fileload)
        std::cout << "Loading: " << file << "\n";

    // Find which source file we are referencing
    SourceFile &sf = files[file];

    // Parse program - Local parser to delete scanner and close file
    // This ensures positions are updated even if there is a 'load'
    // being called during execution.
    if (options.readSerialized)
    {
        if (!reader)
            reader = new Deserializer(std::cin);
        tree = reader->ReadTree();
        if (!reader->IsValid())
        {
            errors->Log(Error("Serialized stream cannot be read: $1")
                        .Arg(file));
            hadError = true;
            return hadError;
        }
    }
    else
    {
        utf8_ifstream ifs(file.c_str(), std::ios::in | std::ios::binary);
        Deserializer ds(ifs);
        tree = ds.ReadTree();
        if (!ds.IsValid())
        {
            std::string decrypted = MAIN->Decrypt(file.c_str());
            if (decrypted != "")
            {
                // Parse decrypted string as XL source
                IFTRACE(fileload)
                    std::cerr << "Info: file was succesfully decrypted\n";
                std::istringstream iss;
                iss.str(decrypted);
                Parser parser (iss, syntax, positions, topLevelErrors);
                tree = parser.Parse();
            }
            else
            {
                // Parse as XL source
                Parser parser (file.c_str(), syntax, positions, topLevelErrors);
                tree = parser.Parse();
            }
        }
        else
        {
            IFTRACE(fileload)
                std::cerr << "Info: file is in serialized format\n";
        }
    }

    if (options.writeSerialized)
    {
        if (!writer)
            writer = new Serializer(std::cout);
        if (tree)
            tree->Do(writer);
    }

    if (tree)
    {
        tree = Normalize(tree);
    }
    else
    {
        if (options.doDiff)
        {
            files[file] = SourceFile (file, NULL, NULL, NULL);
            hadError = false;
        }
    }

    // Create new symbol table for the file, or clear it if we had one
    Context *ctx = MAIN->context;
    Context *savedCtx = ctx;
    Symbols *syms = MAIN->globals;
    Symbols *savedSyms = syms;
    if (sf.context)
    {
        updateContext = false;
        ctx = sf.context;
        syms = sf.symbols;
        ctx->Clear();
        syms->Clear();
    }
    else
    {
        ctx = new Context(ctx, NULL);
        syms = new Symbols(syms);
        syms->name = file;
    }
    MAIN->context = ctx;
    MAIN->globals = syms;
    syms->is_global = true;

    // Connect imports if any
    if (importContext)
        importContext->Import(ctx);
    if (importSymbols)
        importSymbols->Import(syms);

    // HACK - do not hide imported .xl
    if (file.find(".ddd") == file.npos &&
        file.find("tao.xl") == file.npos &&
        file.find("builtins.xl") == file.npos)
    {
        Name_p module_file = new Name("module_file"); // TODO: Position
        Name_p module_dir = new Name("module_dir");
        Text_p module_file_value = new Text(file);
        Text_p module_dir_value = new Text(ParentDir(file));
        ctx->Define(module_file, module_file_value);
        ctx->Define(module_dir, module_dir_value);
        syms->EnterName(module_file->value, module_file_value,Rewrite::LOCAL);
        syms->EnterName(module_dir->value, module_dir_value,Rewrite::LOCAL);
    }

    // Register the source file we had
    sf = SourceFile (file, tree, ctx, syms);
    if (tree)
    {
        // Set symbols and compile if required
        if (!options.parseOnly)
        {
            if (options.optimize_level == 1)
            {
                tree->SetSymbols(syms);
                if (!tree)
                    hadError = true;
                else
                    files[file].tree = tree;
                syms->ProcessDeclarations(tree);
            }

            // TODO: At -O3, do we need to do anything here?
        }
       
        // Graph of the input tree
        if (options.showGV)
        {
            SetNodeIdAction sni;
            BreadthFirstSearch<SetNodeIdAction> bfs(sni);
            tree->Do(bfs);
            GvOutput gvout(std::cout);
            tree->Do(gvout);
        }
    }

    if (options.showSource)
        std::cout << tree << "\n";
    if (options.verbose)
        debugp(tree);

    // Decide if we update symbols for next run
    if (!updateContext)
    {
        MAIN->context = savedCtx;
        MAIN->globals = savedSyms;
    }

    IFTRACE(symbols)
        std::cerr << "Loaded file " << file
                  << " with context " << MAIN->context << '\n';

    return hadError;
}