~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/mcs/lambda.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

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