src/Packages.h
author Asher Baker <asherkin@gmail.com>
Mon Jun 10 15:52:44 2013 +0100 (2013-06-10)
changeset 265 3a903b89a514
parent 263 ba85a47ee414
permissions -rw-r--r--
Fixed type checking for multidimensional arrays.
asherkin@263
     1
/*
asherkin@263
     2
 * Copyright (C) 2012 David Anderson
asherkin@263
     3
 *
asherkin@263
     4
 * This file is part of SourcePawn.
asherkin@263
     5
 *
asherkin@263
     6
 * SourcePawn is free software: you can redistribute it and/or modify it under
asherkin@263
     7
 * the terms of the GNU General Public License as published by the Free
asherkin@263
     8
 * Software Foundation, either version 3 of the License, or (at your option)
asherkin@263
     9
 * any later version.
asherkin@263
    10
 * 
asherkin@263
    11
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
asherkin@263
    12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
asherkin@263
    13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
asherkin@263
    14
 *
asherkin@263
    15
 * You should have received a copy of the GNU General Public License along with
asherkin@263
    16
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
asherkin@263
    17
 */
asherkin@263
    18
#ifndef _include_sp2_packages_h_
asherkin@263
    19
#define _include_sp2_packages_h_
asherkin@263
    20
asherkin@263
    21
#include "PoolAllocator.h"
asherkin@263
    22
#include "Objects.h"
asherkin@263
    23
#include "HashTable.h"
asherkin@263
    24
asherkin@263
    25
namespace ke {
asherkin@263
    26
asherkin@263
    27
class String;
asherkin@263
    28
class Module;
asherkin@263
    29
class Package;
asherkin@263
    30
class ImportStatement;
asherkin@263
    31
class VirtualObjectVisitor;
asherkin@263
    32
asherkin@263
    33
template <typename T> class List;
asherkin@263
    34
asherkin@263
    35
struct PathComponent : PoolObject
asherkin@263
    36
{
asherkin@263
    37
    PathComponent(ScopedRoot<String> *name, PathComponent *next)
asherkin@263
    38
      : name(*name),
asherkin@263
    39
        next(next)
asherkin@263
    40
    {
asherkin@263
    41
    }
asherkin@263
    42
    ScopedRoot<String> &name;
asherkin@263
    43
    PathComponent *next;
asherkin@263
    44
};
asherkin@263
    45
asherkin@263
    46
class Importable : public Object
asherkin@263
    47
{
asherkin@263
    48
  public:
asherkin@263
    49
    Package *parent() {
asherkin@263
    50
        return parent_;
asherkin@263
    51
    }
asherkin@263
    52
    String *path() {
asherkin@263
    53
        return path_;
asherkin@263
    54
    }
asherkin@263
    55
    String *name() {
asherkin@263
    56
        return name_;
asherkin@263
    57
    }
asherkin@263
    58
asherkin@263
    59
    bool isModule() {
asherkin@263
    60
        return is(MapKind_Module);
asherkin@263
    61
    }
asherkin@263
    62
    bool isPackage() {
asherkin@263
    63
        return is(MapKind_Package);
asherkin@263
    64
    }
asherkin@263
    65
asherkin@263
    66
    static inline size_t offsetOfName() {
asherkin@263
    67
        return OFFSETOF(Importable, name_);
asherkin@263
    68
    }
asherkin@263
    69
    static inline size_t offsetOfParent() {
asherkin@263
    70
        return OFFSETOF(Importable, parent_);
asherkin@263
    71
    }
asherkin@263
    72
    static inline size_t offsetOfPath() {
asherkin@263
    73
        return OFFSETOF(Importable, path_);
asherkin@263
    74
    }
asherkin@263
    75
asherkin@263
    76
    static inline Importable *cast(Object *obj) {
asherkin@263
    77
        assert(!obj || obj->is(MapKind_Module) || obj->is(MapKind_Package));
asherkin@263
    78
        return reinterpret_cast<Importable *>(obj);
asherkin@263
    79
    }
asherkin@263
    80
asherkin@263
    81
  protected:
asherkin@263
    82
    Barriered<String> name_;
asherkin@263
    83
    Barriered<Package> parent_;
asherkin@263
    84
    Barriered<String> path_;
asherkin@263
    85
};
asherkin@263
    86
asherkin@263
    87
// A package is a single folder in the file system, and contains any number of
asherkin@263
    88
// modules and sub-packages. The package hierarchy forms a tree. For simplicity
asherkin@263
    89
// the root of the tree is an anonymous package that contains no modules.
asherkin@263
    90
//
asherkin@263
    91
// Each package in the package hierarchy has two components of path information:
asherkin@263
    92
//   (1) Canonical path. This is a normalized path used to compute the paths of
asherkin@263
    93
//       modules.
asherkin@263
    94
//   (2) Name. This is the package's name as it would appear in a path
asherkin@263
    95
//       component. It is optional.
asherkin@263
    96
//
asherkin@263
    97
// Packages may be "hidden", meaning that even if they have names, their name
asherkin@263
    98
// is not accessible from any import statements. Packages may also be "jailed",
asherkin@263
    99
// meaning that other names in the package are not visible to each other.
asherkin@263
   100
//
asherkin@263
   101
// Packages are created in a few ways:
asherkin@263
   102
//
asherkin@263
   103
//   (1) System Roots. A system root is a default search location for imports,
asherkin@263
   104
//       and they are installed at the top-level of the hierarchy by the host
asherkin@263
   105
//       application. A system root has a unique top-level name and path.
asherkin@263
   106
//       System roots are always hidden.
asherkin@263
   107
//
asherkin@263
   108
//   (2) Imports. When importing, the package hierarchy may be extended as
asherkin@263
   109
//       new paths are discovered. Packages discovered this way are never
asherkin@263
   110
//       hidden or jailed.
asherkin@263
   111
//
asherkin@263
   112
//   (3) Via Package::New(), which creates an empty package. This can be used
asherkin@263
   113
//       to create custom packages.
asherkin@263
   114
class Package : public Importable
asherkin@263
   115
{
asherkin@263
   116
  public:
asherkin@263
   117
    enum {
asherkin@263
   118
        Normal = 0,
asherkin@263
   119
asherkin@263
   120
        // These must match the flags in the public API for Package.
asherkin@263
   121
        Hidden = (1 << 0),
asherkin@263
   122
        Jailed = (1 << 1)
asherkin@263
   123
    };
asherkin@263
   124
asherkin@263
   125
  public:
asherkin@263
   126
    static Package *NewNormalized(Zone *zone,
asherkin@263
   127
                                  Handle<Package> parent,
asherkin@263
   128
                                  Handle<String> path,
asherkin@263
   129
                                  Handle<String> name,
asherkin@263
   130
                                  unsigned flags);
asherkin@263
   131
    static Package *New(Zone *zone,
asherkin@263
   132
                        Handle<Package> parent,
asherkin@263
   133
                        const char *path,
asherkin@263
   134
                        Handle<String> name,
asherkin@263
   135
                        unsigned flags);
asherkin@263
   136
asherkin@263
   137
    bool add(Zone *zone, Handle<Importable> component);
asherkin@263
   138
asherkin@263
   139
    bool hidden() {
asherkin@263
   140
        return !!(flags_ & Package::Hidden);
asherkin@263
   141
    }
asherkin@263
   142
    bool jailed() {
asherkin@263
   143
        return !!(flags_ & Package::Jailed);
asherkin@263
   144
    }
asherkin@263
   145
asherkin@263
   146
    void setNativeIdentity(void *identity) {
asherkin@263
   147
        nativeIdentity_ = identity;
asherkin@263
   148
    }
asherkin@263
   149
    void *getNativeIdentity() {
asherkin@263
   150
        return nativeIdentity_;
asherkin@263
   151
    }
asherkin@263
   152
    Importable *import(Handle<String> name);
asherkin@263
   153
asherkin@263
   154
    // Begin GC descriptor.
asherkin@263
   155
    static inline size_t offsetOfContents() {
asherkin@263
   156
        return OFFSETOF(Package, contents_);
asherkin@263
   157
    }
asherkin@263
   158
    // End GC descriptor.
asherkin@263
   159
asherkin@263
   160
    static inline Package *cast(Object *obj) {
asherkin@263
   161
        assert(!obj || obj->is(MapKind_Package));
asherkin@263
   162
        return reinterpret_cast<Package *>(obj);
asherkin@263
   163
    }
asherkin@263
   164
asherkin@263
   165
  private:
asherkin@263
   166
    unsigned flags_;
asherkin@263
   167
    Barriered<List<Importable> > contents_;
asherkin@263
   168
    void *nativeIdentity_;
asherkin@263
   169
};
asherkin@263
   170
asherkin@263
   171
class PackageCache
asherkin@263
   172
{
asherkin@263
   173
  public:
asherkin@263
   174
    PackageCache(Zone *zone);
asherkin@263
   175
    ~PackageCache();
asherkin@263
   176
    bool initialize();
asherkin@263
   177
asherkin@263
   178
    bool findOrAdd(Handle<Package> package, PathComponent *path, Importable **out);
asherkin@263
   179
asherkin@263
   180
    void accept(VirtualObjectVisitor *visitor);
asherkin@263
   181
asherkin@263
   182
  private:
asherkin@263
   183
    bool import(Handle<Package> package, PathComponent *path, Importable **out);
asherkin@263
   184
    bool checkfs(Handle<Package> package, PathComponent *path, Importable **out);
asherkin@263
   185
asherkin@263
   186
  private:
asherkin@263
   187
    Zone *zone_;
asherkin@263
   188
    Vector<Unbarriered<Package> > roots_;
asherkin@263
   189
};
asherkin@263
   190
asherkin@263
   191
} // namespace ke
asherkin@263
   192
asherkin@263
   193
#endif // _include_sp2_packages_h_