hqlrepository.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "hqlrepository.hpp"
  14. #include "hqlerrors.hpp"
  15. #include "hqlplugins.hpp"
  16. #include "jdebug.hpp"
  17. #include "jfile.hpp"
  18. #include "eclrtl.hpp"
  19. #include "hqlexpr.ipp"
  20. #include "hqlerror.hpp"
  21. //-------------------------------------------------------------------------------------------------------------------
  22. static void getRootScopes(HqlScopeArray & rootScopes, IHqlScope * scope)
  23. {
  24. HqlExprArray rootSymbols;
  25. scope->getSymbols(rootSymbols);
  26. ForEachItemIn(i, rootSymbols)
  27. {
  28. IHqlExpression & cur = rootSymbols.item(i);
  29. IHqlScope * scope = cur.queryScope();
  30. if (scope)
  31. rootScopes.append(*LINK(scope));
  32. }
  33. }
  34. void getRootScopes(HqlScopeArray & rootScopes, IHqlScope * scope, HqlLookupContext & ctx)
  35. {
  36. scope->ensureSymbolsDefined(ctx);
  37. getRootScopes(rootScopes, scope);
  38. }
  39. void getRootScopes(HqlScopeArray & rootScopes, IEclRepository * repository, HqlLookupContext & ctx)
  40. {
  41. getRootScopes(rootScopes, repository->queryRootScope(), ctx);
  42. }
  43. void getImplicitScopes(HqlScopeArray& implicitScopes, IEclRepository * repository, IHqlScope * scope, HqlLookupContext & ctx)
  44. {
  45. //Any implicit scope requires explicit module imports
  46. if (scope->isImplicit())
  47. return;
  48. //See note before CMergedScope for notes about implicit scopes.
  49. HqlScopeArray rootScopes;
  50. getRootScopes(rootScopes, repository->queryRootScope(), ctx);
  51. ForEachItemIn(i, rootScopes)
  52. {
  53. IHqlScope & scope = rootScopes.item(i);
  54. if (scope.isImplicit())
  55. implicitScopes.append(OLINK(scope));
  56. }
  57. }
  58. extern HQL_API void importRootModulesToScope(IHqlScope * scope, HqlLookupContext & ctx)
  59. {
  60. IEclRepository * eclRepository = ctx.queryRepository();
  61. HqlScopeArray rootScopes;
  62. getRootScopes(rootScopes, eclRepository, ctx);
  63. ForEachItemIn(i, rootScopes)
  64. {
  65. IHqlScope & cur = rootScopes.item(i);
  66. IIdAtom * curName = cur.queryId();
  67. OwnedHqlExpr resolved = eclRepository->queryRootScope()->lookupSymbol(curName, LSFpublic, ctx);
  68. if (resolved)
  69. scope->defineSymbol(curName, NULL, resolved.getClear(), false, true, ob_import);
  70. }
  71. }
  72. //-------------------------------------------------------------------------------------------------------------------
  73. IHqlExpression * getResolveAttributeFullPath(const char * attrname, unsigned lookupFlags, HqlLookupContext & ctx)
  74. {
  75. Linked<IHqlScope> parentScope = ctx.queryRepository()->queryRootScope();
  76. const char * item = attrname;
  77. loop
  78. {
  79. const char * dot = strchr(item, '.');
  80. IIdAtom * moduleName;
  81. if (dot)
  82. {
  83. moduleName = createIdAtom(item, dot-item);
  84. item = dot + 1;
  85. }
  86. else
  87. {
  88. moduleName = createIdAtom(item);
  89. }
  90. //Check for empty module name
  91. if (!moduleName)
  92. return NULL;
  93. OwnedHqlExpr resolved = parentScope->lookupSymbol(moduleName, lookupFlags, ctx);
  94. if (!resolved || !dot)
  95. return resolved.getClear();
  96. IHqlScope * scope = resolved->queryScope();
  97. if (!scope)
  98. return NULL;
  99. parentScope.set(scope);
  100. }
  101. }
  102. IHqlScope * getResolveDottedScope(const char * modname, unsigned lookupFlags, HqlLookupContext & ctx)
  103. {
  104. if (!modname || !*modname)
  105. return LINK(ctx.queryRepository()->queryRootScope());
  106. OwnedHqlExpr matched = getResolveAttributeFullPath(modname, lookupFlags, ctx);
  107. if (matched)
  108. return LINK(matched->queryScope());
  109. return NULL;
  110. }
  111. //-------------------------------------------------------------------------------------------------------------------
  112. class HQL_API CompoundEclRepository : public CInterface, implements IEclRepository
  113. {
  114. public:
  115. CompoundEclRepository() { rootScope.setown(new CHqlMergedScope(NULL, NULL)); }
  116. IMPLEMENT_IINTERFACE;
  117. void addRepository(IEclRepository & _repository);
  118. virtual IHqlScope * queryRootScope() { return rootScope; }
  119. protected:
  120. IArrayOf<IEclRepository> repositories;
  121. Owned<CHqlMergedScope> rootScope;
  122. };
  123. void CompoundEclRepository::addRepository(IEclRepository & _repository)
  124. {
  125. repositories.append(OLINK(_repository));
  126. rootScope->addScope(_repository.queryRootScope());
  127. }
  128. //-------------------------------------------------------------------------------------------------------------------
  129. extern HQL_API IEclRepository * createCompoundRepositoryF(IEclRepository * repository, ...)
  130. {
  131. Owned<CompoundEclRepository> compound = new CompoundEclRepository;
  132. compound->addRepository(*repository);
  133. va_list args;
  134. va_start(args, repository);
  135. for (;;)
  136. {
  137. IEclRepository * next = va_arg(args, IEclRepository*);
  138. if (!next)
  139. break;
  140. compound->addRepository(*next);
  141. }
  142. va_end(args);
  143. return compound.getClear();
  144. }
  145. extern HQL_API IEclRepository * createCompoundRepository(EclRepositoryArray & repositories)
  146. {
  147. Owned<CompoundEclRepository> compound = new CompoundEclRepository;
  148. ForEachItemIn(i, repositories)
  149. compound->addRepository(repositories.item(i));
  150. return compound.getClear();
  151. }
  152. //-------------------------------------------------------------------------------------------------------------------
  153. class HQL_API NestedEclRepository : public CInterface, implements IEclRepository
  154. {
  155. public:
  156. NestedEclRepository(IIdAtom * name, IEclRepository * _repository) : repository(_repository)
  157. {
  158. rootScope.setown(createScope());
  159. IHqlExpression * scope = repository->queryRootScope()->queryExpression();
  160. rootScope->defineSymbol(name, NULL, LINK(scope), true, false, 0);
  161. }
  162. IMPLEMENT_IINTERFACE;
  163. virtual IHqlScope * queryRootScope() { return rootScope; }
  164. protected:
  165. Linked<IEclRepository> repository;
  166. Owned<IHqlScope> rootScope;
  167. };
  168. //-------------------------------------------------------------------------------------------------------------------
  169. extern HQL_API IEclRepository * createNestedRepository(IIdAtom * name, IEclRepository * repository)
  170. {
  171. if (!repository)
  172. return NULL;
  173. return new NestedEclRepository(name, repository);
  174. }
  175. //-------------------------------------------------------------------------------------------------------------------
  176. static IIdAtom * queryModuleIdFromFullName(const char * name)
  177. {
  178. if (!name)
  179. return NULL;
  180. const char * dot = strrchr(name, '.');
  181. if (dot)
  182. return createIdAtom(dot+1);
  183. return createIdAtom(name);
  184. }
  185. class HQL_API CNewEclRepository : public CInterface, implements IEclRepositoryCallback
  186. {
  187. public:
  188. CNewEclRepository(IEclSourceCollection * _collection, const char * rootScopeFullName) : collection(_collection)
  189. {
  190. rootScope.setown(createRemoteScope(queryModuleIdFromFullName(rootScopeFullName), rootScopeFullName, this, NULL, NULL, true, NULL));
  191. }
  192. IMPLEMENT_IINTERFACE
  193. virtual IHqlScope * queryRootScope() { return rootScope->queryScope(); }
  194. virtual bool loadModule(IHqlRemoteScope *scope, IErrorReceiver *errs, bool forceAll);
  195. virtual IHqlExpression * loadSymbol(IHqlRemoteScope *scope, IIdAtom * searchName);
  196. protected:
  197. IHqlExpression * createSymbol(IHqlRemoteScope * rScope, IEclSource * source);
  198. protected:
  199. Linked<IEclSourceCollection> collection;
  200. Owned<IHqlRemoteScope> rootScope;
  201. CriticalSection cs;
  202. };
  203. bool CNewEclRepository::loadModule(IHqlRemoteScope * rScope, IErrorReceiver *errs, bool forceAll)
  204. {
  205. IEclSource * parent = rScope->queryEclSource();
  206. CHqlRemoteScope * targetScope = static_cast<CHqlRemoteScope *>(rScope);
  207. Owned<IEclSourceIterator> iter = collection->getContained(parent);
  208. if (iter)
  209. {
  210. ForEach(*iter)
  211. {
  212. IEclSource * next = &iter->query();
  213. Owned<IHqlExpression> element = createSymbol(rScope, next);
  214. targetScope->defineSymbol(LINK(element));
  215. }
  216. }
  217. return true;
  218. }
  219. IHqlExpression * CNewEclRepository::loadSymbol(IHqlRemoteScope * rScope, IIdAtom * searchName)
  220. {
  221. IEclSource * parent = rScope->queryEclSource();
  222. Owned<IEclSource> source = collection->getSource(parent, searchName);
  223. return createSymbol(rScope, source);
  224. }
  225. static void getFullName(StringBuffer & fullName, IHqlScope * scope, IIdAtom * attrName)
  226. {
  227. fullName.append(scope->queryFullName());
  228. if (fullName.length())
  229. fullName.append(".");
  230. fullName.append(attrName->str());
  231. }
  232. IHqlExpression * CNewEclRepository::createSymbol(IHqlRemoteScope * rScope, IEclSource * source)
  233. {
  234. IIdAtom * eclId = source->queryEclId();
  235. IHqlScope * scope = rScope->queryScope();
  236. StringBuffer fullName;
  237. getFullName(fullName, scope, eclId);
  238. EclSourceType sourceType = source->queryType();
  239. IFileContents * contents = source->queryFileContents();
  240. OwnedHqlExpr body;
  241. unsigned symbolFlags = 0;
  242. switch (sourceType)
  243. {
  244. case ESTdefinition:
  245. {
  246. Owned<IProperties> props = source->getProperties();
  247. if (props)
  248. {
  249. unsigned flags = props->getPropInt(flagsAtom->str(), 0);
  250. if (flags & ob_sandbox)
  251. symbolFlags |= ob_sandbox;
  252. }
  253. /*
  254. int flags = t->getPropInt("@flags", 0);
  255. if(access >= cs_read)
  256. flags|=ob_showtext;
  257. */
  258. break;
  259. }
  260. case ESTplugin:
  261. case ESTmodule:
  262. case ESTlibrary:
  263. {
  264. //Slightly ugly create a "delayed" nested scope instead. But with a NULL owner - so will never be called back
  265. //Probably should be a difference class instance
  266. Owned<IProperties> props = source->getProperties();
  267. Owned<IHqlRemoteScope> childScope = createRemoteScope(eclId, fullName.str(), NULL, props, contents, true, source);
  268. body.set(queryExpression(childScope->queryScope()));
  269. break;
  270. }
  271. case ESTcontainer:
  272. {
  273. Owned<IProperties> props = source->getProperties();
  274. Owned<IHqlRemoteScope> childScope = createRemoteScope(eclId, fullName.str(), this, props, NULL, true, source);
  275. body.set(queryExpression(childScope->queryScope()));
  276. break;
  277. }
  278. default:
  279. throwUnexpected();
  280. }
  281. return ::createSymbol(eclId, scope->queryId(), body.getClear(), NULL, true, true, symbolFlags, contents, 0, 0, 0, 0, 0);
  282. }
  283. extern HQL_API IEclRepository * createRepository(IEclSourceCollection * source, const char * rootScopeFullName)
  284. {
  285. return new CNewEclRepository(source, rootScopeFullName);
  286. }
  287. extern HQL_API IEclRepository * createRepository(EclSourceCollectionArray & sources)
  288. {
  289. if (sources.ordinality() == 0)
  290. return NULL;
  291. if (sources.ordinality() == 1)
  292. return createRepository(&sources.item(0));
  293. EclRepositoryArray repositories;
  294. ForEachItemIn(i, sources)
  295. repositories.append(*createRepository(&sources.item(i)));
  296. return createCompoundRepository(repositories);
  297. }
  298. //-------------------------------------------------------------------------------------------------------------------
  299. #include "hqlcollect.hpp"
  300. extern HQL_API IEclRepository * createNewSourceFileEclRepository(IErrorReceiver *errs, const char * path, unsigned flags, unsigned trace)
  301. {
  302. Owned<IEclSourceCollection> source = createFileSystemEclCollection(errs, path, flags, trace);
  303. return createRepository(source);
  304. }
  305. extern HQL_API IEclRepository * createSingleDefinitionEclRepository(const char * moduleName, const char * attrName, IFileContents * contents)
  306. {
  307. Owned<IEclSourceCollection> source = createSingleDefinitionEclCollection(moduleName, attrName, contents);
  308. return createRepository(source);
  309. }