hqlcppcase.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249
  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 "hql.hpp"
  20. #include "hqlfunc.hpp"
  21. #include "hqlcpp.ipp"
  22. #include "hqlwcpp.hpp"
  23. #include "hqlutil.hpp"
  24. #include "hqlcpputil.hpp"
  25. #include "hqlcatom.hpp"
  26. #include "hqlcerrors.hpp"
  27. #define INTEGER_SEARCH_THRESHOLD 30 // above this, a table search is generated.
  28. #define MAX_NUM_NOBREAK_CASE 80 // maximum number of case: without a break - compiler workaround
  29. #define INLINE_COMPARE_THRESHOLD 2 // above this, a loop is generated
  30. #define SWITCH_TABLE_DENSITY_THRESHOLD 3 // % used before use array index.
  31. #define RANGE_DENSITY_THRESHOLD 30 // % used before to use array index with range checking
  32. #define MAX_NESTED_CASES 8 // to stop C++ compiler running out of scopes.
  33. //===========================================================================
  34. static IIdAtom * searchDataTableAtom;
  35. static IIdAtom * searchEStringTableAtom;
  36. static IIdAtom * searchQStringTableAtom;
  37. static IIdAtom * searchStringTableAtom;
  38. static IIdAtom * searchVStringTableAtom;
  39. //===========================================================================
  40. MODULE_INIT(INIT_PRIORITY_STANDARD)
  41. {
  42. searchDataTableAtom = createIdAtom("searchDataTable");
  43. searchEStringTableAtom = createIdAtom("searchEStringTable");
  44. searchQStringTableAtom = createIdAtom("searchQStringTable");
  45. searchStringTableAtom = createIdAtom("searchStringTable");
  46. searchVStringTableAtom = createIdAtom("searchVStringTable");
  47. return true;
  48. }
  49. MODULE_EXIT()
  50. {
  51. }
  52. //===========================================================================
  53. //Case helper functions...
  54. void cvtChooseListToPairs(HqlExprArray & target, IHqlExpression * from, unsigned base)
  55. {
  56. unsigned max = from->numChildren();
  57. unsigned idx;
  58. target.ensure(max);
  59. for (idx = 0; idx < max; idx++)
  60. {
  61. IHqlExpression * v1 = createConstant(createIntValue(idx+base, LINK(unsignedType)));
  62. IHqlExpression * v2 = from->queryChild(idx);
  63. ITypeInfo * type = v2->queryType();
  64. target.append(* createValue(no_mapto, LINK(type), v1, LINK(v2)));
  65. }
  66. }
  67. void cvtIndexListToPairs(HqlExprArray & target, IHqlExpression * from)
  68. {
  69. unsigned max = from->numChildren();
  70. unsigned idx;
  71. target.ensure(max);
  72. for (idx = 0; idx < max; idx++)
  73. {
  74. IHqlExpression * v1 = from->queryChild(idx);
  75. IHqlExpression * v2 = createConstant(createIntValue(idx+1, LINK(unsignedType)));
  76. ITypeInfo * type = v2->queryType();
  77. target.append(* createValue(no_mapto, LINK(type), LINK(v1), v2));
  78. }
  79. }
  80. void cvtInListToPairs(HqlExprArray & target, IHqlExpression * from, bool valueIfMatch)
  81. {
  82. unsigned max = from->numChildren();
  83. unsigned idx;
  84. IHqlExpression * tValue = queryBoolExpr(valueIfMatch);
  85. ITypeInfo * type = queryBoolType();
  86. target.ensure(max);
  87. for (idx = 0; idx < max; idx++)
  88. {
  89. IHqlExpression * v1 = from->queryChild(idx);
  90. target.append(* createValue(no_mapto, LINK(type), LINK(v1), LINK(tValue)));
  91. }
  92. }
  93. IHqlExpression * createNotFoundValue()
  94. {
  95. OwnedITypeInfo int4 = makeIntType(4, true);
  96. return createConstant(int4->castFrom(true, -1));
  97. }
  98. //===========================================================================
  99. static int compareValues(IHqlExpression * lexpr, IHqlExpression * rexpr)
  100. {
  101. return lexpr->queryValue()->compare(rexpr->queryValue());
  102. }
  103. static int comparePair(IHqlExpression * lexpr, IHqlExpression * rexpr)
  104. {
  105. return compareValues(lexpr->queryChild(0), rexpr->queryChild(0));
  106. }
  107. static int comparePair(IInterface * const * left, IInterface * const * right)
  108. {
  109. IHqlExpression * lexpr = (IHqlExpression *)*left;
  110. IHqlExpression * rexpr = (IHqlExpression *)*right;
  111. return comparePair(lexpr, rexpr);
  112. }
  113. HqlCppCaseInfo::HqlCppCaseInfo(HqlCppTranslator & _translator) : translator(_translator)
  114. {
  115. complexCompare = false;
  116. constantCases = true;
  117. constantValues = true;
  118. indexType.setown(makeIntType(sizeof(int), true));
  119. }
  120. void HqlCppCaseInfo::addPair(IHqlExpression * expr)
  121. {
  122. IHqlExpression * compareExpr = expr->queryChild(0);
  123. IHqlExpression * resultExpr = expr->queryChild(1);
  124. if (allResultsMatch && pairs.ordinality())
  125. {
  126. if (pairs.tos().queryChild(1) != resultExpr)
  127. allResultsMatch = false;
  128. }
  129. pairs.append(*LINK(expr));
  130. if (!compareExpr->queryValue())
  131. {
  132. constantCases = false;
  133. }
  134. else if (constantCases)
  135. {
  136. if (!lowestCompareExpr || compareValues(compareExpr, lowestCompareExpr) < 0)
  137. lowestCompareExpr.set(compareExpr);
  138. if (!highestCompareExpr || compareValues(compareExpr, highestCompareExpr) > 0)
  139. highestCompareExpr.set(compareExpr);
  140. }
  141. if (!expr->queryChild(1)->queryValue())
  142. constantValues = false;
  143. if (cond && !complexCompare)
  144. {
  145. ITypeInfo * valueType = compareExpr->queryType();
  146. if (valueType != cond->queryType())
  147. complexCompare = isCompare3Valued(compareExpr->queryType());
  148. }
  149. updateResultType(resultExpr);
  150. }
  151. void HqlCppCaseInfo::addPairs(HqlExprArray & _pairs)
  152. {
  153. pairs.ensure(_pairs.ordinality());
  154. ForEachItemIn(idx, _pairs)
  155. addPair(&_pairs.item(idx));
  156. }
  157. bool HqlCppCaseInfo::canBuildStaticList(ITypeInfo * type)
  158. {
  159. switch (type->getTypeCode())
  160. {
  161. case type_int:
  162. return isStandardSizeInt(type);
  163. case type_swapint:
  164. return false;
  165. default:
  166. return isFixedSize(type);
  167. }
  168. }
  169. bool HqlCppCaseInfo::buildAssign(BuildCtx & ctx, const CHqlBoundTarget & target)
  170. {
  171. if (pairs.ordinality() == 0)
  172. {
  173. translator.buildExprAssign(ctx, target, defaultValue);
  174. }
  175. else if (cond.get() && constantCases)
  176. {
  177. processBranches();
  178. BuildCtx subctx(ctx);
  179. CHqlBoundExpr test;
  180. buildSwitchCondition(ctx, test);
  181. if (complexCompare)
  182. {
  183. if (pairs.ordinality() > INLINE_COMPARE_THRESHOLD)
  184. {
  185. if (okToAlwaysEvaluateDefault() || hasLibraryChop())
  186. buildLoopChopMap(subctx, target, test);
  187. else
  188. buildGeneralAssign(subctx, target);
  189. }
  190. else
  191. {
  192. if (okToAlwaysEvaluateDefault())
  193. buildChop3Map(subctx, target, test);
  194. else
  195. buildGeneralAssign(subctx, target);
  196. }
  197. }
  198. else
  199. {
  200. ITypeInfo * condType = test.queryType()->queryPromotedType();
  201. if (!queryBuildArrayLookup(subctx, target, test))
  202. {
  203. if (condType->getTypeCode() != type_real)
  204. {
  205. OwnedHqlExpr search = test.getTranslatedExpr();
  206. if (constantValues && (condType->getTypeCode() == type_int) && (pairs.ordinality() > INTEGER_SEARCH_THRESHOLD) && canBuildStaticList(resultType))
  207. buildIntegerSearchMap(subctx, target, search);
  208. else
  209. buildSwitchMap(subctx, &target, test.expr);
  210. }
  211. else
  212. {
  213. if (okToAlwaysEvaluateDefault() && pairs.ordinality() > 4)
  214. {
  215. translator.buildExprAssign(ctx, target, defaultValue);
  216. buildChop2Map(subctx, target, test, 0, pairs.ordinality());
  217. }
  218. else
  219. buildGeneralAssign(subctx, target);
  220. }
  221. }
  222. }
  223. }
  224. else
  225. buildGeneralAssign(ctx, target);
  226. return true;
  227. }
  228. bool HqlCppCaseInfo::buildReturn(BuildCtx & ctx)
  229. {
  230. if (pairs.ordinality() == 0)
  231. {
  232. translator.buildReturn(ctx, defaultValue);
  233. }
  234. else if (cond.get() && constantCases)
  235. {
  236. processBranches();
  237. BuildCtx subctx(ctx);
  238. CHqlBoundExpr test;
  239. buildSwitchCondition(ctx, test);
  240. if (complexCompare)
  241. {
  242. buildGeneralReturn(subctx);
  243. }
  244. else
  245. {
  246. //if canBuildArrayLookup(test)
  247. //if use a lookup table to map value->constants
  248. if (test.queryType()->getTypeCode() != type_real)
  249. buildSwitchMap(subctx, NULL, test.expr);
  250. else
  251. buildGeneralReturn(subctx);
  252. }
  253. }
  254. else
  255. buildGeneralReturn(ctx);
  256. return true;
  257. }
  258. void HqlCppCaseInfo::buildChop3Map(BuildCtx & ctx, const CHqlBoundTarget & target, CHqlBoundExpr & test, IHqlExpression * temp, unsigned start, unsigned end)
  259. {
  260. if ((end - start) <= 2)
  261. buildChop2Map(ctx, target, test, start, end);
  262. else
  263. {
  264. unsigned mid = start + (end - start) / 2;
  265. generateCompareVar(ctx, temp, test, queryCompare(mid));
  266. OwnedHqlExpr test1 = createValue(no_eq, LINK(temp), getZero());
  267. OwnedHqlExpr test2 = createValue(no_lt, LINK(temp), getZero());
  268. BuildCtx subctx(ctx);
  269. IHqlStmt * if1 = subctx.addFilter(test1); // if (test == 0)
  270. translator.buildExprAssign(subctx, target, queryReturn(mid)); // target = value(n)
  271. subctx.selectElse(if1); // else
  272. IHqlStmt * if2 = subctx.addFilter(test2); // if (test < 0)
  273. buildChop3Map(subctx, target, test, temp, start, mid); // repeat for start..mid
  274. subctx.selectElse(if2); // else
  275. buildChop3Map(subctx, target, test, temp, mid+1, end); // repeat for min..end
  276. }
  277. }
  278. void HqlCppCaseInfo::buildChop3Map(BuildCtx & ctx, const CHqlBoundTarget & target, CHqlBoundExpr & test)
  279. {
  280. translator.buildExprAssign(ctx, target, defaultValue);
  281. if (getNumPairs() <= 2)
  282. {
  283. buildChop2Map(ctx, target, test, 0, getNumPairs());
  284. }
  285. else
  286. {
  287. //need to hack it because there is no signed integer type
  288. OwnedHqlExpr tempVar = ctx.getTempDeclare(indexType, NULL);
  289. buildChop3Map(ctx, target, test, tempVar, 0, getNumPairs());
  290. }
  291. }
  292. void HqlCppCaseInfo::buildChop2Map(BuildCtx & ctx, const CHqlBoundTarget & target, CHqlBoundExpr & test, unsigned start, unsigned end)
  293. {
  294. BuildCtx subctx(ctx);
  295. if ((end - start) <= 3) // (1,2,3) avg(2) cf. (2,2,3) avg(2.3)
  296. {
  297. //optimize the case where they all create the same value
  298. bool same = true;
  299. unsigned index;
  300. for (index=start+1; index < end; ++index)
  301. {
  302. if (queryReturn(index-1) != queryReturn(index))
  303. {
  304. same = false;
  305. break;
  306. }
  307. }
  308. if (same)
  309. {
  310. CompoundBuilder cb(no_or);
  311. for (index=start; index < end; ++index)
  312. {
  313. IHqlExpression * compare = queryCompare(index);
  314. IHqlExpression * cond = createCompareExpr(no_eq, test.getTranslatedExpr(), LINK(compare));
  315. cb.addOperand(cond);
  316. }
  317. OwnedHqlExpr compound = cb.getCompound();
  318. translator.buildFilter(subctx, compound);
  319. translator.buildExprAssign(subctx, target, queryReturn(start));
  320. }
  321. else
  322. {
  323. IHqlStmt * stmt = NULL;
  324. for (index=start; index < end; ++index)
  325. {
  326. if (stmt)
  327. subctx.selectElse(stmt);
  328. IHqlExpression * compare = queryCompare(index);
  329. OwnedHqlExpr cond = createCompareExpr(no_eq, test.getTranslatedExpr(), LINK(compare));
  330. CHqlBoundExpr bound;
  331. translator.buildExpr(subctx, cond, bound);
  332. stmt = subctx.addFilter(bound.expr);
  333. translator.buildExprAssign(subctx, target, queryReturn(index));
  334. }
  335. }
  336. }
  337. else
  338. {
  339. unsigned mid = start + (end - start) / 2;
  340. IHqlExpression * compare = queryCompare(mid);
  341. OwnedHqlExpr cond = createCompareExpr(no_lt, test.getTranslatedExpr(), LINK(compare));
  342. CHqlBoundExpr bound;
  343. translator.buildExpr(subctx, cond, bound);
  344. IHqlStmt * stmt = subctx.addFilter(bound.expr);
  345. buildChop2Map(subctx, target, test, start, mid);
  346. subctx.selectElse(stmt);
  347. buildChop2Map(subctx, target, test, mid, end);
  348. }
  349. }
  350. IHqlExpression * HqlCppCaseInfo::buildIndexedMap(BuildCtx & ctx, const CHqlBoundExpr & test)
  351. {
  352. ITypeInfo * compareType = test.queryType()->queryPromotedType();
  353. type_t compareTypeCode = compareType->getTypeCode();
  354. HqlExprArray values;
  355. IHqlExpression * dft = queryActiveTableSelector(); // value doesn't matter as long as it will not occur
  356. __int64 lower = getIntValue(lowerTableBound, 0);
  357. unsigned num = (getIntValue(upperTableBound, 0)-lower)+1;
  358. CHqlBoundExpr indexExpr;
  359. switch (compareTypeCode)
  360. {
  361. case type_int:
  362. indexExpr.set(test);
  363. break;
  364. case type_string:
  365. indexExpr.expr.setown(createValue(no_index, makeCharType(), LINK(test.expr), getZero()));
  366. indexExpr.expr.setown(createValue(no_cast, makeIntType(1, false), LINK(indexExpr.expr)));
  367. break;
  368. default:
  369. throwUnexpectedType(compareType);
  370. }
  371. if (useRangeIndex && (num != 1))
  372. translator.ensureSimpleExpr(ctx, indexExpr);
  373. OwnedHqlExpr mapped;
  374. ITypeInfo * retType = resultType;
  375. //if num == pairs.ordinality() and all results are identical, avoid the table lookup.
  376. if (allResultsMatch && (num == pairs.ordinality()))
  377. {
  378. mapped.set(pairs.item(0).queryChild(1));
  379. }
  380. else
  381. {
  382. values.ensure(num);
  383. unsigned idx;
  384. for (idx = 0; idx < num; idx++)
  385. values.append(*LINK(dft));
  386. ForEachItemIn(idx2, pairs)
  387. {
  388. IHqlExpression & cur = pairs.item(idx2);
  389. IValue * value = cur.queryChild(0)->queryValue();
  390. unsigned replaceIndex;
  391. switch (compareTypeCode)
  392. {
  393. case type_int:
  394. replaceIndex = (unsigned)(value->getIntValue()-lower);
  395. break;
  396. case type_string:
  397. {
  398. StringBuffer temp;
  399. value->getStringValue(temp);
  400. replaceIndex = (unsigned)((unsigned char)temp.charAt(0)-lower);
  401. break;
  402. }
  403. default:
  404. throwUnexpectedType(compareType);
  405. }
  406. IHqlExpression * mapTo = cur.queryChild(1);
  407. if (mapTo->getOperator() != no_constant)
  408. throwUnexpected();
  409. if (replaceIndex >= num)
  410. translator.reportWarning(CategoryIgnored, HQLWRN_CaseCanNeverMatch, "CASE entry %d can never match the test condition", replaceIndex);
  411. else
  412. values.replace(*ensureExprType(mapTo, resultType),replaceIndex);
  413. }
  414. //Now replace the placeholders with the default values.
  415. for (idx = 0; idx < num; idx++)
  416. {
  417. if (&values.item(idx) == dft)
  418. values.replace(*defaultValue.getLink(),idx);
  419. }
  420. // use a var string type to get better C++ generated...
  421. ITypeInfo * storeType = getArrayElementType(resultType);
  422. ITypeInfo * listType = makeArrayType(storeType, values.ordinality());
  423. OwnedHqlExpr lvalues = createValue(no_list, listType, values);
  424. CHqlBoundExpr boundTable;
  425. translator.buildExpr(ctx, lvalues, boundTable);
  426. LinkedHqlExpr tableIndex = indexExpr.expr;
  427. if (getIntValue(lowerTableBound, 0))
  428. tableIndex.setown(createValue(no_sub, tableIndex->getType(), LINK(tableIndex), LINK(lowerTableBound)));
  429. IHqlExpression * ret = createValue(no_index, LINK(retType), LINK(boundTable.expr), LINK(tableIndex));
  430. mapped.setown(createTranslatedOwned(ret));
  431. }
  432. if (useRangeIndex)
  433. {
  434. if (num != 1)
  435. {
  436. OwnedHqlExpr testValue = indexExpr.getTranslatedExpr();
  437. OwnedHqlExpr aboveLower = createCompare(no_ge, testValue, lowestCompareExpr);
  438. OwnedHqlExpr belowUpper = createCompare(no_le, testValue, highestCompareExpr);
  439. OwnedHqlExpr inRange = createValue(no_and, makeBoolType(), aboveLower.getClear(), belowUpper.getClear());
  440. mapped.setown(createValue(no_if, LINK(retType), inRange.getClear(), LINK(mapped), LINK(defaultValue)));
  441. }
  442. else
  443. {
  444. assertex(allResultsMatch);
  445. OwnedHqlExpr testValue = indexExpr.getTranslatedExpr();
  446. OwnedHqlExpr inRange = createCompare(no_eq, testValue, lowestCompareExpr);
  447. mapped.setown(createValue(no_if, LINK(retType), inRange.getClear(), LINK(mapped), LINK(defaultValue)));
  448. }
  449. }
  450. return mapped.getClear();
  451. }
  452. void HqlCppCaseInfo::buildLoopChopMap(BuildCtx & ctx, const CHqlBoundTarget & target, CHqlBoundExpr & test)
  453. {
  454. //Declare a table that contains all the strings...
  455. ITypeInfo * compareType = queryCompareType();
  456. type_t ctc = compareType->getTypeCode();
  457. if ((ctc == type_data) && !hasLibraryChop())
  458. {
  459. buildGeneralAssign(ctx, target);
  460. return;
  461. }
  462. OwnedHqlExpr values = createCompareList();
  463. CHqlBoundExpr boundTable;
  464. translator.buildExpr(ctx, values, boundTable);
  465. OwnedHqlExpr midVar = createVariable(LINK(indexType));
  466. if (hasLibraryChop())
  467. {
  468. ITypeInfo * tableEntryType = makeReferenceModifier(LINK(compareType));
  469. ITypeInfo * tableType = makePointerType(tableEntryType);
  470. HqlExprArray args;
  471. IIdAtom * func;
  472. switch (ctc)
  473. {
  474. case type_data:
  475. func = searchDataTableAtom;
  476. break;
  477. case type_varstring:
  478. func = searchVStringTableAtom;
  479. break;
  480. case type_qstring:
  481. func = searchQStringTableAtom;
  482. break;
  483. case type_string:
  484. if (compareType->queryCharset()->queryName() == asciiAtom)
  485. func = searchStringTableAtom;
  486. else if (compareType->queryCharset()->queryName() == ebcdicAtom)
  487. func = searchEStringTableAtom;
  488. else
  489. UNIMPLEMENTED;
  490. break;
  491. case type_unicode:
  492. func = searchUnicodeTableId;
  493. break;
  494. case type_utf8:
  495. func = searchUtf8TableId;
  496. break;
  497. case type_varunicode:
  498. func = searchVUnicodeTableId;
  499. break;
  500. default:
  501. throwUnexpectedType(compareType);
  502. }
  503. args.append(*getSizetConstant(values->numChildren()));
  504. if ((ctc != type_varstring) && (ctc != type_varunicode))
  505. args.append(*getSizetConstant(values->queryChild(0)->queryType()->getStringLen()));
  506. args.append(*createValue(no_address, tableType, createValue(no_index, LINK(tableEntryType), LINK(boundTable.expr), getZero())));
  507. if ((ctc != type_varstring) && (ctc != type_varunicode))
  508. args.append(*translator.getBoundLength(test));
  509. args.append(*ensureIndexable(test.expr));
  510. if ((ctc==type_unicode) || (ctc == type_varunicode) || (ctc == type_utf8))
  511. args.append(*createConstant(str(compareType->queryLocale())));
  512. OwnedHqlExpr call = translator.bindTranslatedFunctionCall(func, args);
  513. OwnedHqlExpr search = createTranslated(call);
  514. bool includeDefaultInResult = false;
  515. OwnedHqlExpr resultExpr = createResultsExpr(midVar, true, &includeDefaultInResult);
  516. OwnedHqlExpr simpleResult = queryCreateSimpleResultAssign(search, resultExpr);
  517. if (simpleResult)
  518. translator.buildExprAssign(ctx, target, simpleResult);
  519. else
  520. {
  521. ctx.addDeclare(midVar, NULL);
  522. translator.buildAssignToTemp(ctx, midVar, search);
  523. if (includeDefaultInResult)
  524. {
  525. translator.buildExprAssign(ctx, target, resultExpr);
  526. }
  527. else
  528. {
  529. OwnedHqlExpr compare = createBoolExpr(no_ne, LINK(midVar), createNotFoundValue());
  530. BuildCtx subctx(ctx);
  531. IHqlStmt * stmt = subctx.addFilter(compare);
  532. translator.buildExprAssign(subctx, target, resultExpr);
  533. subctx.selectElse(stmt);
  534. translator.buildExprAssign(subctx, target, defaultValue);
  535. }
  536. }
  537. }
  538. else
  539. {
  540. #if 0
  541. //Keep this as a reminder of what was needed to fix qstrings.
  542. if (ctc == type_qstring)
  543. {
  544. Linked<ITypeInfo> compareType = queryCompareType();
  545. compareType.setown(makeArrayType(compareType.getLink()));
  546. table = createValue(no_typetransfer, compareType.getLink(), table);
  547. }
  548. #endif
  549. OwnedHqlExpr resultExpr = createResultsExpr(midVar, false);
  550. //Now generate the code that performs the binary chop..
  551. ctx.addDeclare(midVar, NULL);
  552. OwnedHqlExpr compareVar = ctx.getTempDeclare(indexType, NULL);
  553. OwnedHqlExpr leftVar = ctx.getTempDeclare(indexType, NULL);
  554. OwnedHqlExpr rightVar = ctx.getTempDeclare(indexType, NULL);
  555. OwnedHqlExpr numPairs = getSizetConstant(getNumPairs());
  556. ctx.addAssign(leftVar, queryZero());
  557. ctx.addAssign(rightVar, numPairs);
  558. translator.buildExprAssign(ctx, target, defaultValue);
  559. OwnedHqlExpr loopc = createBoolExpr(no_lt, LINK(leftVar), LINK(rightVar));
  560. OwnedHqlExpr mid = createValue(no_div, createValue(no_add, LINK(leftVar), LINK(rightVar)), createConstant(indexType->castFrom(false, 2)));
  561. OwnedHqlExpr mid_p1 = createValue(no_add, LINK(indexType), LINK(midVar), createConstant(indexType->castFrom(false, 1)));
  562. OwnedHqlExpr curelem = createValue(no_index, LINK(compareType), boundTable.getTranslatedExpr(), createTranslated(mid_p1));
  563. OwnedHqlExpr test1 = createBoolExpr(no_lt, LINK(compareVar), getZero());
  564. OwnedHqlExpr test2 = createBoolExpr(no_gt, LINK(compareVar), getZero());
  565. OwnedHqlExpr order = createValue(no_order, LINK(indexType), test.getTranslatedExpr(), LINK(curelem));
  566. BuildCtx loopctx(ctx);
  567. loopctx.addLoop(loopc, NULL, true);
  568. translator.buildAssignToTemp(loopctx, midVar, mid);
  569. translator.buildAssignToTemp(loopctx, compareVar, order);
  570. BuildCtx subctx(loopctx);
  571. IHqlStmt * if1 = subctx.addFilter(test1); // if (test < 0)
  572. translator.buildAssignToTemp(subctx, rightVar, midVar); // right = mid;
  573. subctx.selectElse(if1); // else
  574. IHqlStmt * if2 = subctx.addFilter(test2); // if (test > 0)
  575. translator.buildAssignToTemp(subctx, leftVar, mid_p1); // left = mid + 1;
  576. subctx.selectElse(if2); // else
  577. //generate the default assignment...
  578. translator.buildExprAssign(subctx, target, resultExpr);
  579. subctx.addBreak();
  580. }
  581. }
  582. void HqlCppCaseInfo::buildIntegerSearchMap(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * test)
  583. {
  584. ITypeInfo * compareType = queryCompareType();
  585. HqlExprArray args;
  586. args.append(*createCompareList());
  587. args.append(*LINK(test));
  588. IIdAtom * func;
  589. if (compareType->isSigned())
  590. {
  591. if (compareType->getSize() > 4)
  592. func = searchTableInteger8Id;
  593. else
  594. func = searchTableInteger4Id;
  595. }
  596. else
  597. {
  598. if (compareType->getSize() > 4)
  599. func = searchTableUInteger8Id;
  600. else
  601. func = searchTableUInteger4Id;
  602. }
  603. OwnedHqlExpr search = translator.bindFunctionCall(func, args);
  604. OwnedHqlExpr midVar = createVariable(LINK(indexType));
  605. bool includeDefaultInResult = false;
  606. OwnedHqlExpr resultExpr = createResultsExpr(midVar, true, &includeDefaultInResult);
  607. OwnedHqlExpr simpleResult = queryCreateSimpleResultAssign(search, resultExpr);
  608. if (simpleResult)
  609. translator.buildExprAssign(ctx, target, simpleResult);
  610. else
  611. {
  612. ctx.addDeclare(midVar, NULL);
  613. translator.buildAssignToTemp(ctx, midVar, search);
  614. if (includeDefaultInResult)
  615. {
  616. translator.buildExprAssign(ctx, target, resultExpr);
  617. }
  618. else
  619. {
  620. OwnedHqlExpr compare = createBoolExpr(no_ne, LINK(midVar), createNotFoundValue());
  621. BuildCtx subctx(ctx);
  622. IHqlStmt * stmt = subctx.addFilter(compare);
  623. translator.buildExprAssign(subctx, target, resultExpr);
  624. subctx.selectElse(stmt);
  625. translator.buildExprAssign(subctx, target, defaultValue);
  626. }
  627. }
  628. }
  629. void HqlCppCaseInfo::buildSwitchCondition(BuildCtx & ctx, CHqlBoundExpr & bound)
  630. {
  631. OwnedHqlExpr simpleCond = complexCompare ? getSimplifyCompareArg(cond) : LINK(cond);
  632. translator.buildCachedExpr(ctx, simpleCond, bound);
  633. }
  634. void HqlCppCaseInfo::buildSwitchMap(BuildCtx & ctx, const CHqlBoundTarget * target, IHqlExpression * test)
  635. {
  636. bool isCharCompare = (test->queryType()->getTypeCode() == type_string);
  637. Owned<ITypeInfo> unsigned1Type = makeIntType(1, false);
  638. LinkedHqlExpr cond = test;
  639. if (isCharCompare)
  640. cond.setown(createValue(no_implicitcast, LINK(unsigned1Type), createValue(no_index, makeCharType(), LINK(test), getZero())));
  641. BuildCtx subctx(ctx);
  642. IHqlStmt * stmt = subctx.addSwitch(cond);
  643. // are all the comparisons against constant values? If so we optimize it...
  644. unsigned sameCount = 0;
  645. ForEachItemIn(idx, pairs)
  646. {
  647. IHqlExpression & cur = pairs.item(idx);
  648. LinkedHqlExpr compare = cur.queryChild(0);
  649. IHqlExpression * branchValue = cur.queryChild(1);
  650. if (isCharCompare)
  651. {
  652. //Coded this way to avoid problems with ascii v ebcdic strings
  653. const byte * data = reinterpret_cast<const byte *>((char *)compare->queryValue()->queryValue());
  654. byte value = data[0];
  655. Owned<IValue> cast;
  656. if (value < 127)
  657. cast.setown(createCharValue(value, true));
  658. else
  659. cast.setown(createIntValue(data[0], LINK(unsigned1Type)));
  660. compare.setown(createConstant(cast.getClear()));
  661. }
  662. bool same = false;
  663. bool skip = false;
  664. if (idx != pairs.ordinality()-1)
  665. {
  666. IHqlExpression & next = pairs.item(idx+1);
  667. if (next.queryChild(1) == branchValue)
  668. same = true;
  669. //if save item is included twice, remove one so no error
  670. //from the case statement
  671. if (next.queryChild(0) == cur.queryChild(0))
  672. {
  673. skip = true;
  674. #ifdef _DEBUG
  675. throwUnexpected(); // should have been removed as a duplicate
  676. #endif
  677. }
  678. }
  679. if (sameCount >= MAX_NUM_NOBREAK_CASE)
  680. same = false;
  681. if (!skip)
  682. {
  683. subctx.addCase(stmt, compare);
  684. // common up case labels that produce the same result
  685. if (!same)
  686. {
  687. sameCount = 1;
  688. if (target)
  689. translator.buildExprAssign(subctx, *target, branchValue);
  690. else
  691. translator.buildReturn(subctx, branchValue);
  692. }
  693. else
  694. sameCount++;
  695. }
  696. }
  697. if (target)
  698. {
  699. subctx.addDefault(stmt);
  700. translator.buildExprAssign(subctx, *target, defaultValue);
  701. }
  702. else
  703. translator.buildReturn(ctx, defaultValue);
  704. }
  705. void HqlCppCaseInfo::buildGeneralAssign(BuildCtx & ctx, const CHqlBoundTarget & target)
  706. {
  707. unsigned max = pairs.ordinality();
  708. Owned<BuildCtx> subctx = new BuildCtx(ctx);
  709. CHqlBoundExpr pureCond;
  710. if (cond.get())
  711. translator.buildCachedExpr(*subctx, cond, pureCond);
  712. OwnedHqlExpr testMore;
  713. if (max > MAX_NESTED_CASES)
  714. {
  715. //Too many nested blocks cause the compiler indigestion...
  716. Owned<ITypeInfo> t = makeBoolType();
  717. testMore.setown(ctx.getTempDeclare(t, queryBoolExpr(false)));
  718. }
  719. for (unsigned idx = 0; idx < max; idx++)
  720. {
  721. IHqlExpression & cur = pairs.item(idx);
  722. IHqlExpression * curtest = cur.queryChild(0);
  723. IHqlExpression * curvalue = cur.queryChild(1);
  724. OwnedHqlExpr compare;
  725. if (!pureCond.expr)
  726. compare.setown(ensureExprType(curtest, queryBoolType()));
  727. else
  728. compare.setown(createBoolExpr(no_eq, pureCond.getTranslatedExpr(), LINK(curtest)));
  729. if (idx && ((idx % MAX_NESTED_CASES) == 0))
  730. {
  731. translator.buildAssignToTemp(*subctx,testMore,queryBoolExpr(true));
  732. subctx.setown(new BuildCtx(ctx));
  733. subctx->addFilter(testMore);
  734. translator.buildAssignToTemp(*subctx,testMore,queryBoolExpr(false));
  735. }
  736. IHqlStmt * test = translator.buildFilterViaExpr(*subctx, compare);
  737. translator.buildExprAssign(*subctx, target, curvalue);
  738. subctx->selectElse(test);
  739. }
  740. translator.buildExprAssign(*subctx, target, defaultValue);
  741. }
  742. void HqlCppCaseInfo::buildGeneralReturn(BuildCtx & ctx)
  743. {
  744. unsigned max = pairs.ordinality();
  745. CHqlBoundExpr pureCond;
  746. if (cond.get())
  747. translator.buildCachedExpr(ctx, cond, pureCond);
  748. for (unsigned idx = 0; idx < max; idx++)
  749. {
  750. IHqlExpression & cur = pairs.item(idx);
  751. IHqlExpression * curtest = cur.queryChild(0);
  752. IHqlExpression * curvalue = cur.queryChild(1);
  753. OwnedHqlExpr compare;
  754. if (!pureCond.expr)
  755. compare.setown(ensureExprType(curtest, queryBoolType()));
  756. else
  757. compare.setown(createBoolExpr(no_eq, pureCond.getTranslatedExpr(), LINK(curtest)));
  758. BuildCtx subctx(ctx);
  759. translator.buildFilter(subctx, compare);
  760. translator.buildReturn(subctx, curvalue);
  761. }
  762. translator.buildReturn(ctx, defaultValue);
  763. }
  764. bool HqlCppCaseInfo::okToAlwaysEvaluateDefault()
  765. {
  766. if (!canRemoveGuard(defaultValue))
  767. return false;
  768. return true;
  769. }
  770. ITypeInfo * HqlCppCaseInfo::queryCompareType()
  771. {
  772. return cond->queryType()->queryPromotedType();
  773. }
  774. IHqlExpression * HqlCppCaseInfo::createCompareList()
  775. {
  776. //NB: All cases need to have the same type because they are stored in a table
  777. Linked<ITypeInfo> promoted = pairs.item(0).queryChild(0)->queryType();
  778. unsigned max = pairs.ordinality();
  779. for (unsigned idx1 = 1; idx1 < max; idx1++)
  780. {
  781. ITypeInfo * type = pairs.item(idx1).queryChild(0)->queryType();
  782. promoted.setown(getPromotedECLType(promoted, type));
  783. }
  784. HqlExprArray values;
  785. values.ensure(pairs.ordinality());
  786. ForEachItemIn(idx, pairs)
  787. {
  788. IHqlExpression & pair = pairs.item(idx);
  789. IHqlExpression * compare = pair.queryChild(0);
  790. values.append(*ensureExprType(compare, promoted));
  791. }
  792. Linked<ITypeInfo> compareType = queryCompareType();
  793. switch (compareType->getTypeCode())
  794. {
  795. case type_string:
  796. case type_data:
  797. case type_varstring:
  798. case type_qstring:
  799. case type_utf8:
  800. compareType.setown(makePointerType(makeCharType(false)));
  801. break;
  802. case type_unicode:
  803. case type_varunicode:
  804. compareType.setown(makePointerType(makeClassType("UChar")));
  805. break;
  806. }
  807. return createValue(no_list, makeArrayType(compareType.getLink()), values);
  808. }
  809. IHqlExpression * HqlCppCaseInfo::createResultsExpr(IHqlExpression * matchVar, bool canIncludeDefault, bool * includedDefault)
  810. {
  811. if (includedDefault)
  812. *includedDefault = false;
  813. //Look at all the return results and see what relation we can create
  814. //This can generate one of the following:
  815. //1. A single value.
  816. //2. A function of the result. e.g., IN...
  817. //3. A lookup in another table. [ all values are constant ]
  818. //4. A nested map statement
  819. bool areSame = true;
  820. bool areLinear = true;
  821. bool areConstant = true;
  822. __int64 linearStart = 0;
  823. __int64 linearMultiple = 1;
  824. ITypeInfo * retType = resultType;
  825. switch (retType->getTypeCode())
  826. {
  827. case type_int:
  828. case type_boolean:
  829. break;
  830. case type_string:
  831. case type_data:
  832. // areConstant = false; // a temporary hack to stop incorrect table being generated.
  833. areLinear = false;
  834. break;
  835. default:
  836. areLinear = false;
  837. break;
  838. }
  839. IHqlExpression * prevValue = NULL;
  840. HqlExprArray values;
  841. values.ensure(pairs.ordinality());
  842. ForEachItemIn(idx, pairs)
  843. {
  844. IHqlExpression & pair = pairs.item(idx);
  845. IHqlExpression * value = pair.queryChild(1);
  846. IValue * cvalue = value->queryValue();
  847. if (cvalue)
  848. {
  849. if (areLinear)
  850. {
  851. __int64 val = cvalue->getIntValue();
  852. if (idx == 0)
  853. linearStart = val;
  854. else if (idx == 1)
  855. linearMultiple = (val - linearStart);
  856. else if (val != linearStart + idx * linearMultiple)
  857. areLinear = false;
  858. }
  859. }
  860. else
  861. {
  862. areConstant = false;
  863. areLinear = false;
  864. }
  865. if (idx > 0)
  866. {
  867. if (areSame && (prevValue != value))
  868. areSame = false;
  869. }
  870. values.append(*ensureExprType(value, resultType));
  871. prevValue = value;
  872. }
  873. if (areSame)
  874. return LINK(prevValue);
  875. if (areLinear)
  876. {
  877. IHqlExpression * ret = ensureExprType(matchVar, resultType);
  878. if (linearMultiple != 1)
  879. ret = createValue(no_mul, LINK(resultType), ret, createConstant(resultType->castFrom(true, linearMultiple)));
  880. if (linearStart != 0)
  881. ret = createValue(no_add, LINK(resultType), ret, createConstant(resultType->castFrom(true, linearStart)));
  882. return ret;
  883. }
  884. unsigned firstMatchEntry = 0;
  885. if (canIncludeDefault)
  886. {
  887. //If all the values are constant, then can add the default as an extra 0th entry, because -1 will be the index for the default
  888. if (areConstant && defaultValue->isConstant() && defaultValue->queryType() == values.item(0).queryType())
  889. {
  890. firstMatchEntry = 1;
  891. values.add(*LINK(defaultValue), 0);
  892. *includedDefault = true;
  893. }
  894. }
  895. // easy way to create a value list...
  896. ITypeInfo * storeType = getArrayElementType(retType);
  897. OwnedHqlExpr newlist = createValue(no_list, makeSetType(storeType), values);
  898. if (areConstant && canBuildStaticList(resultType))
  899. {
  900. IHqlExpression * index = adjustValue(matchVar, 1+firstMatchEntry);
  901. return createValue(no_index, LINK(retType), LINK(newlist), index, createAttribute(noBoundCheckAtom));
  902. }
  903. //Need to generate a case (switch integer case 1: ..... )
  904. HqlExprArray choosePairs;
  905. cvtChooseListToPairs(choosePairs, newlist, 0);
  906. IHqlExpression * caseExpr = createOpenValue(no_case, LINK(retType));
  907. caseExpr->addOperand(LINK(matchVar));
  908. ForEachItemIn(idx2, choosePairs)
  909. caseExpr->addOperand(&choosePairs.item(idx2));
  910. choosePairs.kill(true);
  911. caseExpr->addOperand(LINK(defaultValue));
  912. return caseExpr->closeExpr();
  913. }
  914. void HqlCppCaseInfo::generateCompareVar(BuildCtx & ctx, IHqlExpression * target, CHqlBoundExpr & test, IHqlExpression * other)
  915. {
  916. OwnedHqlExpr compare = createValue(no_order, test.getTranslatedExpr(), LINK(other));
  917. translator.buildAssignToTemp(ctx, target, compare);
  918. }
  919. unsigned HqlCppCaseInfo::getNumPairs()
  920. {
  921. return pairs.ordinality();
  922. }
  923. bool HqlCppCaseInfo::hasLibraryChop()
  924. {
  925. ITypeInfo * compareType = queryCompareType();
  926. type_t ctc = compareType->getTypeCode();
  927. switch (ctc)
  928. {
  929. case type_data:
  930. return canBuildStaticList(promotedElementType);
  931. case type_string:
  932. case type_varstring:
  933. case type_qstring:
  934. case type_unicode:
  935. case type_varunicode:
  936. case type_utf8:
  937. return true;
  938. }
  939. return false;
  940. }
  941. void HqlCppCaseInfo::processBranches()
  942. {
  943. sortPairs();
  944. removeDuplicates();
  945. promoteTypes();
  946. }
  947. void HqlCppCaseInfo::promoteTypes()
  948. {
  949. Owned<ITypeInfo> promoted = pairs.item(0).queryChild(0)->getType();
  950. unsigned max = pairs.ordinality();
  951. for (unsigned idx1 = 1; idx1 < max; idx1++)
  952. {
  953. ITypeInfo * type = pairs.item(idx1).queryChild(0)->queryType();
  954. if (isStringType(promoted) && isStringType(type))
  955. {
  956. if (promoted->getStringLen() != type->getStringLen())
  957. {
  958. promoted.setown(::getPromotedECLType(promoted, type));
  959. promoted.setown(getStretchedType(UNKNOWN_LENGTH, promoted));
  960. }
  961. }
  962. promoted.setown(::getPromotedECLType(promoted, type));
  963. }
  964. promotedElementType.set(promoted);
  965. if (isStringType(promoted))
  966. promoted.setown(getStretchedType(UNKNOWN_LENGTH, promoted));
  967. ITypeInfo * testType = queryCompareType();
  968. if ((testType->queryCharset() != promoted->queryCharset()) || (testType->queryLocale() != promoted->queryLocale()))
  969. cond.setown(ensureExprType(cond, promoted));
  970. }
  971. bool HqlCppCaseInfo::canBuildArrayLookup(const CHqlBoundExpr & test)
  972. {
  973. if (!constantValues)
  974. return false;
  975. ITypeInfo * condType = test.queryType()->queryPromotedType();
  976. //MORE: Also support this for high density tables that don't start at 0... - checking upper and lower bounds
  977. unsigned bitSize = condType->getBitSize();
  978. if ((bitSize && (bitSize <= 8) && !condType->isSigned()))
  979. {
  980. unsigned limit = (1 << bitSize);
  981. //use case if enough items, or above a certain density...
  982. if (pairs.ordinality() * 100 >= limit * SWITCH_TABLE_DENSITY_THRESHOLD)
  983. {
  984. if ((condType->getTypeCode() == type_int) || (condType->getTypeCode() == type_string))
  985. {
  986. lowerTableBound.setown(getSizetConstant(0));
  987. upperTableBound.setown(getSizetConstant(limit-1));
  988. return true;
  989. }
  990. }
  991. }
  992. if (condType->isInteger() && !isUnknownSize(resultType))
  993. {
  994. unsigned __int64 range = getIntValue(highestCompareExpr, 0) - getIntValue(lowestCompareExpr, 0) + 1;
  995. if (pairs.ordinality() * 100 >= range * RANGE_DENSITY_THRESHOLD)
  996. {
  997. useRangeIndex = true;
  998. lowerTableBound.set(lowestCompareExpr);
  999. upperTableBound.set(highestCompareExpr);
  1000. return true;
  1001. }
  1002. }
  1003. return false;
  1004. }
  1005. bool HqlCppCaseInfo::queryBuildArrayLookup(BuildCtx & ctx, const CHqlBoundTarget & target, const CHqlBoundExpr & test)
  1006. {
  1007. if (canBuildArrayLookup(test) && canBuildStaticList(resultType) && defaultValue->isConstant())
  1008. {
  1009. BuildCtx subctx(ctx);
  1010. OwnedHqlExpr ret = buildIndexedMap(subctx, test);
  1011. translator.buildExprAssign(ctx, target, ret);
  1012. return true;
  1013. }
  1014. return false;
  1015. }
  1016. void HqlCppCaseInfo::removeDuplicates()
  1017. {
  1018. unsigned num = pairs.ordinality();
  1019. if (num > 1)
  1020. {
  1021. num--;
  1022. while (num--)
  1023. {
  1024. IHqlExpression & cur = pairs.item(num);
  1025. IHqlExpression & next = pairs.item(num+1);
  1026. if (cur.queryChild(0) == next.queryChild(0))
  1027. {
  1028. if (cur.queryChild(1) == next.queryChild(1))
  1029. pairs.remove(num+1);
  1030. else
  1031. {
  1032. // we need to keep the first in the original list.... Horrid, but it works...
  1033. unsigned off1 = originalPairs.find(cur);
  1034. unsigned off2 = originalPairs.find(next);
  1035. assertex(off1 != NotFound && off2 != NotFound);
  1036. if (off1 < off2)
  1037. pairs.remove(num+1);
  1038. else
  1039. pairs.remove(num);
  1040. }
  1041. }
  1042. }
  1043. }
  1044. }
  1045. IHqlExpression * HqlCppCaseInfo::queryCreateSimpleResultAssign(IHqlExpression * search, IHqlExpression * resultExpr)
  1046. {
  1047. IHqlExpression * trueExpr = queryBoolExpr(true);
  1048. IHqlExpression * falseExpr = queryBoolExpr(false);
  1049. if (resultExpr == trueExpr && defaultValue == falseExpr)
  1050. return createBoolExpr(no_ne, LINK(search), createNotFoundValue());
  1051. if (resultExpr == falseExpr && defaultValue == trueExpr)
  1052. return createBoolExpr(no_eq, LINK(search), createNotFoundValue());
  1053. return NULL;
  1054. }
  1055. IHqlExpression * HqlCppCaseInfo::queryCompare(unsigned index)
  1056. {
  1057. return pairs.item(index).queryChild(0);
  1058. }
  1059. IHqlExpression * HqlCppCaseInfo::queryReturn(unsigned index)
  1060. {
  1061. return pairs.item(index).queryChild(1);
  1062. }
  1063. void HqlCppCaseInfo::setCond(IHqlExpression * expr)
  1064. {
  1065. cond.set(expr);
  1066. if (isCompare3Valued(expr->queryType()))
  1067. complexCompare = true;
  1068. }
  1069. void HqlCppCaseInfo::setDefault(IHqlExpression * expr)
  1070. {
  1071. defaultValue.set(expr);
  1072. }
  1073. void HqlCppCaseInfo::sortPairs()
  1074. {
  1075. appendArray(originalPairs, pairs);
  1076. pairs.sort(comparePair);
  1077. }
  1078. void HqlCppCaseInfo::updateResultType(IHqlExpression * expr)
  1079. {
  1080. ITypeInfo * curResultType = expr->queryType();
  1081. if (resultType)
  1082. resultType.setown(::getPromotedECLType(resultType, curResultType));
  1083. else
  1084. resultType.set(curResultType);
  1085. }