Преглед на файлове

HPCC-15767 Add syntax for volatile modifier on a function

Note, this prevents a few examples commoning up and then splitting
(a positive improvement to the generated code)

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday преди 9 години
родител
ревизия
28cb835465
променени са 5 файла, в които са добавени 98 реда и са изтрити 73 реда
  1. 3 0
      ecl/hql/hqlexpr.hpp
  2. 8 6
      ecl/hql/hqlgram.hpp
  3. 34 28
      ecl/hql/hqlgram.y
  4. 47 37
      ecl/hql/hqlgram2.cpp
  5. 6 2
      ecl/hqlcpp/hqlwcpp.cpp

+ 3 - 0
ecl/hql/hqlexpr.hpp

@@ -112,6 +112,8 @@ enum
     HEFunbound                  = 0x00000010,
     HEFinternalSelect          = 0x00000020,
     HEFcontainsDatasetAliasLocally= 0x00000040,
+
+//impure properties (see head of hqlexpr.cpp for detailed discussion)
     HEFvolatile                 = 0x00000080,           // value changes each time it is called - e.g., RANDOM()
     HEFcontextDependentException= 0x00000100,           // depends on the context, but not known how
     HEFcostly                   = 0x00000200,           // an expensive operation
@@ -1705,6 +1707,7 @@ inline bool containsCounter(IHqlExpression * expr)      { return (expr->getInfoF
 inline bool isCountProject(IHqlExpression * expr)       { return expr->hasAttribute(_countProject_Atom); }
 inline bool containsSkip(IHqlExpression * expr)         { return (expr->getInfoFlags() & (HEFcontainsSkip)) != 0; }
 inline bool containsSelf(IHqlExpression * expr)         { return (expr->getInfoFlags2() & (HEF2containsSelf)) != 0; }
+
 inline bool isContextDependentExceptGraph(IHqlExpression * expr)    
                                                         { return (expr->getInfoFlags() & (HEFcontextDependent & ~HEFgraphDependent)) != 0; }
 inline bool isGraphDependent(IHqlExpression * expr)     { return (expr->getInfoFlags() & HEFgraphDependent) != 0; }

+ 8 - 6
ecl/hql/hqlgram.hpp

@@ -642,7 +642,7 @@ public:
     void enterScope(bool allowExternal);
     void enterVirtualScope();
     void leaveScope(const attribute & errpos);
-    IHqlExpression * leaveLamdaExpression(attribute & exprattr);
+    IHqlExpression * leaveLamdaExpression(attribute * modifierattr, attribute & exprattr);
     IHqlScope * closeLeaveScope(const YYSTYPE & errpos);
     void enterPatternScope(IHqlExpression * pattern);
     void leavePatternScope(const YYSTYPE & errpos);
@@ -710,8 +710,9 @@ public:
     void addActiveParameterOwn(const attribute & errpos, IHqlExpression * expr, IHqlExpression * defaultValue);
     void gatherActiveParameters(HqlExprCopyArray & target);
 
-
-    IHqlExpression * createUniqueId();  
+    IHqlExpression * createVolatileId() { return ::createUniqueId(_volatileId_Atom); }
+    IHqlExpression * createUniqueId() { return createUniqueId(_uid_Atom); }
+    IHqlExpression * createUniqueId(IAtom * name);
 
     void onOpenBra();
     void onCloseBra();
@@ -814,12 +815,13 @@ protected:
     IHqlExpression * createRecordExcept(IHqlExpression * left, IHqlExpression * right, const attribute & errpos);
     IHqlExpression * createIndexFromRecord(IHqlExpression * record, IHqlExpression * attr, const attribute & errpos);
     IHqlExpression * createProjectRow(attribute & rowAttr, attribute & transformAttr, attribute & seqAttr);
-    void doDefineSymbol(DefineIdSt * defineid, IHqlExpression * expr, IHqlExpression * failure, const attribute & idattr, int assignPos, int semiColonPos, bool isParametered);
-    void defineSymbolInScope(IHqlScope * scope, DefineIdSt * defineid, IHqlExpression * expr, IHqlExpression * failure, const attribute & idattr, int assignPos, int semiColonPos, bool isParametered, HqlExprArray & parameters, IHqlExpression * defaults);
+    void doDefineSymbol(DefineIdSt * defineid, IHqlExpression * expr, IHqlExpression * failure, const attribute & idattr, int assignPos, int semiColonPos, bool isParametered, IHqlExpression * modifiers);
+    void defineSymbolInScope(IHqlScope * scope, DefineIdSt * defineid, IHqlExpression * expr, const attribute & idattr, int assignPos, int semiColonPos);
     void checkDerivedCompatible(IIdAtom * name, IHqlExpression * scope, IHqlExpression * expr, bool isParametered, HqlExprArray & parameters, attribute const & errpos);
     void defineSymbolProduction(attribute & nameattr, attribute & paramattr, attribute & assignattr, attribute * valueattr, attribute * failattr, attribute & semiattr);
-    void definePatternSymbolProduction(attribute & nameattr, const attribute & assignAttr, attribute & valueAttr, attribute & workflowAttr, const attribute & semiattr);
+    void definePatternSymbolProduction(attribute & nameattr, attribute & paramattr, const attribute & assignAttr, attribute & valueAttr, attribute & workflowAttr, const attribute & semiattr);
     void cloneInheritedAttributes(IHqlScope * scope, const attribute & errpos);
+    IHqlExpression * normalizeFunctionExpression(DefineIdSt * defineid, IHqlExpression * expr, IHqlExpression * failure, bool isParametered, HqlExprArray & parameters, IHqlExpression * defaults, IHqlExpression * modifiers);
 
     IHqlExpression * createEvaluateOutputModule(const attribute & errpos, IHqlExpression * scopeExpr, IHqlExpression * ifaceExpr, node_operator outputOp, IIdAtom *matchId);
     IHqlExpression * createStoredModule(const attribute & errpos, IHqlExpression * scopeExpr);

+ 34 - 28
ecl/hql/hqlgram.y

@@ -1450,7 +1450,7 @@ attributeDefinition
                         }
     | definePatternIdWithOptScope parmdef featureParameters ASSIGN pattern optfailure ';'
                         {
-                            parser->definePatternSymbolProduction($1, $4, $5, $6, $7);
+                            parser->definePatternSymbolProduction($1, $2, $4, $5, $6, $7);
                             $$.clear();
                         }
     | defineFeatureIdWithOptScope ';'
@@ -1459,7 +1459,7 @@ attributeDefinition
                             IHqlExpression *expr = createValue(no_null, makeFeatureType());
                             expr = createValue(no_pat_featuredef, expr->getType(), expr);
 
-                            parser->doDefineSymbol(defineid, expr, NULL, $1, $2.pos.position, $2.pos.position, false);
+                            parser->doDefineSymbol(defineid, expr, NULL, $1, $2.pos.position, $2.pos.position, false, NULL);
                             $$.clear();
                         }
     | defineFeatureIdWithOptScope ASSIGN featureDefine ';'
@@ -1468,7 +1468,7 @@ attributeDefinition
                             IHqlExpression *expr = $3.getExpr();
                             expr = createValue(no_pat_featuredef, expr->getType(), expr);
 
-                            parser->doDefineSymbol(defineid, expr, NULL, $1, $2.pos.position, $4.pos.position, false);
+                            parser->doDefineSymbol(defineid, expr, NULL, $1, $2.pos.position, $4.pos.position, false, NULL);
                             $$.clear();
                         }
     ;
@@ -1893,7 +1893,7 @@ transform
     | startCompoundExpression beginInlineFunctionToken optDefinitions RETURN transform ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($5), $7);
+                            $$.setExpr(parser->leaveLamdaExpression(NULL, $5), $7);
                         }
     ;
 
@@ -2816,7 +2816,7 @@ failAction
     | startCompoundExpression beginInlineFunctionToken optDefinitions RETURN action ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($5), $7);
+                            $$.setExpr(parser->leaveLamdaExpression(NULL, $5), $7);
                         }
     | WHEN '(' action ',' action sideEffectOptions ')'
                         {
@@ -3830,7 +3830,7 @@ eventObject
     | startCompoundExpression beginInlineFunctionToken optDefinitions RETURN eventObject ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($5), $7);
+                            $$.setExpr(parser->leaveLamdaExpression(NULL, $5), $7);
                         }
     ;
 
@@ -3844,17 +3844,19 @@ event
     ;
 
 parmdef
-    : realparmdef       {   parser->setParametered(true); $$.clear(); }
-    |                   {   parser->setParametered(false); $$.clear(); }
+    : realparmdef       {   parser->setParametered(true); $$.inherit($1); }
+    |                   {   parser->setParametered(false); $$.setNullExpr(); }
     ;
 
 reqparmdef
-    : realparmdef       {   parser->setParametered(true); $$.clear(); }
+    : realparmdef       {   parser->setParametered(true); $$.inherit($1); }
     ;
 
 realparmdef
-    : '(' params ')'
-    | '(' ')'
+    : '(' params ')' functionModifiers
+                        { $$.inherit($4); }
+    | '(' ')'  functionModifiers
+                        { $$.inherit($3); }
     ;
 
 params
@@ -3988,6 +3990,10 @@ defFuncValue
     | EQ anyFunction    {   $$.setExpr($2.getExpr()); }
     ;
 
+functionModifiers
+    :                   {   $$.setNullExpr(); }
+    | VOLATILE          {   $$.setExpr(createAttribute(volatileAtom), $1); }
+    ;
 service
     : startService funcDefs END
                         {
@@ -4249,7 +4255,7 @@ recordDef
     | startCompoundExpression beginInlineFunctionToken optDefinitions RETURN recordDef ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($5), $7);
+                            $$.setExpr(parser->leaveLamdaExpression(NULL, $5), $7);
                         }
     ;
 
@@ -5204,7 +5210,7 @@ expression
     | startCompoundExpression beginInlineFunctionToken optDefinitions RETURN expression ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($5), $7);
+                            $$.setExpr(parser->leaveLamdaExpression(NULL, $5), $7);
                         }
     ;
 
@@ -5948,7 +5954,7 @@ primexpr1
                         }
     | RANDOM '(' ')'
                         {
-                            $$.setExpr(createValue(no_random, LINK(parser->uint4Type), parser->createUniqueId()));
+                            $$.setExpr(createValue(no_random, LINK(parser->uint4Type), parser->createVolatileId()));
                         }
     | ROUND '(' expression ')'
                         {
@@ -7083,7 +7089,7 @@ abstractModule
     | startCompoundExpression beginInlineFunctionToken optDefinitions RETURN abstractModule ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($5), $7);
+                            $$.setExpr(parser->leaveLamdaExpression(NULL, $5), $7);
                         }
     | IF '(' booleanExpr ',' abstractModule ',' abstractModule ')'
                         {
@@ -7305,7 +7311,7 @@ dataRow
     | startCompoundExpression beginInlineFunctionToken optDefinitions RETURN dataRow ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($5), $7);
+                            $$.setExpr(parser->leaveLamdaExpression(NULL, $5), $7);
                         }
     ;
 
@@ -7807,7 +7813,7 @@ dataSet
     | startCompoundExpression beginInlineFunctionToken optDefinitions RETURN dataSet ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($5), $7);
+                            $$.setExpr(parser->leaveLamdaExpression(NULL, $5), $7);
                         }
     | startSimpleFilter conditions endSimpleFilter /* simple dataset with conditions */
                         {
@@ -11174,7 +11180,7 @@ setOfDatasets
     | startCompoundExpression beginInlineFunctionToken optDefinitions RETURN setOfDatasets ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($5), $7);
+                            $$.setExpr(parser->leaveLamdaExpression(NULL, $5), $7);
                         }
     ;
 
@@ -11340,7 +11346,7 @@ valueFunction
     | startCompoundExpression reqparmdef beginInlineFunctionToken optDefinitions RETURN expression ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($6), $8);
+                            $$.setExpr(parser->leaveLamdaExpression(&$2, $6), $8);
                         }
     ;
 
@@ -11354,7 +11360,7 @@ actionFunction
     | startCompoundExpression reqparmdef beginInlineFunctionToken optDefinitions RETURN action ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($6), $8);
+                            $$.setExpr(parser->leaveLamdaExpression(&$2, $6), $8);
                         }
     ;
 
@@ -11368,7 +11374,7 @@ datarowFunction
     | startCompoundExpression reqparmdef beginInlineFunctionToken optDefinitions RETURN dataRow ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($6), $8);
+                            $$.setExpr(parser->leaveLamdaExpression(&$2, $6), $8);
                         }
     ;
 
@@ -11382,7 +11388,7 @@ datasetFunction
     | startCompoundExpression reqparmdef beginInlineFunctionToken optDefinitions RETURN dataSet ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($6), $8);
+                            $$.setExpr(parser->leaveLamdaExpression(&$2, $6), $8);
                         }
     ;
 
@@ -11396,7 +11402,7 @@ dictionaryFunction
     | startCompoundExpression reqparmdef beginInlineFunctionToken optDefinitions RETURN dictionary ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($6), $8);
+                            $$.setExpr(parser->leaveLamdaExpression(&$2, $6), $8);
                         }
     ;
 
@@ -11410,7 +11416,7 @@ scopeFunction
     | startCompoundExpression reqparmdef beginInlineFunctionToken optDefinitions RETURN abstractModule ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($6), $8);
+                            $$.setExpr(parser->leaveLamdaExpression(&$2, $6), $8);
                         }
     ;
 
@@ -11425,7 +11431,7 @@ transformFunction
     | startCompoundExpression reqparmdef beginInlineFunctionToken optDefinitions RETURN transform ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($6), $8);
+                            $$.setExpr(parser->leaveLamdaExpression(&$2, $6), $8);
                         }
     ;
 
@@ -11440,7 +11446,7 @@ recordFunction
     | startCompoundExpression reqparmdef beginInlineFunctionToken optDefinitions RETURN recordDef ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($6), $8);
+                            $$.setExpr(parser->leaveLamdaExpression(&$2, $6), $8);
                         }
     ;
 
@@ -11454,7 +11460,7 @@ listDatasetFunction
     | startCompoundExpression reqparmdef beginInlineFunctionToken optDefinitions RETURN setOfDatasets ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($6), $8);
+                            $$.setExpr(parser->leaveLamdaExpression(&$2, $6), $8);
                         }
     ;
 
@@ -11469,7 +11475,7 @@ eventFunction
     | startCompoundExpression reqparmdef beginInlineFunctionToken optDefinitions RETURN eventObject ';' endInlineFunctionToken
                         {
                             Owned<ITypeInfo> retType = $1.getType();
-                            $$.setExpr(parser->leaveLamdaExpression($6), $8);
+                            $$.setExpr(parser->leaveLamdaExpression(&$2, $6), $8);
                         }
     ;
 

+ 47 - 37
ecl/hql/hqlgram2.cpp

@@ -680,7 +680,7 @@ IHqlExpression * HqlGram::endFunctionCall()
     return ret.getClear();
 }
 
-IHqlExpression * HqlGram::createUniqueId()
+IHqlExpression * HqlGram::createUniqueId(IAtom * name)
 {
     HqlExprArray args;
     ForEachItemIn(i, defineScopes)
@@ -692,9 +692,9 @@ IHqlExpression * HqlGram::createUniqueId()
     if (args.ordinality())
     {
         args.add(*::createUniqueId(), 0);
-        return createExprAttribute(_uid_Atom, args);
+        return createExprAttribute(name, args);
     }
-    return ::createUniqueId();
+    return ::createUniqueId(name);
 }
 
 IHqlExpression * HqlGram::createActiveSelectorSequence(IHqlExpression * left, IHqlExpression * right)
@@ -1145,7 +1145,7 @@ void HqlGram::processEnum(attribute & idAttr, IHqlExpression * value)
     DefineIdSt * id = new DefineIdSt;
     id->id = idAttr.getId();
     id->scope = EXPORT_FLAG;
-    doDefineSymbol(id, LINK(lastEnumValue), NULL, idAttr, idAttr.pos.position, idAttr.pos.position, false);
+    doDefineSymbol(id, LINK(lastEnumValue), NULL, idAttr, idAttr.pos.position, idAttr.pos.position, false, NULL);
 }
 
 bool HqlGram::extractConstantString(StringBuffer & text, attribute & attr)
@@ -2832,17 +2832,18 @@ IHqlScope * HqlGram::closeLeaveScope(const YYSTYPE & errpos)
     return closeScope(scope);
 }
 
-IHqlExpression * HqlGram::leaveLamdaExpression(attribute & exprattr)
+IHqlExpression * HqlGram::leaveLamdaExpression(attribute * paramattr, attribute & exprattr)
 {
     OwnedHqlExpr resultExpr = exprattr.getExpr();
     OwnedHqlExpr expr = associateSideEffects(resultExpr, exprattr.pos);
+    OwnedHqlExpr modifiers = paramattr ? paramattr->getExpr() : NULL;
 
     if (queryParametered())
     {
         ActiveScopeInfo & activeScope = defineScopes.tos();
         OwnedHqlExpr formals = activeScope.createFormals(false);
         OwnedHqlExpr defaults = activeScope.createDefaults();
-        expr.setown(createFunctionDefinition(atId, expr.getClear(), formals.getClear(), defaults.getClear(), NULL));
+        expr.setown(createFunctionDefinition(atId, expr.getClear(), formals.getClear(), defaults.getClear(), modifiers.getClear()));
     }
 
     leaveScope(exprattr);
@@ -3774,7 +3775,7 @@ IHqlExpression* HqlGram::checkServiceDef(IHqlScope* serviceScope,IIdAtom * name,
                 cppApi = true;
                 checkSvcAttrNoValue(attr, errpos);
             }
-            else if (name == pureAtom || name == templateAtom || name == volatileAtom || name == onceAtom || name == actionAtom || name == timeAtom)
+            else if (name == pureAtom || name == templateAtom || name == volatileAtom || name == onceAtom || name == actionAtom || name == timeAtom || name == noMoveAtom || name == failAtom)
             {
                 checkSvcAttrNoValue(attr, errpos);
             }
@@ -6225,6 +6226,8 @@ IHqlExpression *HqlGram::bindParameters(const attribute & errpos, IHqlExpression
             else
             {
                 //Binding an external, outofline or beginc++ function
+                if (isVolatileFuncdef(function))
+                    actuals.append(*createVolatileId());
                 bool expandCall = insideTemplateFunction() ? false : expandCallsWhenBound;
                 // do the actual binding
                 return createBoundFunction(this, function, actuals, lookupCtx.functionCache, expandCall);
@@ -9190,7 +9193,7 @@ IHqlExpression * HqlGram::associateSideEffects(IHqlExpression * expr, const ECLl
 }
 
 
-void HqlGram::doDefineSymbol(DefineIdSt * defineid, IHqlExpression * _expr, IHqlExpression * failure, const attribute & idattr, int assignPos, int semiColonPos, bool isParametered)
+void HqlGram::doDefineSymbol(DefineIdSt * defineid, IHqlExpression * _expr, IHqlExpression * failure, const attribute & idattr, int assignPos, int semiColonPos, bool isParametered, IHqlExpression * modifiers)
 {
     OwnedHqlExpr expr = _expr;
     // env symbol
@@ -9202,6 +9205,7 @@ void HqlGram::doDefineSymbol(DefineIdSt * defineid, IHqlExpression * _expr, IHql
     if (activeScope.templateAttrContext)
         expr.setown(createTemplateFunctionContext(expr.getClear(), closeScope(activeScope.templateAttrContext.getClear())));
 
+    IHqlScope * targetScope = NULL;
     if (!activeScope.localScope)
     {
         expr.setown(associateSideEffects(expr, idattr.pos));
@@ -9211,7 +9215,7 @@ void HqlGram::doDefineSymbol(DefineIdSt * defineid, IHqlExpression * _expr, IHql
             reportWarning(CategorySyntax, WRN_EXPORT_IGNORED, idattr.pos, "EXPORT/SHARED qualifiers are ignored in this context");
 
         defineid->scope = 0;
-        defineSymbolInScope(activeScope.privateScope, defineid, expr.getClear(), failure, idattr, assignPos, semiColonPos, isParametered, activeScope.activeParameters, activeScope.createDefaults());
+        targetScope = activeScope.privateScope;
     }
     else
     {
@@ -9261,14 +9265,16 @@ void HqlGram::doDefineSymbol(DefineIdSt * defineid, IHqlExpression * _expr, IHql
             //static int i = 0;
             //PrintLog("Kill private scope: %d at %s:%d because of %s", ++i, filename->str(), idattr.lineno, current_id->str());
             activeScope.newPrivateScope();
-            defineSymbolInScope(activeScope.localScope, defineid, expr.getClear(), failure, idattr, assignPos, semiColonPos, isParametered, activeScope.activeParameters, activeScope.createDefaults());
+            targetScope = activeScope.localScope;
             lastpos = semiColonPos+1;
         }
         else
         {
-            defineSymbolInScope(activeScope.privateScope, defineid, expr.getClear(), failure, idattr, assignPos, semiColonPos, isParametered, activeScope.activeParameters, activeScope.createDefaults());
+            targetScope = activeScope.privateScope;
         }
     }
+    OwnedHqlExpr normalized = normalizeFunctionExpression(defineid, expr, failure, isParametered, activeScope.activeParameters, activeScope.createDefaults(), modifiers);
+    defineSymbolInScope(targetScope, defineid, normalized, idattr, assignPos, semiColonPos);
 
     ::Release(failure);
     // clean up
@@ -9303,10 +9309,32 @@ IHqlExpression * HqlGram::attachMetaAttributes(IHqlExpression * ownedExpr, HqlEx
     return ownedExpr;
 }
 
-void HqlGram::defineSymbolInScope(IHqlScope * scope, DefineIdSt * defineid, IHqlExpression * expr, IHqlExpression * failure, const attribute & idattr, int assignPos, int semiColonPos, bool isParametered, HqlExprArray & parameters, IHqlExpression * defaults)
+IHqlExpression * HqlGram::normalizeFunctionExpression(DefineIdSt * defineid, IHqlExpression * expr, IHqlExpression * failure, bool isParametered, HqlExprArray & parameters, IHqlExpression * defaults, IHqlExpression * modifiers)
 {
+    HqlExprCopyArray activeParameters;
+    gatherActiveParameters(activeParameters);
+    HqlExprArray meta;
+    expr = attachWorkflowOwn(meta, LINK(expr), failure, &activeParameters);
+    if (isParametered)
+    {
+        IHqlExpression * formals = createValue(no_sortlist, makeSortListType(NULL), parameters);
+        expr = createFunctionDefinition(defineid->id, expr, formals, defaults, modifiers);
+    }
+    else
+        ::Release(modifiers);
+    expr = attachPendingWarnings(expr);
+    expr = attachMetaAttributes(expr, meta);
+    IPropertyTree * doc = defineid->queryDoc();
+    if (doc)
+        expr = createJavadocAnnotation(expr, LINK(doc));
+    return expr;
+}
+
+void HqlGram::defineSymbolInScope(IHqlScope * scope, DefineIdSt * defineid, IHqlExpression * expr, const attribute & idattr, int assignPos, int semiColonPos)
+{
+    IHqlScope * exprScope = expr->queryScope();
     IHqlExpression * scopeExpr = queryExpression(scope);
-    IIdAtom * moduleName = NULL;
+    IIdAtom * moduleName = nullptr;
     if (!inType)
         moduleName = createIdAtom(scope->queryFullName());
 
@@ -9326,25 +9354,7 @@ void HqlGram::defineSymbolInScope(IHqlScope * scope, DefineIdSt * defineid, IHql
         }
     }
 
-    HqlExprCopyArray activeParameters;
-    gatherActiveParameters(activeParameters);
-
-    HqlExprArray meta;
-    expr = attachWorkflowOwn(meta, expr, failure, &activeParameters);
-    if (isParametered)
-    {
-        IHqlExpression * formals = createValue(no_sortlist, makeSortListType(NULL), parameters);
-        expr = createFunctionDefinition(defineid->id, expr, formals, defaults, NULL);
-    }
-
-    expr = attachPendingWarnings(expr);
-    expr = attachMetaAttributes(expr, meta);
-
-    IPropertyTree * doc = defineid->queryDoc();
-    if (doc)
-        expr = createJavadocAnnotation(expr, LINK(doc));
-
-    scope->defineSymbol(defineid->id, moduleName, expr, (defineid->scope & EXPORT_FLAG) != 0, (defineid->scope & SHARED_FLAG) != 0, symbolFlags, lexObject->query_FileContents(), idattr.pos.lineno, idattr.pos.column, idattr.pos.position, assignPos+2, semiColonPos+1);
+    scope->defineSymbol(defineid->id, moduleName, LINK(expr), (defineid->scope & EXPORT_FLAG) != 0, (defineid->scope & SHARED_FLAG) != 0, symbolFlags, lexObject->query_FileContents(), idattr.pos.lineno, idattr.pos.column, idattr.pos.position, assignPos+2, semiColonPos+1);
 }
 
 
@@ -9521,7 +9531,7 @@ void HqlGram::defineSymbolProduction(attribute & nameattr, attribute & paramattr
                     {
                         if (!matchType->assignableFrom(etype))
                         {
-                            canNotAssignTypeError(type, etype, paramattr);
+                            canNotAssignTypeError(type, etype, nameattr);
                             expr.setown(createNullExpr(matchType));
                         }
                     }
@@ -9541,7 +9551,7 @@ void HqlGram::defineSymbolProduction(attribute & nameattr, attribute & paramattr
             {
                 if (queryRecord(type) != queryNullRecord())
                 {
-                    canNotAssignTypeError(type,etype,paramattr);
+                    canNotAssignTypeError(type,etype,nameattr);
                     switch (type->getTypeCode())
                     {
                     case type_record:
@@ -9573,11 +9583,11 @@ void HqlGram::defineSymbolProduction(attribute & nameattr, attribute & paramattr
     }
 
     // env symbol
-    doDefineSymbol(defineid, expr.getClear(), failure, nameattr, assignattr.pos.position, semiattr.pos.position, activeScope.isParametered);
+    doDefineSymbol(defineid, expr.getClear(), failure, nameattr, assignattr.pos.position, semiattr.pos.position, activeScope.isParametered, paramattr.getExpr());
 }
 
 
-void HqlGram::definePatternSymbolProduction(attribute & nameattr, const attribute & assignAttr, attribute & valueAttr, attribute & workflowAttr, const attribute & semiattr)
+void HqlGram::definePatternSymbolProduction(attribute & nameattr, attribute & paramattr, const attribute & assignAttr, attribute & valueAttr, attribute & workflowAttr, const attribute & semiattr)
 {
     DefineIdSt* defineid = nameattr.getDefineId();
 
@@ -9624,7 +9634,7 @@ void HqlGram::definePatternSymbolProduction(attribute & nameattr, const attribut
             args.append(*createAttribute(_function_Atom));
         expr = createValue(no_pat_instance, expr->getType(), args);
     }
-    doDefineSymbol(defineid, expr, failure, nameattr, assignAttr.pos.position, semiattr.pos.position, queryParametered());
+    doDefineSymbol(defineid, expr, failure, nameattr, assignAttr.pos.position, semiattr.pos.position, queryParametered(), paramattr.getExpr());
 }
 
 //-- SAS style conditional assignments

+ 6 - 2
ecl/hqlcpp/hqlwcpp.cpp

@@ -1205,8 +1205,12 @@ StringBuffer & HqlCppWriter::generateExprCpp(IHqlExpression * expr)
                 }
                 for (unsigned index = firstArg; index < numArgs; index++)
                 {
-                    if (index != firstArg) out.append(',');
-                    generateExprCpp(expr->queryChild(index));
+                    IHqlExpression * cur = expr->queryChild(index);
+                    if (!cur->isAttribute())
+                    {
+                        if (index != firstArg) out.append(',');
+                        generateExprCpp(cur);
+                    }
                 }
                 out.append(')');
                 break;