hqlstmt.cpp 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233
  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 "jliball.hpp"
  14. #include "hql.hpp"
  15. #include "platform.h"
  16. #include "jlib.hpp"
  17. #include "jexcept.hpp"
  18. #include "jmisc.hpp"
  19. #include "hqlexpr.hpp"
  20. #include "hqlstmt.hpp"
  21. #include "hqlstmt.ipp"
  22. #include "hqlfunc.hpp"
  23. #include "hqlcpp.ipp"
  24. #include "hqlcatom.hpp"
  25. #include "hqlcpputil.hpp"
  26. #include "hqlutil.hpp"
  27. #define CLEAR_COPY_THRESHOLD 100
  28. #ifdef _DEBUG
  29. //#define TRACK_SEARCH_DISTANCE
  30. #endif
  31. static unsigned doCalcTotalChildren(const IHqlStmt * stmt);
  32. #ifdef TRACK_SEARCH_DISTANCE
  33. static unsigned __int64 searchDistance = 0;
  34. unsigned __int64 querySearchDistance() { return searchDistance; }
  35. #else
  36. unsigned __int64 querySearchDistance() { return 0; }
  37. #endif
  38. //---------------------------------------------------------------------------
  39. struct HQLCPP_API HqlBoundDefinedValue : public HqlDefinedValue
  40. {
  41. public:
  42. HqlBoundDefinedValue(IHqlExpression * _original, const CHqlBoundExpr & _bound) : HqlDefinedValue(_original)
  43. { bound.set(_bound); }
  44. virtual IHqlExpression * queryExpr() const { return bound.expr; }
  45. virtual void getBound(CHqlBoundExpr & result) { result.set(bound); }
  46. public:
  47. CHqlBoundExpr bound;
  48. };
  49. void HqlExprAssociation::getBound(CHqlBoundExpr & result)
  50. {
  51. result.expr.set(queryExpr());
  52. }
  53. //---------------------------------------------------------------------------
  54. BuildCtx::BuildCtx(HqlCppInstance & _state, IAtom * section) : state(_state)
  55. {
  56. init(state.ensureSection(section));
  57. }
  58. BuildCtx::BuildCtx(HqlCppInstance & _state) : state(_state)
  59. {
  60. init(NULL);
  61. }
  62. BuildCtx::BuildCtx(BuildCtx & _owner) : state(_owner.state)
  63. {
  64. init(_owner.curStmts);
  65. ignoreInput = _owner.ignoreInput;
  66. curPriority = _owner.curPriority;
  67. nextPriority = _owner.nextPriority;
  68. ignoreInput = false;
  69. }
  70. BuildCtx::BuildCtx(BuildCtx & _owner, HqlStmts * _root) : state(_owner.state)
  71. {
  72. init(_root);
  73. }
  74. BuildCtx::BuildCtx(BuildCtx & _owner, IHqlStmt * _container) : state(_owner.state)
  75. {
  76. HqlCompoundStmt * cast = dynamic_cast<HqlCompoundStmt *>(_container);
  77. assertex(cast);
  78. init(&cast->code);
  79. }
  80. BuildCtx::~BuildCtx()
  81. {
  82. }
  83. void BuildCtx::set(IAtom * section)
  84. {
  85. init(state.ensureSection(section));
  86. }
  87. void BuildCtx::set(BuildCtx & _owner)
  88. {
  89. init(_owner.curStmts);
  90. ignoreInput = _owner.ignoreInput;
  91. curPriority = _owner.curPriority;
  92. nextPriority = _owner.nextPriority;
  93. ignoreInput = false;
  94. }
  95. IHqlStmt * BuildCtx::addAlias(IHqlStmt * aliased)
  96. {
  97. if (ignoreInput)
  98. return NULL;
  99. HqlCompoundStmt * next = new HqlCompoundStmt(alias_stmt, curStmts);
  100. HqlStmt * cast = dynamic_cast<HqlStmt *>(aliased);
  101. assertex(cast);
  102. next->code.append(*LINK(cast));
  103. return appendSimple(next);
  104. }
  105. IHqlStmt * BuildCtx::addAssign(IHqlExpression * target, IHqlExpression * value)
  106. {
  107. if (ignoreInput)
  108. return NULL;
  109. HqlStmt * next = new HqlStmt(assign_stmt, curStmts);
  110. next->addExpr(LINK(target));
  111. next->addExpr(LINK(value));
  112. return appendSimple(next);
  113. }
  114. IHqlStmt * BuildCtx::addAssignLink(IHqlExpression * target, IHqlExpression * value)
  115. {
  116. if (ignoreInput)
  117. return NULL;
  118. HqlStmt * next = new HqlStmt(assign_link_stmt, curStmts);
  119. next->addExpr(LINK(target));
  120. next->addExpr(LINK(value));
  121. return appendSimple(next);
  122. }
  123. IHqlStmt * BuildCtx::addAssignIncrement(IHqlExpression * target, IHqlExpression * value)
  124. {
  125. if (ignoreInput)
  126. return NULL;
  127. if (value && !matchesConstantValue(value, 1))
  128. {
  129. HqlStmt * next = new HqlStmt(assigninc_stmt, curStmts);
  130. next->addExpr(LINK(target));
  131. next->addExpr(LINK(value));
  132. return appendSimple(next);
  133. }
  134. else
  135. {
  136. OwnedHqlExpr inc = createValue(no_postinc, target->getType(), LINK(target));
  137. return addExprOwn(inc.getClear());
  138. }
  139. }
  140. IHqlStmt * BuildCtx::addAssignDecrement(IHqlExpression * target, IHqlExpression * value)
  141. {
  142. if (ignoreInput)
  143. return NULL;
  144. if (value && !matchesConstantValue(value, 1))
  145. {
  146. HqlStmt * next = new HqlStmt(assigndec_stmt, curStmts);
  147. next->addExpr(LINK(target));
  148. next->addExpr(LINK(value));
  149. return appendSimple(next);
  150. }
  151. else
  152. {
  153. OwnedHqlExpr inc = createValue(no_postdec, LINK(target->getType()), LINK(target));
  154. return addExprOwn(inc.getClear());
  155. }
  156. }
  157. IHqlStmt * BuildCtx::addBlock()
  158. {
  159. if (ignoreInput)
  160. return NULL;
  161. HqlCompoundStmt * next = new HqlCompoundStmt(block_stmt, curStmts);
  162. return appendCompound(next);
  163. }
  164. IHqlStmt * BuildCtx::addBreak()
  165. {
  166. if (ignoreInput)
  167. return NULL;
  168. HqlStmt * next = new HqlStmt(break_stmt, curStmts);
  169. return appendSimple(next);
  170. }
  171. IHqlStmt * BuildCtx::addCase(IHqlStmt * _owner, IHqlExpression * source)
  172. {
  173. if (ignoreInput)
  174. return NULL;
  175. assertThrow(_owner->getStmt() == switch_stmt);
  176. HqlCompoundStmt & owner = (HqlCompoundStmt &)*_owner;
  177. curStmts = &owner.code;
  178. HqlCompoundStmt * next = new HqlCompoundStmt(case_stmt, curStmts);
  179. next->addExpr(LINK(source));
  180. return appendCompound(next);
  181. }
  182. IHqlStmt * BuildCtx::addCatch(IHqlExpression * caught)
  183. {
  184. if (ignoreInput)
  185. return NULL;
  186. HqlCompoundStmt * next = new HqlCompoundStmt(catch_stmt, curStmts);
  187. if (caught)
  188. next->addExpr(LINK(caught));
  189. return appendCompound(next);
  190. }
  191. IHqlStmt * BuildCtx::addConditionalGroup(IHqlStmt * stmt)
  192. {
  193. if (ignoreInput)
  194. return NULL;
  195. HqlCompoundStmt * next = new HqlConditionalGroupStmt(curStmts, stmt);
  196. return appendCompound(next);
  197. }
  198. IHqlStmt * BuildCtx::addContinue()
  199. {
  200. if (ignoreInput)
  201. return NULL;
  202. HqlStmt * next = new HqlStmt(continue_stmt, curStmts);
  203. return appendSimple(next);
  204. }
  205. IHqlStmt * BuildCtx::addDeclare(IHqlExpression * name, IHqlExpression * value)
  206. {
  207. assertex(name->getOperator() == no_variable);
  208. if (ignoreInput)
  209. return NULL;
  210. HqlStmt * next = new HqlStmt(declare_stmt, curStmts);
  211. next->addExpr(LINK(name));
  212. if (value)
  213. next->addExpr(LINK(value));
  214. appendSimple(next);
  215. return next;
  216. }
  217. IHqlStmt * BuildCtx::addDeclareExternal(IHqlExpression * name)
  218. {
  219. assertex(name->getOperator() == no_variable);
  220. if (ignoreInput)
  221. return NULL;
  222. HqlStmt * next = new HqlStmt(external_stmt, curStmts);
  223. next->addExpr(LINK(name));
  224. appendSimple(next);
  225. return next;
  226. }
  227. IHqlStmt * BuildCtx::addDeclareAssign(IHqlExpression * name, IHqlExpression * value)
  228. {
  229. addDeclare(name);
  230. return addAssign(name, value);
  231. }
  232. IHqlStmt * BuildCtx::addDefault(IHqlStmt * _owner)
  233. {
  234. if (ignoreInput)
  235. return NULL;
  236. assertThrow(_owner->getStmt() == switch_stmt);
  237. selectCompound(_owner);
  238. HqlCompoundStmt * next = new HqlCompoundStmt(default_stmt, curStmts);
  239. return appendCompound(next);
  240. }
  241. IHqlStmt * BuildCtx::addExpr(IHqlExpression * value)
  242. {
  243. if (ignoreInput)
  244. return NULL;
  245. HqlStmt * next = new HqlStmt(expr_stmt, curStmts);
  246. next->addExpr(LINK(value));
  247. return appendSimple(next);
  248. }
  249. IHqlStmt * BuildCtx::addExprOwn(IHqlExpression * value)
  250. {
  251. if (ignoreInput)
  252. {
  253. value->Release();
  254. return NULL;
  255. }
  256. HqlStmt * next = new HqlStmt(expr_stmt, curStmts);
  257. next->addExpr(value);
  258. return appendSimple(next);
  259. }
  260. IHqlStmt * BuildCtx::addReturn(IHqlExpression * value)
  261. {
  262. if (ignoreInput)
  263. return NULL;
  264. HqlStmt * next = new HqlStmt(return_stmt, curStmts);
  265. if (value)
  266. next->addExpr( LINK(value));
  267. return appendSimple(next);
  268. }
  269. IHqlStmt * BuildCtx::addFilter(IHqlExpression * condition)
  270. {
  271. HqlCompoundStmt * next = new HqlCompoundStmt(filter_stmt, curStmts);
  272. next->addExpr(LINK(condition));
  273. appendCompound(next);
  274. addBlock();
  275. return next;
  276. }
  277. IHqlStmt * BuildCtx::addFunction(IHqlExpression * funcdef)
  278. {
  279. if (ignoreInput)
  280. return NULL;
  281. HqlCompoundStmt * next = new HqlCompoundStmt(function_stmt, curStmts);
  282. next->addExpr(LINK(funcdef));
  283. return appendCompound(next);
  284. }
  285. IHqlStmt * BuildCtx::addIndirection(const BuildCtx & _parent)
  286. {
  287. HqlCompoundStmt * next = new HqlCompoundStmt(indirect_stmt, _parent.curStmts);
  288. return appendCompound(next);
  289. }
  290. IHqlStmt * BuildCtx::addLoop(IHqlExpression * cond, IHqlExpression * inc, bool atEnd)
  291. {
  292. if (ignoreInput)
  293. return NULL;
  294. HqlCompoundStmt * next = new HqlCompoundStmt(loop_stmt, curStmts);
  295. if (cond)
  296. next->addExpr(LINK(cond));
  297. if (inc)
  298. next->addExpr(LINK(inc));
  299. if (atEnd)
  300. next->addExpr(createAttribute(endAtom));
  301. return appendCompound(next);
  302. }
  303. IHqlStmt * BuildCtx::addGoto(const char * labelText)
  304. {
  305. if (ignoreInput)
  306. return NULL;
  307. HqlStmt * next = new HqlStmt(goto_stmt, curStmts);
  308. IHqlExpression * label= createVariable(labelText, makeBoolType());
  309. next->addExpr(label);
  310. return appendSimple(next);
  311. }
  312. IHqlStmt * BuildCtx::addGroup()
  313. {
  314. if (ignoreInput)
  315. return NULL;
  316. HqlCompoundStmt * next = new HqlCompoundStmt(group_stmt, curStmts);
  317. return appendCompound(next);
  318. }
  319. IHqlStmt * BuildCtx::addGroupPass(IHqlExpression * pass)
  320. {
  321. if (ignoreInput)
  322. return NULL;
  323. HqlCompoundStmt * next = new HqlCompoundStmt(pass_stmt, curStmts);
  324. next->addExpr(LINK(pass));
  325. return appendCompound(next);
  326. }
  327. IHqlStmt * BuildCtx::addLabel(const char * labelText)
  328. {
  329. if (ignoreInput)
  330. return NULL;
  331. HqlStmt * next = new HqlStmt(label_stmt, curStmts);
  332. IHqlExpression * label= createVariable(labelText, makeBoolType());
  333. next->addExpr(label);
  334. return appendSimple(next);
  335. }
  336. IHqlStmt * BuildCtx::addLine(const char * filename, unsigned lineNum)
  337. {
  338. if (ignoreInput)
  339. return NULL;
  340. HqlStmt * next = new HqlStmt(line_stmt, curStmts);
  341. if (filename)
  342. {
  343. next->addExpr(createConstant(filename));
  344. next->addExpr(createConstant(createIntValue(lineNum, sizeof(int), true)));
  345. }
  346. return appendSimple(next);
  347. }
  348. IHqlStmt * BuildCtx::addQuoted(const char * text)
  349. {
  350. if (ignoreInput)
  351. return NULL;
  352. HqlStmt * next = new HqlQuoteStmt(quote_stmt, curStmts, text);
  353. return appendSimple(next);
  354. }
  355. IHqlStmt * BuildCtx::addQuotedLiteral(const char * text)
  356. {
  357. if (ignoreInput)
  358. return NULL;
  359. HqlStmt * next = new HqlQuoteLiteralStmt(quote_stmt, curStmts, text);
  360. return appendSimple(next);
  361. }
  362. IHqlStmt * BuildCtx::addQuotedF(const char * format, ...)
  363. {
  364. if (ignoreInput)
  365. return NULL;
  366. StringBuffer text;
  367. va_list args;
  368. va_start(args, format);
  369. text.valist_appendf(format, args);
  370. va_end(args);
  371. HqlStmt * next = new HqlQuoteStmt(quote_stmt, curStmts, text.str());
  372. return appendSimple(next);
  373. }
  374. IHqlStmt * BuildCtx::addQuotedCompound(const char * text, const char * extra)
  375. {
  376. if (ignoreInput)
  377. return NULL;
  378. HqlCompoundStmt * next = new HqlQuoteCompoundStmt(quote_compound_stmt, curStmts, text);
  379. if (extra)
  380. next->addExpr(createQuoted(extra, makeVoidType()));
  381. return appendCompound(next);
  382. }
  383. IHqlStmt * BuildCtx::addQuotedFunction(const char * text, bool dynamicText)
  384. {
  385. if (dynamicText)
  386. return addQuotedCompound(text, nullptr);
  387. else
  388. return addQuotedCompoundLiteral(text, nullptr);
  389. }
  390. IHqlStmt * BuildCtx::addQuotedCompoundLiteral(const char * text, const char * extra)
  391. {
  392. if (ignoreInput)
  393. return NULL;
  394. HqlCompoundStmt * next = new HqlQuoteLiteralCompoundStmt(quote_compound_stmt, curStmts, text);
  395. if (extra)
  396. next->addExpr(createQuoted(extra, makeVoidType()));
  397. return appendCompound(next);
  398. }
  399. IHqlStmt * BuildCtx::addQuotedCompoundOpt(const char * text, const char * extra)
  400. {
  401. if (ignoreInput)
  402. return NULL;
  403. HqlCompoundStmt * next = new HqlQuoteCompoundStmt(quote_compoundopt_stmt, curStmts, text);
  404. if (extra)
  405. next->addExpr(createQuoted(extra, makeVoidType()));
  406. return appendCompound(next);
  407. }
  408. IHqlStmt * BuildCtx::addSwitch(IHqlExpression * source)
  409. {
  410. if (ignoreInput)
  411. return NULL;
  412. HqlCompoundStmt * next = new HqlCompoundStmt(switch_stmt, curStmts);
  413. next->addExpr(LINK(source));
  414. return appendCompound(next);
  415. }
  416. IHqlStmt * BuildCtx::addThrow(IHqlExpression * thrown)
  417. {
  418. if (ignoreInput)
  419. return NULL;
  420. HqlStmt * next = new HqlStmt(throw_stmt, curStmts);
  421. if (thrown)
  422. next->addExpr(LINK(thrown));
  423. return appendSimple(next);
  424. }
  425. IHqlStmt * BuildCtx::addTry()
  426. {
  427. if (ignoreInput)
  428. return NULL;
  429. HqlCompoundStmt * next = new HqlCompoundStmt(try_stmt, curStmts);
  430. return appendCompound(next);
  431. }
  432. HqlStmt * BuildCtx::appendCompound(HqlCompoundStmt * next)
  433. {
  434. assertThrow(!ignoreInput);
  435. appendSimple(next);
  436. curStmts = &next->code;
  437. return next;
  438. }
  439. HqlStmt * BuildCtx::appendSimple(HqlStmt * next)
  440. {
  441. assertThrow(!ignoreInput);
  442. if (nextPriority == OutermostScopePrio)
  443. {
  444. appendToOutermostScope(next);
  445. }
  446. else
  447. {
  448. next->setPriority(nextPriority);
  449. curStmts->appendStmt(*next);
  450. }
  451. nextPriority = curPriority;
  452. return next;
  453. }
  454. void BuildCtx::appendToOutermostScope(HqlStmt * next)
  455. {
  456. HqlStmts * searchStmts = curStmts;
  457. HqlStmts * insertStmts = NULL;
  458. HqlStmt * insertBefore = NULL;
  459. for (;;)
  460. {
  461. HqlStmt * owner = searchStmts->owner;
  462. if (!owner)
  463. break;
  464. HqlStmts * ownerStmts = owner->queryContainer();
  465. switch (owner->getStmt())
  466. {
  467. case quote_compound_stmt:
  468. case quote_compoundopt_stmt:
  469. case indirect_stmt:
  470. goto found;
  471. case group_stmt:
  472. break;
  473. default:
  474. insertBefore = owner;
  475. insertStmts = ownerStmts;
  476. break;
  477. }
  478. searchStmts = ownerStmts;
  479. }
  480. found:
  481. if (insertBefore)
  482. {
  483. next->setPriority(insertBefore->queryPriority());
  484. insertStmts->add(*next, insertStmts->find(*insertBefore));
  485. }
  486. else
  487. {
  488. next->setPriority(curPriority);
  489. curStmts->appendStmt(*next);
  490. }
  491. }
  492. void BuildCtx::associate(HqlExprAssociation & next)
  493. {
  494. #ifdef _DEBUG
  495. if (next.represents->getOperator() == no_self)
  496. assertex(!queryAssociation(next.represents, next.getKind(), NULL));
  497. #endif
  498. assertex(next.represents->queryBody() == next.represents);
  499. if (!ignoreInput)
  500. {
  501. curStmts->appendOwn(OLINK(next));
  502. }
  503. }
  504. void BuildCtx::associateOwn(HqlExprAssociation & next)
  505. {
  506. assertex(next.represents->queryBody() == next.represents);
  507. if (!ignoreInput)
  508. {
  509. curStmts->appendOwn(next);
  510. }
  511. else
  512. next.Release(); // can cause serious problems....
  513. }
  514. HqlExprAssociation *BuildCtx::associateExpr(IHqlExpression * represents, IHqlExpression * expr)
  515. {
  516. if (!ignoreInput)
  517. {
  518. HqlExprAssociation * assoc = new HqlSimpleDefinedValue(represents->queryBody(), expr);
  519. curStmts->appendOwn(*assoc);
  520. return assoc;
  521. }
  522. return NULL;
  523. }
  524. HqlExprAssociation * BuildCtx::associateExpr(IHqlExpression * represents, const CHqlBoundExpr & bound)
  525. {
  526. if (!ignoreInput)
  527. {
  528. HqlExprAssociation * assoc = new HqlBoundDefinedValue(represents->queryBody(), bound);
  529. curStmts->appendOwn(*assoc);
  530. return assoc;
  531. }
  532. return NULL;
  533. }
  534. IHqlExpression * BuildCtx::getTempDeclare(ITypeInfo * type, IHqlExpression * value)
  535. {
  536. IHqlExpression * temp = createVariable(LINK(type));
  537. addDeclare(temp, value);
  538. return temp;
  539. }
  540. bool BuildCtx::hasAssociation(HqlExprAssociation & search, bool unconditional)
  541. {
  542. HqlStmts * searchStmts = curStmts;
  543. for (;;)
  544. {
  545. if (searchStmts->defs.contains(search))
  546. return true;
  547. HqlStmt * limitStmt = searchStmts->queryStmt();
  548. if (!limitStmt)
  549. return false;
  550. if (!unconditional)
  551. {
  552. switch (limitStmt->getStmt())
  553. {
  554. case filter_stmt:
  555. if (!matchesBoolean(limitStmt->queryExpr(0), true))
  556. return false;
  557. break;
  558. case quote_compound_stmt:
  559. case quote_compoundopt_stmt:
  560. case switch_stmt:
  561. case case_stmt:
  562. case default_stmt:
  563. case loop_stmt:
  564. return false;
  565. }
  566. }
  567. searchStmts = limitStmt->queryContainer();
  568. }
  569. }
  570. bool BuildCtx::isSameLocation(const BuildCtx & other) const
  571. {
  572. if (this == &other)
  573. return true;
  574. if (curStmts != other.curStmts)
  575. return false;
  576. if (nextPriority != other.nextPriority)
  577. return false;
  578. return true;
  579. }
  580. bool BuildCtx::isOuterContext() const
  581. {
  582. HqlStmts * searchStmts = curStmts;
  583. for (;;)
  584. {
  585. HqlStmt * owner = searchStmts->owner;
  586. if (!owner)
  587. return true;
  588. switch (owner->getStmt())
  589. {
  590. case quote_compound_stmt:
  591. case quote_compoundopt_stmt:
  592. case indirect_stmt:
  593. return true;
  594. case group_stmt:
  595. break;
  596. default:
  597. return false;
  598. }
  599. searchStmts = owner->queryContainer();
  600. }
  601. }
  602. HqlExprAssociation * BuildCtx::queryAssociation(IHqlExpression * search, AssocKind kind, HqlExprCopyArray * selectors)
  603. {
  604. return curStmts->queryAssociation(search, kind, selectors);
  605. }
  606. void BuildCtx::removeAssociation(HqlExprAssociation * search)
  607. {
  608. if (!search)
  609. return;
  610. HqlStmts * searchStmts = curStmts;
  611. for (;;)
  612. {
  613. bool matched = searchStmts->zap(*search);
  614. if (matched)
  615. return;
  616. HqlStmt * limitStmt = searchStmts->queryStmt();
  617. if (!limitStmt)
  618. break;
  619. searchStmts = limitStmt->queryContainer();
  620. }
  621. assertex(!"Association not found");
  622. }
  623. HqlExprAssociation * BuildCtx::queryFirstAssociation(AssocKind searchKind)
  624. {
  625. HqlStmts * searchStmts = curStmts;
  626. unsigned searchMask = searchKind;
  627. // search all statements in the tree before this one, to see
  628. // if an expression already exists... If so return the target
  629. // of the assignment.
  630. for (;;)
  631. {
  632. if (searchStmts->associationMask & searchMask)
  633. {
  634. CIArray & defs = searchStmts->defs;
  635. ForEachItemInRev(idx, defs)
  636. {
  637. HqlExprAssociation & cur = (HqlExprAssociation &)defs.item(idx);
  638. if (cur.getKind() == searchKind)
  639. return &cur;
  640. }
  641. }
  642. HqlStmt * limitStmt = searchStmts->queryStmt();
  643. if (!limitStmt)
  644. break;
  645. searchStmts = limitStmt->queryContainer();
  646. }
  647. return NULL;
  648. }
  649. //Search for an association, but don't allow it to be conditional, or be hidden by the definition of a cursor.
  650. HqlExprAssociation * BuildCtx::queryFirstCommonAssociation(AssocKind searchKind)
  651. {
  652. HqlStmts * searchStmts = curStmts;
  653. unsigned searchMask = searchKind|AssocCursor;
  654. // search all statements in the tree before this one, to see
  655. // if an expression already exists... If so return the target
  656. // of the assignment.
  657. for (;;)
  658. {
  659. if (searchStmts->associationMask & searchMask)
  660. {
  661. CIArray & defs = searchStmts->defs;
  662. ForEachItemInRev(idx, defs)
  663. {
  664. HqlExprAssociation & cur = (HqlExprAssociation &)defs.item(idx);
  665. AssocKind kind = cur.getKind();
  666. if (kind == searchKind)
  667. return &cur;
  668. if (kind == AssocCursor)
  669. return NULL;
  670. }
  671. }
  672. HqlStmt * limitStmt = searchStmts->queryStmt();
  673. if (!limitStmt)
  674. break;
  675. switch (limitStmt->getStmt())
  676. {
  677. //case quote_compound_stmt:
  678. //case quote_compoundopt_stmt,
  679. case filter_stmt:
  680. case label_stmt:
  681. case switch_stmt:
  682. case case_stmt:
  683. case default_stmt:
  684. case break_stmt:
  685. case continue_stmt:
  686. return NULL;
  687. }
  688. searchStmts = limitStmt->queryContainer();
  689. }
  690. return NULL;
  691. }
  692. void BuildCtx::walkAssociations(AssocKind searchMask, IAssociationVisitor & visitor)
  693. {
  694. HqlStmts * searchStmts = curStmts;
  695. // search all statements in the tree before this one, to see
  696. // if an expression already exists... If so return the target
  697. // of the assignment.
  698. for (;;)
  699. {
  700. if (searchStmts->associationMask & searchMask)
  701. {
  702. CIArray & defs = searchStmts->defs;
  703. ForEachItemInRev(idx, searchStmts->defs)
  704. {
  705. HqlExprAssociation & cur = (HqlExprAssociation &)searchStmts->defs.item(idx);
  706. if (cur.getKind() & searchMask)
  707. {
  708. if (visitor.visit(cur))
  709. return;
  710. }
  711. }
  712. }
  713. HqlStmt * limitStmt = searchStmts->queryStmt();
  714. if (!limitStmt)
  715. break;
  716. searchStmts = limitStmt->queryContainer();
  717. }
  718. }
  719. HqlExprAssociation * BuildCtx::queryMatchExpr(IHqlExpression * search)
  720. {
  721. HqlExprCopyArray selectors;
  722. search->gatherTablesUsed(NULL, &selectors);
  723. return queryAssociation(search, AssocExpr, selectors.ordinality() ? &selectors : NULL);
  724. }
  725. bool BuildCtx::getMatchExpr(IHqlExpression * expr, CHqlBoundExpr & tgt)
  726. {
  727. HqlExprAssociation * match = queryMatchExpr(expr);
  728. if (match)
  729. {
  730. match->getBound(tgt);
  731. return true;
  732. }
  733. return false;
  734. }
  735. void BuildCtx::init(HqlStmts * _root)
  736. {
  737. root = _root;
  738. curStmts = root;
  739. curPriority = NormalPrio;
  740. nextPriority = curPriority;
  741. ignoreInput = false;
  742. }
  743. bool BuildCtx::isChildOf(HqlStmt * stmt, HqlStmts * stmts)
  744. {
  745. //MORE: Could improve by using depths
  746. do
  747. {
  748. if (stmts->find(*stmt) != NotFound)
  749. return true;
  750. stmt = stmt->queryContainer()->queryStmt();
  751. } while (stmt);
  752. return false;
  753. }
  754. void BuildCtx::selectCompound(IHqlStmt * stmt)
  755. {
  756. HqlCompoundStmt & owner = (HqlCompoundStmt &)*stmt;
  757. curStmts = &owner.code;
  758. }
  759. void BuildCtx::selectContainer()
  760. {
  761. HqlStmt * limitStmt = curStmts->queryStmt();
  762. assertex(limitStmt);
  763. curStmts = limitStmt->queryContainer();
  764. assertex(curStmts);
  765. }
  766. void BuildCtx::selectElse(IHqlStmt * stmt)
  767. {
  768. //Ignoring input does not work, because code expects associations to be kept
  769. assertex(stmt);
  770. switch (stmt->getStmt())
  771. {
  772. case filter_stmt:
  773. assertThrow(stmt->numChildren() == 1);
  774. selectCompound(stmt);
  775. addBlock();
  776. break;
  777. default:
  778. throwUnexpected();
  779. break;
  780. }
  781. }
  782. unsigned BuildCtx::setPriority(unsigned newPrio)
  783. {
  784. unsigned oldPriority = curPriority;
  785. if (!ignoreInput)
  786. {
  787. curPriority = newPrio;
  788. nextPriority = curPriority;
  789. }
  790. return oldPriority;
  791. }
  792. void BuildCtx::setNextPriority(unsigned newPrio)
  793. {
  794. if (!ignoreInput)
  795. nextPriority = newPrio;
  796. }
  797. IHqlStmt * BuildCtx::recursiveGetBestContext(HqlStmts * searchStmts, HqlExprCopyArray & required)
  798. {
  799. //Is it ok to move the expression before the owner statement?
  800. //First fail if any of the datasets that this expression is dependent on are defined in this scope.
  801. if (required.ordinality())
  802. {
  803. ForEachItemIn(i, searchStmts->defs)
  804. {
  805. HqlExprAssociation & cur = (HqlExprAssociation &)searchStmts->defs.item(i);
  806. if (required.contains(*cur.represents.get()))
  807. return NULL;
  808. }
  809. }
  810. HqlStmt * owner = searchStmts->owner;
  811. //Now check for poor places to hoist
  812. bool worthHoistingHere = false;
  813. switch (owner->getStmt())
  814. {
  815. case block_stmt:
  816. case group_stmt:
  817. break;
  818. case quote_compound_stmt:
  819. case quote_compoundopt_stmt:
  820. case indirect_stmt:
  821. case catch_stmt:
  822. case try_stmt:
  823. return NULL;
  824. case filter_stmt:
  825. case switch_stmt:
  826. //MORE: Should make whether something ishoisted dependent on efficiency of the filter condition
  827. break;
  828. case loop_stmt:
  829. //MORE: Should make it dependent on the ordinality of the loop condition.
  830. worthHoistingHere = true;
  831. break;
  832. case case_stmt:
  833. case default_stmt:
  834. //Can't hoist here
  835. break;
  836. default:
  837. throwUnexpected();
  838. }
  839. HqlStmts * container = owner->queryContainer();
  840. if (container->owner)// && canHoistInParent)
  841. {
  842. IHqlStmt * match = recursiveGetBestContext(container, required);
  843. if (match)
  844. return match;
  845. }
  846. if (!worthHoistingHere)
  847. return NULL;
  848. //We've found somewhere we can insert the expression....
  849. unsigned existingPos = container->find(*owner);
  850. assertex(existingPos != NotFound);
  851. //insert a group just before the current statement
  852. HqlCompoundStmt * next = new HqlCompoundStmt(group_stmt, container);
  853. next->setPriority(owner->queryPriority());
  854. container->add(*next, existingPos);
  855. curStmts = &next->code;
  856. return next;
  857. }
  858. IHqlStmt * BuildCtx::replaceExpr(IHqlStmt * stmt, IHqlExpression * expr)
  859. {
  860. //Highly dangerous - use with utmost care!
  861. assertex(stmt->getStmt() == expr_stmt);
  862. HqlStmt * castStmt = static_cast<HqlStmt *>(stmt);
  863. castStmt->killExprs();
  864. castStmt->addExpr(LINK(expr));
  865. return castStmt;
  866. }
  867. IHqlStmt * BuildCtx::selectBestContext(IHqlExpression * expr)
  868. {
  869. if (containsTranslated(expr) || !curStmts->owner)
  870. return NULL;
  871. //MORE: Access to global context, context and other things...
  872. HqlExprCopyArray inScope;
  873. expr->gatherTablesUsed(NULL, &inScope);
  874. return recursiveGetBestContext(curStmts, inScope);
  875. }
  876. //---------------------------------------------------------------------------
  877. HqlStmts::HqlStmts(HqlStmt * _owner) : owner(_owner)
  878. {
  879. associationMask = 0;
  880. }
  881. void HqlStmts::appendOwn(HqlExprAssociation & next)
  882. {
  883. AssocKind kind = next.getKind();
  884. if (kind == AssocCursor)
  885. {
  886. //Self selectors are unique, so no need to check if they already exists in the context
  887. if (next.represents->getOperator() != no_self)
  888. {
  889. //If a cursor is hiding another cursor then indicate the hash table can not be used
  890. if (queryAssociation(next.represents, kind, nullptr))
  891. associationMask |= AssocSequentialSearch;
  892. }
  893. #ifdef _DEBUG
  894. else
  895. {
  896. assertex(!queryAssociation(next.represents, next.getKind(), NULL));
  897. }
  898. #endif
  899. }
  900. defs.append(next);
  901. associationMask |= kind;
  902. if (kind == AssocExpr)
  903. exprAssociationCache.replace(next);
  904. if (kind == AssocCursor)
  905. maxCursor = defs.ordinality();
  906. }
  907. void HqlStmts::inheritDefinitions(HqlStmts & other)
  908. {
  909. associationMask |= other.associationMask;
  910. ForEachItemIn(i, other.defs)
  911. {
  912. HqlExprAssociation & cur = other.defs.item(i);
  913. defs.append(OLINK(cur));
  914. AssocKind kind = cur.getKind();
  915. if (kind == AssocExpr)
  916. exprAssociationCache.replace(cur);
  917. if (kind == AssocCursor)
  918. maxCursor = defs.ordinality();
  919. }
  920. }
  921. void HqlStmts::appendStmt(HqlStmt & stmt)
  922. {
  923. unsigned newPrio = stmt.queryPriority();
  924. unsigned right = ordinality();
  925. if (right == 0)
  926. {
  927. append(stmt);
  928. }
  929. else if (newPrio >= item(right-1).queryPriority())
  930. {
  931. while (item(right-1).isIncomplete())
  932. {
  933. if (newPrio > item(right-1).queryPriority())
  934. break;
  935. right--;
  936. if (right == 0)
  937. break;
  938. }
  939. add(stmt, right);
  940. }
  941. else
  942. {
  943. unsigned left = 0;
  944. while (right - left >= 2)
  945. {
  946. unsigned mid = left + (right - 1 - left) / 2;
  947. HqlStmt & cur = item(mid);
  948. if (newPrio >= cur.queryPriority())
  949. left = mid+1;
  950. else
  951. right = mid+1;
  952. }
  953. if (newPrio >= item(left).queryPriority())
  954. ++left;
  955. while (left && item(left-1).isIncomplete() && (newPrio == item(left-1).queryPriority()))
  956. --left;
  957. add(stmt, left);
  958. }
  959. }
  960. bool HqlStmts::zap(HqlExprAssociation & next)
  961. {
  962. unsigned match = defs.find(next);
  963. if (match == NotFound)
  964. return false;
  965. //MORE: Try and avoid this if we can - we should probably use a different kind for items that are removed
  966. if (next.getKind() == AssocExpr)
  967. {
  968. exprAssociationCache.removeExact(&next);
  969. IHqlExpression * search = next.represents;
  970. for (unsigned i=match; i-- != 0; )
  971. {
  972. HqlExprAssociation & cur = defs.item(i);
  973. if ((cur.getKind() == AssocExpr) && (cur.represents == search))
  974. {
  975. exprAssociationCache.add(cur);
  976. break;
  977. }
  978. }
  979. }
  980. defs.remove(match);
  981. if (defs.ordinality() < maxCursor)
  982. maxCursor = defs.ordinality();
  983. return true;
  984. }
  985. HqlExprAssociation * HqlStmts::queryAssociation(IHqlExpression * search, AssocKind kind, HqlExprCopyArray * selectors)
  986. {
  987. HqlStmts * searchStmts = this;
  988. if (!search)
  989. return NULL;
  990. search = search->queryBody();
  991. unsigned searchMask = kind;
  992. if (selectors)
  993. searchMask |= AssocSequentialSearch;
  994. // search all statements in the tree before this one, to see
  995. // if an expression already exists... If so return the target
  996. // of the assignment.
  997. for (;;)
  998. {
  999. unsigned stmtMask = searchStmts->associationMask;
  1000. if (stmtMask & searchMask)
  1001. {
  1002. //Safe to use the hash iterator if no selectors, or this definition list contains no cursors
  1003. if (((kind == AssocExpr)) && (!selectors || !(stmtMask & AssocSequentialSearch)))
  1004. {
  1005. HqlExprAssociation * match = searchStmts->exprAssociationCache.find(*search);
  1006. if (match)
  1007. return match;
  1008. }
  1009. else
  1010. {
  1011. const CIArrayOf<HqlExprAssociation> & defs = searchStmts->defs;
  1012. unsigned max = defs.ordinality();
  1013. //If searching for a cursor, then restrict the search to the known range.
  1014. //This is also valid even if selectors != null - since selectors also match AssocCursor.
  1015. if (kind == AssocCursor)
  1016. max = searchStmts->maxCursor;
  1017. if (!selectors)
  1018. {
  1019. for (unsigned idx=max; idx--; )
  1020. {
  1021. HqlExprAssociation & cur = defs.item(idx);
  1022. IHqlExpression * represents = cur.represents.get();
  1023. #ifdef TRACK_SEARCH_DISTANCE
  1024. searchDistance++;
  1025. #endif
  1026. if (represents == search)
  1027. {
  1028. if (cur.getKind() == kind)
  1029. return &cur;
  1030. }
  1031. }
  1032. }
  1033. else
  1034. {
  1035. for (unsigned idx=max; idx--; )
  1036. {
  1037. HqlExprAssociation & cur = defs.item(idx);
  1038. IHqlExpression * represents = cur.represents.get();
  1039. AssocKind curKind = cur.getKind();
  1040. if (curKind == AssocCursor)
  1041. {
  1042. if (selectors->contains(*represents))
  1043. return NULL;
  1044. }
  1045. #ifdef TRACK_SEARCH_DISTANCE
  1046. searchDistance++;
  1047. #endif
  1048. if (represents == search)
  1049. {
  1050. if (curKind == kind)
  1051. return &cur;
  1052. }
  1053. }
  1054. }
  1055. }
  1056. }
  1057. HqlStmt * limitStmt = searchStmts->queryStmt();
  1058. if (!limitStmt)
  1059. break;
  1060. searchStmts = limitStmt->queryContainer();
  1061. }
  1062. return NULL;
  1063. }
  1064. //---------------------------------------------------------------------------
  1065. HqlStmt::HqlStmt(StmtKind _kind, HqlStmts * _container)
  1066. {
  1067. kind = _kind;
  1068. container = _container;
  1069. incomplete = false;
  1070. included = true;
  1071. priority = 0;
  1072. }
  1073. void HqlStmt::addExpr(IHqlExpression * expr)
  1074. {
  1075. //Only allocate a single extra expression at a time, since statements generally have very few (1) expressions
  1076. exprs.ensure(exprs.ordinality()+1);
  1077. exprs.append(*expr);
  1078. }
  1079. StmtKind HqlStmt::getStmt() const
  1080. {
  1081. return (StmtKind)kind;
  1082. }
  1083. StringBuffer & HqlStmt::getTextExtra(StringBuffer & out) const
  1084. {
  1085. return out;
  1086. }
  1087. static bool isEmptyGroup(IHqlStmt * stmt)
  1088. {
  1089. if (!stmt)
  1090. return true;
  1091. switch (stmt->getStmt())
  1092. {
  1093. case group_stmt:
  1094. case block_stmt:
  1095. return stmt->numChildren() == 0;
  1096. }
  1097. return false;
  1098. }
  1099. bool HqlStmt::hasChildren() const
  1100. {
  1101. if (numChildren() == 0)
  1102. return false;
  1103. unsigned count = numChildren();
  1104. for (unsigned index = 0; index < count; index++)
  1105. {
  1106. IHqlStmt * cur = queryChild(index);
  1107. if (cur->isIncluded())
  1108. return true;
  1109. }
  1110. return false;
  1111. }
  1112. bool HqlStmt::isIncluded() const
  1113. {
  1114. if (!included)
  1115. return false;
  1116. switch (kind)
  1117. {
  1118. case quote_compoundopt_stmt:
  1119. case group_stmt:
  1120. return hasChildren();
  1121. case filter_stmt:
  1122. if (isEmptyGroup(queryChild(0)) && isEmptyGroup(queryChild(1)))
  1123. return false;
  1124. break;
  1125. }
  1126. return true;
  1127. }
  1128. unsigned HqlStmt::numChildren() const
  1129. {
  1130. return 0;
  1131. }
  1132. IHqlStmt * HqlStmt::queryChild(unsigned index) const
  1133. {
  1134. return NULL;
  1135. }
  1136. HqlStmts * HqlStmt::queryContainer()
  1137. {
  1138. return container;
  1139. }
  1140. IHqlExpression * HqlStmt::queryExpr(unsigned index) const
  1141. {
  1142. if (exprs.isItem(index))
  1143. return &exprs.item(index);
  1144. return NULL;
  1145. }
  1146. //---------------------------------------------------------------------------
  1147. #ifdef _MSC_VER
  1148. #pragma warning(push)
  1149. #pragma warning( disable : 4355 ) // 'this' : used in base member initializer list
  1150. #endif
  1151. HqlCompoundStmt::HqlCompoundStmt(StmtKind _kind, HqlStmts * _container) : HqlStmt(_kind, _container), code(this)
  1152. {
  1153. frameworkCount = 0;
  1154. }
  1155. #ifdef _MSC_VER
  1156. #pragma warning(pop)
  1157. #endif
  1158. void HqlCompoundStmt::finishedFramework()
  1159. {
  1160. frameworkCount = doCalcTotalChildren(this);
  1161. }
  1162. bool HqlCompoundStmt::isIncluded() const
  1163. {
  1164. if (!HqlStmt::isIncluded())
  1165. return false;
  1166. if (frameworkCount == 0)
  1167. return true;
  1168. return frameworkCount != doCalcTotalChildren(this);
  1169. }
  1170. void HqlCompoundStmt::mergeScopeWithContainer()
  1171. {
  1172. container->inheritDefinitions(code);
  1173. }
  1174. unsigned HqlCompoundStmt::numChildren() const
  1175. {
  1176. return code.ordinality();
  1177. }
  1178. IHqlStmt * HqlCompoundStmt::queryChild(unsigned index) const
  1179. {
  1180. if (code.isItem(index))
  1181. return &code.item(index);
  1182. return NULL;
  1183. }
  1184. bool HqlConditionalGroupStmt::isIncluded() const
  1185. {
  1186. return HqlCompoundStmt::isIncluded() && stmt->isIncluded();
  1187. }
  1188. //---------------------------------------------------------------------------
  1189. StringBuffer & HqlQuoteStmt::getTextExtra(StringBuffer & out) const
  1190. {
  1191. return out.append(text);
  1192. }
  1193. StringBuffer & HqlQuoteLiteralStmt::getTextExtra(StringBuffer & out) const
  1194. {
  1195. return out.append(text);
  1196. }
  1197. StringBuffer & HqlQuoteCompoundStmt::getTextExtra(StringBuffer & out) const
  1198. {
  1199. return out.append(text);
  1200. }
  1201. StringBuffer & HqlQuoteLiteralCompoundStmt::getTextExtra(StringBuffer & out) const
  1202. {
  1203. return out.append(text);
  1204. }
  1205. //---------------------------------------------------------------------------
  1206. int queryMemsetChar(IHqlExpression * expr)
  1207. {
  1208. if (expr->getOperator() != no_constant)
  1209. return -1;
  1210. unsigned size = expr->queryType()->getSize();
  1211. if (size == 0)
  1212. return -1;
  1213. const byte * data = (const byte *)expr->queryValue()->queryValue();
  1214. byte match = data[0];
  1215. while (--size)
  1216. if (*++data != match)
  1217. return -1;
  1218. return match;
  1219. }
  1220. static IHqlExpression * extractNonConstant(IHqlExpression * expr, unsigned & delta)
  1221. {
  1222. switch (expr->getOperator())
  1223. {
  1224. case no_constant:
  1225. delta += (unsigned)getIntValue(expr);
  1226. return NULL;
  1227. case no_add:
  1228. {
  1229. IHqlExpression * left = expr->queryChild(0);
  1230. OwnedHqlExpr newLeft = extractNonConstant(left, delta);
  1231. IHqlExpression * right = expr->queryChild(1);
  1232. OwnedHqlExpr newRight = extractNonConstant(right, delta);
  1233. if (!newLeft) return newRight.getClear();
  1234. if (!newRight) return newLeft.getClear();
  1235. if ((left == newLeft) && (right == newRight))
  1236. return LINK(expr);
  1237. return createValue(no_add, expr->getType(), newLeft.getClear(), newRight.getClear());
  1238. }
  1239. }
  1240. return LINK(expr);
  1241. }
  1242. IHqlExpression * peepholeAddExpr(IHqlExpression * left, IHqlExpression * right)
  1243. {
  1244. unsigned delta = 0;
  1245. IHqlExpression * simpleLeft = extractNonConstant(left, delta);
  1246. IHqlExpression * simpleRight = extractNonConstant(right, delta);
  1247. IHqlExpression * ret;
  1248. if (simpleLeft)
  1249. {
  1250. if (simpleRight)
  1251. ret = createValue(no_add, left->getType(), simpleLeft, simpleRight);
  1252. else
  1253. ret = simpleLeft;
  1254. }
  1255. else
  1256. ret = simpleRight;
  1257. if (!delta && ret)
  1258. return ret;
  1259. IHqlExpression * value = getSizetConstant(delta);
  1260. if (!ret)
  1261. return value;
  1262. return createValue(no_add, left->getType(), ret, value);
  1263. }
  1264. bool rightFollowsLeft(IHqlExpression * left, IHqlExpression * leftLen, IHqlExpression * right)
  1265. {
  1266. OwnedHqlExpr sum = peepholeAddExpr(left, leftLen);
  1267. if (sum == right)
  1268. return true;
  1269. if (left->getOperator() != right->getOperator())
  1270. {
  1271. if (right->getOperator() == no_add)
  1272. {
  1273. if ((left == right->queryChild(0)) && (leftLen == right->queryChild(1)))
  1274. return true;
  1275. if ((left == right->queryChild(1)) && (leftLen == right->queryChild(0)))
  1276. return true;
  1277. }
  1278. return false;
  1279. }
  1280. switch (left->getOperator())
  1281. {
  1282. case no_constant:
  1283. {
  1284. ITypeInfo * leftType = left->queryType();
  1285. ITypeInfo * rightType = right->queryType();
  1286. if (leftType->getTypeCode() != rightType->getTypeCode())
  1287. return false;
  1288. switch (leftType->getTypeCode())
  1289. {
  1290. case type_int:
  1291. if (leftLen->getOperator() != no_constant)
  1292. return false;
  1293. if (left->queryValue()->getIntValue() + leftLen->queryValue()->getIntValue() == right->queryValue()->getIntValue())
  1294. return true;
  1295. return false;
  1296. }
  1297. return false;
  1298. }
  1299. case no_add:
  1300. if ((left == right->queryChild(0)) && (leftLen == right->queryChild(1)))
  1301. return true;
  1302. if (left->queryChild(1) == right->queryChild(1))
  1303. {
  1304. if (rightFollowsLeft(left->queryChild(0), leftLen, right->queryChild(0)))
  1305. return true;
  1306. }
  1307. //fall through
  1308. case no_index:
  1309. if (left->queryChild(0) != right->queryChild(0))
  1310. return false;
  1311. return rightFollowsLeft(left->queryChild(1), leftLen, right->queryChild(1));
  1312. }
  1313. unsigned numLeft = left->numChildren();
  1314. if (numLeft == 0 || (numLeft != right->numChildren()))
  1315. return false;
  1316. ForEachChild(idx, left)
  1317. {
  1318. if (!rightFollowsLeft(left->queryChild(idx), leftLen, right->queryChild(idx)))
  1319. return false;
  1320. }
  1321. return true;
  1322. }
  1323. static IHqlExpression * createDataForMemset(unsigned size, byte value)
  1324. {
  1325. if (size < 100)
  1326. {
  1327. void * temp = alloca(size);
  1328. memset(temp, value, size);
  1329. return createConstant(createDataValue((char *)temp, size));
  1330. }
  1331. void * temp = malloc(size);
  1332. memset(temp, value, size);
  1333. IHqlExpression * ret = createConstant(createDataValue((char *)temp, size));
  1334. free(temp);
  1335. return ret;
  1336. }
  1337. static IHqlExpression * createDataForIntegerZero(unsigned size)
  1338. {
  1339. return createDataForMemset(size, 0);
  1340. }
  1341. class SpecialFunction
  1342. {
  1343. public:
  1344. SpecialFunction() { wasAssign = false; name = NULL; }
  1345. HqlStmt * createStmt(HqlStmts & curStmts, HqlCppTranslator & translator);
  1346. bool canOptimize() const;
  1347. void expandValue(void * target) const;
  1348. bool extractIsSpecial(IHqlStmt & stmt, bool memsetOnly, unsigned peepholeOptions);
  1349. bool isBigClear() const;
  1350. int queryClearValue() const;
  1351. bool queryCombine(const SpecialFunction & next, bool memsetOnly, size32_t combineStringLimit);
  1352. private:
  1353. IIdAtom * name;
  1354. HqlExprAttr src;
  1355. HqlExprAttr tgt;
  1356. HqlExprAttr srcLen;
  1357. HqlExprAttr tgtLen;
  1358. bool wasAssign;
  1359. };
  1360. //Always convert rtlWriteInt(rtlReadInt()) the inline memcpy is going to be much better.
  1361. //It should probably be converted earlier....
  1362. static bool isAwkwardIntSize(IHqlExpression * size)
  1363. {
  1364. IValue * value = size->queryValue();
  1365. if (value)
  1366. {
  1367. switch (value->getIntValue())
  1368. {
  1369. case 3:
  1370. case 5:
  1371. case 6:
  1372. case 7:
  1373. return true;
  1374. }
  1375. }
  1376. return false;
  1377. }
  1378. static bool isConstOrVar(IHqlExpression * expr)
  1379. {
  1380. switch (expr->getOperator())
  1381. {
  1382. case no_constant:
  1383. case no_variable:
  1384. return true;
  1385. case no_add:
  1386. case no_mul:
  1387. return isConstOrVar(expr->queryChild(0)) && isConstOrVar(expr->queryChild(1));
  1388. }
  1389. return false;
  1390. }
  1391. bool SpecialFunction::canOptimize() const
  1392. {
  1393. if ((name == memcpyId) && (queryMemsetChar(src) >= 0))
  1394. {
  1395. if ((getIntValue(srcLen, 0) > 1) || !wasAssign)
  1396. return true;
  1397. }
  1398. if ((name == memcpyId) && isAwkwardIntSize(srcLen))
  1399. return true;
  1400. return false;
  1401. }
  1402. HqlStmt * SpecialFunction::createStmt(HqlStmts & curStmts, HqlCppTranslator & translator)
  1403. {
  1404. HqlExprArray args;
  1405. IIdAtom * func = name;
  1406. if (name == memsetId)
  1407. {
  1408. func = memsetId;
  1409. args.append(*LINK(tgt));
  1410. args.append(*LINK(src));
  1411. args.append(*LINK(srcLen));
  1412. }
  1413. else if (name == memcpyId)
  1414. {
  1415. int clearByte = queryMemsetChar(src);
  1416. size32_t size = (size32_t)getIntValue(srcLen, 0);
  1417. if (clearByte == 0)
  1418. {
  1419. //if length is 1,2,4 then use an assignment instead.
  1420. switch (size)
  1421. {
  1422. case 1:
  1423. case 2:
  1424. case 4:
  1425. case 8:
  1426. {
  1427. OwnedITypeInfo type = makeIntType(size, false);
  1428. OwnedHqlExpr castTgt = createValue(no_cast, makePointerType(LINK(type)), LINK(tgt));
  1429. OwnedHqlExpr deref = createValue(no_deref, makeReferenceModifier(LINK(type)), LINK(castTgt));
  1430. OwnedHqlExpr src = createConstant(type->castFrom(true, (__int64)0));
  1431. HqlStmt * next = new HqlStmt(assign_stmt, &curStmts);
  1432. next->addExpr(LINK(deref));
  1433. next->addExpr(LINK(src));
  1434. return next;
  1435. }
  1436. }
  1437. }
  1438. //MORE: assignment of 1,2,4 bytes possibly better as an assign?
  1439. if (clearByte >= 0)
  1440. {
  1441. func = memsetId;
  1442. args.append(*LINK(tgt));
  1443. args.append(*createConstant(createIntValue(clearByte, sizeof(int), true)));
  1444. args.append(*LINK(srcLen));
  1445. }
  1446. else
  1447. {
  1448. args.append(*LINK(tgt));
  1449. args.append(*LINK(src));
  1450. args.append(*LINK(srcLen));
  1451. }
  1452. }
  1453. else if (name == deserializerReadNId || name == serializerPutId)
  1454. {
  1455. args.append(*LINK(src));
  1456. args.append(*LINK(tgtLen));
  1457. args.append(*LINK(tgt));
  1458. }
  1459. else if ((name == ebcdic2asciiId) || (name == ascii2ebcdicId))
  1460. {
  1461. args.append(*LINK(tgtLen));
  1462. args.append(*LINK(tgt));
  1463. args.append(*LINK(srcLen));
  1464. args.append(*LINK(src));
  1465. }
  1466. else if (name == deserializerSkipNId)
  1467. {
  1468. args.append(*LINK(src));
  1469. args.append(*LINK(srcLen));
  1470. }
  1471. else
  1472. UNIMPLEMENTED;
  1473. HqlStmt * next = new HqlStmt(expr_stmt, &curStmts);
  1474. next->addExpr(translator.bindTranslatedFunctionCall(func, args));
  1475. return next;
  1476. }
  1477. IHqlExpression * stripTranslatedCasts(IHqlExpression * e)
  1478. {
  1479. for (;;)
  1480. {
  1481. switch (e->getOperator())
  1482. {
  1483. case no_cast:
  1484. case no_implicitcast:
  1485. case no_typetransfer:
  1486. {
  1487. IHqlExpression * child = e->queryChild(0);
  1488. if (hasWrapperModifier(child->queryType()))
  1489. return e;
  1490. e = child;
  1491. break;
  1492. }
  1493. default:
  1494. return e;
  1495. }
  1496. }
  1497. }
  1498. void SpecialFunction::expandValue(void * target) const
  1499. {
  1500. size32_t size = (size32_t)getIntValue(srcLen);
  1501. if (name == memsetId)
  1502. memset(target, (int)getIntValue(src), size);
  1503. else
  1504. memcpy(target, src->queryValue()->queryValue(), size);
  1505. }
  1506. bool SpecialFunction::extractIsSpecial(IHqlStmt & stmt, bool memsetOnly, unsigned peepholeOptions)
  1507. {
  1508. if (stmt.getStmt() == expr_stmt)
  1509. {
  1510. IHqlExpression * expr = stmt.queryExpr(0);
  1511. if (expr->getOperator() != no_externalcall)
  1512. return false;
  1513. name = expr->queryId();
  1514. if (name == memcpyId)
  1515. {
  1516. src.set(stripTranslatedCasts(expr->queryChild(1)));
  1517. if (memsetOnly && (queryMemsetChar(src) == -1))
  1518. return false;
  1519. tgt.set(stripTranslatedCasts(expr->queryChild(0)));
  1520. srcLen.set(expr->queryChild(2));
  1521. tgtLen.set(srcLen);
  1522. return true;
  1523. }
  1524. if (name == deserializerReadNId || name == serializerPutId)
  1525. {
  1526. if (memsetOnly)
  1527. return false;
  1528. src.set(expr->queryChild(0));
  1529. tgt.set(stripTranslatedCasts(expr->queryChild(2)));
  1530. tgtLen.set(expr->queryChild(1));
  1531. return true;
  1532. }
  1533. if ((name == ebcdic2asciiId) || (name == ascii2ebcdicId))
  1534. {
  1535. if (memsetOnly)
  1536. return false;
  1537. src.set(expr->queryChild(3));
  1538. tgt.set(expr->queryChild(1));
  1539. srcLen.set(expr->queryChild(2));
  1540. tgtLen.set(expr->queryChild(0));
  1541. return srcLen == tgtLen;
  1542. }
  1543. if (name == memsetId)
  1544. {
  1545. IHqlExpression * value = expr->queryChild(1);
  1546. IHqlExpression * len = expr->queryChild(2);
  1547. if (len->queryValue() && value->queryValue())
  1548. {
  1549. tgt.set(stripTranslatedCasts(expr->queryChild(0)));
  1550. src.set(value);
  1551. srcLen.set(len);
  1552. tgtLen.set(srcLen);
  1553. }
  1554. return true;
  1555. }
  1556. if (name == deserializerSkipNId)
  1557. {
  1558. src.set(expr->queryChild(0));
  1559. srcLen.set(expr->queryChild(1));
  1560. return true;
  1561. }
  1562. unsigned size = 0;
  1563. if (name == writeIntId[3])
  1564. size = 3;
  1565. else if (name == writeIntId[5])
  1566. size = 5;
  1567. else if (name == writeIntId[6])
  1568. size = 6;
  1569. else if (name == writeIntId[7])
  1570. size = 7;
  1571. if (size)
  1572. {
  1573. IHqlExpression * value = expr->queryChild(1);
  1574. if (isZero(value))
  1575. {
  1576. name = memcpyId;
  1577. src.setown(createDataForIntegerZero(size));
  1578. tgt.set(stripTranslatedCasts(expr->queryChild(0)));
  1579. srcLen.setown(getSizetConstant(size));
  1580. tgtLen.set(srcLen);
  1581. return true;
  1582. }
  1583. if (memsetOnly)
  1584. return false;
  1585. while (value->getOperator() == no_typetransfer)
  1586. value = value->queryChild(0);
  1587. if (value->getOperator() == no_externalcall)
  1588. {
  1589. if ((value->queryId() == readIntId[size][true]) ||
  1590. (value->queryId() == readIntId[size][false]))
  1591. {
  1592. name = memcpyId;
  1593. src.set(stripTranslatedCasts(value->queryChild(0)));
  1594. tgt.set(stripTranslatedCasts(expr->queryChild(0)));
  1595. srcLen.setown(getSizetConstant(size));
  1596. tgtLen.set(srcLen);
  1597. return true;
  1598. }
  1599. }
  1600. }
  1601. return false;
  1602. }
  1603. else if (stmt.getStmt() == assign_stmt)
  1604. {
  1605. wasAssign = true;
  1606. tgt.set(stmt.queryExpr(0));
  1607. src.set(stmt.queryExpr(1));
  1608. ITypeInfo * tgtType = tgt->queryType();
  1609. ITypeInfo * srcType = src->queryType();
  1610. if (!isSameBasicType(srcType, tgtType))
  1611. {
  1612. if (!isSameFullyUnqualifiedType(srcType, tgtType))
  1613. return false;
  1614. }
  1615. while (tgt->getOperator() == no_typetransfer)
  1616. tgt.set(tgt->queryChild(0));
  1617. if (tgt->getOperator() != no_deref)
  1618. return false;
  1619. while (src->getOperator() == no_typetransfer)
  1620. src.set(src->queryChild(0));
  1621. size32_t targetSize = tgtType->getSize();
  1622. if (src->getOperator() != no_deref)
  1623. {
  1624. type_t tc = tgtType->getTypeCode();
  1625. OwnedHqlExpr newSrcExpr;
  1626. switch (tc)
  1627. {
  1628. case type_pointer:
  1629. case type_table:
  1630. //case type_row:
  1631. if (src->getOperator() == no_nullptr)
  1632. {
  1633. void * ptr = NULL;
  1634. targetSize = sizeof(void *);
  1635. newSrcExpr.setown(createConstant(createDataValue((const char *)&ptr, targetSize)));
  1636. }
  1637. break;
  1638. }
  1639. if (!memsetOnly)
  1640. {
  1641. switch (tc)
  1642. {
  1643. case type_int:
  1644. case type_swapint:
  1645. case type_boolean:
  1646. if (src->getOperator() == no_constant)
  1647. {
  1648. OwnedHqlExpr cast = ensureExprType(src, tgtType);
  1649. IValue * castValue = cast->queryValue();
  1650. if (castValue)
  1651. {
  1652. void * temp = alloca(targetSize);
  1653. castValue->toMem(temp);
  1654. newSrcExpr.setown(createConstant(createDataValue((const char *)temp, targetSize)));
  1655. }
  1656. }
  1657. break;
  1658. case type_real:
  1659. if ((peepholeOptions & PHOconvertReal) && (src->getOperator() == no_constant))
  1660. {
  1661. OwnedHqlExpr cast = ensureExprType(src, tgtType);
  1662. IValue * castValue = cast->queryValue();
  1663. if (castValue)
  1664. {
  1665. void * temp = alloca(targetSize);
  1666. castValue->toMem(temp);
  1667. newSrcExpr.setown(createConstant(createDataValue((const char *)temp, targetSize)));
  1668. }
  1669. }
  1670. break;
  1671. }
  1672. }
  1673. if (!newSrcExpr && isZero(src))
  1674. newSrcExpr.setown(createDataForIntegerZero(targetSize));
  1675. if (!newSrcExpr)
  1676. return false;
  1677. src.set(newSrcExpr);
  1678. }
  1679. else
  1680. {
  1681. if (memsetOnly)
  1682. return false;
  1683. src.set(src->queryChild(0));
  1684. }
  1685. srcLen.setown(getSizetConstant(targetSize));
  1686. tgtLen.set(srcLen);
  1687. tgt.set(stripTranslatedCasts(tgt->queryChild(0)));
  1688. src.set(stripTranslatedCasts(src));
  1689. name = memcpyId;
  1690. return true;
  1691. }
  1692. return false;
  1693. }
  1694. bool SpecialFunction::isBigClear() const
  1695. {
  1696. if ((name == memsetId) || (name == memcpyId))
  1697. return getIntValue(srcLen, 0) > CLEAR_COPY_THRESHOLD;
  1698. return false;
  1699. }
  1700. int SpecialFunction::queryClearValue() const
  1701. {
  1702. if (name == memcpyId)
  1703. return queryMemsetChar(src);
  1704. if (name == memsetId)
  1705. return (int)getIntValue(src, -1);
  1706. return -1;
  1707. }
  1708. bool SpecialFunction::queryCombine(const SpecialFunction & next, bool memsetOnly, size32_t combineStringLimit)
  1709. {
  1710. if (name != next.name)
  1711. {
  1712. if (!((name == memsetId) && (next.name == memcpyId)) &&
  1713. !((name == memcpyId) && (next.name == memsetId)))
  1714. return false;
  1715. }
  1716. if (name == deserializerSkipNId)
  1717. {
  1718. if (src != next.src)
  1719. return false;
  1720. //Only combine skips which are constants, or variables explicitly read from the file - not expressions that may be dependent on querySelf()
  1721. if (!isConstOrVar(srcLen) || !isConstOrVar(next.srcLen))
  1722. return false;
  1723. srcLen.setown(peepholeAddExpr(srcLen, next.srcLen));
  1724. return true;
  1725. }
  1726. if (rightFollowsLeft(tgt, tgtLen, next.tgt))
  1727. {
  1728. if ((name != memsetId) && (next.name != memsetId))
  1729. {
  1730. if (name == deserializerReadNId || name == serializerPutId)
  1731. {
  1732. tgtLen.setown(peepholeAddExpr(tgtLen, next.tgtLen));
  1733. return true;
  1734. }
  1735. if (rightFollowsLeft(src, srcLen, next.src))
  1736. {
  1737. srcLen.setown(peepholeAddExpr(srcLen, next.srcLen));
  1738. tgtLen.setown(peepholeAddExpr(tgtLen, next.tgtLen));
  1739. return true;
  1740. }
  1741. }
  1742. IValue * srcValue = src->queryValue();
  1743. IValue * nextValue = next.src->queryValue();
  1744. if (srcValue && nextValue)
  1745. {
  1746. //Don't combine things that can be converted to different memsets.
  1747. //This would work better if we first combined items that could be done as memsets and then combined strings
  1748. //processing in order we hit them doesn't work as well.
  1749. int clearValue = queryClearValue();
  1750. int nextClearValue = next.queryClearValue();
  1751. if (memsetOnly)
  1752. {
  1753. assertex((clearValue != -1) && (nextClearValue != -1));
  1754. if (clearValue != nextClearValue)
  1755. return false;
  1756. }
  1757. if ((isBigClear() && (clearValue != -1)) || (next.isBigClear() && (nextClearValue != -1)))
  1758. {
  1759. if (clearValue != nextClearValue)
  1760. return false;
  1761. }
  1762. size32_t curSize = (size32_t)getIntValue(srcLen);
  1763. size32_t nextSize = (size32_t)getIntValue(next.srcLen);
  1764. if (curSize + nextSize > combineStringLimit)
  1765. return false;
  1766. byte * temp = (byte *)malloc(curSize + nextSize);
  1767. expandValue(temp);
  1768. next.expandValue(temp+curSize);
  1769. src.setown(createConstant(createDataValue((const char *)temp, curSize + nextSize)));
  1770. free(temp);
  1771. srcLen.setown(getSizetConstant(curSize + nextSize));
  1772. tgtLen.set(srcLen);
  1773. if (name == memsetId)
  1774. name = memcpyId;
  1775. return true;
  1776. }
  1777. }
  1778. return false;
  1779. }
  1780. PeepHoleOptimizer::PeepHoleOptimizer(HqlCppTranslator & _translator) : translator(_translator)
  1781. {
  1782. combineStringLimit = -1;
  1783. peepholeOptions = 0;
  1784. if (translator.queryOptions().convertRealAssignToMemcpy)
  1785. peepholeOptions |= PHOconvertReal;
  1786. switch (translator.queryOptions().targetCompiler)
  1787. {
  1788. case Vs6CppCompiler:
  1789. combineStringLimit = 32000;
  1790. break;
  1791. }
  1792. }
  1793. void PeepHoleOptimizer::optimize(HqlStmts & stmts)
  1794. {
  1795. unsigned max = stmts.ordinality(); // can change as processing proceeds.
  1796. SpecialFunction prevMatch;
  1797. for (unsigned pass=0; pass < 2; pass++)
  1798. {
  1799. bool memsetOnly = (pass == 0);
  1800. for (unsigned i =0; i < max; i++)
  1801. {
  1802. IHqlStmt & cur = stmts.item(i);
  1803. if (prevMatch.extractIsSpecial(cur, memsetOnly, peepholeOptions))
  1804. {
  1805. unsigned j = i+1;
  1806. unsigned prevMax = max;
  1807. SpecialFunction nextMatch;
  1808. while (j < max)
  1809. {
  1810. IHqlStmt & next = stmts.item(j);
  1811. if (!nextMatch.extractIsSpecial(next, memsetOnly, peepholeOptions))
  1812. break;
  1813. if (!prevMatch.queryCombine(nextMatch, memsetOnly, combineStringLimit))
  1814. break;
  1815. stmts.remove(i);
  1816. max--;
  1817. }
  1818. if (max != prevMax || prevMatch.canOptimize())
  1819. {
  1820. stmts.remove(i);
  1821. stmts.add(*prevMatch.createStmt(stmts, translator), i);
  1822. }
  1823. }
  1824. }
  1825. }
  1826. for (unsigned i2=0; i2 < max; i2++)
  1827. {
  1828. IHqlStmt & cur = stmts.item(i2);
  1829. if (cur.numChildren() != 0)
  1830. optimize(((HqlCompoundStmt&)cur).code);
  1831. }
  1832. }
  1833. void peepholeOptimize(HqlCppInstance & instance, HqlCppTranslator & translator)
  1834. {
  1835. PeepHoleOptimizer optimizer(translator);
  1836. ForEachItemIn(idx, instance.sections)
  1837. optimizer.optimize(((HqlCppSection&)instance.sections.item(idx)).stmts);
  1838. }
  1839. //---------------------------------------------------------------------------
  1840. AssociationIterator::AssociationIterator(BuildCtx & ctx)
  1841. {
  1842. rootStmts = ctx.curStmts;
  1843. curStmts = NULL;
  1844. curIdx = 0;
  1845. searchMask = (unsigned)-1;
  1846. }
  1847. bool AssociationIterator::first()
  1848. {
  1849. curStmts = rootStmts;
  1850. if (curStmts->associationMask & searchMask)
  1851. curIdx = curStmts->defs.ordinality();
  1852. else
  1853. curIdx = 0;
  1854. return doNext();
  1855. }
  1856. bool AssociationIterator::doNext()
  1857. {
  1858. for (;;)
  1859. {
  1860. if (curIdx-- != 0)
  1861. return true;
  1862. HqlStmt * limitStmt = curStmts->queryStmt();
  1863. if (!limitStmt)
  1864. {
  1865. curStmts = NULL;
  1866. return false;
  1867. }
  1868. curStmts = limitStmt->queryContainer();
  1869. if (curStmts->associationMask & searchMask)
  1870. curIdx = curStmts->defs.ordinality();
  1871. else
  1872. curIdx = 0;
  1873. }
  1874. }
  1875. HqlExprAssociation & AssociationIterator::get()
  1876. {
  1877. CIArray & defs = curStmts->defs;
  1878. return (HqlExprAssociation &)defs.item(curIdx);
  1879. }
  1880. //---------------------------------------------------------------------------
  1881. bool FilteredAssociationIterator::doNext()
  1882. {
  1883. while (AssociationIterator::doNext())
  1884. {
  1885. HqlExprAssociation & cur = AssociationIterator::get();
  1886. if (cur.getKind() == searchKind)
  1887. return true;
  1888. }
  1889. return false;
  1890. }
  1891. bool RowAssociationIterator::doNext()
  1892. {
  1893. while (AssociationIterator::doNext())
  1894. {
  1895. HqlExprAssociation & cur = AssociationIterator::get();
  1896. if (cur.isRowAssociation())
  1897. return true;
  1898. }
  1899. return false;
  1900. };
  1901. unsigned doCalcTotalChildren(const IHqlStmt * stmt)
  1902. {
  1903. unsigned num = stmt->numChildren();
  1904. unsigned total = 1;
  1905. switch (stmt->getStmt())
  1906. {
  1907. case alias_stmt:
  1908. case group_stmt:
  1909. case pass_stmt:
  1910. case indirect_stmt:
  1911. total = 0;
  1912. break;
  1913. }
  1914. for (unsigned i=0; i < num; i++)
  1915. total += calcTotalChildren(stmt->queryChild(i));
  1916. return total;
  1917. }
  1918. unsigned calcTotalChildren(const IHqlStmt * stmt)
  1919. {
  1920. if (!stmt->isIncluded())
  1921. return 0;
  1922. return doCalcTotalChildren(stmt);
  1923. }
  1924. #include "hqltcppc.hpp"
  1925. void outputSizeStmts()
  1926. {
  1927. printf("Sizes: stmt(%u) stmts(%u) compound(%u) cache(%u) defined(%u) boundrow(%u)\n",
  1928. (unsigned)sizeof(HqlStmt),
  1929. (unsigned)sizeof(HqlStmts),
  1930. (unsigned)sizeof(HqlCompoundStmt),
  1931. (unsigned)sizeof(AssociationCache),
  1932. (unsigned)sizeof(HqlSimpleDefinedValue),
  1933. (unsigned)sizeof(BoundRow)
  1934. );
  1935. }