/*
 * Copyright (C) 2012 David Anderson
 *
 * This file is part of SourcePawn.
 *
 * SourcePawn is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 * 
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
 */
#ifndef _include_jc_module_h_
#define _include_jc_module_h_

#include "Heap.h"
#include "Code.h"
#include "Functions.h"
#include "FixedArray.h"
#include "Packages.h"

namespace ke {

class Environment;
class Struct;
class Package;
struct TranslationUnit;

class Module : public Importable
{
    Barriered<Code> code_;
    Barriered<Struct> globals_;
    void *nativeIdentity_;
    TranslationUnit *unit_;
    Barriered<FixedArray> imports_;

  public:
    static Module *New(Zone *zone, Handle<Package> package, Handle<String> path, Handle<String> name);
    
    Code *code() {
        return code_;
    }
    Struct *globals() {
        return globals_;
    }

    bool compiled() {
        return !!code_;
    }

    // Modules are pre-created, and may have their intermediate compilation
    // data attached while they are being compiled.
    bool compiling() {
        return !!unit_;
    }
    TranslationUnit *translationUnit() {
        return unit_;
    }
    void setTranslationUnit(TranslationUnit *unit) {
        unit_ = unit;
    }

    unsigned imports() {
        return imports_ ? imports_->length() / 2 : 0;
    }
    Importable *getImportAt(unsigned index) {
        return Importable::cast(imports_->at(index * 2));
    }
    FixedArray *importPathAt(unsigned index) {
        return FixedArray::cast(imports_->at(index * 2 + 1));
    }
    void setImports(Handle<FixedArray> imports) {
        imports_ = imports;
    }
    void setCode(Handle<Code> code) {
        code_ = code;
    }
    void setGlobals(Handle<Struct> globals) {
        globals_ = globals;
    }

    // Begin GC Descriptor.
    static inline size_t offsetOfCode() {
        return OFFSETOF(Module, code_);
    }
    static inline size_t offsetOfGlobals() {
        return OFFSETOF(Module, globals_);
    }
    static inline size_t offsetOfImports() {
        return OFFSETOF(Module, imports_);
    }
    // End GC Descriptor.

    static inline Module *cast(Object *obj) {
        assert(!obj || obj->is(MapKind_Module));
        return reinterpret_cast<Module *>(obj);
    }
};

}

#endif // _include_jc_module_h_
