@@ -53,7 +53,7 @@ public partial class ExpressionEvaluator
5353 protected static readonly Regex lambdaExpressionRegex = new Regex ( @"^(?>\s*)(?<args>((?>\s*)[(](?>\s*)([\p{L}_](?>[\p{L}_0-9]*)(?>\s*)([,](?>\s*)[\p{L}_][\p{L}_0-9]*(?>\s*))*)?[)])|[\p{L}_](?>[\p{L}_0-9]*))(?>\s*)=>(?<expression>.*)$" , RegexOptions . Singleline | RegexOptions . Compiled ) ;
5454 protected static readonly Regex lambdaArgRegex = new Regex ( @"[\p{L}_](?>[\p{L}_0-9]*)" , RegexOptions . Compiled ) ;
5555 protected static readonly Regex initInNewBeginningRegex = new Regex ( @"^(?>\s*){" , RegexOptions . Compiled ) ;
56- protected static readonly Regex functionArgKeywordsRegex = new Regex ( @"^\s*(?<keyword>out|ref)\s* (?<varName>[\p{L}_](?>[\p{L}_0-9]*))" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
56+ protected static readonly Regex functionArgKeywordsRegex = new Regex ( @"^\s*(?<keyword>out|ref)\s+((?<typeName>[\p{L}_][\p{L}_0-9\.\[\]<>]*[?]?)\s+(?=[\p{L}_]))? (?<varName>[\p{L}_](?>[\p{L}_0-9]*))" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
5757
5858 // Depending on OptionInlineNamespacesEvaluationActive. Initialized in constructor
5959 protected string InstanceCreationWithNewKeywordRegexPattern { get { return @"^new(?>\s*)((?<isAnonymous>[{{])|((?<name>[\p{L}_][\p{L}_0-9" + ( OptionInlineNamespacesEvaluationActive ? @"\." : string . Empty ) + @"]*)(?>\s*)(?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?>\s*)((?<isfunction>[(])|(?<isArray>\[)|(?<isInit>[{{]))?))" ; } }
@@ -1907,6 +1907,18 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
19071907 {
19081908 OutOrRefArg outOrRefArg = new OutOrRefArg ( ) { Index = argIndex , VariableName = functionArgKeywordsMatch . Groups [ "varName" ] . Value } ;
19091909 outOrRefArgs . Add ( outOrRefArg ) ;
1910+
1911+ if ( functionArgKeywordsMatch . Groups [ "typeName" ] . Success )
1912+ {
1913+ Type fixedType = ( ( ClassOrEnumType ) Evaluate ( functionArgKeywordsMatch . Groups [ "typeName" ] . Value ) ) . Type ;
1914+
1915+ variables [ outOrRefArg . VariableName ] = new StronglyTypedVariable ( ) { Type = fixedType , Value = GetDefaultValueOfType ( fixedType ) } ;
1916+ }
1917+ else if ( ! variables . ContainsKey ( outOrRefArg . VariableName ) )
1918+ {
1919+ variables [ outOrRefArg . VariableName ] = null ;
1920+ }
1921+
19101922 argValue = Evaluate ( outOrRefArg . VariableName ) ;
19111923 }
19121924 else
@@ -1917,6 +1929,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
19171929 argIndex ++ ;
19181930 return argValue ;
19191931 } ) ;
1932+
19201933 BindingFlags flag = DetermineInstanceOrStatic ( ref objType , ref obj , ref valueTypeNestingTrace ) ;
19211934
19221935 if ( ! OptionStaticMethodsCallActive && ( flag & BindingFlags . Static ) != 0 )
@@ -1952,7 +1965,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
19521965 {
19531966 oArgs . Insert ( 0 , obj ) ;
19541967 objType = obj . GetType ( ) ;
1955- //obj = null;
1968+
19561969 object extentionObj = null ;
19571970 for ( int e = 0 ; e < StaticTypesForExtensionsMethods . Count && methodInfo == null ; e ++ )
19581971 {
@@ -1966,7 +1979,7 @@ protected virtual bool EvaluateVarOrFunc(string expression, Stack<object> stack,
19661979 {
19671980 object [ ] argsArray = oArgs . ToArray ( ) ;
19681981 stack . Push ( methodInfo . Invoke ( isExtention ? null : obj , argsArray ) ) ;
1969- outOrRefArgs . ForEach ( outOrRefArg => variables [ outOrRefArg . VariableName ] = argsArray [ outOrRefArg . Index ] ) ;
1982+ outOrRefArgs . ForEach ( outOrRefArg => AssignVariable ( outOrRefArg . VariableName , argsArray [ outOrRefArg . Index ] ) ) ;
19701983 }
19711984 else if ( objType . GetProperty ( varFuncName , StaticBindingFlag ) is PropertyInfo staticPropertyInfo
19721985 && ( staticPropertyInfo . PropertyType . IsSubclassOf ( typeof ( Delegate ) ) || staticPropertyInfo . PropertyType == typeof ( Delegate ) )
@@ -2297,7 +2310,7 @@ where method.GetParameters()[0].ParameterType == objType // static extMethod(thi
22972310 Variables [ varFuncName ] = new StronglyTypedVariable
22982311 {
22992312 Type = classOrEnum . Type ,
2300- Value = ! varFuncMatch . Groups [ "assignationOperator" ] . Success && classOrEnum . Type . IsValueType ? Activator . CreateInstance ( classOrEnum . Type ) : null ,
2313+ Value = GetDefaultValueOfType ( classOrEnum . Type ) ,
23012314 } ;
23022315 }
23032316
@@ -2331,27 +2344,7 @@ where method.GetParameters()[0].ParameterType == objType // static extMethod(thi
23312344
23322345 if ( assign )
23332346 {
2334- if ( Variables . ContainsKey ( varFuncName ) && Variables [ varFuncName ] is StronglyTypedVariable stronglyTypedVariable )
2335- {
2336- if ( cusVarValueToPush == null && stronglyTypedVariable . Type . IsValueType && Nullable . GetUnderlyingType ( stronglyTypedVariable . Type ) == null )
2337- {
2338- throw new ExpressionEvaluatorSyntaxErrorException ( $ "Can not cast null to { stronglyTypedVariable . Type } because it's not a nullable valueType") ;
2339- }
2340-
2341- Type typeToAssign = cusVarValueToPush ? . GetType ( ) ;
2342- if ( typeToAssign == null || stronglyTypedVariable . Type . IsAssignableFrom ( typeToAssign ) )
2343- {
2344- stronglyTypedVariable . Value = cusVarValueToPush ;
2345- }
2346- else
2347- {
2348- throw new InvalidCastException ( $ "A object of type { typeToAssign } can not be cast implicitely in { stronglyTypedVariable . Type } ") ;
2349- }
2350- }
2351- else
2352- {
2353- Variables [ varFuncName ] = cusVarValueToPush ;
2354- }
2347+ AssignVariable ( varFuncName , cusVarValueToPush ) ;
23552348 }
23562349 }
23572350 else if ( varFuncMatch . Groups [ "assignationOperator" ] . Success )
@@ -3042,6 +3035,33 @@ protected virtual object ManageKindOfAssignation(string expression, ref int inde
30423035 return result ;
30433036 }
30443037
3038+ protected virtual void AssignVariable ( string varName , object value )
3039+ {
3040+ if ( Variables . ContainsKey ( varName ) && Variables [ varName ] is StronglyTypedVariable stronglyTypedVariable )
3041+ {
3042+ if ( value == null && stronglyTypedVariable . Type . IsValueType && Nullable . GetUnderlyingType ( stronglyTypedVariable . Type ) == null )
3043+ {
3044+ throw new ExpressionEvaluatorSyntaxErrorException ( $ "Can not cast null to { stronglyTypedVariable . Type } because it's not a nullable valueType") ;
3045+ }
3046+
3047+ Type typeToAssign = value ? . GetType ( ) ;
3048+ if ( typeToAssign == null || stronglyTypedVariable . Type . IsAssignableFrom ( typeToAssign ) )
3049+ {
3050+ stronglyTypedVariable . Value = value ;
3051+ }
3052+ else
3053+ {
3054+ throw new InvalidCastException ( $ "A object of type { typeToAssign } can not be cast implicitely in { stronglyTypedVariable . Type } ") ;
3055+ }
3056+ }
3057+ else
3058+ {
3059+ Variables [ varName ] = value ;
3060+ }
3061+ }
3062+
3063+ protected virtual object GetDefaultValueOfType ( Type type ) => type . IsValueType ? Activator . CreateInstance ( type ) : null ;
3064+
30453065 protected virtual bool GetLambdaExpression ( string expression , Stack < object > stack )
30463066 {
30473067 Match lambdaExpressionMatch = lambdaExpressionRegex . Match ( expression ) ;
@@ -3238,7 +3258,15 @@ protected virtual MethodInfo TryToCastMethodParametersToMakeItCallable(MethodInf
32383258 {
32393259 if ( ! methodInfoToCast . GetParameters ( ) [ a ] . ParameterType . IsAssignableFrom ( modifiedArgs [ a ] . GetType ( ) ) )
32403260 {
3241- modifiedArgs [ a ] = Convert . ChangeType ( modifiedArgs [ a ] , methodInfoToCast . GetParameters ( ) [ a ] . ParameterType ) ;
3261+ if ( methodInfoToCast . GetParameters ( ) [ a ] . ParameterType . IsByRef )
3262+ {
3263+ if ( ! methodInfoToCast . GetParameters ( ) [ a ] . ParameterType . GetElementType ( ) . IsAssignableFrom ( modifiedArgs [ a ] . GetType ( ) ) )
3264+ modifiedArgs [ a ] = Convert . ChangeType ( modifiedArgs [ a ] , methodInfoToCast . GetParameters ( ) [ a ] . ParameterType . GetElementType ( ) ) ;
3265+ }
3266+ else
3267+ {
3268+ modifiedArgs [ a ] = Convert . ChangeType ( modifiedArgs [ a ] , methodInfoToCast . GetParameters ( ) [ a ] . ParameterType ) ;
3269+ }
32423270 }
32433271 }
32443272 catch
0 commit comments