ITypeInfo * getConcatResultType(IHqlExpression * expr) { assertex(!"not sure if this is unicode safe, but appears not to be used"); //first work out the maximum size of the target unsigned max = expr->numChildren(); unsigned idx; unsigned totalSize = 0; bool unknown = false; type_t resultType = type_string; for (idx = 0; idx < max; idx++) { ITypeInfo * type = expr->queryChild(idx)->queryType(); unsigned size = type->getStringLen(); if (size == UNKNOWN_LENGTH) unknown = true; else totalSize += size; if (type->getTypeCode() == type_varstring) resultType = type_varstring; } if (unknown) totalSize = 1023; if (resultType == type_string) return makeStringType(totalSize, NULL, NULL); return makeVarStringType(totalSize); }
IHqlExpression * HqlCppCaseInfo::buildIndexedMap(BuildCtx & ctx, IHqlExpression * test, unsigned lower, unsigned upper) { ITypeInfo * compareType = test->queryType()->queryPromotedType(); type_t compareTypeCode = compareType->getTypeCode(); HqlExprArray values; IHqlExpression * dft = queryActiveTableSelector(); // value doesn't matter as long as it will not occur unsigned num = (upper-lower+1); values.ensure(num); unsigned idx; for (idx = 0; idx < num; idx++) values.append(*LINK(dft)); ForEachItemIn(idx2, pairs) { IHqlExpression & cur = pairs.item(idx2); IValue * value = cur.queryChild(0)->queryValue(); unsigned replaceIndex; switch (compareTypeCode) { case type_int: replaceIndex = (int)value->getIntValue()-lower; break; case type_string: { StringBuffer temp; value->getStringValue(temp); replaceIndex = (int)(unsigned char)temp.charAt(0)-lower; break; } default: throwUnexpectedType(compareType); } IHqlExpression * mapTo = cur.queryChild(1); if (mapTo->getOperator() != no_constant) throwUnexpected(); if (replaceIndex >= num) translator.reportWarning(CategoryIgnored, HQLWRN_CaseCanNeverMatch, "CASE entry %d can never match the test condition", replaceIndex); else values.replace(*LINK(mapTo),replaceIndex); }
bool canCreateTemporary(IHqlExpression * expr) { switch (expr->getOperator()) { case no_range: case no_rangefrom: case no_rangeto: case no_rangecommon: case no_constant: case no_all: case no_mapto: case no_record: case no_attr: case no_attr_expr: case no_attr_link: case no_joined: case no_sizeof: case no_offsetof: case no_newtransform: case no_transform: case no_assign: case no_assignall: case no_left: case no_right: case no_self: case no_top: case no_activetable: case no_alias: case no_skip: case no_assert: case no_counter: case no_sortlist: case no_matched: case no_matchtext: case no_matchunicode: case no_matchposition: case no_matchlength: case no_matchattr: case no_matchrow: case no_matchutf8: case no_recordlist: case no_transformlist: case no_rowvalue: case no_pipe: case no_colon: case no_globalscope: case no_subgraph: case no_forcelocal: case no_forcenolocal: case no_allnodes: case no_thisnode: case no_libraryscopeinstance: case no_loopbody: case no_external: return false; } ITypeInfo * type = expr->queryType(); if (!type) return false; switch (type->getTypeCode()) { case type_transform: case type_null: case type_void: case type_rule: case type_pattern: case type_token: case type_event: return false; default: return true; } }
bool HqlCppCaseInfo::buildAssign(BuildCtx & ctx, const CHqlBoundTarget & target) { if (pairs.ordinality() == 0) { translator.buildExprAssign(ctx, target, defaultValue); } else if (cond.get() && constantCases) { processBranches(); BuildCtx subctx(ctx); CHqlBoundExpr test; buildSwitchCondition(ctx, test); if (complexCompare) { if (pairs.ordinality() > INLINE_COMPARE_THRESHOLD) { if (okToAlwaysEvaluateDefault() || hasLibraryChop()) buildLoopChopMap(subctx, target, test); else buildGeneralAssign(subctx, target); } else { if (okToAlwaysEvaluateDefault()) buildChop3Map(subctx, target, test); else buildGeneralAssign(subctx, target); } } else { ITypeInfo * condType = test.queryType()->queryPromotedType(); if (!queryBuildArrayLookup(subctx, target, test)) { if (condType->getTypeCode() != type_real) { OwnedHqlExpr search = test.getTranslatedExpr(); if (constantValues && (condType->getTypeCode() == type_int) && (pairs.ordinality() > INTEGER_SEARCH_THRESHOLD) && canBuildStaticList(resultType)) buildIntegerSearchMap(subctx, target, search); else buildSwitchMap(subctx, &target, test.expr); } else { if (okToAlwaysEvaluateDefault() && pairs.ordinality() > 4) { translator.buildExprAssign(ctx, target, defaultValue); buildChop2Map(subctx, target, test, 0, pairs.ordinality()); } else buildGeneralAssign(subctx, target); } } } } else buildGeneralAssign(ctx, target); return true; }
IHqlExpression * HqlCppCaseInfo::buildIndexedMap(BuildCtx & ctx, const CHqlBoundExpr & test) { ITypeInfo * compareType = test.queryType()->queryPromotedType(); type_t compareTypeCode = compareType->getTypeCode(); HqlExprArray values; IHqlExpression * dft = queryActiveTableSelector(); // value doesn't matter as long as it will not occur __int64 lower = getIntValue(lowerTableBound, 0); unsigned num = (getIntValue(upperTableBound, 0)-lower)+1; CHqlBoundExpr indexExpr; switch (compareTypeCode) { case type_int: indexExpr.set(test); break; case type_string: indexExpr.expr.setown(createValue(no_index, makeCharType(), LINK(test.expr), getZero())); indexExpr.expr.setown(createValue(no_cast, makeIntType(1, false), LINK(indexExpr.expr))); break; default: throwUnexpectedType(compareType); } if (useRangeIndex && (num != 1)) translator.ensureSimpleExpr(ctx, indexExpr); OwnedHqlExpr mapped; ITypeInfo * retType = resultType; //if num == pairs.ordinality() and all results are identical, avoid the table lookup. if (allResultsMatch && (num == pairs.ordinality())) { mapped.set(pairs.item(0).queryChild(1)); } else { values.ensure(num); unsigned idx; for (idx = 0; idx < num; idx++) values.append(*LINK(dft)); ForEachItemIn(idx2, pairs) { IHqlExpression & cur = pairs.item(idx2); IValue * value = cur.queryChild(0)->queryValue(); unsigned replaceIndex; switch (compareTypeCode) { case type_int: replaceIndex = (unsigned)(value->getIntValue()-lower); break; case type_string: { StringBuffer temp; value->getStringValue(temp); replaceIndex = (unsigned)((unsigned char)temp.charAt(0)-lower); break; } default: throwUnexpectedType(compareType); } IHqlExpression * mapTo = cur.queryChild(1); if (mapTo->getOperator() != no_constant) throwUnexpected(); if (replaceIndex >= num) translator.reportWarning(CategoryIgnored, HQLWRN_CaseCanNeverMatch, "CASE entry %d can never match the test condition", replaceIndex); else values.replace(*LINK(mapTo),replaceIndex); } //Now replace the placeholders with the default values. for (idx = 0; idx < num; idx++) { if (&values.item(idx) == dft) values.replace(*defaultValue.getLink(),idx); } // use a var string type to get better C++ generated... ITypeInfo * storeType = getArrayElementType(resultType); ITypeInfo * listType = makeArrayType(storeType, values.ordinality()); OwnedHqlExpr lvalues = createValue(no_list, listType, values); CHqlBoundExpr boundTable; translator.buildExpr(ctx, lvalues, boundTable); LinkedHqlExpr tableIndex = indexExpr.expr; if (getIntValue(lowerTableBound, 0)) tableIndex.setown(createValue(no_sub, tableIndex->getType(), LINK(tableIndex), LINK(lowerTableBound))); IHqlExpression * ret = createValue(no_index, LINK(retType), LINK(boundTable.expr), LINK(tableIndex)); mapped.setown(createTranslatedOwned(ret)); }