blob: d10a3efbf4a843af4eef106668f18837395ba0b3 [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"
Andreas Huberc9410c72016-07-28 12:18:40 -07007#include "Scope.h"
8
Andreas Hubereb1081f2016-07-28 13:13:24 -07009#include <android-base/logging.h>
Andreas Huberc9410c72016-07-28 12:18:40 -070010#include <stdlib.h>
Andreas Huber68f24592016-07-29 14:53:48 -070011#include <sys/dir.h>
Andreas Huberc9410c72016-07-28 12:18:40 -070012
Andreas Huberc9410c72016-07-28 12:18:40 -070013namespace android {
14
Andreas Huber5345ec22016-07-29 13:33:27 -070015AST::AST(Coordinator *coordinator)
16 : mCoordinator(coordinator),
17 mScanner(NULL),
Andreas Huber31629bc2016-08-03 09:06:40 -070018 mRootScope(new Scope) {
Andreas Huberc9410c72016-07-28 12:18:40 -070019 enterScope(mRootScope);
20}
21
22AST::~AST() {
Andreas Huberc9410c72016-07-28 12:18:40 -070023 delete mRootScope;
24 mRootScope = NULL;
25
Andreas Hubereb1081f2016-07-28 13:13:24 -070026 CHECK(mScanner == NULL);
Andreas Huberc9410c72016-07-28 12:18:40 -070027
Andreas Huber5345ec22016-07-29 13:33:27 -070028 // Ownership of "coordinator" was NOT transferred.
Andreas Huberc9410c72016-07-28 12:18:40 -070029}
30
31void *AST::scanner() {
32 return mScanner;
33}
34
35void AST::setScanner(void *scanner) {
36 mScanner = scanner;
37}
38
Andreas Huber84f89de2016-07-28 15:39:51 -070039bool AST::setPackage(const char *package) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070040 mPackage.setTo(package);
41 CHECK(mPackage.isValid());
Andreas Huber84f89de2016-07-28 15:39:51 -070042
Andreas Huberda51b8e2016-07-28 16:00:57 -070043 if (mPackage.package().empty()
44 || mPackage.version().empty()
45 || !mPackage.name().empty()) {
Andreas Huber84f89de2016-07-28 15:39:51 -070046 return false;
47 }
48
Andreas Huber84f89de2016-07-28 15:39:51 -070049 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -070050}
51
Andreas Hubera2723d22016-07-29 15:36:07 -070052FQName AST::package() const {
53 return mPackage;
54}
55
56bool AST::isInterface(std::string *ifaceName) const {
57 return mRootScope->containsSingleInterface(ifaceName);
58}
59
Andreas Huber5345ec22016-07-29 13:33:27 -070060bool AST::addImport(const char *import) {
61 FQName fqName(import);
62 CHECK(fqName.isValid());
Andreas Hubereb1081f2016-07-28 13:13:24 -070063
Andreas Huber5345ec22016-07-29 13:33:27 -070064 fqName.applyDefaults(mPackage.package(), mPackage.version());
65
Andreas Huber68f24592016-07-29 14:53:48 -070066 // LOG(INFO) << "importing " << fqName.string();
Andreas Huber5345ec22016-07-29 13:33:27 -070067
68 if (fqName.name().empty()) {
Andreas Huberdc981332016-07-29 15:46:54 -070069 const std::string packagePath = mCoordinator->getPackagePath(fqName);
Andreas Huber68f24592016-07-29 14:53:48 -070070 DIR *dir = opendir(packagePath.c_str());
71
72 if (dir == NULL) {
73 return false;
74 }
75
76 // Enumerate all regular files ending in ".hal" in the package directory
77 // and attempt to import all of them.
78
79 Vector<std::string> fileNames;
80
81 struct dirent *ent;
82 while ((ent = readdir(dir)) != NULL) {
83 if (ent->d_type != DT_REG) {
84 continue;
85 }
86
Andreas Huberf5dc73e2016-08-03 12:54:08 -070087 const auto suffix = ".hal";
88 const auto suffix_len = std::strlen(suffix);
89 const auto d_namelen = strlen(ent->d_name);
90
91 if (d_namelen < suffix_len
92 || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) {
Andreas Huber68f24592016-07-29 14:53:48 -070093 continue;
94 }
95
Andreas Huberf5dc73e2016-08-03 12:54:08 -070096 fileNames.push_back(std::string(ent->d_name, d_namelen - suffix_len));
Andreas Huber68f24592016-07-29 14:53:48 -070097 }
98
99 closedir(dir);
100 dir = NULL;
101
102 for (size_t i = 0; i < fileNames.size(); ++i) {
103 FQName subFQName(
104 fqName.package() + fqName.version() + "::" + fileNames[i]);
105
106 if (!subFQName.isValid()) {
107 LOG(WARNING)
108 << "Whole-package import encountered invalid filename '"
109 << fileNames[i]
110 << "' in package "
111 << fqName.package()
112 << fqName.version();
113
114 continue;
115 }
116
117 if (mCoordinator->parse(subFQName) == NULL) {
118 return false;
119 }
120 }
121
122 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700123 }
124
Andreas Huber68f24592016-07-29 14:53:48 -0700125 AST *importAST = mCoordinator->parse(fqName);
Andreas Huber5345ec22016-07-29 13:33:27 -0700126
Andreas Huber68f24592016-07-29 14:53:48 -0700127 if (importAST == NULL) {
128 return false;
129 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700130
131 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700132}
133
Andreas Huberc9410c72016-07-28 12:18:40 -0700134void AST::enterScope(Scope *container) {
135 mScopePath.push_back(container);
136}
137
138void AST::leaveScope() {
139 mScopePath.pop();
140}
141
142Scope *AST::scope() {
Andreas Hubereb1081f2016-07-28 13:13:24 -0700143 CHECK(!mScopePath.empty());
Andreas Huberc9410c72016-07-28 12:18:40 -0700144 return mScopePath.top();
145}
146
Andreas Huber5a545442016-08-03 10:44:56 -0700147bool AST::addScopedType(const char *localName, NamedType *type) {
Andreas Huber31629bc2016-08-03 09:06:40 -0700148 // LOG(INFO) << "adding scoped type '" << localName << "'";
149
Andreas Huber5a545442016-08-03 10:44:56 -0700150 bool success = scope()->addType(localName, type);
151 if (!success) {
152 return false;
153 }
154
Andreas Huber31629bc2016-08-03 09:06:40 -0700155 std::string path;
156 for (size_t i = 1; i < mScopePath.size(); ++i) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700157 path.append(mScopePath[i]->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700158 path.append(".");
159 }
160 path.append(localName);
161
162 type->setLocalName(localName);
163
164 FQName fqName(mPackage.package(), mPackage.version(), path);
165 type->setFullName(fqName);
166
Andreas Huber5a545442016-08-03 10:44:56 -0700167 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700168}
169
Andreas Huberfd4afab2016-08-03 13:02:57 -0700170Type *AST::lookupType(const char *name) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700171 FQName fqName(name);
172 CHECK(fqName.isValid());
173
Andreas Huberda51b8e2016-07-28 16:00:57 -0700174 if (fqName.name().empty()) {
175 // Given a package and version???
176 return NULL;
177 }
178
Andreas Huber84f89de2016-07-28 15:39:51 -0700179 if (fqName.package().empty() && fqName.version().empty()) {
180 // This is just a plain identifier, resolve locally first if possible.
181
182 for (size_t i = mScopePath.size(); i-- > 0;) {
183 Type *type = mScopePath[i]->lookupType(name);
184
185 if (type != NULL) {
Andreas Huberfd4afab2016-08-03 13:02:57 -0700186 return type->ref();
Andreas Huber84f89de2016-07-28 15:39:51 -0700187 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700188 }
189 }
190
Andreas Huberda51b8e2016-07-28 16:00:57 -0700191 fqName.applyDefaults(mPackage.package(), mPackage.version());
Andreas Huber84f89de2016-07-28 15:39:51 -0700192
Andreas Huber68f24592016-07-29 14:53:48 -0700193 // LOG(INFO) << "lookupType now looking for " << fqName.string();
Andreas Huber84f89de2016-07-28 15:39:51 -0700194
Andreas Huberfd4afab2016-08-03 13:02:57 -0700195 Type *resultType = mCoordinator->lookupType(fqName);
Andreas Huber737080b2016-08-02 15:38:04 -0700196
197 if (resultType) {
Andreas Huberfd4afab2016-08-03 13:02:57 -0700198 if (!resultType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700199 // Non-interface types are declared in the associated types header.
200 FQName typesName(fqName.package(), fqName.version(), "types");
201 mImportedNames.insert(typesName);
202 } else {
203 mImportedNames.insert(fqName);
204 }
Andreas Huber737080b2016-08-02 15:38:04 -0700205 }
206
207 return resultType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700208}
209
210Type *AST::lookupTypeInternal(const std::string &namePath) const {
211 Scope *scope = mRootScope;
212
213 size_t startPos = 0;
214 for (;;) {
215 size_t dotPos = namePath.find('.', startPos);
216
217 std::string component;
218 if (dotPos == std::string::npos) {
219 component = namePath.substr(startPos);
220 } else {
221 component = namePath.substr(startPos, dotPos - startPos);
222 }
223
224 Type *type = scope->lookupType(component.c_str());
225
226 if (type == NULL) {
227 return NULL;
228 }
229
230 if (dotPos == std::string::npos) {
231 return type;
232 }
233
234 if (!type->isScope()) {
235 return NULL;
236 }
237
238 scope = static_cast<Scope *>(type);
239 startPos = dotPos + 1;
240 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700241}
242
Andreas Huberc9410c72016-07-28 12:18:40 -0700243} // namespace android;