blob: f23c37d67a8850148dee0e78ccdf2523d4c21b0e [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 Huber31629bc2016-08-03 09:06:40 -0700144void AST::addScopedType(const char *localName, NamedType *type) {
145 // LOG(INFO) << "adding scoped type '" << localName << "'";
146
147 std::string path;
148 for (size_t i = 1; i < mScopePath.size(); ++i) {
149 path.append(mScopePath[i]->name());
150 path.append(".");
151 }
152 path.append(localName);
153
154 type->setLocalName(localName);
155
156 FQName fqName(mPackage.package(), mPackage.version(), path);
157 type->setFullName(fqName);
158
159 scope()->addType(localName, type);
160}
161
Andreas Huber737080b2016-08-02 15:38:04 -0700162Type *AST::lookupType(const char *name) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700163 FQName fqName(name);
164 CHECK(fqName.isValid());
165
Andreas Huberda51b8e2016-07-28 16:00:57 -0700166 if (fqName.name().empty()) {
167 // Given a package and version???
168 return NULL;
169 }
170
Andreas Huber84f89de2016-07-28 15:39:51 -0700171 if (fqName.package().empty() && fqName.version().empty()) {
172 // This is just a plain identifier, resolve locally first if possible.
173
174 for (size_t i = mScopePath.size(); i-- > 0;) {
175 Type *type = mScopePath[i]->lookupType(name);
176
177 if (type != NULL) {
Andreas Huber867fcb62016-08-02 16:26:34 -0700178 return new RefType(type);
Andreas Huber84f89de2016-07-28 15:39:51 -0700179 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700180 }
181 }
182
Andreas Huberda51b8e2016-07-28 16:00:57 -0700183 fqName.applyDefaults(mPackage.package(), mPackage.version());
Andreas Huber84f89de2016-07-28 15:39:51 -0700184
Andreas Huber68f24592016-07-29 14:53:48 -0700185 // LOG(INFO) << "lookupType now looking for " << fqName.string();
Andreas Huber84f89de2016-07-28 15:39:51 -0700186
Andreas Huber737080b2016-08-02 15:38:04 -0700187 Type *resultType = mCoordinator->lookupType(fqName);
188
189 if (resultType) {
190 mImportedNames.insert(fqName);
191 }
192
193 return resultType;
Andreas Huber5345ec22016-07-29 13:33:27 -0700194}
195
196Type *AST::lookupTypeInternal(const std::string &namePath) const {
197 Scope *scope = mRootScope;
198
199 size_t startPos = 0;
200 for (;;) {
201 size_t dotPos = namePath.find('.', startPos);
202
203 std::string component;
204 if (dotPos == std::string::npos) {
205 component = namePath.substr(startPos);
206 } else {
207 component = namePath.substr(startPos, dotPos - startPos);
208 }
209
210 Type *type = scope->lookupType(component.c_str());
211
212 if (type == NULL) {
213 return NULL;
214 }
215
216 if (dotPos == std::string::npos) {
217 return type;
218 }
219
220 if (!type->isScope()) {
221 return NULL;
222 }
223
224 scope = static_cast<Scope *>(type);
225 startPos = dotPos + 1;
226 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700227}
228
Andreas Huberc9410c72016-07-28 12:18:40 -0700229} // namespace android;