blob: b085814c3bb74980f144f81e789116ecc381463f [file] [log] [blame]
Andreas Huberc9410c72016-07-28 12:18:40 -07001#include "AST.h"
2
Andreas Huber5345ec22016-07-29 13:33:27 -07003#include "Coordinator.h"
Andreas Huberc9410c72016-07-28 12:18:40 -07004#include "Formatter.h"
Andreas Huber84f89de2016-07-28 15:39:51 -07005#include "FQName.h"
Andreas Hubereb1081f2016-07-28 13:13:24 -07006#include "HandleType.h"
7#include "RefType.h"
Andreas Huberc9410c72016-07-28 12:18:40 -07008#include "Scope.h"
9
Andreas Hubereb1081f2016-07-28 13:13:24 -070010#include <android-base/logging.h>
Andreas Huberc9410c72016-07-28 12:18:40 -070011#include <stdlib.h>
Andreas Huber68f24592016-07-29 14:53:48 -070012#include <sys/dir.h>
Andreas Huberc9410c72016-07-28 12:18:40 -070013
Andreas Huberc9410c72016-07-28 12:18:40 -070014namespace android {
15
Andreas Huber5345ec22016-07-29 13:33:27 -070016AST::AST(Coordinator *coordinator)
17 : mCoordinator(coordinator),
18 mScanner(NULL),
Andreas Huber31629bc2016-08-03 09:06:40 -070019 mRootScope(new Scope) {
Andreas Huberc9410c72016-07-28 12:18:40 -070020 enterScope(mRootScope);
21}
22
23AST::~AST() {
Andreas Huberc9410c72016-07-28 12:18:40 -070024 delete mRootScope;
25 mRootScope = NULL;
26
Andreas Hubereb1081f2016-07-28 13:13:24 -070027 CHECK(mScanner == NULL);
Andreas Huberc9410c72016-07-28 12:18:40 -070028
Andreas Huber5345ec22016-07-29 13:33:27 -070029 // Ownership of "coordinator" was NOT transferred.
Andreas Huberc9410c72016-07-28 12:18:40 -070030}
31
32void *AST::scanner() {
33 return mScanner;
34}
35
36void AST::setScanner(void *scanner) {
37 mScanner = scanner;
38}
39
Andreas Huber84f89de2016-07-28 15:39:51 -070040bool AST::setPackage(const char *package) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070041 mPackage.setTo(package);
42 CHECK(mPackage.isValid());
Andreas Huber84f89de2016-07-28 15:39:51 -070043
Andreas Huberda51b8e2016-07-28 16:00:57 -070044 if (mPackage.package().empty()
45 || mPackage.version().empty()
46 || !mPackage.name().empty()) {
Andreas Huber84f89de2016-07-28 15:39:51 -070047 return false;
48 }
49
Andreas Huber84f89de2016-07-28 15:39:51 -070050 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -070051}
52
Andreas Hubera2723d22016-07-29 15:36:07 -070053FQName AST::package() const {
54 return mPackage;
55}
56
57bool AST::isInterface(std::string *ifaceName) const {
58 return mRootScope->containsSingleInterface(ifaceName);
59}
60
Andreas Huber5345ec22016-07-29 13:33:27 -070061bool AST::addImport(const char *import) {
62 FQName fqName(import);
63 CHECK(fqName.isValid());
Andreas Hubereb1081f2016-07-28 13:13:24 -070064
Andreas Huber5345ec22016-07-29 13:33:27 -070065 fqName.applyDefaults(mPackage.package(), mPackage.version());
66
Andreas Huber68f24592016-07-29 14:53:48 -070067 // LOG(INFO) << "importing " << fqName.string();
Andreas Huber5345ec22016-07-29 13:33:27 -070068
69 if (fqName.name().empty()) {
Andreas Huberdc981332016-07-29 15:46:54 -070070 const std::string packagePath = mCoordinator->getPackagePath(fqName);
Andreas Huber68f24592016-07-29 14:53:48 -070071 DIR *dir = opendir(packagePath.c_str());
72
73 if (dir == NULL) {
74 return false;
75 }
76
77 // Enumerate all regular files ending in ".hal" in the package directory
78 // and attempt to import all of them.
79
80 Vector<std::string> fileNames;
81
82 struct dirent *ent;
83 while ((ent = readdir(dir)) != NULL) {
84 if (ent->d_type != DT_REG) {
85 continue;
86 }
87
88 if (ent->d_namlen < 4
89 || strcmp(ent->d_name + ent->d_namlen - 4, ".hal")) {
90 continue;
91 }
92
93 fileNames.push_back(std::string(ent->d_name, ent->d_namlen - 4));
94 }
95
96 closedir(dir);
97 dir = NULL;
98
99 for (size_t i = 0; i < fileNames.size(); ++i) {
100 FQName subFQName(
101 fqName.package() + fqName.version() + "::" + fileNames[i]);
102
103 if (!subFQName.isValid()) {
104 LOG(WARNING)
105 << "Whole-package import encountered invalid filename '"
106 << fileNames[i]
107 << "' in package "
108 << fqName.package()
109 << fqName.version();
110
111 continue;
112 }
113
114 if (mCoordinator->parse(subFQName) == NULL) {
115 return false;
116 }
117 }
118
119 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700120 }
121
Andreas Huber68f24592016-07-29 14:53:48 -0700122 AST *importAST = mCoordinator->parse(fqName);
Andreas Huber5345ec22016-07-29 13:33:27 -0700123
Andreas Huber68f24592016-07-29 14:53:48 -0700124 if (importAST == NULL) {
125 return false;
126 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700127
128 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700129}
130
Andreas Huberc9410c72016-07-28 12:18:40 -0700131void AST::enterScope(Scope *container) {
132 mScopePath.push_back(container);
133}
134
135void AST::leaveScope() {
136 mScopePath.pop();
137}
138
139Scope *AST::scope() {
Andreas Hubereb1081f2016-07-28 13:13:24 -0700140 CHECK(!mScopePath.empty());
Andreas Huberc9410c72016-07-28 12:18:40 -0700141 return mScopePath.top();
142}
143
Andreas Huber5a545442016-08-03 10:44:56 -0700144bool AST::addScopedType(const char *localName, NamedType *type) {
Andreas Huber31629bc2016-08-03 09:06:40 -0700145 // LOG(INFO) << "adding scoped type '" << localName << "'";
146
Andreas Huber5a545442016-08-03 10:44:56 -0700147 bool success = scope()->addType(localName, type);
148 if (!success) {
149 return false;
150 }
151
Andreas Huber31629bc2016-08-03 09:06:40 -0700152 std::string path;
153 for (size_t i = 1; i < mScopePath.size(); ++i) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700154 path.append(mScopePath[i]->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700155 path.append(".");
156 }
157 path.append(localName);
158
159 type->setLocalName(localName);
160
161 FQName fqName(mPackage.package(), mPackage.version(), path);
162 type->setFullName(fqName);
163
Andreas Huber5a545442016-08-03 10:44:56 -0700164 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700165}
166
Andreas Huber0e00de42016-08-03 09:56:02 -0700167RefType *AST::lookupType(const char *name) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700168 FQName fqName(name);
169 CHECK(fqName.isValid());
170
Andreas Huberda51b8e2016-07-28 16:00:57 -0700171 if (fqName.name().empty()) {
172 // Given a package and version???
173 return NULL;
174 }
175
Andreas Huber84f89de2016-07-28 15:39:51 -0700176 if (fqName.package().empty() && fqName.version().empty()) {
177 // This is just a plain identifier, resolve locally first if possible.
178
179 for (size_t i = mScopePath.size(); i-- > 0;) {
180 Type *type = mScopePath[i]->lookupType(name);
181
182 if (type != NULL) {
Andreas Huber867fcb62016-08-02 16:26:34 -0700183 return new RefType(type);
Andreas Huber84f89de2016-07-28 15:39:51 -0700184 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700185 }
186 }
187
Andreas Huberda51b8e2016-07-28 16:00:57 -0700188 fqName.applyDefaults(mPackage.package(), mPackage.version());
Andreas Huber84f89de2016-07-28 15:39:51 -0700189
Andreas Huber68f24592016-07-29 14:53:48 -0700190 // LOG(INFO) << "lookupType now looking for " << fqName.string();
Andreas Huber84f89de2016-07-28 15:39:51 -0700191
Andreas Huber0e00de42016-08-03 09:56:02 -0700192 RefType *resultType = mCoordinator->lookupType(fqName);
Andreas Huber737080b2016-08-02 15:38:04 -0700193
194 if (resultType) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700195 if (!resultType->referencedType()->isInterface()) {
196 // Non-interface types are declared in the associated types header.
197 FQName typesName(fqName.package(), fqName.version(), "types");
198 mImportedNames.insert(typesName);
199 } else {
200 mImportedNames.insert(fqName);
201 }
Andreas Huber737080b2016-08-02 15:38:04 -0700202 }
203
204 return resultType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700205}
206
207Type *AST::lookupTypeInternal(const std::string &namePath) const {
208 Scope *scope = mRootScope;
209
210 size_t startPos = 0;
211 for (;;) {
212 size_t dotPos = namePath.find('.', startPos);
213
214 std::string component;
215 if (dotPos == std::string::npos) {
216 component = namePath.substr(startPos);
217 } else {
218 component = namePath.substr(startPos, dotPos - startPos);
219 }
220
221 Type *type = scope->lookupType(component.c_str());
222
223 if (type == NULL) {
224 return NULL;
225 }
226
227 if (dotPos == std::string::npos) {
228 return type;
229 }
230
231 if (!type->isScope()) {
232 return NULL;
233 }
234
235 scope = static_cast<Scope *>(type);
236 startPos = dotPos + 1;
237 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700238}
239
Andreas Huberc9410c72016-07-28 12:18:40 -0700240} // namespace android;