PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/model/VarDef.cc

https://code.google.com/p/crack-language/
C++ | 517 lines | 416 code | 70 blank | 31 comment | 60 complexity | 0b7aad7b8a37ab740bbe873b456b4926 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0, LGPL-3.0, Apache-2.0
  1. // Copyright 2009-2012 Google Inc.
  2. // Copyright 2010 Shannon Weyrick <weyrick@mozek.us>
  3. //
  4. // This Source Code Form is subject to the terms of the Mozilla Public
  5. // License, v. 2.0. If a copy of the MPL was not distributed with this
  6. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  7. //
  8. #include "VarDef.h"
  9. #include <sstream>
  10. #include "builder/Builder.h"
  11. #include "spug/check.h"
  12. #include "AssignExpr.h"
  13. #include "Deserializer.h"
  14. #include "GlobalNamespace.h"
  15. #include "VarDefImpl.h"
  16. #include "Context.h"
  17. #include "CompositeNamespace.h"
  18. #include "Expr.h"
  19. #include "ModuleDefMap.h"
  20. #include "ModuleStub.h"
  21. #include "NestedDeserializer.h"
  22. #include "OverloadDef.h"
  23. #include "ProtoBuf.h"
  24. #include "ResultExpr.h"
  25. #include "Serializer.h"
  26. #include "StubDef.h"
  27. #include "TypeDef.h"
  28. using namespace std;
  29. using namespace model;
  30. VarDef::VarDef(TypeDef *type, const std::string &name) :
  31. type(type),
  32. name(name),
  33. owner(0),
  34. constant(false),
  35. stubFree(false) {
  36. }
  37. VarDef::~VarDef() {}
  38. ResultExprPtr VarDef::emitAssignment(Context &context, Expr *expr) {
  39. AssignExprPtr assign = new AssignExpr(0, this, expr);
  40. return impl->emitAssignment(context, assign.get());
  41. }
  42. bool VarDef::hasInstSlot() {
  43. return impl->hasInstSlot();
  44. }
  45. int VarDef::getInstSlot() const {
  46. return impl->getInstSlot();
  47. }
  48. bool VarDef::isStatic() const {
  49. return false;
  50. }
  51. std::string VarDef::getFullName() const {
  52. if (!fullName.empty())
  53. return fullName;
  54. if (owner && !owner->getNamespaceName().empty())
  55. fullName = owner->getNamespaceName()+"."+name;
  56. else
  57. fullName = name;
  58. return fullName;
  59. }
  60. std::string VarDef::getDisplayName() const {
  61. assert(owner && "no owner defined when getting display name");
  62. std::string module = owner->getNamespaceName();
  63. if (!module.compare(0, 6, ".main.")) {
  64. // find the next namespace after the main script
  65. size_t pos = module.find('.', 6);
  66. if (pos != string::npos)
  67. return module.substr(pos + 1) + "." + name;
  68. else
  69. return name;
  70. } else if (module == ".builtin") {
  71. return name;
  72. } else {
  73. return getFullName();
  74. }
  75. }
  76. bool VarDef::isConstant() {
  77. return constant;
  78. }
  79. bool VarDef::isHidden() const {
  80. return owner->isHiddenScope();
  81. }
  82. void VarDef::dump(ostream &out, const string &prefix) const {
  83. out << prefix << (type ? type->getFullName() : string("<null>")) << " " << name << endl;
  84. }
  85. void VarDef::dump() const {
  86. dump(std::cerr, "");
  87. }
  88. ModuleDef *VarDef::getModule() const {
  89. return owner->getModule().get();
  90. }
  91. namespace {
  92. bool isExported(const Namespace *ns, const string &name) {
  93. const ModuleDef *modDef = dynamic_cast<const ModuleDef *>(ns);
  94. return modDef && (modDef->exports.find(name) != modDef->exports.end());
  95. }
  96. }
  97. bool VarDef::isImportableFrom(ModuleDef *module, const string &impName) const {
  98. return owner->getRealModule().get() == module ||
  99. module->exports.find(impName) != module->exports.end();
  100. }
  101. bool VarDef::isImportable(const Namespace *ns, const string &name) const {
  102. // A symbol is importable if:
  103. // 1) it is either defined in the namespace we are importing it from or
  104. // explicitly exported from the namespace we are importing it from
  105. // (the "second order import" rules) _and_
  106. // 2) It is either non-private (no leading underscore) or type-scoped and
  107. // not class-private.
  108. return (owner == ns || isExported(ns, name)) &&
  109. (name[0] != '_' ||
  110. (TypeDefPtr::cast(owner) && name.substr(0, 2) != "__")
  111. );
  112. }
  113. bool VarDef::isSerializable() const {
  114. return name[0] != ':';
  115. }
  116. void VarDef::addDependenciesTo(ModuleDef *mod, VarDef::Set &added) const {
  117. ModuleDefPtr depMod = getModule();
  118. mod->addDependency(depMod.get());
  119. // add the dependencies of the type
  120. if (type.get() != this)
  121. type->addDependenciesTo(mod, added);
  122. }
  123. void VarDef::serializeExternCommon(Serializer &serializer,
  124. const TypeDef::TypeVec *localDeps
  125. ) const {
  126. ModuleDefPtr module = getModule();
  127. serializer.write(module->getFullName(), "module");
  128. // calcuate the module relative name.
  129. list<string> moduleRelativeName;
  130. moduleRelativeName.push_front(name);
  131. NamespacePtr cur = getOwner();
  132. while (cur != module.get()) {
  133. // special-case the builtin module, which currently doesn't have an
  134. // ownership chain to its module.
  135. if (GlobalNamespace *gns = GlobalNamespacePtr::rcast(cur))
  136. if (gns->builtin)
  137. break;
  138. // Convert to a VarDef, push the name segment.
  139. VarDef *def = cur->asVarDef();
  140. SPUG_CHECK(def,
  141. "namespace " << cur->getNamespaceName() <<
  142. " is not a VarDef."
  143. );
  144. moduleRelativeName.push_front(def->name);
  145. cur = cur->getNamespaceOwner();
  146. }
  147. // is this a shared library function?
  148. const FuncDef *funcDef = dynamic_cast<const FuncDef *>(this);
  149. if (funcDef && !(funcDef->flags & FuncDef::shlib))
  150. // if it's not a shared library function, clear it so we don't a field
  151. // for it.
  152. funcDef = 0;
  153. ostringstream tmp;
  154. Serializer sub(serializer, tmp);
  155. // For primitive generic specializations, the "name" attribute currently
  156. // contains the parameters, so we trim them.
  157. const TypeDef *asType = dynamic_cast<const TypeDef *>(this);
  158. if (asType && asType->primitiveGenericSpec) {
  159. sub.write(CRACK_PB_KEY(3, string), "name.header");
  160. sub.write(name.substr(0, name.find('[')), "name");
  161. localDeps = &asType->genericParms;
  162. } else {
  163. // write the full name.
  164. for (list<string>::iterator i = moduleRelativeName.begin();
  165. i != moduleRelativeName.end();
  166. ++i
  167. ) {
  168. sub.write(CRACK_PB_KEY(3, string), "name.header");
  169. sub.write(*i, "name");
  170. }
  171. }
  172. if (funcDef) {
  173. ostringstream funcDefData;
  174. Serializer funcDefSerializer(funcDefData);
  175. funcDef->serializeCommon(funcDefSerializer);
  176. sub.write(CRACK_PB_KEY(1, string), "shlibFuncDef.header");
  177. sub.write(funcDefData.str(), "shlibFuncDef.body");
  178. }
  179. // write the local deps list.
  180. if (localDeps) {
  181. for (TypeDef::TypeVec::const_iterator iter = localDeps->begin();
  182. iter != localDeps->end();
  183. ++iter
  184. ) {
  185. sub.write(CRACK_PB_KEY(2, ref), "localDeps.header");
  186. (*iter)->serialize(sub, false, 0);
  187. }
  188. }
  189. serializer.write(tmp.str(), "optional");
  190. }
  191. void VarDef::serializeExternRef(Serializer &serializer,
  192. const TypeDef::TypeVec *localDeps
  193. ) const {
  194. if (serializer.writeObject(this, "ext"))
  195. serializeExternCommon(serializer, localDeps);
  196. }
  197. void VarDef::serializeExtern(Serializer &serializer) const {
  198. serializeExternCommon(serializer, 0);
  199. }
  200. void VarDef::serializeAlias(Serializer &serializer, const string &alias) const {
  201. serializer.write(Serializer::aliasId, "kind");
  202. serializer.write(alias, "alias");
  203. serializeExternRef(serializer, 0);
  204. }
  205. namespace {
  206. enum SymbolKind {
  207. K_TYPE,
  208. K_OVLD,
  209. K_VAR
  210. };
  211. VarDefPtr resolveActualPath(Context &context, ModuleDef *module,
  212. list<string>::iterator curName,
  213. list<string>::iterator endName
  214. ) {
  215. list<string>::iterator next = curName;
  216. ++next;
  217. NamespacePtr ns = module;
  218. for (; next != endName; ++curName, ++next) {
  219. ns = ns->lookUp(*curName);
  220. SPUG_CHECK(ns,
  221. "Path element " << *curName << " in module " <<
  222. module << " should be a namespace."
  223. );
  224. }
  225. return ns->lookUp(*curName);
  226. }
  227. // Resolve path for stub modules.
  228. VarDefPtr resolveStubPath(Context &context, ModuleStub *module,
  229. list<string>::iterator curName,
  230. list<string>::iterator endName,
  231. SymbolKind kind
  232. ) {
  233. module->dependents.insert(
  234. ModuleDefPtr::arcast(context.getModuleContext()->ns)
  235. );
  236. list<string>::iterator next = curName;
  237. ++next;
  238. NamespaceStubPtr ns = module;
  239. for (; next != endName; ++curName, ++next)
  240. ns = ns->getTypeNSStub(*curName);
  241. switch (kind) {
  242. case K_TYPE:
  243. return ns->getTypeStub(*curName);
  244. case K_OVLD:
  245. return ns->getOverloadStub(*curName);
  246. case K_VAR:
  247. return ns->getVarStub(*curName);
  248. default:
  249. SPUG_CHECK(false, "Unknoan symbol kind: " << kind);
  250. }
  251. }
  252. template<typename T>
  253. struct IterPair {
  254. typedef T iterator;
  255. T beginVal, endVal;
  256. T begin() const { return beginVal; }
  257. T end() const { return endVal; }
  258. IterPair(const T &beginVal, const T &endVal) :
  259. beginVal(beginVal),
  260. endVal(endVal) {
  261. }
  262. template <typename Container>
  263. IterPair(Container &container) :
  264. beginVal(container.begin()),
  265. endVal(container.end()) {
  266. }
  267. };
  268. template <typename T>
  269. ostream &operator <<(ostream &out, const IterPair<T> &val) {
  270. T i = val.begin();
  271. out << *i;
  272. ++i;
  273. for (; i != val.end(); ++i)
  274. out << "." << *i;
  275. return out;
  276. }
  277. template <typename T>
  278. IterPair<T> makeIterPair(const T &begin, const T &end) {
  279. return IterPair<T>(begin, end);
  280. }
  281. template <typename T>
  282. IterPair<typename T::iterator> makeIterPair(T &container) {
  283. return IterPair<typename T::iterator>(container.begin(),
  284. container.end()
  285. );
  286. }
  287. VarDefPtr resolvePath(Context &context, const string &moduleName,
  288. list<string>::iterator curName,
  289. list<string>::iterator endName,
  290. SymbolKind kind
  291. ) {
  292. ModuleDefPtr module = context.construct->getModule(moduleName);
  293. SPUG_CHECK(module,
  294. "Unable to find module " << moduleName <<
  295. " which contains referenced symbol " <<
  296. makeIterPair(curName, endName)
  297. );
  298. if (module->finished) {
  299. return resolveActualPath(context, module.get(), curName, endName);
  300. } else {
  301. ModuleStubPtr stub = ModuleStubPtr::rcast(module);
  302. SPUG_CHECK(stub,
  303. "Referenced module " << module->getFullName() <<
  304. " is not finished, but isn't a stub."
  305. );
  306. return resolveStubPath(context, stub.get(), curName, endName, kind);
  307. }
  308. }
  309. VarDefPtr deserializeAliasBody(Deserializer &deser, SymbolKind kind) {
  310. string moduleName = deser.readString(Serializer::modNameSize,
  311. "module"
  312. );
  313. list<string> moduleRelativePath;
  314. FuncDef::Spec spec;
  315. bool sharedLibSym = false;
  316. TypeDef::TypeVecObjPtr paramTypes;
  317. CRACK_PB_BEGIN(deser, 256, optional)
  318. CRACK_PB_FIELD(3, string) {
  319. string name =
  320. optionalDeser.readString(Serializer::varNameSize, "name");
  321. moduleRelativePath.push_back(name);
  322. break;
  323. }
  324. CRACK_PB_FIELD(1, string) {
  325. NestedDeserializer funcDefDeser(optionalDeser, 32,
  326. "shlibFuncDef"
  327. );
  328. spec.deserialize(funcDefDeser);
  329. sharedLibSym = true;
  330. break;
  331. }
  332. CRACK_PB_FIELD(2, ref)
  333. if (!paramTypes)
  334. paramTypes = new TypeDef::TypeVecObj();
  335. paramTypes->push_back(TypeDef::deserializeRef(optionalDeser));
  336. break;
  337. CRACK_PB_END
  338. SPUG_CHECK(!sharedLibSym || kind == K_OVLD,
  339. "Symbol " << moduleName << "." <<
  340. makeIterPair(moduleRelativePath) <<
  341. " is a shared library symbol but we were expecting "
  342. "an object of kind = " << kind
  343. );
  344. VarDefPtr varDef;
  345. if (sharedLibSym) {
  346. ImportedDefVec symbols;
  347. SPUG_CHECK(moduleRelativePath.size() == 1,
  348. "Got a multi-level path for a shared library import: "
  349. << makeIterPair(moduleRelativePath)
  350. );
  351. string name = moduleRelativePath.front();
  352. symbols.push_back(ImportedDef(name, name));
  353. // XXX: this is horrible. This is importing the shared library
  354. // symbol into a fake namespace and then extracting it from the
  355. // namespace. We should probably add a special hook into the
  356. // builder to do this instead.
  357. GlobalNamespace ns(0, "");
  358. deser.context->builder.importSharedLibrary(moduleName,
  359. symbols,
  360. *deser.context,
  361. &ns
  362. );
  363. FuncDefPtr funcDef;
  364. varDef = ns.lookUp(name);
  365. StubDefPtr stub = StubDefPtr::rcast(varDef);
  366. if (!stub) {
  367. OverloadDefPtr ovld = OverloadDefPtr::rcast(varDef);
  368. funcDef = ovld->getSigMatch(spec.args);
  369. SPUG_CHECK(funcDef,
  370. "non-matching shared library function " <<
  371. moduleName << "." << name
  372. );
  373. return ovld;
  374. }
  375. funcDef = deser.context->builder.createExternFunc(
  376. *deser.context, spec.flags, name,
  377. spec.returnType.get(),
  378. spec.receiverType.get(),
  379. spec.args,
  380. stub->address,
  381. 0 // symbol name, need to persist.
  382. );
  383. return stub->getOwner()->replaceDef(funcDef.get());
  384. }
  385. varDef = resolvePath(*deser.context, moduleName,
  386. moduleRelativePath.begin(),
  387. moduleRelativePath.end(),
  388. kind);
  389. if (paramTypes) {
  390. TypeDefPtr typeDef = varDef;
  391. return typeDef->getSpecialization(*deser.context, paramTypes.get());
  392. } else {
  393. return varDef;
  394. }
  395. }
  396. } // anon namespace
  397. TypeDefPtr VarDef::deserializeTypeAliasBody(Deserializer &deser) {
  398. return deserializeAliasBody(deser, K_TYPE);
  399. }
  400. OverloadDefPtr VarDef::deserializeOverloadAliasBody(Deserializer &deser) {
  401. return deserializeAliasBody(deser, K_OVLD);
  402. }
  403. VarDefPtr VarDef::deserializeVarAliasBody(Deserializer &deser) {
  404. return deserializeAliasBody(deser, K_VAR);
  405. }
  406. namespace {
  407. struct AliasReader : public Deserializer::ObjectReader {
  408. virtual spug::RCBasePtr read(Deserializer &deser) const {
  409. return VarDef::deserializeVarAliasBody(deser);
  410. }
  411. };
  412. }
  413. VarDefPtr VarDef::deserializeAlias(Deserializer &serializer) {
  414. return VarDefPtr::rcast(serializer.readObject(AliasReader(),
  415. "ext"
  416. ).object
  417. );
  418. }
  419. void VarDef::serialize(Serializer &serializer, bool writeKind,
  420. const Namespace *ns
  421. ) const {
  422. if (writeKind)
  423. serializer.write(Serializer::variableId, "kind");
  424. serializer.write(name, "name");
  425. serializer.write(getInstSlot() + 1, "instSlot");
  426. type->serialize(serializer, false, ns);
  427. }
  428. VarDefPtr VarDef::deserialize(Deserializer &deser) {
  429. string name = deser.readString(16, "name");
  430. int instSlot = static_cast<int>(deser.readUInt("instSlot")) - 1;
  431. TypeDefPtr type = TypeDef::deserializeRef(deser);
  432. return deser.context->builder.materializeVar(*deser.context, name,
  433. type.get(),
  434. instSlot
  435. );
  436. }
  437. VarDefPtr VarDef::replaceAllStubs(Context &context) {
  438. if (stubFree)
  439. return this;
  440. stubFree = true;
  441. VarDefPtr replacement = replaceStub(context);
  442. if (replacement)
  443. return replacement;
  444. if (type)
  445. type = type->replaceAllStubs(context);
  446. return this;
  447. }