blob: 651b14a74c89a0c58d582f2b14ec46144c0be2d6 [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
Andreas Huberf5dc73e2016-08-03 12:54:08 -070088 const auto suffix = ".hal";
89 const auto suffix_len = std::strlen(suffix);
90 const auto d_namelen = strlen(ent->d_name);
91
92 if (d_namelen < suffix_len
93 || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) {
Andreas Huber68f24592016-07-29 14:53:48 -070094 continue;
95 }
96
Andreas Huberf5dc73e2016-08-03 12:54:08 -070097 fileNames.push_back(std::string(ent->d_name, d_namelen - suffix_len));
Andreas Huber68f24592016-07-29 14:53:48 -070098 }
99
100 closedir(dir);
101 dir = NULL;
102
103 for (size_t i = 0; i < fileNames.size(); ++i) {
104 FQName subFQName(
105 fqName.package() + fqName.version() + "::" + fileNames[i]);
106
107 if (!subFQName.isValid()) {
108 LOG(WARNING)
109 << "Whole-package import encountered invalid filename '"
110 << fileNames[i]
111 << "' in package "
112 << fqName.package()
113 << fqName.version();
114
115 continue;
116 }
117
118 if (mCoordinator->parse(subFQName) == NULL) {
119 return false;
120 }
121 }
122
123 return true;
Andreas Huber5345ec22016-07-29 13:33:27 -0700124 }
125
Andreas Huber68f24592016-07-29 14:53:48 -0700126 AST *importAST = mCoordinator->parse(fqName);
Andreas Huber5345ec22016-07-29 13:33:27 -0700127
Andreas Huber68f24592016-07-29 14:53:48 -0700128 if (importAST == NULL) {
129 return false;
130 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700131
132 return true;
Andreas Hubereb1081f2016-07-28 13:13:24 -0700133}
134
Andreas Huberc9410c72016-07-28 12:18:40 -0700135void AST::enterScope(Scope *container) {
136 mScopePath.push_back(container);
137}
138
139void AST::leaveScope() {
140 mScopePath.pop();
141}
142
143Scope *AST::scope() {
Andreas Hubereb1081f2016-07-28 13:13:24 -0700144 CHECK(!mScopePath.empty());
Andreas Huberc9410c72016-07-28 12:18:40 -0700145 return mScopePath.top();
146}
147
Andreas Huber5a545442016-08-03 10:44:56 -0700148bool AST::addScopedType(const char *localName, NamedType *type) {
Andreas Huber31629bc2016-08-03 09:06:40 -0700149 // LOG(INFO) << "adding scoped type '" << localName << "'";
150
Andreas Huber5a545442016-08-03 10:44:56 -0700151 bool success = scope()->addType(localName, type);
152 if (!success) {
153 return false;
154 }
155
Andreas Huber31629bc2016-08-03 09:06:40 -0700156 std::string path;
157 for (size_t i = 1; i < mScopePath.size(); ++i) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700158 path.append(mScopePath[i]->localName());
Andreas Huber31629bc2016-08-03 09:06:40 -0700159 path.append(".");
160 }
161 path.append(localName);
162
163 type->setLocalName(localName);
164
165 FQName fqName(mPackage.package(), mPackage.version(), path);
166 type->setFullName(fqName);
167
Andreas Huber5a545442016-08-03 10:44:56 -0700168 return true;
Andreas Huber31629bc2016-08-03 09:06:40 -0700169}
170
Andreas Huber0e00de42016-08-03 09:56:02 -0700171RefType *AST::lookupType(const char *name) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700172 FQName fqName(name);
173 CHECK(fqName.isValid());
174
Andreas Huberda51b8e2016-07-28 16:00:57 -0700175 if (fqName.name().empty()) {
176 // Given a package and version???
177 return NULL;
178 }
179
Andreas Huber84f89de2016-07-28 15:39:51 -0700180 if (fqName.package().empty() && fqName.version().empty()) {
181 // This is just a plain identifier, resolve locally first if possible.
182
183 for (size_t i = mScopePath.size(); i-- > 0;) {
184 Type *type = mScopePath[i]->lookupType(name);
185
186 if (type != NULL) {
Andreas Huber867fcb62016-08-02 16:26:34 -0700187 return new RefType(type);
Andreas Huber84f89de2016-07-28 15:39:51 -0700188 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700189 }
190 }
191
Andreas Huberda51b8e2016-07-28 16:00:57 -0700192 fqName.applyDefaults(mPackage.package(), mPackage.version());
Andreas Huber84f89de2016-07-28 15:39:51 -0700193
Andreas Huber68f24592016-07-29 14:53:48 -0700194 // LOG(INFO) << "lookupType now looking for " << fqName.string();
Andreas Huber84f89de2016-07-28 15:39:51 -0700195
Andreas Huber0e00de42016-08-03 09:56:02 -0700196 RefType *resultType = mCoordinator->lookupType(fqName);
Andreas Huber737080b2016-08-02 15:38:04 -0700197
198 if (resultType) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700199 if (!resultType->referencedType()->isInterface()) {
200 // Non-interface types are declared in the associated types header.
201 FQName typesName(fqName.package(), fqName.version(), "types");
202 mImportedNames.insert(typesName);
203 } else {
204 mImportedNames.insert(fqName);
205 }
Andreas Huber737080b2016-08-02 15:38:04 -0700206 }
207
208 return resultType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700209}
210
211Type *AST::lookupTypeInternal(const std::string &namePath) const {
212 Scope *scope = mRootScope;
213
214 size_t startPos = 0;
215 for (;;) {
216 size_t dotPos = namePath.find('.', startPos);
217
218 std::string component;
219 if (dotPos == std::string::npos) {
220 component = namePath.substr(startPos);
221 } else {
222 component = namePath.substr(startPos, dotPos - startPos);
223 }
224
225 Type *type = scope->lookupType(component.c_str());
226
227 if (type == NULL) {
228 return NULL;
229 }
230
231 if (dotPos == std::string::npos) {
232 return type;
233 }
234
235 if (!type->isScope()) {
236 return NULL;
237 }
238
239 scope = static_cast<Scope *>(type);
240 startPos = dotPos + 1;
241 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700242}
243
Andreas Huberc9410c72016-07-28 12:18:40 -0700244} // namespace android;