? .expression.cs.swo
? .expression.cs.swp
? .x.swp
? 1.cs
? 1.objtmp
? 2.cs
? 3.cs
? PLAN
? PROFILE
? a.cs
? a.objtmp
? a1.cs
? a2.cs
? a3.cs
? a4.cs
? aa.cs
? aaa.cs
? anonymous-2.patch
? anonymous.patch
? at.cs
? b.cs
? bb.cs
? bug.cs
? c.cs
? ch.cs
? co.cs
? cs.cs
? d.cs
? de.cs
? de2.cs
? delegate.cs-orig
? delegate.cs.new
? e.cs
? e1.cs
? e2.cs
? e3.cs
? e4.cs
? e5.cs
? e6.cs
? emcs.cs
? en.cs
? f.cs
? fo.cs
? fu.cs
? g.cs
? h.cs
? i.cs
? ic.cs
? ii.cs
? j.cs
? jj.cs
? l-2
? l.cs
? log
? log2
? m.cs
? mcs-parser-bash-more-qi.patch
? old-statement.cs
? p
? patch-declspace-double-hash.diff
? r.cs
? res
? revert
? sa.cs
? split-lookup.patch
? ss.cs
? sss.cs
? t.cs
? te.cs
? tt.cs
? tu.cs
? u.cs
? w.cs
? x-decl.cs
? x.cs
? xx
? xx.cs
? xx.dll
? xy.cs
? y.cs
? z.cs
Index: ChangeLog
===================================================================
RCS file: /cvs/public/mcs/mcs/ChangeLog,v
retrieving revision 1.1363
diff -u -u -r1.1363 ChangeLog
--- ChangeLog	5 Mar 2004 20:37:57 -0000	1.1363
+++ ChangeLog	10 Mar 2004 02:53:43 -0000
@@ -1,3 +1,43 @@
+<<<<<<< ChangeLog
+2004-02-23  Miguel de Icaza  <miguel@ximian.com>
+
+	* codegen.cs (EmitContext.EmitTopBlock): If we have an EmitContext
+	container, use the container capture_info, so we can propagate the
+	information about variables captured (otherwise they were only
+	being flagged as "captured" on the inner anonymous method block,
+	not the parent).
+	
+	(EmitContext.CaptureField, EmitContext.CaptureVariable): hook up
+	the parent capture_info if we have to initialize it.
+
+2004-02-15  Miguel de Icaza  <miguel@ximian.com>
+
+	* statement.cs (Switch): Do not allocate labels during the resolve
+	phase, as "ig" might be null (reverted temporarily, due to the
+	crash). 
+	
+	* assign.cs (LocalTemporary): Allocate the LocalBuilder during the
+	Emit phase, not the resolve phase.
+
+	* statement.cs (ResolveMeta): Do not generate a local_map for the
+	parent if we are a toplevel block.
+
+	* cs-parser.jay: In anonymous methods, we link the `Parent' of a
+	Toplevel for the anonymous block to its container, so we can
+	resolve local variable references to the container.
+
+	* anonymous.cs (CaptureInfo, BlockCaptureInfo): New classes that
+	encapsulate the captured variables and emit the helper classes
+	that track the captured/lifted values.
+
+	* statement.cs (TopLevel), codegen.cs (EmitContext): Moved the
+	code to capture variables from TopLevel to the EmitContext which
+	proxies to a CaptureInfo class most of the requests.
+
+	* codegen.cs: New API entry points for capturing locals and fields
+	and querying their state. 
+	
+=======
 2004-03-05  Martin Baulig  <martin@ximian.com>
 
 	* location.cs (SourceFile.HasLineDirective): New public field;
@@ -74,6 +114,7 @@
 	* interface.cs (FindMembers): The operation is performed on all base
 	interfaces and not only on the first. It is required for future CLS Compliance patch.
 
+>>>>>>> 1.1363
 2004-02-12 Ben Maurer  <bmaurer@users.sourceforge.net>
 
 	* statement.cs, codegen.cs:
@@ -114,6 +155,40 @@
         
 2004-02-11  Miguel de Icaza  <miguel@ximian.com>
 
+	* expression.cs (LocalVariableReference): drop `is_readonly' use
+	the ReadOnly property from the LocalInfo instead.
+
+	* codegen.cs: Split EmitTopBlock into ResolveTopBlock who only
+	does resolution and EmitResolvedTopBlock that does the emission in
+	preparation for having an extra pass that resolves block 
+
+2004-02-08  Miguel de Icaza  <miguel@ximian.com>
+
+	* codegen.cs: remove RemapLocalLValue, now the caller code calls
+	the proper DoResolve/DoResolveLValue on the return.
+
+	* expression.cs (LocalVariableReference.DoResolveLValue): Perform
+	is_readonly check before the rest, I noticed that we might not do
+	this test for iterators/anonymous methods otherwise.
+	
+	If we are in an anonymous method, return a captured variable.
+
+	Resolve.
+
+	(DoResolve): If we are in an anonymous method, return the captured
+	variable. 
+
+2004-01-24  Miguel de Icaza  <miguel@ximian.com>
+
+	* convert.cs (Error_CannotChangeAccessModifiers): Improve error
+	reporting when we have anonymous methods.
+
+	* codegen.cs (EmitContext.EmitTopBlock): Now we require a
+	ToplevelBlock as an argument, the split 
+	
+
+2004-02-11  Miguel de Icaza  <miguel@ximian.com>
+
 	* cs-parser.jay: Fix small regression: we were not testing V2
 	compiler features correctly.
 
@@ -201,6 +276,7 @@
 
 	* cs-tokenizer.cs: yield is no longer a keyword.
 
+>>>>>>> 1.1345
 2004-01-23  Marek Safar  <marek.safar@seznam.cz>
 
 	* cs-parser.jay, class.cs (DefineDefaultConstructor): Fixed ModFlags
Index: TODO
===================================================================
RCS file: /cvs/public/mcs/mcs/TODO,v
retrieving revision 1.126
diff -u -u -r1.126 TODO
--- TODO	12 Feb 2004 00:08:15 -0000	1.126
+++ TODO	10 Mar 2004 02:53:43 -0000
@@ -1,3 +1,27 @@
+Anonymous methods
+-----------------
+
+	We are flagging 428 when doing anonymous method conversions from
+	a:
+
+		object o = delegate {}
+
+	Check if this is the error code (currently we know that 428 is ok
+	for object var = method_group_assignment case).
+
+	In anonymous.cs, when we create the EmitContext, investigate
+	the implications and the interactions of iterator methods with
+	anonymous method blocks and set the flag accordingly. 
+
+Review:
+	Every use of ToplevelBlock linkage to its parent (due to anon
+	methods).
+
+Clean Up
+--------
+
+	Move MapVariable from CodeGen into Block?
+
 Error Reporting:
 ----------------
 
@@ -5,9 +29,6 @@
 
 Iterators
 ---------
-	* `yield' is no longer a keyword, it only has special
-	  meaning before a return or break keywords.
-
 	* Study side effects with assign
 	* Study TemporaryStorage/LocalStorage -> Merge/rename
 
Index: anonymous.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/anonymous.cs,v
retrieving revision 1.1
diff -u -u -r1.1 anonymous.cs
--- anonymous.cs	28 May 2003 05:00:13 -0000	1.1
+++ anonymous.cs	10 Mar 2004 02:53:43 -0000
@@ -4,7 +4,7 @@
 // Author:
 //   Miguel de Icaza (miguel@ximain.com)
 //
-// (C) 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, Inc.
 //
 
 using System;
@@ -17,13 +17,23 @@
 	public class AnonymousMethod : Expression {
 		// An array list of AnonymousMethodParameter or null
 		Parameters parameters;
-		Block block;
+		public ToplevelBlock Block;
+		static int anonymous_method_count;
+		Method method;
+		MethodInfo invoke_mb;
 		
-		public AnonymousMethod (Parameters parameters, Block block, Location l)
+		// The emit context for the anonymous method
+		public EmitContext aec;
+		bool unreachable;
+		
+		public AnonymousMethod (Parameters parameters, ToplevelBlock container, ToplevelBlock block, Location l)
 		{
+			anonymous_method_count++;
 			this.parameters = parameters;
-			this.block = block;
+			Block = block;
 			loc = l;
+
+			container.RegisterAnonymousMethod (this);
 		}
 
 		public override Expression DoResolve (EmitContext ec)
@@ -39,13 +49,499 @@
 			// anywhere', we depend on special conversion
 			// rules.
 			// 
-			type = typeof (AnonymousMethod);
+			type = TypeManager.anonymous_method_type;
 			return this;
 		}
 
 		public override void Emit (EmitContext ec)
 		{
 			// nothing, as we only exist to not do anything.
+		}
+
+		//
+		// Creates the host for the anonymous method
+		//
+		bool CreateMethodHost (EmitContext ec, Type return_type)
+		{
+			int modifiers = Modifiers.PRIVATE;
+
+			//
+			// Crude hack follows: we replace the TypeBuilder during the
+			// definition to get the method hosted in the right class
+			//
+			
+			TypeBuilder current_type = ec.TypeContainer.TypeBuilder;
+			if (current_type == ec.GetAnonymousMethodHost ()){
+				if (ec.IsStatic)
+					modifiers |= Modifiers.STATIC;
+				current_type = null;
+			} 
+				
+			method = new Method (ec.DeclSpace, new TypeExpression (return_type, loc),
+					     modifiers, "__AnonymousMethod$" + anonymous_method_count,
+					     parameters, null, loc);
+			method.Block = Block;
+
+			if (current_type != null)
+				ec.TypeContainer.TypeBuilder = ec.GetAnonymousMethodHost ();
+			bool res = method.Define ((TypeContainer) ec.TypeContainer);
+			if (current_type != null)
+				ec.TypeContainer.TypeBuilder = current_type;
+			return res;
+		}
+		
+		void Error_ParameterMismatch (Type t)
+		{
+			Report.Error (1661, loc, String.Format ("Anonymous method could not be converted to delegate `" +
+								"{0}' since there is a parameter mismatch", t));
+		}
+		
+		//
+		// Returns true if this anonymous method can be implicitly
+		// converted to the delegate type `delegate_type'
+		//
+		public Expression Compatible (EmitContext ec, Type delegate_type)
+		{
+			invoke_mb = (MethodInfo) Delegate.GetInvokeMethod (ec, delegate_type, loc);
+
+			//
+			// At this point its the first time we know the return type that is 
+			// needed for the anonymous method.  We create the method here.
+			//
+
+			//
+			// We do this to do the proper checking later
+			//
+			Parameters declared_parameters = parameters;
+			if (parameters == null)
+				parameters = Parameters.EmptyReadOnlyParameters;
+
+			ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);
+
+			//
+			// First, parameter types of `delegate_type' must be compatible
+			// with the anonymous method.
+			//
+			InternalParameters amp;
+			amp = new InternalParameters (ec.DeclSpace, parameters);
+			
+			if (declared_parameters == null){
+				//
+				// If A does not contain an anonymous-method-signature, just check that
+				// the delegate does not have any `out' parameters
+				//
+				for (int i = invoke_pd.Count; i > 0;){
+					i--;
+
+					if ((invoke_pd.ParameterModifier (i) & Parameter.Modifier.OUT) != 0){
+						Report.Error (1676, loc, String.Format (
+							"Parameter {0} must include the `out' modifier ", i+1));
+						Error_ParameterMismatch (delegate_type);
+						return null;
+					}
+				}
+			} else {
+				// If we have a signature
+				
+				if (amp.Count != invoke_pd.Count){
+					Report.Error (1593, loc, String.Format (
+				        	"Anonymous method has {0} parameters, while delegate requires {1}",
+						amp.Count, invoke_pd.Count));
+					Error_ParameterMismatch (delegate_type);
+					return null;
+				}
+
+				for (int i = 0; i < amp.Count; i++){
+					Parameter.Modifier amp_mod = amp.ParameterModifier (i);
+					if (amp_mod != invoke_pd.ParameterModifier (i)){
+						Report.Error (1676, loc, String.Format (
+						      "Signature mismatch in parameter modifier for parameter #{0}", i + 1));
+						Error_ParameterMismatch (delegate_type);
+						return null;
+					}
+
+					if (amp.ParameterType (i) != invoke_pd.ParameterType (i)){
+						Report.Error (1678, loc, String.Format (
+						      "Signature mismatch in parameter {0}: need `{1}' got `{2}'", i + 1,
+						      TypeManager.CSharpName (invoke_pd.ParameterType (i)),
+						      TypeManager.CSharpName (amp.ParameterType (i))));
+						Error_ParameterMismatch (delegate_type);
+						return null;
+					}
+				}
+			}
+
+			//
+			// Second: the return type of the delegate must be compatible with 
+			// the anonymous type.   Instead of doing a pass to examine the block
+			// we satisfy the rule by setting the return type on the EmitContext
+			// to be the delegate type return type.
+			//
+
+			//MethodBuilder builder = method_data.MethodBuilder;
+			//ILGenerator ig = builder.GetILGenerator ();
+			
+			aec = new EmitContext (
+				ec.TypeContainer, ec.DeclSpace, ec.loc, null,
+				invoke_mb.ReturnType,
+				(ec.IsStatic ? Modifiers.STATIC : 0) |
+				/* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
+				(ec.InUnsafe ? Modifiers.UNSAFE : 0),
+				/* No constructor */ false);
+
+			aec.InAnonymousMethod = true;
+			aec.EmitContainer = ec;
+			bool res = aec.ResolveTopBlock (Block, amp, loc, out unreachable);
+			
+			if (res){
+				aec.EmitMeta (Block, amp);
+				return new AnonymousDelegate (this, delegate_type, loc).Resolve (ec);
+			}
+			return null;
+		}
+
+		public MethodBuilder GetMethodBuilder ()
+		{
+			return method.MethodData.MethodBuilder;
+		}
+		
+		public void EmitMethod (EmitContext ec)
+		{
+			if (!CreateMethodHost (ec, invoke_mb.ReturnType))
+				return;
+
+			MethodBuilder builder = GetMethodBuilder ();
+			ILGenerator ig = builder.GetILGenerator ();
+			aec.ig = ig;
+			
+			MethodCore.LabelParameters (aec, builder, parameters, null, loc);
+
+			aec.InAnonymousMethod = true;
+			aec.EmitResolvedTopBlock (Block, unreachable);
+		}
+	}
+
+	//
+	// This will emit the code for the delegate, as well delegate creation on the host
+	//
+	public class AnonymousDelegate : DelegateCreation {
+		AnonymousMethod am;
+
+		public AnonymousDelegate (AnonymousMethod am, Type target_type, Location l)
+		{
+			type = target_type;
+			loc = l;
+			this.am = am;
+		}
+
+		public override Expression DoResolve (EmitContext ec)
+		{
+			delegate_instance_expr = new AnonymousInstance (this);
+			eclass = ExprClass.Value;
+			return this;
+		}
+		
+		public override void Emit (EmitContext ec)
+		{
+			//
+			// Emit the method on its own EmitContext
+			//
+			am.EmitMethod (ec);
+
+			//
+			// Now emit the delegate creation.
+			//
+			Expression ml = Expression.MemberLookup (ec, type, ".ctor", loc);
+			constructor_method = ((MethodGroupExpr) ml).Methods [0];
+			delegate_method = am.GetMethodBuilder ();
+			base.Emit (ec);
+		}
+
+		class AnonymousInstance : Expression {
+			public bool had_instance;
+			AnonymousDelegate ad;
+			
+			public AnonymousInstance (AnonymousDelegate ad)
+			{
+				this.ad = ad;
+				eclass = ExprClass.Value;
+				type = null;
+			}
+
+			public override Expression DoResolve (EmitContext ec)
+			{
+				return this;
+			}
+			
+			public override void Emit (EmitContext ec)
+			{
+				ad.am.aec.EmitHostInstance (ec);
+			}
+		}
+	}
+	
+	//
+	// This tracks all the captured variables, invoked from the ToplevelBlock code.
+	//
+	public class BlockCaptureInfo {
+		public Block Block;
+		public Hashtable variables;
+		public TypeBuilder TypeBuilder;
+		public ConstructorBuilder Constructor;
+		public FieldBuilder THIS;
+		public FieldBuilder ParentLink;
+		public LocalBuilder Local;
+		
+		public BlockCaptureInfo (Block block, LocalInfo variable)
+		{
+			this.Block = block;
+			variables = new Hashtable ();
+
+			// Any value will do it, as long as variables [variable]
+			variables [variable] = block;
+		}
+
+		static int count;
+
+		public string MakeHelperName ()
+		{
+			return "__Locals_" + (count++);
+		}
+
+		//
+		// Emits a single helper class to proxy the variable uses,
+		// one field per variable;   Optionally generate a `this' pointer
+		// and optionally generate a `link' to the container
+		//
+		public void EmitHelperClass (EmitContext ec, bool need_this, TypeBuilder link)
+		{
+			TypeBuilder container = ec.TypeContainer.TypeBuilder;
+
+			TypeBuilder = container.DefineNestedType (
+				MakeHelperName (), TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.NestedPublic,
+				TypeManager.object_type, null);
+
+			if (need_this)
+				THIS = TypeBuilder.DefineField ("THIS", container, FieldAttributes.Public);
+
+			if (link != null)
+				ParentLink = TypeBuilder.DefineField ("parent", link, FieldAttributes.Public);
+
+			if (need_this && link != null){
+				//
+				// Code in EmitLocalCaptureContext also assumes this:
+				//
+				throw new Exception ("I was not expecting THIS && parent link");
+				
+			}
+			
+			foreach (LocalInfo info in variables.Keys){
+				info.FieldBuilder = TypeBuilder.DefineField (
+					"_" + info.Name, info.VariableType, FieldAttributes.Public);
+			}
+
+			Type [] constructor_types = TypeManager.NoTypes;
+			Parameters constructor_parameters = Parameters.EmptyReadOnlyParameters;
+			Constructor = TypeBuilder.DefineConstructor (
+				MethodAttributes.Public | MethodAttributes.HideBySig |
+				MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
+				CallingConventions.HasThis, constructor_types);
+			InternalParameters parameter_info = new InternalParameters (constructor_types, constructor_parameters);
+			TypeManager.RegisterMethod (Constructor, parameter_info, constructor_types);
+
+			ILGenerator ig = Constructor.GetILGenerator ();
+			ig.Emit (OpCodes.Ldarg_0);
+			ig.Emit (OpCodes.Call, TypeManager.object_ctor);
+			ig.Emit (OpCodes.Ret);
+		}
+	}
+
+	public class CaptureInfo {
+		public TypeBuilder MethodHost;
+		ArrayList block_list;
+		Hashtable captured_fields;
+		bool closed;
+		
+		public CaptureInfo ()
+		{
+			block_list = new ArrayList ();
+			captured_fields = new Hashtable ();
+		}
+
+		public void AddLocal (LocalInfo li)
+		{
+			Block variable_block = li.Block;
+			int top = block_list.Count;
+
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+				if (bci.Block == variable_block){
+					if (bci.variables.Contains (li))
+						return;
+					bci.variables [li] = true;
+					break;
+				}
+			}
+			block_list.Add (new BlockCaptureInfo (variable_block, li));
+		}
+
+		public bool HaveCapturedVariables ()
+		{
+			return block_list.Count > 0;
+		}
+
+		public bool HaveCapturedFields ()
+		{
+			return captured_fields.Count > 0;
+		}
+		
+		public bool IsCaptured (LocalInfo li)
+		{
+			Block variable_block = li.Block;
+			int top = block_list.Count;
+
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+				if (bci.Block == variable_block)
+					return (bci.variables [li] != null);
+			}
+			return false;
+		}
+		
+		public void AddField (FieldExpr fe)
+		{
+			captured_fields [fe] = true;
+		}
+
+		public bool NeedThis ()
+		{
+			return (block_list.Count > 1) || (captured_fields.Count > 0);
+		}
+		
+		public void EmitHelperClasses (EmitContext ec)
+		{
+			int top = block_list.Count;
+			bool need_this = NeedThis ();
+			TypeBuilder last = null;
+			
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+
+				bci.EmitHelperClass (ec, need_this, last);
+				last = bci.TypeBuilder;
+				need_this = false;
+			}
+			MethodHost = last;
+		}
+
+		public void CloseHelperClasses ()
+		{
+			if (closed)
+				return;
+			
+			int top = block_list.Count;
+			
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+
+				bci.TypeBuilder.CreateType ();
+			}
+			closed = true;
+		}
+
+		//
+		// Emits the instance pointer for the host method
+		//
+		public void EmitHostInstance (EmitContext ec)
+		{
+			int top = block_list.Count;
+			ILGenerator ig = ec.ig;
+
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+				if (i == 0)
+					ig.Emit (OpCodes.Ldloc, bci.Local);
+				else
+					ig.Emit (OpCodes.Ldfld, bci.ParentLink);
+			}
+		}
+
+		public void EmitCapturedContext (EmitContext ec, LocalInfo li)
+		{
+			int top = block_list.Count;
+			ILGenerator ig = ec.ig;
+
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+				if (i == 0)
+					ig.Emit (OpCodes.Ldloc, bci.Local);
+				else
+					ig.Emit (OpCodes.Ldfld, bci.ParentLink);
+			}
+		}
+
+		//
+		// This emits the helper local variable
+		//
+		public void EmitLocalCaptureContext (EmitContext ec, Block b)
+		{
+			int top = block_list.Count;
+			
+			ILGenerator ig = ec.ig;
+			BlockCaptureInfo last = null;
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+
+				if (bci.Block == b)
+					break;
+
+				// Construct object
+				ig.Emit (OpCodes.Newobj, (ConstructorInfo) bci.Constructor);
+				if (bci.Local == null)
+					bci.Local = ig.DeclareLocal (bci.TypeBuilder);
+
+				ig.Emit (OpCodes.Stloc, bci.Local);
+					
+
+				//
+				// Link THIS
+				//
+				if (bci.THIS != null){
+					ig.Emit (OpCodes.Ldloc, bci.Local);
+					ig.Emit (OpCodes.Ldarg_0);
+					ig.Emit (OpCodes.Stfld, bci.THIS);
+				}
+
+				//
+				// Setup link to parent
+				//
+				if (last != null){
+					ig.Emit (OpCodes.Ldloc, bci.Local);
+					ig.Emit (OpCodes.Ldloc, last.Local);
+					ig.Emit (OpCodes.Stfld, bci.ParentLink);
+
+				}
+				last = bci;
+					
+			}
+			
+		}
+		
+		public void EmitContext (EmitContext ec, LocalInfo li)
+		{
+			int top = block_list.Count;
+			Block variable_block = li.Block;
+			
+			ILGenerator ig = ec.ig;
+			ig.Emit (OpCodes.Ldarg_0);
+			for (int i = 0; i < top; i++){
+				BlockCaptureInfo bci = (BlockCaptureInfo) block_list [i];
+
+				if (bci.Block == variable_block)
+					break;
+
+				ig.Emit (OpCodes.Ldfld, bci.ParentLink);
+			}
 		}
 	}
 }
Index: assign.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/assign.cs,v
retrieving revision 1.75
diff -u -u -r1.75 assign.cs
--- assign.cs	7 Feb 2004 05:54:15 -0000	1.75
+++ assign.cs	10 Mar 2004 02:53:43 -0000
@@ -64,7 +64,6 @@
 			type = t;
 			eclass = ExprClass.Value;
 			loc = Location.Null;
-			builder = ec.GetTemporaryLocal (t);
 		}
 
 		public void Release (EmitContext ec)
@@ -88,16 +87,22 @@
 
 		public override void Emit (EmitContext ec)
 		{
+			if (builder == null)
+				builder = ec.GetTemporaryLocal (type);
 			ec.ig.Emit (OpCodes.Ldloc, builder); 
 		}
 
 		public void Store (EmitContext ec)
 		{
+			if (builder == null)
+				builder = ec.GetTemporaryLocal (type);
 			ec.ig.Emit (OpCodes.Stloc, builder);
 		}
 
 		public void AddressOf (EmitContext ec, AddressOp mode)
 		{
+			if (builder == null)
+				builder = ec.GetTemporaryLocal (type);
 			ec.ig.Emit (OpCodes.Ldloca, builder);
 		}
 	}
Index: class.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/class.cs,v
retrieving revision 1.405
diff -u -u -r1.405 class.cs
--- class.cs	5 Mar 2004 20:37:57 -0000	1.405
+++ class.cs	10 Mar 2004 02:53:44 -0000
@@ -2228,7 +2228,7 @@
 
 	public abstract class MethodCore : MemberBase {
 		public readonly Parameters Parameters;
-		protected Block block;
+		protected ToplevelBlock block;
 		protected DeclSpace ds;
 		
 		//
@@ -2266,7 +2266,7 @@
 			}
 		}
 		
-		public Block Block {
+		public ToplevelBlock Block {
 			get {
 				return block;
 			}
@@ -2640,7 +2640,7 @@
 					    ParameterTypes, ParameterInfo,
 					    ModFlags, Location);
 
-				Block new_block = ih.Setup (block);
+				ToplevelBlock new_block = ih.Setup (block);
 				if (new_block == null)
 					return false;
 				block = new_block;
@@ -3401,7 +3401,7 @@
 		//
 		// Emits the code
 		// 
-		public virtual void Emit (TypeContainer container, Block block, object kind)
+		public virtual void Emit (TypeContainer container, ToplevelBlock block, object kind)
 		{
 			ILGenerator ig;
 			EmitContext ec;
@@ -3492,7 +3492,7 @@
 			}
 		}
 
-		void EmitDestructor (EmitContext ec, Block block)
+		void EmitDestructor (EmitContext ec, ToplevelBlock block)
 		{
 			ILGenerator ig = ec.ig;
 			
@@ -4077,10 +4077,10 @@
 		//
 		// Null if the accessor is empty, or a Block if not
 		//
-		public Block Block;
+		public ToplevelBlock Block;
 		public Attributes OptAttributes;
 		
-		public Accessor (Block b, Attributes attrs)
+		public Accessor (ToplevelBlock b, Attributes attrs)
 		{
 			Block = b;
 			OptAttributes = attrs;
@@ -4311,7 +4311,7 @@
 										   "get", container, MemberType,
 										   parameters, ip, ModFlags, Location);
 					
-					Block new_block = ih.Setup (block);
+					ToplevelBlock new_block = ih.Setup (block);
 					if (new_block == null)
 						return false;
 					block = new_block;
@@ -4975,7 +4975,7 @@
 		public readonly Expression ReturnType;
 		public readonly Expression FirstArgType, SecondArgType;
 		public readonly string FirstArgName, SecondArgName;
-		public Block           Block;
+		public ToplevelBlock   Block;
 		public MethodBuilder   OperatorMethodBuilder;
 		
 		public string MethodName;
@@ -4984,7 +4984,7 @@
 		public Operator (OpType type, Expression ret_type, int mod_flags,
 				 Expression arg1type, string arg1name,
 				 Expression arg2type, string arg2name,
-				 Block block, Attributes attrs, Location loc)
+				 ToplevelBlock block, Attributes attrs, Location loc)
 			: base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
 		{
 			OperatorType = type;
Index: codegen.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/codegen.cs,v
retrieving revision 1.143
diff -u -u -r1.143 codegen.cs
--- codegen.cs	25 Feb 2004 09:11:13 -0000	1.143
+++ codegen.cs	10 Mar 2004 02:53:44 -0000
@@ -336,8 +336,20 @@
 		/// </summary>
 		public bool InEnumContext;
 
+		/// <summary>
+		///   Anonymous methods can capture local variables and fields,
+		///   this object tracks it.
+		/// </summary>
+		CaptureInfo capture_info;
+
 		FlowBranching current_flow_branching;
-		
+
+		/// <summary>
+		///   In anonymous methods, points to the parent, so
+		///   capture information about variables can be tracked
+		/// </summary>
+		public EmitContext emit_container;
+
 		public EmitContext (DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
 				    Type return_type, int code_flags, bool is_constructor)
 		{
@@ -365,7 +377,7 @@
 					InUnsafe = (code_flags & Modifiers.UNSAFE) != 0;
 			}
 			loc = l;
-			
+
 			if (ReturnType == TypeManager.void_type)
 				ReturnType = null;
 		}
@@ -446,19 +458,135 @@
 			current_flow_branching = current_flow_branching.Parent;
 		}
 
-		public void EmitTopBlock (Block block, InternalParameters ip, Location loc)
+		public void CaptureVariable (LocalInfo li)
+		{
+			Console.WriteLine ("Capturing: " + li.Name);
+			if (capture_info == null){
+				capture_info = new CaptureInfo ();
+				if (emit_container != null){
+					if (emit_container.capture_info != null)
+						throw new Exception ("we should have propagated capture_info");
+					emit_container.capture_info = capture_info;
+				}
+			}
+			capture_info.AddLocal (li);
+			li.IsCaptured = true;
+		}
+
+		//
+		// Whether anonymous methods have captured variables
+		//
+		public bool HaveCapturedVariables ()
+		{
+			if (capture_info != null)
+				return capture_info.HaveCapturedVariables ();
+			return false;
+		}
+
+		//
+		// Whether anonymous methods have captured fields or this.
+		//
+		public bool HaveCapturedFields ()
+		{
+			if (capture_info != null)
+				return capture_info.HaveCapturedFields ();
+			return false;
+		}
+
+		public void EmitHostInstance (EmitContext target)
+		{
+			if (capture_info != null)
+				capture_info.EmitHostInstance (target);
+			else
+				target.ig.Emit (OpCodes.Ldnull);
+		}
+
+		//
+		// Returns whether the `local' variable has been captured by an anonymous
+		// method
+		//
+		public bool IsCaptured (LocalInfo local)
+		{
+			return capture_info.IsCaptured (local);
+		}
+
+		public void EmitLocalCaptureContext (Block b)
+		{
+			capture_info.EmitLocalCaptureContext (this, b);
+		}
+		
+		public void CaptureField (FieldExpr fe)
 		{
-			bool unreachable = false;
+			if (capture_info == null){
+				capture_info = new CaptureInfo ();
+				if (emit_container != null){
+					if (emit_container.capture_info != null)
+						throw new Exception ("we should have propagated capture_info");
+					emit_container.capture_info = capture_info;
+				}
+			}
+
+			capture_info.AddField (fe);
+		}
+
+		public void EmitMeta (ToplevelBlock b, InternalParameters ip)
+		{
+			if (capture_info != null)
+				capture_info.EmitHelperClasses (this);
+			b.EmitMeta (b, this, ip);
+		}
 
+		public EmitContext EmitContainer {
+			get {
+				return emit_container;
+			}
+
+			set {
+				emit_container = value;
+				capture_info = emit_container.capture_info;
+			}
+		}
+
+		//
+		// Here until we can fix the problem with Mono.CSharp.Switch, which
+		// currently can not cope with ig == null during resolve (which must
+		// be fixed for switch statements to work on anonymous methods).
+		//
+		ILGenerator cheat;
+
+		public void EmitTopBlock (ToplevelBlock block, InternalParameters ip, Location loc)
+		{
+			bool unreachable;
+
+			if (EmitContainer != null)
+				capture_info = EmitContainer.capture_info;
+			
+			cheat = ig;
+			//ig = null;
+			if (ResolveTopBlock (block, ip, loc, out unreachable)){
+				ig = cheat;
+				EmitMeta (block, ip);
+				
+				EmitResolvedTopBlock (block, unreachable);
+			}
+		}
+
+		public bool ResolveTopBlock (ToplevelBlock block, InternalParameters ip, Location loc, out bool unreachable)
+		{
+			unreachable = false;
+			
 			if (!Location.IsNull (loc))
 				CurrentFile = loc.File;
 
 			if (block != null){
+#if false
 			    try {
+#endif
 				int errors = Report.Errors;
 
-				block.EmitMeta (this, ip);
+				block.ResolveMeta (block, this, ip);
 
+				
 				if (Report.Errors == errors){
 					bool old_do_flow_analysis = DoFlowAnalysis;
 					DoFlowAnalysis = true;
@@ -469,7 +597,7 @@
 					if (!block.Resolve (this)) {
 						current_flow_branching = null;
 						DoFlowAnalysis = old_do_flow_analysis;
-						return;
+						return false;
 					}
 
 					FlowBranching.Reachability reachability = current_flow_branching.MergeTopBlock ();
@@ -477,13 +605,12 @@
 					
 					DoFlowAnalysis = old_do_flow_analysis;
 
-					block.Emit (this);
-
 					if (reachability.AlwaysReturns ||
 					    reachability.AlwaysThrows ||
 					    reachability.IsUnreachable)
 						unreachable = true;
 				}
+#if false
 			    } catch (Exception e) {
 					Console.WriteLine ("Exception caught by the compiler while compiling:");
 					Console.WriteLine ("   Block that caused the problem begin at: " + loc);
@@ -493,19 +620,26 @@
 								   CurrentBlock.StartLocation, CurrentBlock.EndLocation);
 					}
 					Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
-					Console.WriteLine (Report.FriendlyStackTrace (e));
-					
-					Environment.Exit (1);
+					throw;
 			    }
+#endif
 			}
 
 			if (ReturnType != null && !unreachable){
 				if (!InIterator){
 					Report.Error (161, loc, "Not all code paths return a value");
-					return;
+					return false;
 				}
 			}
+			return true;
+		}
 
+		public void EmitResolvedTopBlock (ToplevelBlock block, bool unreachable)
+		{
+			if (block != null){
+				block.Emit (this);
+			}
+			
 			if (HasReturnLabel)
 				ig.MarkLabel (ReturnLabel);
 			if (return_value != null){
@@ -533,6 +667,9 @@
 					ig.Emit (OpCodes.Ret);
 				}
 			}
+
+			if (capture_info != null)
+				capture_info.CloseHelperClasses ();
 		}
 
 		/// <summary>
@@ -646,7 +783,7 @@
 		public void NeedReturnLabel ()
 		{
 			if (!HasReturnLabel) {
-				ReturnLabel = ig.DefineLabel ();
+				ReturnLabel = cheat.DefineLabel ();
 				HasReturnLabel = true;
 			}
 		}
@@ -671,14 +808,7 @@
 		{
 			FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc);
 			fe.InstanceExpression = new ProxyInstance ();
-			return fe.DoResolve (this);
-		}
-
-		public Expression RemapLocalLValue (LocalInfo local_info, Expression right_side)
-		{
-			FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc);
-			fe.InstanceExpression = new ProxyInstance ();
-			return fe.DoResolveLValue (this, right_side);
+			return fe;
 		}
 
 		public Expression RemapParameter (int idx)
@@ -711,6 +841,36 @@
 			}
 		}
 
+		public void EmitCapturedContext (LocalInfo li)
+		{
+			if (capture_info != null){
+				if (InAnonymousMethod)
+					ig.Emit (OpCodes.Ldarg_0);
+				else
+					capture_info.EmitCapturedContext (this, li);
+			} 
+		}
+
+		//
+		// Returns the TypeBuilder that hosts the anonymous method:
+		// it can be the current one (no captured locals for example),
+		// or it can be the same type.
+		//
+		public TypeBuilder GetAnonymousMethodHost ()
+		{
+			//
+			// If we have captured information, the anonymous method will be
+			// nested in the helper class
+			//
+			if (capture_info != null)
+				return capture_info.MethodHost;
+
+			//
+			// Otherwise it is compiled in the same type
+			//
+			return TypeContainer.TypeBuilder;
+		}
+		
 		public Expression GetThis (Location loc)
 		{
 			This my_this;
Index: convert.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/convert.cs,v
retrieving revision 1.19
diff -u -u -r1.19 convert.cs
--- convert.cs	17 Jan 2004 19:50:19 -0000	1.19
+++ convert.cs	10 Mar 2004 02:53:44 -0000
@@ -1026,18 +1026,21 @@
 			Type expr_type = expr.Type;
 			Expression e;
 
-			if (expr.eclass == ExprClass.MethodGroup){
-				if (!TypeManager.IsDelegateType (target_type)){
-					Report.Error (428, loc,
-						      String.Format (
-							   "Cannot convert method group to `{0}', since it is not a delegate",
-							   TypeManager.CSharpName (target_type)));
-					return null;
-				}
+			if (RootContext.V2){
+				if (expr.eclass == ExprClass.MethodGroup){
+					if (!TypeManager.IsDelegateType (target_type)){
+						Report.Error (428, loc,
+							String.Format (
+								"Cannot convert method group to `{0}', since it is not a delegate",
+								TypeManager.CSharpName (target_type)));
+						return null;
+					}
 
-				return ImplicitDelegateCreation.Create (ec, (MethodGroupExpr) expr, target_type, loc);
+					Console.WriteLine ("Triggering");
+					return ImplicitDelegateCreation.Create (ec, (MethodGroupExpr) expr, target_type, loc);
+				}
 			}
-			
+
 			if (expr_type == target_type && !(expr is NullLiteral))
 				return expr;
 
@@ -1053,7 +1056,7 @@
 			     target_type.IsSubclassOf (TypeManager.enum_type)) &&
 			    expr is IntLiteral){
 				IntLiteral i = (IntLiteral) expr;
-
+				
 				if (i.Value == 0)
 					return new EnumConstant ((Constant) expr, target_type);
 			}
@@ -1082,6 +1085,31 @@
 				}
 			}
 
+			if (expr_type == TypeManager.anonymous_method_type){
+				if (!TypeManager.IsDelegateType (target_type)){
+					Report.Error (428, loc,
+						      String.Format (
+							      "Cannot convert anonymous method to `{0}', since it is not a delegate",
+							      TypeManager.CSharpName (target_type)));
+					return null;
+				}
+
+				AnonymousMethod am = (AnonymousMethod) expr;
+				int errors = Report.Errors;
+
+				Expression conv = am.Compatible (ec, target_type);
+				if (conv != null)
+					return conv;
+				
+				//
+				// We return something instead of null, to avoid
+				// the duplicate error, since am.Compatible would have
+				// reported that already
+				//
+				if (errors != Report.Errors)
+					return new EmptyCast (expr, target_type);
+			}
+			
 			return null;
 		}
 
@@ -1142,9 +1170,10 @@
 
 		static public void Error_CannotImplicitConversion (Location loc, Type source, Type target)
 		{
-			string msg = "Cannot convert implicitly from `"+
-				TypeManager.CSharpName (source) + "' to `" +
-				TypeManager.CSharpName (target) + "'";
+			string msg = String.Format ("Cannot convert implicitly from {0} to `{1}'",
+						    source == TypeManager.anonymous_method_type ?
+						    "anonymous method" : "`" + TypeManager.CSharpName (source) + "'",
+						    TypeManager.CSharpName (target));
 
 			Report.Error (29, loc, msg);
 		}
Index: cs-parser.jay
===================================================================
RCS file: /cvs/public/mcs/mcs/cs-parser.jay,v
retrieving revision 1.284
diff -u -u -r1.284 cs-parser.jay
--- cs-parser.jay	27 Feb 2004 06:39:38 -0000	1.284
+++ cs-parser.jay	10 Mar 2004 02:53:45 -0000
@@ -42,12 +42,6 @@
 		/// </summary>
 		Block      current_block;
 
-		/// <summary>
-                ///   If true, creates a toplevel block in the block production
-                ///   This is flagged by the delegate creation
-                /// </summary>
-                bool       create_toplevel_block;
-	
                 /// <summary>
 		/// <summary>
 		///   Current interface is used by the various declaration
@@ -872,7 +866,7 @@
 			}
 		}
 
-		method.Block = (Block) $3;
+		method.Block = (ToplevelBlock) $3;
 		CheckDef (current_container.AddMethod (method), method.Name, method.Location);
 
 		current_local_parameters = null;
@@ -1109,7 +1103,7 @@
 	  }
           accessor_body
 	  {
-		$$ = new Accessor ((Block) $4, (Attributes) $1);
+		$$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1);
 		current_local_parameters = null;
 		lexer.PropertyParsing = true;
 	  }
@@ -1146,7 +1140,7 @@
 	  }
 	  accessor_body
 	  {
-		$$ = new Accessor ((Block) $4, (Attributes) $1);
+		$$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1);
 		current_local_parameters = null;
 		lexer.PropertyParsing = true;
 	  }
@@ -1372,7 +1366,7 @@
 		OperatorDeclaration decl = (OperatorDeclaration) $3;
 		
 		Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
-					    decl.arg2type, decl.arg2name, (Block) $5, (Attributes) $1, decl.location);
+					    decl.arg2type, decl.arg2name, (ToplevelBlock) $4, (Attributes) $1, decl.location);
 
 		if (SimpleIteratorContainer.Simple.Yields)
 			op.SetYields ();
@@ -1501,7 +1495,7 @@
 	  constructor_body
 	  { 
 		Constructor c = (Constructor) $3;
-		c.Block = (Block) $4;
+		c.Block = (ToplevelBlock) $4;
 		c.OptAttributes = (Attributes) $1;
 		c.ModFlags = (int) $2;
 	
@@ -1616,7 +1610,7 @@
 				current_container, TypeManager.system_void_expr, m, "Finalize", 
 				new Parameters (null, null, l), (Attributes) $1, l);
 		  
-			d.Block = (Block) $7;
+			d.Block = (ToplevelBlock) $7;
 			CheckDef (current_container.AddMethod (d), d.Name, d.Location);
 		}
 	  }
@@ -1704,7 +1698,7 @@
 	  }
           block
 	  {
-		$$ = new Accessor ((Block) $4, (Attributes) $1);
+		$$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1);
 		lexer.EventParsing = true;
 	  }
 	| opt_attributes ADD error {
@@ -1728,7 +1722,7 @@
 	  }
           block
 	  {
-		$$ = new Accessor ((Block) $4, (Attributes) $1);
+		$$ = new Accessor ((ToplevelBlock) $4, (Attributes) $1);
 		lexer.EventParsing = true;
 	  }
 	| opt_attributes REMOVE error {
@@ -2460,20 +2454,28 @@
 	: DELEGATE opt_anonymous_method_signature {
 		oob_stack.Push (current_local_parameters);
 		current_local_parameters = (Parameters)$2;
-		create_toplevel_block = true;
+
+		// Force the next block to be created as a ToplevelBlock
+		oob_stack.Push (current_block);
+		current_block = null;
 	  } block {
-		create_toplevel_block = false;
+		current_block = (Block) oob_stack.Pop ();
 		if (!RootContext.V2){
 			Report.Error (-213, lexer.Location, "Anonymous methods are only supported in V2");
 			$$ = null;
-		} else 
-			$$ = new AnonymousMethod ((Parameters) $2, (Block) $4, lexer.Location);
+		} else  {
+			ToplevelBlock anon_block = (ToplevelBlock) $4;
+
+			anon_block.Parent = current_block;
+			$$ = new AnonymousMethod ((Parameters) $2, (ToplevelBlock) current_block, 
+				anon_block, lexer.Location);
+		}
 		current_local_parameters = (Parameters) oob_stack.Pop ();
 	  }
 	;
 
 opt_anonymous_method_signature
-	: /* empty */			{ $$ = Parameters.EmptyReadOnlyParameters; }
+	: /* empty */			{ $$ = null; } 
 	| anonymous_method_signature
 	;
 
@@ -2492,7 +2494,7 @@
 	;
 
 opt_anonymous_method_parameter_list
-	: /* empty */	{ $$ = null; } 
+	: /* empty */	                   { $$ = null; } 
 	| anonymous_method_parameter_list  { $$ = $1; }
 	;
 
@@ -2513,7 +2515,11 @@
 
 anonymous_method_parameter
 	: opt_parameter_modifier type IDENTIFIER {
-		$$ = new Parameter ((Expression) $2, (string) $2, (Parameter.Modifier) $1, null);
+		$$ = new Parameter ((Expression) $2, (string) $3, (Parameter.Modifier) $1, null);
+	  }
+	| PARAMS type IDENTIFIER {
+		Report.Error (-221, lexer.Location, "params modifier not allowed in anonymous method declaration");
+		$$ = null;
 	  }
 	;
 
@@ -2935,7 +2941,7 @@
 block
 	: OPEN_BRACE 
 	  {
-		if (current_block == null || create_toplevel_block){
+		if (current_block == null){
 			current_block = new ToplevelBlock (current_local_parameters, lexer.Location);
 		} else {
 			current_block = new Block (current_block, current_local_parameters,
Index: delegate.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/delegate.cs,v
retrieving revision 1.96
diff -u -u -r1.96 delegate.cs
--- delegate.cs	25 Feb 2004 09:11:13 -0000	1.96
+++ delegate.cs	10 Mar 2004 02:53:46 -0000
@@ -355,6 +355,23 @@
 			return true;
 		}
 
+		//
+		// Returns the MethodBase for "Invoke" from a delegate type, this is used
+		// to extract the signature of a delegate.
+		//
+		public static MethodInfo GetInvokeMethod (EmitContext ec, Type delegate_type, Location loc)
+		{
+			Expression ml = Expression.MemberLookup (
+				ec, delegate_type, "Invoke", loc);
+
+			if (!(ml is MethodGroupExpr)) {
+				Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+				return null;
+			}
+
+			return (MethodInfo) (((MethodGroupExpr) ml).Methods [0]);
+		}
+		
 		/// <summary>
 		///  Verifies whether the method in question is compatible with the delegate
 		///  Returns the method itself if okay and null if not.
@@ -711,7 +728,7 @@
 				return null;
 		}
 	}
-	
+
 	//
 	// A delegate-creation-expression, invoked from the `New' class 
 	//
Index: expression.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/expression.cs,v
retrieving revision 1.525
diff -u -u -r1.525 expression.cs
--- expression.cs	28 Feb 2004 00:34:14 -0000	1.525
+++ expression.cs	10 Mar 2004 02:53:47 -0000
@@ -3288,16 +3288,12 @@
 			Label false_target = ig.DefineLabel ();
 			Label end_target = ig.DefineLabel ();
 
-			ig.Emit (OpCodes.Nop);
-
 			(is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
 			left.Emit (ec);
 			ig.Emit (OpCodes.Br, end_target);
 			ig.MarkLabel (false_target);
 			op.Emit (ec);
 			ig.MarkLabel (end_target);
-
-			ig.Emit (OpCodes.Nop);
 		}
 	}
 
@@ -3521,8 +3517,10 @@
 			eclass = ExprClass.Variable;
 		}
 
+		//
 		// Setting `is_readonly' to false will allow you to create a writable
 		// reference to a read-only variable.  This is used by foreach and using.
+		//
 		public LocalVariableReference (Block block, string name, Location l,
 					       LocalInfo local_info, bool is_readonly)
 			: this (block, name, l)
@@ -3532,7 +3530,9 @@
 		}
 
 		public VariableInfo VariableInfo {
-			get { return local_info.VariableInfo; }
+			get {
+				return local_info.VariableInfo;
+			}
 		}
 
 		public bool IsReadOnly {
@@ -3541,7 +3541,7 @@
 			}
 		}
 
-		protected void DoResolveBase (EmitContext ec)
+		protected Expression DoResolveBase (EmitContext ec, Expression lvalue_right_side)
 		{
 			if (local_info == null) {
 				local_info = Block.GetLocalInfo (Name);
@@ -3549,14 +3549,18 @@
 			}
 
 			type = local_info.VariableType;
-#if false
-			if (ec.InAnonymousMethod)
-				Block.LiftVariable (local_info);
-#endif
-		}
 
-		protected Expression DoResolve (EmitContext ec, bool is_lvalue)
-		{
+			VariableInfo variable_info = local_info.VariableInfo;
+			if (lvalue_right_side != null){
+				if (is_readonly){
+					Error (1604, "cannot assign to `" + Name + "' because it is readonly");
+					return null;
+				}
+				
+				if (variable_info != null)
+					variable_info.SetAssigned (ec);
+			}
+			
 			Expression e = Block.GetConstantExpression (Name);
 			if (e != null) {
 				local_info.Used = true;
@@ -3564,48 +3568,40 @@
 				return e;
 			}
 
-			VariableInfo variable_info = local_info.VariableInfo; 
 			if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
 				return null;
 
-			if (!is_lvalue)
+			if (lvalue_right_side == null)
 				local_info.Used = true;
 
-			if (local_info.LocalBuilder == null)
-				return ec.RemapLocal (local_info);
+			if (ec.InAnonymousMethod){
+				//
+				// If we are referencing a variable from the external block
+				// flag it for capturing
+				//
+				if (local_info.Block.Toplevel != ec.CurrentBlock.Toplevel)
+					ec.CaptureVariable (local_info);
+			}
+			
+			if (ec.RemapToProxy){
+				Expression new_local = ec.RemapLocal (local_info);
+				if (lvalue_right_side == null)
+					return new_local.DoResolve (ec);
+				else
+					return new_local.DoResolveLValue (ec, lvalue_right_side);
+			}
 			
 			return this;
 		}
 		
 		public override Expression DoResolve (EmitContext ec)
 		{
-			DoResolveBase (ec);
-
-			return DoResolve (ec, false);
+			return DoResolveBase (ec, null);
 		}
 
 		override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
 		{
-			DoResolveBase (ec);
-
-			VariableInfo variable_info = local_info.VariableInfo; 
-			if (variable_info != null)
-				variable_info.SetAssigned (ec);
-
-			Expression e = DoResolve (ec, true);
-
-			if (e == null)
-				return null;
-
-			if (is_readonly){
-				Error (1604, "cannot assign to `" + Name + "' because it is readonly");
-				return null;
-			}
-
-			if (local_info.LocalBuilder == null)
-				return ec.RemapLocalLValue (local_info, right_side);
-			
-			return this;
+			return DoResolveBase (ec, right_side);
 		}
 
 		public bool VerifyFixed (bool is_expression)
@@ -3617,15 +3613,26 @@
 		{
 			ILGenerator ig = ec.ig;
 
-			ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
+			if (local_info.FieldBuilder == null){
+				ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
+			} else {
+				ec.EmitCapturedContext (local_info);
+				ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
+			}
 		}
 		
 		public void EmitAssign (EmitContext ec, Expression source)
 		{
 			ILGenerator ig = ec.ig;
 
-			source.Emit (ec);
-			ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
+			if (local_info.FieldBuilder == null){
+				source.Emit (ec);
+				ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
+			} else {
+				ec.EmitCapturedContext (local_info);
+				source.Emit (ec);
+				ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
+			}
 		}
 		
 		public void AddressOf (EmitContext ec, AddressOp mode)
Index: iterators.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/iterators.cs,v
retrieving revision 1.16
diff -u -u -r1.16 iterators.cs
--- iterators.cs	27 Feb 2004 06:39:38 -0000	1.16
+++ iterators.cs	10 Mar 2004 02:53:47 -0000
@@ -172,7 +172,7 @@
 		Type return_type;
 		Type [] param_types;
 		InternalParameters parameters;
-		Block original_block;
+		ToplevelBlock original_block;
 		Location loc;
 		int modifiers;
 
@@ -673,7 +673,7 @@
 		//
 		// Returns the new block for the method, or null on failure
 		//
-		public Block Setup (Block block)
+		public ToplevelBlock Setup (ToplevelBlock block)
 		{
 			if (!(IsIEnumerator (return_type) || IsIEnumerable (return_type))){
 				Report.Error (
@@ -694,7 +694,7 @@
 			}
 
 			original_block = block;
-			Block b = new Block (null);
+			ToplevelBlock b = new ToplevelBlock (loc);
 
 			// return new InnerClass ()
 			b.AddStatement (new NoCheckReturn (new NewInnerType (this, loc), loc));
Index: report.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/report.cs,v
retrieving revision 1.40
diff -u -u -r1.40 report.cs
--- report.cs	31 Dec 2003 20:53:22 -0000	1.40
+++ report.cs	10 Mar 2004 02:53:47 -0000
@@ -115,9 +115,6 @@
 			Errors++;
 			Console.WriteLine (msg);
 
-			if (Stacktrace)
-				Console.WriteLine (FriendlyStackTrace (new StackTrace (true)));
-			
 			if (Fatal)
 				throw new Exception (msg);
 		}
Index: rootcontext.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/rootcontext.cs,v
retrieving revision 1.121
diff -u -u -r1.121 rootcontext.cs
--- rootcontext.cs	25 Feb 2004 09:11:13 -0000	1.121
+++ rootcontext.cs	10 Mar 2004 02:53:47 -0000
@@ -65,7 +65,8 @@
 		//
 		// If set, enable C# version 2 features
 		//
-		public static bool V2;
+		public static bool V2 = true;
+		
 		//
 		// Constructor
 		//
Index: statement.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/statement.cs,v
retrieving revision 1.239
diff -u -u -r1.239 statement.cs
--- statement.cs	25 Feb 2004 09:11:13 -0000	1.239
+++ statement.cs	10 Mar 2004 02:53:48 -0000
@@ -6,6 +6,7 @@
 //   Martin Baulig (martin@gnome.org)
 //
 // (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, Inc.
 //
 
 using System;
@@ -550,6 +551,11 @@
 		{
 			if (ec.ReturnType == null){
 				if (Expr != null){
+					if (ec.InAnonymousMethod){
+						Report.Error (1662, loc, String.Format (
+							"Anonymous method could not be converted to delegate " +
+							"since the return value does not match the delegate value"));
+					}
 					Error (127, "Return with a value not allowed here");
 					return false;
 				}
@@ -944,13 +950,17 @@
 		}
 	}
 
+	//
+	// The information about a user-perceived local variable
+	//
 	public class LocalInfo {
 		public Expression Type;
 
 		//
 		// Most of the time a variable will be stored in a LocalBuilder
 		//
-		// But sometimes, it will be stored in a field.  The context of the field will
+		// But sometimes, it will be stored in a field (variables that have been
+		// hoisted by iterators or by anonymous methods).  The context of the field will
 		// be stored in the EmitContext
 		//
 		//
@@ -967,7 +977,8 @@
 		enum Flags : byte {
 			Used = 1,
 			ReadOnly = 2,
-			Fixed = 4
+			Fixed = 4,
+			Captured = 8
 		}
 
 		Flags flags;
@@ -1032,6 +1043,16 @@
 			}
 		}
 
+		public bool IsCaptured {
+			get {
+				return (flags & Flags.Captured) != 0;
+			}
+
+			set {
+				flags |= Flags.Captured;
+			}
+		}
+
 		public override string ToString ()
 		{
 			return String.Format ("LocalInfo ({0},{1},{2},{3})",
@@ -1075,9 +1096,9 @@
 	///   they contain extra information that is not necessary on normal blocks.
 	/// </remarks>
 	public class Block : Statement {
-		public readonly Block     Parent;
+		public Block    Parent;
 		public readonly Location  StartLocation;
-		public Location           EndLocation = Location.Null;
+		public Location EndLocation = Location.Null;
 
 		[Flags]
 		public enum Flags : byte {
@@ -1086,7 +1107,8 @@
 			BlockUsed = 4,
 			VariablesInitialized = 8,
 			HasRet = 16,
-			IsDestructor = 32	
+			IsDestructor = 32,
+			IsToplevel = 64
 		}
 		Flags flags;
 
@@ -1543,7 +1565,7 @@
 		public VariableMap ParameterMap {
 			get {
 				if ((flags & Flags.VariablesInitialized) == 0)
-					throw new Exception ();
+					throw new Exception ("Variables have not been initialized yet");
 
 				return param_map;
 			}
@@ -1552,17 +1574,12 @@
 		public VariableMap LocalMap {
 			get {
 				if ((flags & Flags.VariablesInitialized) == 0)
-					throw new Exception ();
+					throw new Exception ("Variables have not been initialized yet");
 
 				return local_map;
 			}
 		}
 
-		public bool LiftVariable (LocalInfo local_info)
-		{
-			return false;
-		}
-		
 		/// <summary>
 		///   Emits the variable declarations and labels.
 		/// </summary>
@@ -1570,7 +1587,7 @@
 		///   tc: is our typecontainer (to resolve type references)
 		///   ig: is the code generator:
 		/// </remarks>
-		public void EmitMeta (EmitContext ec, InternalParameters ip)
+		public void ResolveMeta (ToplevelBlock toplevel, EmitContext ec, InternalParameters ip)
 		{
 			ILGenerator ig = ec.ig;
 
@@ -1601,8 +1618,7 @@
 
 			bool old_check_state = ec.ConstantCheckState;
 			ec.ConstantCheckState = (flags & Flags.Unchecked) == 0;
-			bool remap_locals = ec.RemapToProxy;
-				
+			
 			//
 			// Process this block variables
 			//
@@ -1627,11 +1643,6 @@
 							continue;
 					}
 
-					if (remap_locals)
-						vi.FieldBuilder = ec.MapVariable (name, vi.VariableType);
-					else
-						vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
-
 					if (constants == null)
 						continue;
 
@@ -1669,7 +1680,35 @@
 			//
 			if (children != null){
 				foreach (Block b in children)
-					b.EmitMeta (ec, ip);
+					b.ResolveMeta (toplevel, ec, ip);
+			}
+		}
+
+		//
+		// Emits the local variable declarations for a block
+		//
+		public void EmitMeta (ToplevelBlock toplevel, EmitContext ec, InternalParameters ip)
+		{
+			ILGenerator ig = ec.ig;
+			
+			if (variables != null){
+				bool have_captured_vars = ec.HaveCapturedVariables ();
+				if (have_captured_vars)
+					ec.EmitLocalCaptureContext (this);
+				
+				foreach (DictionaryEntry de in variables){
+					LocalInfo vi = (LocalInfo) de.Value;
+					
+					if (have_captured_vars && ec.IsCaptured (vi))
+						continue;
+					
+					vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
+				}
+			}
+
+			if (children != null){
+				foreach (Block b in children)
+					b.EmitMeta (toplevel, ec, ip);
 			}
 		}
 
@@ -1832,20 +1871,110 @@
 
 			ec.CurrentBlock = prev_block;
 		}
+
+		//
+		// Invoked during parsing to register all anonymous methods,
+		// it registers the method with the topmost block.
+		//
+		public void RegisterAnonymousMethod (AnonymousMethod m)
+		{
+			Block b = this;
+			while (b.Parent != null)
+				b = b.Parent;
+			ToplevelBlock tl = (ToplevelBlock) b;
+			
+			tl.DoRegisterAnonymousMethod (m);
+		}
+
+		public ToplevelBlock Toplevel {
+			get {
+				Block b = this;
+				while (b.Parent != null){
+					if ((b.flags & Flags.IsToplevel) != 0)
+						break;
+					b = b.Parent;
+				}
+
+				return (ToplevelBlock) b;
+			}
+		}
 	}
 
 	//
+	// A toplevel block contains extra information, the split is done
+	// only to separate information that would otherwise bloat the more
+	// lightweight Block.
+	//
+	// In particular, this was introduced when the support for Anonymous
+	// Methods was implemented. 
 	// 
 	public class ToplevelBlock : Block {
+		public ArrayList AnonymousMethods;
+		CaptureInfo capture_info;
+
+		//
+		// Parent is only used by anonymous blocks to link back to their
+		// parents
+		//
 		public ToplevelBlock (Parameters parameters, Location start) :
-			base (null, parameters, start, Location.Null)
+			base (null, Flags.IsToplevel, parameters, start, Location.Null)
 		{
 		}
 
 		public ToplevelBlock (Flags flags, Parameters parameters, Location start) :
-			base (null, flags, parameters, start, Location.Null)
+			base (null, Flags.IsToplevel, parameters, start, Location.Null)
+		{
+		}
+
+		public ToplevelBlock (Location loc) : base (null, Flags.IsToplevel, loc, loc)
+		{
+		}
+
+		public bool HaveAnonymousMethods {
+			get {
+				return AnonymousMethods != null;
+			}
+		}
+		
+		//
+		// Invoked by Block.RegisterAnonymousMethod
+		//
+		public void DoRegisterAnonymousMethod (AnonymousMethod m)
+		{
+			if (AnonymousMethods == null)
+				AnonymousMethods = new ArrayList ();
+			AnonymousMethods.Add (m);
+		}
+
+		public FieldBuilder GetCapturedField (LocalInfo local_info)
+		{
+			return null;
+		}
+		
+		public void EmitAnonymousMethods (EmitContext ec, InternalParameters ip)
 		{
+			foreach (AnonymousMethod am in AnonymousMethods){
+				//
+				// The anonymous EmitContext two properties:
+				//    * ReturnType is null
+				//    * ILGenerator is null
+				//
+				EmitContext aec = new EmitContext (
+					ec.TypeContainer, ec.DeclSpace, ec.loc, null, null,
+					(ec.IsStatic ? Modifiers.STATIC : 0) |
+					(ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
+					(ec.InUnsafe ? Modifiers.UNSAFE : 0),
+					ec.IsConstructor);
+				
+				aec.InAnonymousMethod = true;
+
+				//
+				// TODO: Define parameters, currently "ip" is used, which is incomplete. 
+				//
+				aec.EmitTopBlock (am.Block, ip, am.Location);
+			}
 		}
+
 	}
 	
 	public class SwitchLabel {
Index: typemanager.cs
===================================================================
RCS file: /cvs/public/mcs/mcs/typemanager.cs,v
retrieving revision 1.268
diff -u -u -r1.268 typemanager.cs
--- typemanager.cs	27 Feb 2004 06:49:46 -0000	1.268
+++ typemanager.cs	10 Mar 2004 02:53:49 -0000
@@ -84,6 +84,7 @@
 	static public object obsolete_attribute_type;
 	static public object conditional_attribute_type;
 	static public Type in_attribute_type;
+	static public Type anonymous_method_type;
 
 	//
 	// An empty array of types
@@ -1113,6 +1114,11 @@
 		system_asynccallback_expr.Type = asynccallback_type;
 		system_iasyncresult_expr.Type = iasyncresult_type;
 		system_valuetype_expr.Type = value_type;
+
+		//
+		// These are only used for compare purposes
+		//
+		anonymous_method_type = typeof (AnonymousMethod);
 	}
 
 	//
