2008-06-11 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / mcs / lambda.cs
index 9a30fddcb846336b299fbe7f2f2ffddb2afe8790..b561487a33783739f9d9e3814bbaa76bfcb208a0 100644 (file)
@@ -4,9 +4,9 @@
 // Authors: Miguel de Icaza (miguel@gnu.org)
 //          Marek Safar (marek.safar@gmail.com)
 //
-// Licensed under the terms of the GNU GPL
+// Dual licensed under the terms of the MIT X11 or GNU GPL
 //
-// (C) 2007 Novell, Inc
+// Copyright 2007-2008 Novell, Inc
 //
 
 using System;
@@ -34,6 +34,24 @@ namespace Mono.CSharp {
                                explicit_parameters = !(parameters.FixedParameters [0] is ImplicitLambdaParameter);
                }
 
+               protected override Expression CreateExpressionTree (EmitContext ec, Type delegate_type)
+               {
+                       if (ec.IsInProbingMode)
+                               return this;
+                       
+                       Expression args = Parameters.CreateExpressionTree (ec, loc);
+                       Expression expr = Block.CreateExpressionTree (ec);
+                       if (expr == null)
+                               return null;
+
+                       ArrayList arguments = new ArrayList (2);
+                       arguments.Add (new Argument (expr));
+                       arguments.Add (new Argument (args));
+                       return CreateExpressionFactoryCall ("Lambda",
+                               new TypeArguments (loc, new TypeExpression (delegate_type, loc)),
+                               arguments);
+               }
+
                public override bool HasExplicitParameters {
                        get {
                                return explicit_parameters;
@@ -131,18 +149,59 @@ namespace Mono.CSharp {
                                return "lambda expression";
                        }
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return Block.CreateExpressionTree (ec);
+               }
        }
 
        //
        // This is a return statement that is prepended lambda expression bodies that happen
        // to be expressions.  Depending on the return type of the delegate this will behave
        // as either { expr (); return (); } or { return expr (); }
-
+       //
        public class ContextualReturn : Return
        {
                public ContextualReturn (Expression expr)
                        : base (expr, expr.Location)
                {
                }
+
+               public override Expression CreateExpressionTree (EmitContext ec)
+               {
+                       return Expr.CreateExpressionTree (ec);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       if (ec.ReturnType == TypeManager.void_type)
+                               ((ExpressionStatement) Expr).EmitStatement (ec);
+                       else
+                               base.Emit (ec);
+               }
+
+               protected override bool DoResolve (EmitContext ec)
+               {       
+                       //
+                       // When delegate returns void, only expression statements can be used
+                       //
+                       if (ec.ReturnType == TypeManager.void_type) {
+                               Expr = Expr.Resolve (ec);
+                               if (Expr == null)
+                                       return false;
+                               
+                               if (Expr is ExpressionStatement) {
+                                       if (Expr is Invocation)
+                                               return TypeManager.IsEqual (Expr.Type, TypeManager.void_type);
+                                       return true;
+                               }
+                               
+                               Expr.Error_InvalidExpressionStatement ();
+                               return false;
+                       }
+
+                       return base.DoResolve (ec);
+               }
        }
 }