|
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_ |