IHqlExpression * peepholeOptimize(BuildCtx & ctx, IHqlExpression * expr) { switch (expr->getOperator()) { case no_eq: case no_ne: case no_le: case no_lt: case no_ge: case no_gt: return peepholeOptimizeCompare(ctx, expr); case no_and: case no_or: case no_not: { HqlExprArray args; bool same = true; ForEachChild(i, expr) { IHqlExpression * cur = expr->queryChild(i); IHqlExpression * optimized = peepholeOptimize(ctx, expr); args.append(*optimized); if (cur != optimized) same = false; } if (!same) return expr->clone(args); break; } }
void HqlCppLibrary::extractOutputs() { HqlExprArray symbols; scopeExpr->queryScope()->getSymbols(symbols); IHqlScope * scope = scopeExpr->queryScope(); HqlDummyLookupContext dummyctx(NULL); ForEachItemIn(i, symbols) { IHqlExpression & cur = symbols.item(i); if (isExported(&cur)) { _ATOM name = cur.queryName(); OwnedHqlExpr value = scope->lookupSymbol(name, LSFpublic, dummyctx); if (value && !value->isFunction()) { if (value->isDataset() || value->isDatarow() || value->queryType()->isScalar()) { OwnedHqlExpr null = createNullExpr(value); outputs.append(*cur.cloneAllAnnotations(null)); } } } }
void CChildLinkedDatasetColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeFormat) { if (isConditional()) checkAssignOk(translator, ctx, selector, queryZero(), sizeof(size32_t) + sizeof(byte * *)); OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0); OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t)); IHqlExpression * record = column->queryRecord(); CHqlBoundTarget boundTarget; boundTarget.count.setown(convertAddressToValue(addressSize, sizetType)); boundTarget.expr.setown(convertAddressToValue(addressData, queryType())); IIdAtom * func = NULL; HqlExprArray args; args.append(*translator.createSerializer(ctx, record, serializeFormat, deserializerAtom)); if (column->isDictionary()) { if (serializeFormat == diskAtom) { func = deserializeChildDictionaryFromDatasetFromStreamId; StringBuffer lookupHelperName; translator.buildDictionaryHashClass(record, lookupHelperName); args.append(*createQuoted(lookupHelperName.str(), makeBoolType())); } else func = deserializeChildDictionaryFromStreamId; } else func = deserializeChildRowsetFromStreamId; args.append(*LINK(helper)); OwnedHqlExpr call = translator.bindFunctionCall(func, args, queryType()); translator.buildExprAssign(ctx, boundTarget, call); }
IHqlExpression * createLocationAttr(ISourcePath * sourcePath, int lineno, int column, int position) { HqlExprArray args; args.append(*getSizetConstant(lineno)); args.append(*getSizetConstant(column)); args.append(*getSizetConstant(position)); if (sourcePath) args.append(*createUnknown(no_attr, makeNullType(), filenameAtom, LINK(sourcePath))); return createAttribute(_location_Atom, args); }
inline bool appendUniqueExpr(HqlExprArray & list, IHqlExpression * expr) { if (list.find(*expr) == NotFound) { list.append(*expr); return true; } expr->Release(); return false; }
static void getRootScopes(HqlScopeArray & rootScopes, IHqlScope * scope) { HqlExprArray rootSymbols; scope->getSymbols(rootSymbols); ForEachItemIn(i, rootSymbols) { IHqlExpression & cur = rootSymbols.item(i); IHqlScope * scope = cur.queryScope(); if (scope) rootScopes.append(*LINK(scope)); }
void CColumnInfo::buildDeserializeChildLoop(HqlCppTranslator & translator, BuildCtx & loopctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm) { OwnedHqlExpr endMarker = loopctx.getTempDeclare(sizetType, NULL); HqlExprArray args; args.append(*LINK(helper)); OwnedHqlExpr beginCall = translator.bindTranslatedFunctionCall(deserializerBeginNestedId, args); loopctx.addAssign(endMarker, beginCall); args.append(*LINK(helper)); args.append(*LINK(endMarker)); OwnedHqlExpr loopCall = createBoolExpr(no_not, translator.bindTranslatedFunctionCall(deserializerFinishedNestedId, args)); loopctx.addLoop(loopCall, NULL, false); }
IHqlExpression * addMemberSelector(IHqlExpression * expr, IHqlExpression * selector) { if (!expr) return NULL; if (expr->getOperator() == no_variable) return createValue(no_pselect, expr->getType(), LINK(selector), LINK(expr)); if (expr->numChildren() == 0) return LINK(expr); HqlExprArray args; ForEachChild(i, expr) args.append(*addMemberSelector(expr->queryChild(i), selector)); return expr->clone(args); }
void cvtIndexListToPairs(HqlExprArray & target, IHqlExpression * from) { unsigned max = from->numChildren(); unsigned idx; target.ensure(max); for (idx = 0; idx < max; idx++) { IHqlExpression * v1 = from->queryChild(idx); IHqlExpression * v2 = createConstant(createIntValue(idx+1, LINK(unsignedType))); ITypeInfo * type = v2->queryType(); target.append(* createValue(no_mapto, LINK(type), LINK(v1), v2)); } }
void cvtInListToPairs(HqlExprArray & target, IHqlExpression * from, bool valueIfMatch) { unsigned max = from->numChildren(); unsigned idx; IHqlExpression * tValue = queryBoolExpr(valueIfMatch); ITypeInfo * type = queryBoolType(); target.ensure(max); for (idx = 0; idx < max; idx++) { IHqlExpression * v1 = from->queryChild(idx); target.append(* createValue(no_mapto, LINK(type), LINK(v1), LINK(tValue))); } }
ForEachChild(i, record) { IHqlExpression * cur = record->queryChild(i); switch (cur->getOperator()) { case no_record: expandFieldNames(errorProcessor, out, cur, prefix, sep, formatFunc); break; case no_ifblock: expandFieldNames(errorProcessor, out, cur->queryChild(1), prefix, sep, formatFunc); break; case no_field: { StringBuffer lowerName; lowerName.append(cur->queryName()).toLowerCase(); if (formatFunc) { HqlExprArray args; args.append(*createConstant(lowerName.str())); OwnedHqlExpr bound = createBoundFunction(NULL, formatFunc, args, NULL, true); OwnedHqlExpr folded = foldHqlExpression(errorProcessor, bound, NULL, HFOthrowerror|HFOfoldimpure|HFOforcefold); assertex(folded->queryValue()); lowerName.clear(); getStringValue(lowerName, folded); } switch (cur->queryType()->getTypeCode()) { case type_record: case type_row: { unsigned len = prefix.length(); prefix.append(lowerName).append("."); expandFieldNames(errorProcessor, out, cur->queryRecord(), prefix, sep, formatFunc); prefix.setLength(len); break; } default: { if (out.length()) out.append(sep); out.append(prefix).append(lowerName); break; } } break; } } }
ForEachItemIn(i2, expandedOrder) { IHqlExpression * cur = &expandedOrder.item(i2); if (explicitStepped) { if (!extractCondition(stepArgs, cur)) { StringBuffer s; if (cur->getOperator() == no_select) s.append(cur->queryChild(1)->queryName()); else getExprECL(cur, s); throwError1(HQLERR_SteppingNotMatchSortCondition, s.str()); } if (stepArgs.ordinality() == 0) break; } else { if (!extractCondition(args, cur)) break; foundStepped = true; } if (compareLhs) break; }
unsigned getNumUniqueExpressions(const HqlExprArray & exprs) { TransformMutexBlock block; ExpressionStatsInfo info; ForEachItemIn(i, exprs) calcNumUniqueExpressions(&exprs.item(i),info); return info.count; }
static void expandUnnamedFunnel(HqlExprArray & inputs, IHqlExpression * expr) { while ((expr->getOperator() == no_addfiles) && (expr->queryBody() == expr)) { expandUnnamedFunnel(inputs, expr->queryChild(0)); expr = expr->queryChild(1); } inputs.append(*LINK(expr)); }
void LogicalGraphCreator::createLogicalGraph(HqlExprArray & exprs) { graph.setown(createPTree("graph")); // beginSubGraph(NULL, false); ForEachItemIn(i, exprs) createRootGraphActivity(&exprs.item(i)); // endSubGraph(); wu->createGraph("Logical", NULL, GraphTypeEcl, graph.getClear(), 0); }
void ScopeConsistencyChecker::checkConsistent(IHqlExpression * root, const HqlExprArray & _activeTables) { ForEachItemIn(i, _activeTables) activeTables.append(OLINK(_activeTables.item(i))); if (root->isDataset()) pushScope(); analyse(root, 0); if (root->isDataset()) popScope(); }
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); }
void reportAbstractModule(IErrorReceiver & errors, IHqlExpression * expr, const ECLlocation & errpos) { IHqlScope * scope = expr->queryScope(); StringBuffer fieldText; if (scope) { HqlExprArray symbols; scope->getSymbols(symbols); symbols.sort(compareSymbolsByName); ForEachItemIn(i, symbols) { IHqlExpression & cur = symbols.item(i); if (isPureVirtual(&cur)) { if (fieldText.length()) fieldText.append(","); fieldText.append(cur.queryName()); } } }
void CChildLinkedDatasetColumnInfo::buildSerialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeFormat) { IHqlExpression * record = column->queryRecord(); IIdAtom * func = NULL; HqlExprArray args; args.append(*LINK(helper)); args.append(*translator.createSerializer(ctx, record, serializeFormat, serializerAtom)); args.append(*LINK(selector->queryExpr())); if (column->isDictionary()) { if (serializeFormat == diskAtom) func = serializeChildDictionaryToDatasetToStreamId; else func = serializeChildDictionaryToStreamId; } else func = serializeChildRowsetToStreamId; OwnedHqlExpr call = translator.bindTranslatedFunctionCall(func, args); translator.buildStmt(ctx, call); }
IHqlExpression * buildDiskFileViewerEcl(const char * logicalName, IHqlExpression * record) { //Add filepos to the incomming record structure... IHqlExpression * filePosAttr = createAttribute(virtualAtom, createAttribute(filepositionAtom)); OwnedHqlExpr filepos = createField(fileposName, makeIntType(8, false), NULL, filePosAttr); IHqlExpression * sizeofAttr = createAttribute(virtualAtom, createAttribute(sizeofAtom)); OwnedHqlExpr reclen = createField(recordlenName, makeIntType(2, false), NULL, sizeofAttr); HqlExprArray fields; unwindChildren(fields, record); fields.append(*filepos.getLink()); fields.append(*reclen.getLink()); OwnedHqlExpr newRecord = createRecord(fields); newRecord.setown(createSymbol(createIdentifierAtom("_SourceRecord_"), newRecord.getLink(), ob_private)); OwnedHqlExpr dataset = createNewDataset(createConstant(logicalName), newRecord.getLink(), createValue(no_thor), NULL, NULL, NULL); OwnedHqlExpr filtered = addFilter(dataset, filepos); OwnedHqlExpr projected = addSimplifyProject(filtered); OwnedHqlExpr output = addOutput(projected); return output.getClear(); }
void LogicalGraphCreator::createLogicalGraph(HqlExprArray & exprs) { graph.setown(createPTree("graph")); // beginSubGraph(NULL, false); ForEachItemIn(i, exprs) createRootGraphActivity(&exprs.item(i)); // endSubGraph(); Owned<IWUGraph> wug = wu->updateGraph("Logical"); wug->setXGMMLTree(graph.getClear()); wug->setType(GraphTypeEcl); }
void ViewFieldECLTransformer::transform(unsigned & lenTarget, char * & target, unsigned lenSource, const char * source, const HqlExprArray & extraArgs) { Owned<ITypeInfo> sourceType = makeUtf8Type(lenSource, 0); IValue * sourceValue = createUtf8Value(source, LINK(sourceType)); OwnedHqlExpr sourceExpr = createConstant(sourceValue); HqlExprArray actuals; actuals.append(*LINK(sourceExpr)); appendArray(actuals, extraArgs); Owned<IErrorReceiver> errorReporter = createThrowingErrorReceiver(); OwnedHqlExpr call = createBoundFunction(errorReporter, function, actuals, NULL, true); OwnedHqlExpr castValue = ensureExprType(call, utf8Type); OwnedHqlExpr folded = quickFoldExpression(castValue, NULL, 0); IValue * foldedValue = folded->queryValue(); assertex(foldedValue); unsigned len = foldedValue->queryType()->getStringLen(); const char * data = static_cast<const char *>(foldedValue->queryValue()); unsigned size = rtlUtf8Size(len, data); lenTarget = len; target = (char *)rtlMalloc(size); memcpy(target, data, size); }
bool CChildLinkedDatasetColumnInfo::modifyColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * value, node_operator op) { if (hasDatasetLimits() || (op != no_assign_addfiles)) return false; OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0); OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t)); ITypeInfo * resultType = queryType(); ITypeInfo * valueType = value->queryType(); assertex(recordTypesMatch(valueType, resultType)); CHqlBoundTarget boundTarget; boundTarget.count.setown(convertAddressToValue(addressSize, sizetType)); boundTarget.expr.setown(convertAddressToValue(addressData, queryType())); HqlExprArray args; args.append(*LINK(value)); OwnedHqlExpr call = translator.bindFunctionCall(appendRowsToRowsetId, args, resultType); translator.buildDatasetAssign(ctx, boundTarget, call); return true; }
void ViewTransformerRegistry::addPlugins(const char * name) { loadedPlugins.setown(new SafePluginMap(&pluginCtx, true)); loadedPlugins->loadFromList(name); Owned<IErrorReceiver> errorReporter = createThrowingErrorReceiver(); dataServer.setown(createNewSourceFileEclRepository(errorReporter, name, ESFallowplugins, 0)); HqlScopeArray scopes; HqlParseContext parseCtx(dataServer, NULL, NULL); HqlLookupContext ctx(parseCtx, errorReporter); getRootScopes(scopes, dataServer, ctx); ForEachItemIn(i, scopes) { IHqlScope * scope = &scopes.item(i); HqlExprArray symbols; try { scope->ensureSymbolsDefined(ctx); scope->getSymbols(symbols); ForEachItemIn(j, symbols) { IHqlExpression & cur = symbols.item(j); if (cur.getOperator() == no_service) addServiceDefinition(&cur); } } catch (IException * e) { const char * name = str(scope->queryName()); VStringBuffer msg("Error loading plugin %s", name); EXCLOG(e, msg.str()); } }
bool HqlGram::checkTemplateFunctionParameters(IHqlExpression* func, HqlExprArray& actuals, const attribute& errpos) { bool anyErrors = false; IHqlExpression * formals = func->queryChild(1); ForEachItemIn(idx, actuals) { IHqlExpression* formal = formals->queryChild(idx); if (isAbstractDataset(formal)) { IHqlExpression * actual = &actuals.item(idx); IHqlExpression* mapping = queryFieldMap(actual); bool hadError = false; OwnedHqlExpr ignore = processAbstractDataset(NULL, formal, actual, mapping, errpos, true, hadError); if (hadError) anyErrors = true; } }
void HqlCppCaseInfo::addPairs(HqlExprArray & _pairs) { pairs.ensure(_pairs.ordinality()); ForEachItemIn(idx, _pairs) addPair(&_pairs.item(idx)); }
IHqlExpression * PositionTransformer::createTransformed(IHqlExpression * _expr) { OwnedHqlExpr transformed = NewHqlTransformer::createTransformed(_expr); switch (transformed->getOperator()) { case no_table: { IHqlExpression * mode = transformed->queryChild(2); HqlExprArray fields; HqlExprArray args; if (mode->getOperator() == no_thor) { unwindChildren(fields, transformed->queryChild(1)); IHqlExpression * filePosAttr = createComma(createAttribute(virtualAtom, createAttribute(filepositionAtom)), insertedAttr.getLink()); IHqlExpression * sizeofAttr = createComma(createAttribute(virtualAtom, createAttribute(sizeofAtom)), insertedAttr.getLink()); fields.append(*createField(fileposName, makeIntType(8, false), NULL, filePosAttr)); fields.append(*createField(recordlenName, makeIntType(2, false), NULL, sizeofAttr)); unwindChildren(args, transformed); args.replace(*createRecord(fields), 1); return transformed->clone(args); } } break; case no_iterate: case no_hqlproject: { HqlExprArray args; HqlExprArray assigns; IHqlExpression * transform = transformed->queryChild(1); unwindChildren(args, transformed); unwindChildren(assigns, transform); IHqlExpression * inRecord = transformed->queryChild(0)->queryRecord(); IHqlExpression * outRecord = transform->queryRecord(); HqlExprArray fields; unwindChildren(fields, outRecord); ForEachChild(idx, inRecord) { IHqlExpression * child = inRecord->queryChild(idx); if (child->hasProperty(insertedAtom)) { IHqlExpression * newTarget = createField(child->queryName(), child->getType(), LINK(child), insertedAttr.getLink()); fields.append(*newTarget); assigns.append(*createValue(no_assign, makeVoidType(), newTarget, createSelectExpr(createValue(no_left), LINK(newTarget)))); } } IHqlExpression * newRecord = createRecord(fields); args.replace(*createValue(no_transform, newRecord->getType(), assigns), 1); return transformed->clone(args); } break; case no_join: //only ok if join first case no_rollup: case no_newaggregate: case no_aggregate: fail(); break; case no_usertable: case no_selectfields: { IHqlExpression * grouping = transformed->queryChild(2); if (grouping && (grouping->getOperator() != no_attr)) fail(); IHqlExpression * record = transformed->queryRecord(); HqlExprArray fields; unwindChildren(fields, transformed->queryChild(1)); ForEachChild(idx, record) { IHqlExpression * child = record->queryChild(idx); if (child->hasProperty(insertedAtom)) fields.append(*createField(child->queryName(), child->getType(), LINK(child), insertedAttr.getLink())); } HqlExprArray args; unwindChildren(args, transformed); args.replace(*createRecord(fields), 1); return transformed->clone(args); }
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)); }
static IHqlExpression * optimizedReplaceSelector(IHqlExpression * expr, IHqlExpression * oldDataset, IHqlExpression * newDataset) { switch (expr->getOperator()) { case no_constant: case no_attr: return LINK(expr); case no_select: { IHqlExpression * lhs = expr->queryChild(0); IHqlExpression * field = expr->queryChild(1); OwnedHqlExpr newLhs; if (expr->hasAttribute(newAtom)) { newLhs.setown(optimizedReplaceSelector(lhs, oldDataset, newDataset)); } else { if (lhs == oldDataset) { if (newDataset->getOperator() == no_newrow) return createNewSelectExpr(LINK(newDataset->queryChild(0)), LINK(field)); if (newDataset->getOperator() == no_activerow) newDataset = newDataset->queryChild(0); return createSelectExpr(LINK(newDataset->queryNormalizedSelector()), LINK(field)); } else newLhs.setown(optimizedReplaceSelector(lhs, oldDataset, newDataset)); } if (newLhs) return replaceChild(expr, 0, newLhs); return NULL; } case no_implicitcast: case no_cast: { IHqlExpression * newUncast = optimizedReplaceSelector(expr->queryChild(0), oldDataset, newDataset); if (!newUncast) return NULL; OwnedHqlExpr ret = createValue(expr->getOperator(), expr->getType(), newUncast); return expr->cloneAllAnnotations(ret); } case no_hash: case no_hash32: case no_hash64: case no_sortlist: case no_concat: case no_trim: case no_negate: case no_eq: case no_ne: case no_sizeof: case no_attr_expr: case no_add: { HqlExprArray args; ForEachChild(i, expr) { IHqlExpression * cur = expr->queryChild(i); IHqlExpression * newCur = optimizedReplaceSelector(cur, oldDataset, newDataset); if (!newCur) return NULL; args.append(*newCur); } return expr->clone(args); } }
static void addDependent(HqlExprArray & dependents, IHqlExpression * expr) { if (dependents.find(*expr) == NotFound) dependents.append(*LINK(expr)); }