public override Expression asCLRSetValueExpression(Expression newValue) { return(Expression.Condition( isMutable, Expression.Assign(Expression.ArrayAccess(namedSlots, slotIndex), newValue), Expression.Block( TypeGuru.objectType, Expression.Throw(Expression.Constant(new ImmutableObjectException())), newValue))); }
/// <summary> /// Fixes up lambda body and parameters to match the signature of the given delegate if needed. /// </summary> /// <param name="delegateType"></param> private void EnsureSignature(Type delegateType) { System.Diagnostics.Debug.Assert(_params != null, "must have parameter list here"); //paramMapping is the dictionary where we record how we want to map parameters //the key is the parameter, the value is the expression it should be redirected to //so far the parameter can only be redirected to itself (means no change needed) or to //a synthetic variable that is added to the lambda when the original parameter has no direct //parameter backing in the delegate signature // Example: // delegate siganture del(x, params y[]) // lambda signature lambda(a, b, param n[]) // // for the situation above the mapping will be <a, x>, <b, V1>, <n, V2> // where V1 and V2 are synthetic variables and initialized as follows - V1 = y[0] , V2 = {y[1], y[2],... y[n]} ParameterInfo[] delegateParams = delegateType.GetMethod("Invoke").GetParameters(); bool delegateHasParamarray = delegateParams.Length > 0 && delegateParams[delegateParams.Length - 1].IsDefined(typeof(ParamArrayAttribute), false); bool lambdaHasParamarray = ParamsArray != null; if (lambdaHasParamarray && !delegateHasParamarray) { throw new ArgumentException("paramarray lambdas must have paramarray delegate type"); } int copy = delegateHasParamarray ? delegateParams.Length - 1 : delegateParams.Length; int unwrap = _params.Count - copy; if (lambdaHasParamarray) { unwrap--; } // Lambda must have at least as many parameters as the delegate, not counting the paramarray if (unwrap < 0) { throw new ArgumentException("lambda does not have enough parameters"); } // shortcircuit if no rewrite is needed. if (!delegateHasParamarray) { bool needRewrite = false; for (int i = 0; i < copy; i++) { if (_params[i].Type != delegateParams[i].ParameterType) { needRewrite = true; } } if (!needRewrite) { return; } } List <ParameterExpression> newParams = new List <ParameterExpression>(delegateParams.Length); List <ParameterExpression> backingVars = new List <ParameterExpression>(); List <Expression> preambuleExpressions = new List <Expression>(); Dictionary <ParameterExpression, ParameterExpression> paramMapping = new Dictionary <ParameterExpression, ParameterExpression>(); for (int i = 0; i < copy; i++) { // map to a converted variable if (_params[i].Type != delegateParams[i].ParameterType) { ParameterExpression newParameter = Expression.Parameter(delegateParams[i].ParameterType, delegateParams[i].Name); ParameterExpression mappedParameter = _params[i]; ParameterExpression backingVariable = Expression.Variable(mappedParameter.Type, mappedParameter.Name); newParams.Add(newParameter); backingVars.Add(backingVariable); paramMapping.Add(mappedParameter, backingVariable); preambuleExpressions.Add( Expression.Assign( backingVariable, Expression.Convert( newParameter, mappedParameter.Type ) ) ); } else { //use the same parameter expression newParams.Add(_params[i]); paramMapping.Add(_params[i], _params[i]); } } if (delegateHasParamarray) { ParameterInfo delegateParamarrayPi = delegateParams[delegateParams.Length - 1]; ParameterExpression delegateParamarray = Expression.Parameter(delegateParamarrayPi.ParameterType, delegateParamarrayPi.Name); newParams.Add(delegateParamarray); //unwarap delegate paramarray into variables and map parameters to the variables for (int i = 0; i < unwrap; i++) { ParameterExpression mappedParameter = _params[copy + i]; ParameterExpression backingVariable = Expression.Variable(mappedParameter.Type, mappedParameter.Name); backingVars.Add(backingVariable); paramMapping.Add(mappedParameter, backingVariable); preambuleExpressions.Add( Expression.Assign( backingVariable, AstUtils.Convert( Expression.ArrayAccess( delegateParamarray, AstUtils.Constant(i) ), mappedParameter.Type ) ) ); } //lambda's paramarray should get elements from the delegate paramarray after skipping those that we unwrapped. if (lambdaHasParamarray) { ParameterExpression mappedParameter = _paramsArray; ParameterExpression backingVariable = Expression.Variable(mappedParameter.Type, mappedParameter.Name); backingVars.Add(backingVariable); paramMapping.Add(mappedParameter, backingVariable); // Call the helper MethodInfo shifter = typeof(RuntimeHelpers).GetMethod("ShiftParamsArray"); shifter = shifter.MakeGenericMethod(delegateParamarrayPi.ParameterType.GetElementType()); preambuleExpressions.Add( Expression.Assign( backingVariable, AstUtils.Convert( Expression.Call( shifter, delegateParamarray, AstUtils.Constant(unwrap) ), mappedParameter.Type ) ) ); } } Expression newBody = new LambdaParameterRewriter(paramMapping).Visit(_body); preambuleExpressions.Add(newBody); _body = Expression.Block(preambuleExpressions); _paramsArray = null; _locals.AddRange(backingVars); _params = newParams; for (int i = 0; i < _visibleVars.Count; i++) { ParameterExpression p = _visibleVars[i].Key as ParameterExpression; ParameterExpression v; if (p != null && paramMapping.TryGetValue(p, out v)) { _visibleVars[i] = new KeyValuePair <ParameterExpression, bool>(v, _visibleVars[i].Value); } } }
public override Expression asCLRGetValueExpression() { return(Expression.ArrayAccess(namedSlots, slotIndex)); }