blob: c26c99c6dfc45752f854d0f061411a4dcadeb0a1 [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"
Andreas Huber8d3ac0c2016-08-04 14:49:23 -07008#include "TypeDef.h"
Andreas Huberc9410c72016-07-28 12:18:40 -07009
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 Huberfd4afab2016-08-03 13:02:57 -0700171Type *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 Huber8d3ac0c2016-08-04 14:49:23 -0700187 // Resolve typeDefs to the target type.
188 while (type->isTypeDef()) {
189 type = static_cast<TypeDef *>(type)->referencedType();
190 }
191
Andreas Huberfd4afab2016-08-03 13:02:57 -0700192 return type->ref();
Andreas Huber84f89de2016-07-28 15:39:51 -0700193 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700194 }
195 }
196
Andreas Huberda51b8e2016-07-28 16:00:57 -0700197 fqName.applyDefaults(mPackage.package(), mPackage.version());
Andreas Huber84f89de2016-07-28 15:39:51 -0700198
Andreas Huber68f24592016-07-29 14:53:48 -0700199 // LOG(INFO) << "lookupType now looking for " << fqName.string();
Andreas Huber84f89de2016-07-28 15:39:51 -0700200
Andreas Huberfd4afab2016-08-03 13:02:57 -0700201 Type *resultType = mCoordinator->lookupType(fqName);
Andreas Huber737080b2016-08-02 15:38:04 -0700202
203 if (resultType) {
Andreas Huberfd4afab2016-08-03 13:02:57 -0700204 if (!resultType->isInterface()) {
Andreas Huber0e00de42016-08-03 09:56:02 -0700205 // Non-interface types are declared in the associated types header.
206 FQName typesName(fqName.package(), fqName.version(), "types");
207 mImportedNames.insert(typesName);
208 } else {
209 mImportedNames.insert(fqName);
210 }
Andreas Huber737080b2016-08-02 15:38:04 -0700211 }
212
213 return resultType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700214}
215
216Type *AST::lookupTypeInternal(const std::string &namePath) const {
217 Scope *scope = mRootScope;
218
219 size_t startPos = 0;
220 for (;;) {
221 size_t dotPos = namePath.find('.', startPos);
222
223 std::string component;
224 if (dotPos == std::string::npos) {
225 component = namePath.substr(startPos);
226 } else {
227 component = namePath.substr(startPos, dotPos - startPos);
228 }
229
230 Type *type = scope->lookupType(component.c_str());
231
232 if (type == NULL) {
233 return NULL;
234 }
235
236 if (dotPos == std::string::npos) {
Andreas Huber8d3ac0c2016-08-04 14:49:23 -0700237 // Resolve typeDefs to the target type.
238 while (type->isTypeDef()) {
239 type = static_cast<TypeDef *>(type)->referencedType();
240 }
241
Andreas Huber5345ec22016-07-29 13:33:27 -0700242 return type;
243 }
244
245 if (!type->isScope()) {
246 return NULL;
247 }
248
249 scope = static_cast<Scope *>(type);
250 startPos = dotPos + 1;
251 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700252}
253
Andreas Huberc9410c72016-07-28 12:18:40 -0700254} // namespace android;