Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2817-BinPackingSpeedup/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/lambda.cs

Last change on this file was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 5.8 KB
Line 
1//
2// lambda.cs: support for lambda expressions
3//
4// Authors: Miguel de Icaza (miguel@gnu.org)
5//          Marek Safar (marek.safar@gmail.com)
6//
7// Dual licensed under the terms of the MIT X11 or GNU GPL
8//
9// Copyright 2007-2008 Novell, Inc
10// Copyright 2011 Xamarin Inc
11//
12
13#if STATIC
14using IKVM.Reflection.Emit;
15#else
16using System.Reflection.Emit;
17#endif
18
19namespace Mono.CSharp {
20  public class LambdaExpression : AnonymousMethodExpression
21  {
22    //
23    // The parameters can either be:
24    //    A list of Parameters (explicitly typed parameters)
25    //    An ImplicitLambdaParameter
26    //
27    public LambdaExpression (Location loc)
28      : base (loc)
29    {
30    }
31
32    protected override Expression CreateExpressionTree (ResolveContext ec, TypeSpec delegate_type)
33    {
34      if (ec.IsInProbingMode)
35        return this;
36
37      BlockContext bc = new BlockContext (ec.MemberContext, ec.ConstructorBlock, ec.BuiltinTypes.Void) {
38        CurrentAnonymousMethod = ec.CurrentAnonymousMethod
39      };
40
41      Expression args = Parameters.CreateExpressionTree (bc, loc);
42      Expression expr = Block.CreateExpressionTree (ec);
43      if (expr == null)
44        return null;
45
46      Arguments arguments = new Arguments (2);
47      arguments.Add (new Argument (expr));
48      arguments.Add (new Argument (args));
49      return CreateExpressionFactoryCall (ec, "Lambda",
50        new TypeArguments (new TypeExpression (delegate_type, loc)),
51        arguments);
52    }
53
54    public override bool HasExplicitParameters {
55      get {
56        return Parameters.Count > 0 && !(Parameters.FixedParameters [0] is ImplicitLambdaParameter);
57      }
58    }
59
60    protected override ParametersCompiled ResolveParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegateType)
61    {
62      if (!delegateType.IsDelegate)
63        return null;
64
65      AParametersCollection d_params = Delegate.GetParameters (delegateType);
66
67      if (HasExplicitParameters) {
68        if (!VerifyExplicitParameters (ec, tic, delegateType, d_params))
69          return null;
70
71        return Parameters;
72      }
73
74      //
75      // If L has an implicitly typed parameter list we make implicit parameters explicit
76      // Set each parameter of L is given the type of the corresponding parameter in D
77      //
78      if (!VerifyParameterCompatibility (ec, tic, delegateType, d_params, ec.IsInProbingMode))
79        return null;
80
81      TypeSpec [] ptypes = new TypeSpec [Parameters.Count];
82      for (int i = 0; i < d_params.Count; i++) {
83        // D has no ref or out parameters
84        if ((d_params.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != 0)
85          return null;
86
87        TypeSpec d_param = d_params.Types [i];
88
89        //
90        // When type inference context exists try to apply inferred type arguments
91        //
92        if (tic != null) {
93          d_param = tic.InflateGenericArgument (ec, d_param);
94        }
95
96        ptypes [i] = d_param;
97        ImplicitLambdaParameter ilp = (ImplicitLambdaParameter) Parameters.FixedParameters [i];
98        ilp.SetParameterType (d_param);
99        ilp.Resolve (null, i);
100      }
101
102      Parameters.Types = ptypes;
103      return Parameters;
104    }
105
106    protected override AnonymousMethodBody CompatibleMethodFactory (TypeSpec returnType, TypeSpec delegateType, ParametersCompiled p, ParametersBlock b)
107    {
108      return new LambdaMethod (p, b, returnType, delegateType, loc);
109    }
110
111    protected override bool DoResolveParameters (ResolveContext rc)
112    {
113      //
114      // Only explicit parameters can be resolved at this point
115      //
116      if (HasExplicitParameters) {
117        return Parameters.Resolve (rc);
118      }
119
120      return true;
121    }
122
123    public override string GetSignatureForError ()
124    {
125      return "lambda expression";
126    }
127   
128    public override object Accept (StructuralVisitor visitor)
129    {
130      return visitor.Visit (this);
131    }
132  }
133
134  class LambdaMethod : AnonymousMethodBody
135  {
136    public LambdaMethod (ParametersCompiled parameters,
137          ParametersBlock block, TypeSpec return_type, TypeSpec delegate_type,
138          Location loc)
139      : base (parameters, block, return_type, delegate_type, loc)
140    {
141    }
142
143    #region Properties
144
145    public override string ContainerType {
146      get {
147        return "lambda expression";
148      }
149    }
150
151    #endregion
152
153    protected override void CloneTo (CloneContext clonectx, Expression target)
154    {
155      // TODO: nothing ??
156    }
157
158    public override Expression CreateExpressionTree (ResolveContext ec)
159    {
160      BlockContext bc = new BlockContext (ec.MemberContext, Block, ReturnType);
161      Expression args = parameters.CreateExpressionTree (bc, loc);
162      Expression expr = Block.CreateExpressionTree (ec);
163      if (expr == null)
164        return null;
165
166      Arguments arguments = new Arguments (2);
167      arguments.Add (new Argument (expr));
168      arguments.Add (new Argument (args));
169      return CreateExpressionFactoryCall (ec, "Lambda",
170        new TypeArguments (new TypeExpression (type, loc)),
171        arguments);
172    }
173  }
174
175  //
176  // This is a return statement that is prepended lambda expression bodies that happen
177  // to be expressions.  Depending on the return type of the delegate this will behave
178  // as either { expr (); return (); } or { return expr (); }
179  //
180  public class ContextualReturn : Return
181  {
182    ExpressionStatement statement;
183
184    public ContextualReturn (Expression expr)
185      : base (expr, expr.StartLocation)
186    {
187    }
188
189    public override Expression CreateExpressionTree (ResolveContext ec)
190    {
191      return Expr.CreateExpressionTree (ec);
192    }
193
194    protected override void DoEmit (EmitContext ec)
195    {
196      if (statement != null) {
197        statement.EmitStatement (ec);
198        if (unwind_protect)
199          ec.Emit (OpCodes.Leave, ec.CreateReturnLabel ());
200        else {
201          ec.Emit (OpCodes.Ret);
202        }
203        return;
204      }
205
206      base.DoEmit (ec);
207    }
208
209    protected override bool DoResolve (BlockContext ec)
210    {
211      //
212      // When delegate returns void, only expression statements can be used
213      //
214      if (ec.ReturnType.Kind == MemberKind.Void) {
215        Expr = Expr.Resolve (ec);
216        if (Expr == null)
217          return false;
218
219        statement = Expr as ExpressionStatement;
220        if (statement == null)
221          Expr.Error_InvalidExpressionStatement (ec);
222
223        return true;
224      }
225
226      return base.DoResolve (ec);
227    }
228  }
229}
Note: See TracBrowser for help on using the repository browser.