/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 * 
 * ExternLayer.h
 *
 *  Created on: 4/21/15
 *      Author: pgess <v.melnychenko@xreate.org>
 */

#ifndef XREATE_EXTERNLAYER_H
#define XREATE_EXTERNLAYER_H

#include "llvmlayer.h"
#include <vector>
#include <string>
#include <map>
#include "ast.h"
#include "clang/AST/ASTContext.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/CodeGen/CodeGenABITypes.h"

namespace xreate {
    struct ExternData {
        void addLibrary(Atom<Identifier_t>&& name, Atom<String_t>&& package);
        void addIncludeDecl(Expression&& e);

        std::vector<ExternEntry> entries;
        std::map<std::string, std::string> __dictLibraries;
    };

    class ExternLayer {
    public:
        ExternLayer(LLVMLayer* llvm);

        llvm::Function* lookupFunction(const std::string& name);
        clang::QualType lookupType(const std::string& id);
        std::vector<std::string> getStructFields(const clang::QualType& ty);

        llvm::Type* toLLVMType(const clang::QualType& t);
        bool isPointer(const clang::QualType& t);

        void init(const AST* root);
        static std::vector<std::string> fetchPackageFlags(const ExternEntry& entry);
        static std::vector<std::string> fetchPackageLibs(const ExternEntry& entry);
    private:

        std::unique_ptr<clang::ASTUnit> ast;
        std::unique_ptr<clang::CodeGen::CodeGenModule> __cgm;
        std::unique_ptr<clang::CodeGenOptions> __cgo;
        LLVMLayer* __llvm;
        std::vector<ExternEntry> entries;
        std::map<std::string, llvm::Function*> __functions;

        void addExternalData(const std::vector<ExternEntry>& data);
        void loadLibraries(std::vector<std::string>&& libs);
    };
}
#endif //XREATE_EXTERNLAYER_H
