This import contains a verbatim copy of mcs at the time of this writing;
authorMiguel de Icaza <miguel@gnome.org>
Thu, 24 Jul 2003 16:28:24 +0000 (16:28 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Thu, 24 Jul 2003 16:28:24 +0000 (16:28 -0000)
This directory is only for the development of the generics version of MCS,
we will later fold all those changes into the main branch.  But wanted to
share the code with others in the meantime instead of keeping a separate
tree.

svn path=/trunk/mcs/; revision=16611

45 files changed:
mcs/gmcs/AssemblyInfo.cs [new file with mode: 0644]
mcs/gmcs/ChangeLog [new file with mode: 0755]
mcs/gmcs/Makefile [new file with mode: 0644]
mcs/gmcs/anonymous.cs [new file with mode: 0644]
mcs/gmcs/assign.cs [new file with mode: 0755]
mcs/gmcs/attribute.cs [new file with mode: 0644]
mcs/gmcs/cfold.cs [new file with mode: 0755]
mcs/gmcs/class.cs [new file with mode: 0755]
mcs/gmcs/codegen.cs [new file with mode: 0755]
mcs/gmcs/const.cs [new file with mode: 0755]
mcs/gmcs/constant.cs [new file with mode: 0755]
mcs/gmcs/convert.cs [new file with mode: 0644]
mcs/gmcs/cs-parser.jay [new file with mode: 0755]
mcs/gmcs/cs-tokenizer.cs [new file with mode: 0755]
mcs/gmcs/decl.cs [new file with mode: 0755]
mcs/gmcs/delegate.cs [new file with mode: 0644]
mcs/gmcs/driver.cs [new file with mode: 0755]
mcs/gmcs/ecore.cs [new file with mode: 0755]
mcs/gmcs/enum.cs [new file with mode: 0755]
mcs/gmcs/errors.cs [new file with mode: 0755]
mcs/gmcs/expression.cs [new file with mode: 0755]
mcs/gmcs/gen-il.cs [new file with mode: 0755]
mcs/gmcs/gen-treedump.cs [new file with mode: 0755]
mcs/gmcs/generic.cs [new file with mode: 0644]
mcs/gmcs/genericparser.cs [new file with mode: 0644]
mcs/gmcs/interface.cs [new file with mode: 0755]
mcs/gmcs/iterators.cs [new file with mode: 0644]
mcs/gmcs/literal.cs [new file with mode: 0755]
mcs/gmcs/location.cs [new file with mode: 0644]
mcs/gmcs/mcs.exe.config [new file with mode: 0644]
mcs/gmcs/modifiers.cs [new file with mode: 0755]
mcs/gmcs/namespace.cs [new file with mode: 0755]
mcs/gmcs/old-code.cs [new file with mode: 0755]
mcs/gmcs/parameter.cs [new file with mode: 0755]
mcs/gmcs/parameterCollection.cs [new file with mode: 0755]
mcs/gmcs/parser.cs [new file with mode: 0755]
mcs/gmcs/pending.cs [new file with mode: 0755]
mcs/gmcs/report.cs [new file with mode: 0644]
mcs/gmcs/rootcontext.cs [new file with mode: 0755]
mcs/gmcs/statement.cs [new file with mode: 0755]
mcs/gmcs/statementCollection.cs [new file with mode: 0755]
mcs/gmcs/support.cs [new file with mode: 0755]
mcs/gmcs/symbolwriter.cs [new file with mode: 0644]
mcs/gmcs/tree.cs [new file with mode: 0755]
mcs/gmcs/typemanager.cs [new file with mode: 0755]

diff --git a/mcs/gmcs/AssemblyInfo.cs b/mcs/gmcs/AssemblyInfo.cs
new file mode 100644 (file)
index 0000000..26e3ce2
--- /dev/null
@@ -0,0 +1,8 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyVersion("0.25.99")]
+[assembly: AssemblyTitle ("Mono C# Compiler")]
+[assembly: AssemblyDescription ("Mono C# Compiler")]
+[assembly: AssemblyCopyright ("2001, 2002, 2003 Ximian, Inc.")]
+[assembly: AssemblyCompany ("Ximian, Inc.")]
diff --git a/mcs/gmcs/ChangeLog b/mcs/gmcs/ChangeLog
new file mode 100755 (executable)
index 0000000..ec6d491
--- /dev/null
@@ -0,0 +1,12189 @@
+2003-07-22  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Invocation.OverloadResolve): Follow the spec more
+       closely: we eliminate methods in base types when we have an
+       applicable method in a top-level type.
+
+        Please see section 14.5.5.1 for an exact description of what goes
+       on. 
+
+       This fixes bug #45127 and a host of other related to corlib compilation.
+
+        * ecore.cs (MethodGroupExpr.DeclaringType): The element in the
+       array is the method corresponding to the top-level type (this is
+       because of the changes made to icall.c) so we change this
+       accordingly.
+
+       (MethodGroupExpr.Name): This too.
+
+       * typemanager.cs (GetElementType): New method which does the right
+       thing when compiling corlib. 
+
+       * everywhere: Make use of the above in the relevant places.
+
+2003-07-22  Martin Baulig  <martin@ximian.com>
+
+       * cs-parser.jay (invocation_expression): Moved
+       `OPEN_PARENS expression CLOSE_PARENS unary_expression' here from
+       `cast_expression', but create a InvocationOrCast which later
+       resolves to either an Invocation or a Cast.
+
+       * ecore.cs (ExpressionStatement.ResolveStatement): New virtual
+       method; call this before EmitStatement() to make sure that this
+       expression can be used as a statement.
+
+       * expression.cs (InvocationOrCast): New class; resolves to either
+       an Invocation or a Cast.
+
+       * statement.cs (StatementExpression): Call ResolveStatement() on
+       the ExpressionStatement before emitting it.
+
+2003-07-21  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (Invocation.VerifyArgumentsCompat): Check whether
+       `ref' and `out' attributes match; fixes #46220.
+       (MemberAccess.ResolveMemberAccess): You can't reference a type
+       through an expression; fixes #33180.
+       (Indexers.GetIndexersForType): Don't return the indexers from
+       interfaces the class implements; fixes #46502.
+
+2003-07-21  Martin Baulig  <martin@ximian.com>
+
+       * class.cs (TypeContainer.CheckPairedOperators): Added CS0660 and
+       CS0661 checks; fixes bug #30442.
+
+2003-07-21  Martin Baulig  <martin@ximian.com>
+
+       * decl.cs (AdditionResult): Added `Error'.
+
+       * enum.cs (AddEnumMember): Report a CS0076 if name is `value__'.
+
+       * typemanager.cs (TypeManager.ChangeType): Catch exceptions;
+       makes cs0031.cs actually work.
+
+2003-07-20  Martin Baulig  <martin@ximian.com>
+
+       * namespace.cs: Fixed that bug which caused a crash when compiling
+       the debugger's GUI.
+
+2003-07-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (LookupTypeReflection): Never expose types which
+       are NotPublic, NestedPrivate, NestedAssembly, or
+       NestedFamANDAssem.  We used to return these, and later do a check
+       that would report a meaningful error, but the problem is that we
+       would not get the real match, if there was a name override.
+
+2003-07-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * namespace.cs (Namespace, Name): Do not compute the namespace
+       name dynamically, compute it in the constructor.  This reduced
+       memory usage by 1697 KB.
+
+       * driver.cs: Use --pause to pause at the end.
+
+2003-07-17  Peter Williams  <peter@newton.cx>
+
+       * Makefile: Change the name of the test target so that it doesn't
+       conflict with the recursive test target.
+
+2003-07-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (LocalVariableReference.Emit, EmitAssign,
+       AddressOf): Do not use EmitThis, that was wrong, use the actual
+       this pointer.
+
+2003-07-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (MethodData.Define): While checking if a method is an
+       interface implementation, improve the test: If we are not public
+       (use new test here: use the computed MethodAttributes directly,
+       instead of the parsed modifier flags) check if the `implementing'
+       method comes from an interface or not.
+
+       * pending.cs (VerifyPendingMethods): Slightly better error
+       message.
+
+       * makefile: add test target that does the mcs bootstrap.
+
+2003-07-16  Ravi Pratap  <ravi@ximian.com>
+
+       * interface.cs (Define): Do nothing here since there are no
+       members to populate etc. Move the attribute emission out of here
+       since this was just totally the wrong place to put it. Attribute
+       application happens during the 'Emit' phase, not in the 'Define'
+       phase.
+
+       (Emit): Add this method and move the attribute emission here
+
+       * rootcontext.cs (EmitCode): Call the Emit method on interface
+       types too.
+
+2003-07-14  Ravi Pratap M  <ravi@ximian.com>
+
+       * expression.cs (OverloadResolve): Report error only if Location
+       is not 'Null' which means that there was a probe going on.
+
+2003-07-14  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (ConditionalLogicalOperator): New public class to
+       implement user defined conditional logical operators.
+       This is section 14.11.2 in the spec and bug #40505.
+
+2003-07-14  Martin Baulig  <martin@ximian.com>
+
+       * ecore.cs (FieldExpr.DoResolveLValue): Fixed bug #46198.
+
+2003-07-14  Martin Baulig  <martin@ximian.com>
+
+       * codegen.cs (EmitContext.InFixedInitializer): New public field.
+
+       * ecore.cs (IVariable.VerifyFixed): New interface method.
+
+       * expression.cs (Unary.ResolveOperator): When resolving the `&'
+       operator, check whether the variable is actually fixed.  Fixes bug
+       #36055.  Set a variable definitely assigned when taking its
+       address as required by the spec.
+
+       * statement.cs (LocalInfo.IsFixed): New field.
+       (LocalInfo.MakePinned): Set `IsFixed' to true.
+
+2003-07-14  Ravi Pratap M  <ravi@ximian.com>
+
+       * attribute.cs (Attribute.Resolve): While doing a Member lookup
+       for .ctors, ensure that we only ask for members declared in the
+       attribute type (BindingFlags.DeclaredOnly).
+
+       Fixes bug #43632.
+
+       * expression.cs (Error_WrongNumArguments): Report error 1501
+       correctly the way CSC does.
+
+2003-07-13  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (MemberAccess.ResolveAsTypeStep): Try to do a type
+       lookup on the fully qualified name, to make things like "X.X" work
+       where "X.X" is a fully qualified type name, but we also have a
+       namespace "X" in the using list.  Fixes #41975.
+
+2003-07-13  Martin Baulig  <martin@ximian.com>
+
+       * assign.cs (Assign.GetEmbeddedAssign): New protected virtual
+       function. If we're a CompoundAssign, we need to create an embedded
+       CompoundAssign, not an embedded Assign.
+       (Assign.DoResolve): Make this work for embedded CompoundAssign's.
+       Fixes #45854.
+
+2003-07-13  Martin Baulig  <martin@ximian.com>
+
+       * typemanager.cs (TypeManager.IsNestedChildOf): Make this actually
+       work to fix bug #46088.
+
+2003-07-13  Ravi Pratap <ravi@ximian.com>
+
+       * class.cs (Operator.Emit): Do not emit attributes here - it is
+       taken care of by the Method class that we delegate too. This takes
+       care of bug #45876.
+       
+2003-07-10  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (TypeOfVoid): New class.
+       (TypeOf): Report a CS0673 if it's System.Void.  Fixes #42264.
+
+2003-07-10  Martin Baulig  <martin@ximian.com>
+
+       * class.cs (MethodCore.DoDefineParameters): Added CS0225 check;
+       bug #35957.
+
+2003-07-10  Martin Baulig  <martin@ximian.com>
+
+       * rootcontext.cs (RootContext.NamespaceLookup): Take a DeclSpace,
+       not a NamespaceEntry, so we can use DeclSpace.CheckAccessLevel().
+
+       * decl.cs (DeclSpace.FindType): Use DeclSpace.CheckAccessLevel().
+
+       * typemanager.cs (TypeManager.IsAccessibleFrom): Removed.
+
+2003-07-10  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (ArrayCreation): Don't use a byte blob for arrays
+       of decimal.  Fixes #42850.
+
+       NOTE: I also fixed the created byte blob, but this doesn't work on
+       the MS runtime and csc never produces any byte blobs for decimal
+       arrays.
+
+2003-07-10  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (StructInfo.GetStructInfo): Catch deep cycles in
+       structs; fixes #32068.
+       (Block.AddChildVariableNames): Fixed #44302.
+
+2003-07-07  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * namespace.cs: fixed compilation with csc. It's bugzilla #44302.
+       
+2003-07-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs: And this test is onger needed.
+
+2003-07-08  Martin Baulig  <martin@ximian.com>
+
+       * rootcontext.cs (RootContext.NamespaceLookup): Ignore
+       inaccessible types.  Fixes #36313.
+
+       * decl.cs (DeclSpace.FindType): Ignore inaccessible types.
+
+       * namespace.cs (NamespaceEntry): Create implicit entries for all
+       namespaces; ie. if we have `namespace N1.N2.N3 { ... }', we create
+       implicit entries for N1.N2 and N1.
+
+2003-07-08  Martin Baulig  <martin@ximian.com>
+
+       Rewrote the handling of namespaces to fix a lot of the issues
+       wrt. `using' aliases etc.
+
+       * namespace.cs (Namespace): Splitted this class into a
+       per-assembly `Namespace' and a per-file `NamespaceEntry'.
+
+       * typemanager.cs (TypeManager.IsNamespace): Removed.
+       (TypeManager.ComputeNamespaces): Only compute namespaces from
+       loaded assemblies here, not the namespaces from the assembly we're
+       currently compiling.
+
+2003-07-08  Martin Baulig  <martin@ximian.com>
+
+       * rootcontext.cs, class.cs: Fixed the CS1530 reporting.
+
+2003-07-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs: Reverted patch from Gonzalo, my previous patch
+       already fixed it.  
+
+       I thought about the memory savings here, but LookupTypeReflection
+       is used under already very constrained scenarios.  Compiling
+       corlib or mcs only exposes one hit, so it would not really reduce
+       any memory consumption.
+
+2003-07-07  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * typemanager.cs: fixes bug #45889 by only adding public types from
+       other assemblies to the list of known types.
+
+2003-07-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs (Attribute.Resolve): Add call to CheckAccessLevel
+       on the type we resolved.
+
+2003-07-05  Martin Baulig  <martin@ximian.com>
+
+       * pending.cs (PendingImplementation.ParentImplements): Don't
+       create the proxy if the parent is abstract.
+
+       * class.cs (TypeContainer.DefineIndexers): Process explicit
+       interface implementations first.  Fixes #37714.
+
+2003-07-04  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (MemberAccess.ResolveMemberAccess): Events are
+       defined recursively;  but since we modify the input parameters
+       (left is set to `this' temporarily), we reset this value if the
+       left_is_explicit is false, which gives the original semantics to
+       the code.  
+
+       * literal.cs (NullPointer): new class used to represent a null
+       literal in a pointer context.
+
+       * convert.cs (Convert.ImplicitReferenceConversion): Is the target
+       type is a pointer, use a NullPointer object instead of a
+       NullLiteral.   Closes 43687
+
+       (ExplicitConversion): Convert pointer values using
+       the conv opcode to the proper type.
+
+       * ecore.cs (New): change ValueTypeVariable property into a method,
+       that returns whether the valuetype is suitable for being used.
+
+       * expression.cs (Binary.DoNumericPromotions): Only return if we
+       the int constant was a valid uint, and we can return both left and
+       right as uints.  If not, we continue processing, to trigger the
+       type conversion.  This fixes 39018.
+
+       * statement.cs (Block.EmitMeta): During constant resolution, set
+       the CurrentBlock property on the emitcontext, so that we resolve
+       constants propertly.
+
+2003-07-02  Martin Baulig  <martin@ximian.com>
+
+       * codegen.cs (EmitContext.NeedExplicitReturn): New public variable.
+       (EmitContext.EmitTopBlock): Emit an explicit return if it's set.
+
+       * statement.cs (Try.Resolve): Set ec.NeedExplicitReturn rather
+       than emitting it here.
+
+       * statement.cs: Fixed some more flow analysis bugs.
+
+2003-07-02  Martin Baulig  <martin@ximian.com>
+
+       * class.cs (MethodData.Define): When implementing interface
+       methods, set Final unless we're Virtual.
+
+       * decl.cs (MemberCore.CheckMethodAgainstBase): Make the CS0506
+       check work for interface methods.
+
+2003-07-01  Martin Baulig  <martin@ximian.com>
+
+       * ecore.cs (EmitContext.This): Replaced this property with a
+       GetThis() method which takes a Location argument.  This ensures
+       that we get the correct error location for a CS0188.
+
+2003-07-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs: (Convert.ConvertIntLiteral): Add test for
+       ImplicitStandardConversion.
+
+       * class.cs (TypeContainer.GetClassBases): Small bug fix for 45649.
+
+2003-07-01  Zoltan Varga  <vargaz@freemail.hu>
+
+       * expression.cs (ResolveOperator): Fix Concat (string, string, string)
+       optimization.
+
+2003-06-30  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Constructor.Define): Turn off initlocals for unsafe
+       constructors.
+
+       (MethodData.Define): Turn off initlocals for unsafe methods.
+
+2003-06-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * decl.cs (DeclSpace.CheckAccessLevel): Make this routine
+       complete;  Fixes #37521.
+
+       * delegate.cs: Use Modifiers.TypeAttr to compute the
+       TypeAttributes, instead of rolling our own.  This makes the flags
+       correct for the delegates.
+
+2003-06-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Constructor.Define): Set the private flag for static
+       constructors as well.
+
+       * cs-parser.jay (statement_expression): Set the return value to
+       null, to avoid a crash when we catch an error.
+
+2003-06-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Applied patch from Jackson that adds support for
+       extern and unsafe modifiers to destructor declarations.
+
+       * expression.cs: Report error 21 if the user is trying to index a
+       System.Array.
+
+       * driver.cs: Add an error message, suggested by the bug report.
+
+       * class.cs (TypeContainer.Emit): Only call EmitFieldInitializers
+       if we do not have a ": this ()" constructor initializer.  Fixes 45149
+
+2003-06-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * namespace.cs: Add some information to reduce FAQs.
+
+2003-06-13  Miguel de Icaza  <miguel@ximian.com>
+
+       * cfold.cs (BinaryFold): BitwiseAnd, BitwiseOr: handle other
+       underlying enumeration types.  Fixes #43915.
+
+       * expression.cs: Treat ushort/short as legal values to be used in
+       bitwise operations.
+
+Wed Jun 4 13:19:04 CEST 2003 Paolo Molaro <lupus@ximian.com>
+
+       * delegate.cs: transfer custom attributes for paramenters from
+       the delegate declaration to Invoke and BeginInvoke.
+
+Tue Jun 3 11:11:08 CEST 2003 Paolo Molaro <lupus@ximian.com>
+
+       * attribute.cs: handle custom marshalers and emit marshal info
+       for fields, too.
+
+2003-05-28  Hector E. Gomez Morales  <hgomez_36@flashmail.com>
+
+       * makefile.gnu: Added anonymous.cs to the compiler sources.
+
+2003-05-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * iterators.cs: Change the name of the proxy class to include two
+       underscores.
+
+       * cs-parser.jay: Update grammar to include anonymous methods.
+       
+       * anonymous.cs: new file.
+
+2003-05-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Field.Define): Add missing test for pointers and
+       safety. 
+
+2003-05-27  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (ArrayAccess.GetStoreOpCode): For System.IntPtr,
+       we use the stobj opcode.
+
+       (ArrayCreation.EmitDynamicInitializers): Revert Miguel's patch
+       since it wasn't the correct fix. 
+
+       It still is puzzling that we are required to use stobj for IntPtr
+       which seems to be a ValueType.
+
+2003-05-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (SimpleName.SimpleNameResolve): Consider using aliases
+       during regular simple name resolution.   Now, the trick is that
+       instead of returning for processing the simplename, we do a
+       TypeManager.LookupType (ie, a rooted lookup as opposed to a
+       contextual lookup type).   If a match is found, return that, if
+       not, return for further composition.
+
+       This fixes long-standing 30485.
+
+       * expression.cs (ArrayCreation.EmitDynamicInitializers): When
+       using the address to initialize an object, do an Stobj instead of
+       using the regular Stelem.
+
+       (IndexerAccess.Emit, IndexerAccess.EmitAssign):
+       Pass `is_base_indexer' to Invocation.EmitCall instead of false.
+       Because if we are a BaseIndexerAccess that value will be true.
+       Fixes 43643.
+
+       * statement.cs (GotoCase.Resolve): Return after reporting an
+       error, do not attempt to continue. 
+
+       * expression.cs (PointerArithmetic.Emit): If our operand is a
+       long, convert our constants to match the operand before
+       multiplying.  Convert to I type before adding.   Fixes 43670.
+       
+2003-05-14  Ravi Pratap  <ravi@ximian.com>
+
+       * enum.cs (ImplicitConversionExists) : Rename to
+       ImplicitEnumConversionExists to remove ambiguity. 
+
+       * ecore.cs (NullCast): New type of cast expression class which
+       basically is very similar to EmptyCast with the difference being
+       it still is a constant since it is used only to cast a null to
+       something else
+       (eg. (string) null)
+
+       * convert.cs (ImplicitReferenceConversion): When casting a null
+       literal, we return a NullCast.
+
+       * literal.cs (NullLiteralTyped): Remove - I don't see why this
+       should be around anymore.
+
+       The renaming (reported was slightly wrong). Corrections:
+
+       ConvertImplicitStandard -> ImplicitConversionStandard
+       ConvertExplicitStandard -> ExplicitConversionStandard
+
+       * expression.cs (StaticCallExpr.MakeSimpleCall): Resolve arguments
+       before passing them in !
+
+       * convert.cs (ImplicitConversionStandard): When comparing for
+       equal expr and target types, ensure that expr is not a
+       NullLiteral.
+
+       In general, we must not be checking (expr_type ==
+       target_type) in the top level conversion methods
+       (ImplicitConversion, ExplicitConversion etc). This checking is
+       done in the methods that they delegate to.
+
+2003-05-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * convert.cs: Move Error_CannotConvertType,
+       ImplicitReferenceConversion, ImplicitReferenceConversionExists,
+       ImplicitNumericConversion, ImplicitConversionExists,
+       ImplicitUserConversionExists, StandardConversionExists,
+       FindMostEncompassedType, FindMostSpecificSource,
+       FindMostSpecificTarget, ImplicitUserConversion,
+       ExplicitUserConversion, GetConversionOperators,
+       UserDefinedConversion, ConvertImplicit, ConvertImplicitStandard,
+       TryImplicitIntConversion, Error_CannotConvertImplicit,
+       ConvertImplicitRequired, ConvertNumericExplicit,
+       ExplicitReferenceConversionExists, ConvertReferenceExplicit,
+       ConvertExplicit, ConvertExplicitStandard from the ecore.cs into
+       its own file.
+
+       Perform the following renames:
+       
+       StandardConversionExists -> ImplicitStandardConversionExists
+       ConvertImplicit -> ImplicitConversion
+        ConvertImplicitStandard -> ImplicitStandardConversion
+        TryImplicitIntConversion -> ImplicitIntConversion
+        ConvertImplicitRequired -> ImplicitConversionRequired
+        ConvertNumericExplicit -> ExplicitNumericConversion
+        ConvertReferenceExplicit -> ExplicitReferenceConversion
+        ConvertExplicit -> ExplicitConversion
+        ConvertExplicitStandard -> ExplicitStandardConversion
+
+2003-05-19  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (TypeInfo.StructInfo): Made this type protected.
+       (TypeInfo): Added support for structs having structs as fields.
+
+       * ecore.cs (FieldExpr): Implement IVariable.
+       (FieldExpr.DoResolve): Call VariableInfo.GetSubStruct() to get the
+       VariableInfo for the field.
+
+2003-05-18  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (This.DoResolve): Report a CS0027 if we're
+       emitting a field initializer.
+
+2003-05-18  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (This.ResolveBase): New public function.
+       (This.DoResolve): Check for CS0188.
+
+       * codegen.cs (EmitContext.This): Just call This.ResolveBase(), not
+       This.Resolve().
+
+       * ecore.cs (MethodGroupExpr.DoResolve): Set the
+       `instance_expression' to null if we don't have any non-static
+       methods.
+
+2003-05-18  Martin Baulig  <martin@ximian.com>
+
+       Reworked the way how local variables and parameters are handled by
+       the flow analysis code.
+
+       * statement.cs (TypeInfo, VariableMap): New public classes.
+       (VariableInfo): New public class.  This is now responsible for
+       checking whether a variable has been assigned.  It is used for
+       parameters and local variables.
+       (Block.EmitMeta): Take the InternalParameters as argument; compute
+       the layout of the flow vectors here.
+       (Block.LocalMap, Block.ParameterMap): New public properties.
+       (FlowBranching): The .ctor doesn't get the InternalParameters
+       anymore since Block.EmitMeta() now computes the layout of the flow
+       vector.
+       (MyStructInfo): This class is now known as `StructInfo' and nested
+       in `TypeInfo'; we don't access this directly anymore.
+
+       * ecore.cs (IVariable): Added `VariableInfo VariableInfo'
+       property and removed IsAssigned(), IsFieldAssigned(),
+       SetAssigned() and SetFieldAssigned(); we now call them on the
+       VariableInfo so we don't need to duplicate this code everywhere.
+
+       * expression.cs (ParameterReference): Added `Block block' argument
+       to the .ctor.
+       (LocalVariableReference, ParameterReference, This): The new
+       VariableInfo class is now responsible for all the definite
+       assignment stuff.
+
+       * codegen.cs (EmitContext.IsVariableAssigned, SetVariableAssigned,
+       IsParameterAssigned, SetParameterAssigned): Removed.
+
+2003-05-18  Martin Baulig  <martin@ximian.com>
+
+       * typemanager.cs (InitCoreTypes): Try calling
+       SetCorlibTypeBuilders() with 4 args; if that fails, fall back to
+       the 3-args-version.  Corlib now also needs our `void_type'.
+       (GetMethod): Added overloaded version which takes an optional
+       `bool report_errors' to allow lookups of optional methods.
+
+2003-05-12  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (VariableInfo): Renamed to LocalInfo since it's
+       only used for locals and not for parameters.
+
+2003-05-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * support.cs (InternalParameters.ParameterType): Return the
+       ExternalType of the parameter.
+
+       * parameter.cs (Parameter.ExternalType): drop the two arguments,
+       they were unused.
+
+2003-05-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (MethodData.Define): Do not set the `newslot' on
+       interface members, if they are also flagged as "override".
+
+       * expression.cs (UnaryMutator.EmitCode): Simple workaround to emit
+       better code for ++i and i++.  This only works for static fields
+       and local variables.
+
+       * typemanager.cs (LookupDeclSpace): Add new method, sometimes we
+       want to pull the DeclSpace out of the builder_to_declspace instead
+       of the TypeBuilder (like in TypeContainer.FindMembers).
+
+       * class.cs (TypeContainer.FindMembers): Use LookupDeclSpace
+       instead of LookupTypeContainer.  Fixes the crash on .NET for
+       looking up interface members.
+
+       * const.cs: Create our own emit context during the Definition
+       stage, so that constants are evaluated in the proper context, when
+       a recursive definition happens.
+
+2003-05-11  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (Block.CreateSwitchBlock): New method.  Creates a
+       new block for a switch section.
+       (Block.AddLabel, Block.LookupLabel): If we're a switch section, do
+       the adding/lookup in the switch block.  Fixes #39828.
+
+2003-05-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (UnaryMutator.LoadOneAndEmitOp): Missing
+       functionality: I needed to convert the data after I had performed
+       the add/sub operation into the operands type size.
+
+       * ecore.cs (ImplicitReferenceConversion): When boxing an interface
+       pass the type for the box operation, otherwise the resulting
+       object would have been of type object.
+
+       (BoxedCast): Add constructor to specify the type to box as.
+
+2003-05-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * iterators.cs: I was reusing the `count' variable inadvertently,
+       take steps to not allow this to happen.
+
+2003-05-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs (Attribute.Resolve): Params attributes are encoded
+       by creating an array at the point where the params starts and
+       putting all those arguments there, then adjusting the size of the
+       array.
+
+2003-05-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (New.AddressOf): Implement interface
+       IMemoryLocation.  This is used when the `new' operator is used in
+       the context of an invocation to a method on a value type.
+
+       See http://bugzilla.ximian.com/show_bug.cgi?id=#42390 for an
+       example. 
+
+       * namespace.cs: Also check the using aliases here.
+
+       * driver.cs: Move the test for using validity after the types have
+       been entered, so we do a single pass that also includes the using
+       aliases. 
+
+       * statement.cs (Try.Resolve): Avoid crashing if there is a failure
+       in the regular case.   CreateSiblingForFinally is doing extra
+       error checking.
+
+       * attribute.cs (GetAttributeArgumentExpression): Store the result
+       on an out value, and use the return value to indicate failure
+       instead of using null (which is a valid return for Constant.GetValue).
+
+       * statement.cs: Perform the analysis flow for the increment
+       portion after the statement, because this will be the real flow of
+       execution.  Fixes #42385
+
+       * codegen.cs (EmitContext.EmitArgument,
+       EmitContext.EmitStoreArgument): New helper functions when the
+       RemapToProxy flag is set.
+
+       * expression.cs (ParameterReference.EmitLdarg): Expose this useful
+       function.
+
+       Add support for remapping parameters. 
+
+       * iterators.cs: Propagate parameter values;  Store parameter
+       values in the proxy classes.
+       
+2003-05-04  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (FieldExpr): Fix an obvious bug.  static fields do not
+       need a proxy reference;  I do not know what I was thinking
+
+       * cs-parser.jay (constructor_initializer): catch another error,
+       and display nice message.
+       
+       (field_declaration): catch void field declaration
+       to flag a better error. 
+
+       * class.cs (MemberBase.CheckBase): Report an error instead of a
+       warning if a new protected member is declared in a struct. 
+       (Field.Define): catch the error of readonly/volatile.
+
+       * ecore.cs (FieldExpr.EmitAssign): reuse the field lookup.
+
+       (FieldExpr.AddressOf): ditto.  Catch error where the address of a
+       volatile variable is taken
+
+2003-05-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Fixed.Resolve): Report an error if we are not in
+       an unsafe context.
+
+2003-05-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs: reuse the code that handles type clashes for
+       delegates and enumerations.
+
+       * class.cs (Report28): Always report.
+
+       * expression.cs (EncodeAsAttribute): Allow nulls here.
+
+2003-04-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs (Attribute.GetAttributeArgumentExpression): Moved
+       the functionality for testing whether an expression is valid for
+       an attribute here.  Also handle the case of arrays of elements
+       being stored. 
+
+       * expression.cs (ArrayCreation.EncodeAsAttribute): Add support for
+       encoding a linear array into an array of objects that are suitable
+       to be passed to an CustomAttributeBuilder.
+
+       * delegate.cs: Check unsafe types being used outside of an Unsafe context.
+
+       * ecore.cs: (FieldExpr): Handle field remapping here.
+
+       * iteratators.cs: Pass the instance variable (if the method is an
+       instance method) to the constructors, so we can access the field
+       variables on the class.
+
+       TODO: Test this with structs.  I think the THIS variable on
+       structs might have to be a pointer, and not a refenrece
+
+2003-04-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * codegen.cs (EmitContext.Mapvariable): Adds a mechanism to map
+       local variables to fields in a proxy class.
+
+       * iterators.cs (PopulateProxy): Rename our internal fields to
+       <XXX>.  
+       Create a <THIS> field if we are an instance method, so we can
+       reference our parent container variables.
+       (MapVariable): Called back from the EmitContext code to enter a
+       new variable to field mapping into the proxy class (we just create
+       a FieldBuilder).
+
+       * expression.cs
+       (LocalVariableReference.{Emit,EmitAssign,AddressOf}): Add support
+       for using the remapped locals to fields.
+
+       I placed the code here, because that gives the same semantics to
+       local variables, and only changes the Emit code.
+
+       * statement.cs (Fixed.Resolve): it is not allowed to have fixed
+       statements inside iterators.
+       (VariableInfo): Add a FieldBuilder for the cases when we are
+       remapping local variables to fields in a proxy class
+
+       * ecore.cs (SimpleNameResolve): Avoid testing two times for
+       current_block != null.
+
+       * statement.cs (Swithc.SimpleSwitchEmit): Removed code that did
+       not cope with strings, as it has been moved to the
+       TableSwitchEmit.  Fixed bug in switch generation.
+
+       * expression.cs (New.DoResolve): Provide more context for the user
+       when reporting an error.
+
+       * ecore.cs (Expression.LoadFromPtr): Use ldind_i when loading
+       pointers. 
+
+       * expression.cs (MemberAccess.DoResolve): When we get a type back,
+       check the permissions for it.  Note than in a type-resolution
+       context the check was already present in DeclSpace.ResolveType,
+       but was missing from the MemberAccess.
+
+       (ArrayCreation.CheckIndices): warn if the user has
+       more nested levels of expressions, but there are no more
+       dimensions specified.  Avoids crash on bug 41906.
+
+2003-04-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Block): replace Implicit bool, for a generic
+       flags.   
+       New flag: `Unchecked'.  This is used during the EmitMeta phase
+       (which is out-of-line with the regular Resolve/Emit process for a
+       statement, as this is done ahead of time, but still gets a chance
+       to call constant resolve).
+       
+       (Block.Flags): new enum for adding a new flag.
+
+       (Block.EmitMeta): track the state of unchecked.
+       
+       (Unchecked): Set the "UnChecked" flags on any blocks we enclose,
+       to enable constant resolution to work there as well.
+
+2003-04-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (ienumerable_type): Also look up
+       System.Collections.IEnumerable. 
+
+2003-04-21  Miguel de Icaza  <miguel@ximian.com>
+
+       TODO: Test more than one conditional per method.
+       
+       * class.cs (Indexer.Define): Report the location where the user is
+       referencing the unsupported feature.
+
+       (MethodData): Overload the use of `conditionals' to
+       minimize the creation of needless ArrayLists.   This saves roughly
+       212kb on my machine.
+
+       (Method): Implement the new IIteratorContainer interface.
+       (Method.SetYields): Implement the method by setting the ModFlags
+       to contain METHOD_YIELDS.
+       
+       * expression.cs (Unary.ResolveOperator): Use expr_type, not Expr,
+       which just got set to null.
+
+       * iterators.cs: New file.
+
+       (Yield, YieldBreak): New statements.
+
+       * statement.cs (Return.Resolve): Flag an error if we are used in
+       an iterator method.
+
+       * codegen.cs (InIterator): New flag set if the code is being
+       compiled in an iterator method.
+
+       * modifiers.cs: New flag METHOD_YIELDS.  This modifier is an
+       internal modifier, and we just use it to avoid adding extra
+       fields, as this is seldom used.  
+
+       * cs-parser.jay: Add yield_statement (yield and yield break).
+
+       * driver.cs: New flag -v2 to turn on version 2 features. 
+
+       * cs-tokenizer.cs (Tokenizer): Add yield and __yield to the
+       hashtable when v2 is enabled.
+
+2003-04-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (TypeManager.NamespaceClash): Use to check if
+       there is already a namespace defined with this name.
+
+       (TypeManager.InitCoreTypes): Remove the temporary workaround, as
+       people upgraded their corlibs.
+
+       (TypeManager.CoreLookupType): Use LookupTypeDirect, as we
+       always use fully qualified types, no need to use the compiler
+       front end.
+
+       (TypeManager.IsNamespace): Use binarysearch.
+       
+       * class.cs (AddClass, AddStruct, AddInterface, AddEvent,
+       AddDelegate): I did not quite use the new IsValid API properly: I
+       have to pass the short-name and the fullname.  I was passing only
+       the basename instead of the fullname sometimes. 
+
+       (TypeContainer.DefineType): call NamespaceClash.
+
+       * interface.cs (Interface.DefineType): use NamespaceClash before
+       defining the type.
+
+       * delegate.cs (Delegate.DefineType): use NamespaceClash before
+       defining the type.
+
+       * enum.cs: (Enum.DefineType): use NamespaceClash before
+       defining the type.
+
+       * typemanager.cs (: 3-line patch that gives us some tasty 11%
+       speed increase.  First, use the negative_hits cache when we get a
+       negative.  Second, add the type with its full original name
+       instead of the new . and + encoded name (reflection uses + to
+       separate type from a nested type).  Use LookupTypeReflection
+       directly which bypasses the type->name hashtable (that we already
+       know does not contain the type.
+       
+       * decl.cs (DeclSpace.ResolveTypeExpr): track the
+       location/container type. 
+
+       * driver.cs: When passing utf8, use directly the UTF8Encoding.
+
+2003-04-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * decl.cs (ResolveTypeExpr): Mirror check acess here too.
+
+       * delegate.cs (NewDelegate.Resolve): Test whether an instance
+       method is being referenced in the method group from a static
+       context, and report error 120 if so.
+
+       * expression.cs, ecore.cs (Error_UnexpectedKind): New name for
+       Error118. 
+
+       * typemanager.cs: Add intermediate namespaces (if a namespace A.B
+       is created, we create the A namespace).
+
+       * cs-parser.jay: A namespace also introduces a DeclarationFound.
+       Fixes #41591
+
+2003-04-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (GetReferenceType, GetPointerType): In .NET each
+       invocation to ModuleBuilder.GetType with the same values will
+       return a new type instance, so we need to cache its return
+       values. 
+
+       * expression.cs (Binary.ResolveOperator): Only allow the compare
+       operators on enums if they are of the same type.
+
+       * ecore.cs (Expression.ImplicitReferenceConversion): handle target
+       types of ValueType on their own case.  Before we were giving them
+       the same treatment as objects.
+
+       * decl.cs (DeclSpace.IsValid): IsValid takes the short name and
+       fullname.  Short name is used to compare against container name.
+       Fullname is used to check against defined namespace names.
+       
+       * class.cs (AddProperty, AddField, AddClass, AddStruct, AddEnum,
+       AddDelegate, AddEvent): Pass new parameter to DeclSpace.IsValid
+
+       (Method.CheckBase): Call parent.
+       (MemberBase.CheckBase): Check for protected members on sealed
+       classes.
+       (PropertyBase.CheckBase): Call parent.
+       (Field.Define): Call parent.
+
+       * report.cs: Negative error codes are now mapped to 8000 - code,
+       so that the display is render more nicely.
+
+       * typemanager.cs: Do not use try/catch, instead report a regular
+       error. 
+
+       (GetPointerType, GetReferenceType): These methods provide
+       mechanisms to obtain the T* and T& from a T.  We had the code
+       previously scattered around the code base, and it also used
+       TypeManager.LookupType that would go through plenty of caches.
+       This one goes directly to the type source.
+
+       In some places we did the Type.GetType followed by
+       ModuleBuilder.GetType, but not in others, so this unifies the
+       processing as well.
+
+       * namespace.cs (VerifyUsing): Perform a non-lazy approach to using
+       statements now that we have namespace information.
+
+       * typemanager.cs (IsNamespace): New method, returns whether the
+       string presented is a namespace or not.
+
+       (ComputeNamespaces): New public entry point, computes the list of
+       available namespaces, using the GetNamespaces API call in Mono, or
+       the slower version in MS.NET.   
+
+       Now before we start the semantic analysis phase, we have a
+       complete list of namespaces including everything that the user has
+       provided.
+
+       Deleted old code to cache namespaces in .nsc files.
+
+2003-04-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs: (TypeContainer.DefineDefaultConstructor): Use the
+       class/struct location definition Location for the implicit
+       constructor location.
+
+       (Operator.Define): Use the location of the operator for the
+       implicit Method definition.
+
+       (Constructor.Emit): use the constructor location for the implicit
+       base initializer constructor.
+
+       * ecore.cs: Remove ITypeExpression.  This interface is now gone,
+       and the Expression class now contains two new methods:
+
+       ResolveAsTypeStep and ResolveAsTypeTerminal.  This is used to
+       isolate type lookup from the rest of the resolution process.
+
+       Since we use Expressions to hold type definitions due to the way
+       we parse the input we have historically overloaded Resolve to
+       perform the Type lookups if a special flag is passed.  Now this is
+       eliminated and two methods take their place. 
+       
+       The differences in the two methods between xStep and xTerminal is
+       that xStep is involved in our current lookup system that uses
+       SimpleNames to compose a name, while xTerminal is used just to
+       catch the case where the simplename lookup failed.
+       
+2003-04-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ResolveMemberAccess): Remove redundant code.
+       TypeExpr expressions are always born fully resolved.
+
+       * interface.cs (PopulateMethod): Do not lookup the types twice.
+       We were doing it once during SemanticAnalysis and once during
+       PopulateMethod.
+
+       * cs-parser.jay: Due to our hack in the grammar, things like A.B[]
+       in local variable type definitions, were being returned as a
+       SimpleName (we decomposed everything into a string), that is
+       because primary_expression was being used instead of a type in the
+       grammar (reduce/reduce conflicts).
+
+       The part that was wrong is that we converted the expression into a
+       string (an oversimplification in one hand, compounded with primary
+       expressions doing string concatenation).
+
+       So things like:
+
+       A.B.C [] x;
+
+       Would return "A.B.C[]" as a SimpleName.  This stopped things like
+       using clauses from working on this particular context.  And a type
+       was being matched directly against "A.B.C[]".
+
+       We now use the correct approach, and allow for ComposedCast to be
+       part of the unary expression.  So the "A.B.C []" become a composed
+       cast of "A.B.C" (as a nested group of MemberAccess with a
+       SimpleName at the end) plus the rank composition "[]". 
+
+       Also fixes 35567
+       
+2003-04-10  Miguel de Icaza  <miguel@ximian.com>
+
+       * decl.cs (CheckAccessLevel): Implement the NestedPrivate rules
+       for the access level checking.
+
+       * class.cs: Cosmetic changes.  Renamed `TypeContainer parent' to
+       `TypeContainer container', because I kept getting confused when I
+       was debugging this code.
+
+       * expression.cs (Indexers): Instead of tracking getters/setters,
+       we now track them in parallel.  We create one arraylist less, but
+       most importantly it is possible now for the LValue code to find a
+       matching get for a set.
+
+       (IndexerAccess.DoResolveLValue): Update the code.
+       GetIndexersForType has been modified already to extract all the
+       indexers from a type.  The code assumed it did not.
+
+       Also make the code set the correct return type for the indexer.
+       This was fixed a long time ago for properties, but was missing for
+       indexers.  It used to be void_type.
+
+       (Binary.Emit): Test first for doubles instead of
+       floats, as they are more common.
+
+       (Binary.EmitBranchable): Use the .un version of the branch opcodes
+       when dealing with floats and the <=, >= operators.  This fixes bug
+       #39314 
+
+       * statement.cs (Foreach.EmitArrayForeach): bug fix: The code used
+       to load the array value by emitting a load on the foreach variable
+       type.  This was incorrect.  
+
+       We now emit the code to load an element using the the array
+       variable type, and then we emit the conversion operator.
+
+       Fixed #40176
+
+2003-04-10  Zoltan Varga  <vargaz@freemail.hu>
+
+       * attribute.cs: Avoid allocation of ArrayLists in the common case.
+
+2003-04-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (MethodSignature.InheritableMemberSignatureCompare):
+       test for protection before we test for signatures. 
+
+       (MethodSignature.ToString): implement.
+
+       * expression.cs (Unary.TryReduceNegative): Add missing minus sign
+       to the case where we reduced into a LongConstant.
+
+       * decl.cs (CheckAccessLevel): If the type is an array, we can not
+       depend on whether the information is acurrate, because the
+       Microsoft runtime will always claim that the array type is public,
+       regardless of the real state.
+
+       If the type is a pointer, another problem happens: the type is
+       reported as non-public in Microsoft.  
+
+       In both cases we have to call CheckAccessLevel recursively with
+       the underlying type as the argument to be tested.
+
+2003-04-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * assign.cs (Assign.Emit): If we are dealing with a compound
+       assignment expression, we should use the code path that stores the
+       intermediate result in a temporary value.  This fixes #40903.
+
+       *expression.cs (Indirection.ToString): Provide ToString method for
+       debugging. 
+       
+2003-04-08  Zoltan Varga  <vargaz@freemail.hu>
+
+        * class.cs: Null out fields holding references to Block objects so
+        they can be garbage collected.
+
+        * expression.cs (OverloadResolve): Remove unused local.
+
+2003-04-07  Martin Baulig  <martin@ximian.com>
+
+       * codegen.cs (EmitContext.CurrentFile): New public field.
+       (EmitContext.Mark): Use the CurrentFile to check whether the
+       location is in the correct file.
+       (EmitContext.EmitTopBlock): Initialize CurrentFile here.
+
+2003-04-07  Martin Baulig  <martin@ximian.com>
+
+       * ecore.cs (Expression.ResolveBoolean): Don't call ec.Mark().
+
+       * codegen.cs (EmitContext.EmitTopBlock): Don't call Mark() on the
+       location.  [FIXME: The location argument which gets passed to this
+       method is sometimes wrong!]
+
+2003-04-07  Nick Drochak <ndrochak@gol.com>
+
+       * codegen.cs: Be more verbose when we can't find the symbol writer dll.
+
+2003-04-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Indirection.EmitAssign): We were using the
+       temporary, but returning immediately instead of continuing the
+       EmitAssing flow.
+
+2003-04-06  Martin Baulig  <martin@ximian.com>
+
+       * ecore.cs (SimpleName.SimpleNameResolve): Don't report an error
+       if it's a nested child, but also deriving from the outer class.
+       See test 190.cs.
+
+       * typemanager.cs (IsNestedChildOf): Make this work if it's a
+       nested child, but also deriving from the outer class.  See
+       test-190.cs.
+       (FilterWithClosure): We may access private members of the outer
+       class if we're a nested child and deriving from the outer class.
+       (RealMemberLookup): Only set `closure_private_ok' if the
+       `original_bf' contained BindingFlags.NonPublic.
+
+2003-04-05  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (FlowBranching.UsageVector.MergeChildren): Fix bug #40670.
+
+2003-04-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Event.Define): Do not allow abstract events to have
+       initializers. 
+
+2003-04-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Add error productions for ADD/REMOVE missing a
+       block in event declarations.
+
+       * ecore.cs (FieldExpr.AddressOf): If our instance expression is a
+       value type, get its address.
+
+       * expression.cs (Is.Emit): For action `LeaveOnStack' we were
+       leaving a class on the stack instead of a boolean value (int
+       0/1).  Change the code so we compare against null, and then the
+       result against zero.
+
+       * class.cs (TypeContainer.GetClassBases): We were checking for the
+       parent class being sealed too late.
+
+       * expression.cs (Binary.Emit): For <= and >= when dealing with
+       floating point values, use cgt.un and clt.un instead of cgt and
+       clt alone.
+
+2003-04-01  Zoltan Varga  <vargaz@freemail.hu>
+
+       * statement.cs: Apply the same optimization as MS: skip the 
+       GetEnumerator returning an IEnumerator, and use the one returning a 
+       CharEnumerator instead. This allows us to avoid the try-finally block 
+       and the boxing.
+
+2003-03-31  Gaurav Vaish <gvaish_mono@lycos.com>
+
+       * cs-parser.jay: Attributes cannot be applied to
+                        namespaces. Fixes #40473
+
+2003-03-31  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * class.cs:
+       (Add*): check if the name is valid using the full name for constants,
+       fields, properties and events.
+
+2003-03-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * enum.cs (Enum.DefineType, Enum.IsValidEnumConstant): Also allow
+       char constants to be part of the enumeration.
+
+       * expression.cs (Conditional.DoResolve): Add support for operator
+       true. Implements the missing functionality from 14.12
+
+       * class.cs (TypeContainer.CheckPairedOperators): Report error for missmatch on
+       operator true/false as required by the spec.
+
+       * expression.cs (Unary.ResolveOperator): In LogicalNot, do an
+       implicit conversion to boolean.
+
+       * statement.cs (Statement.ResolveBoolean): A boolean expression is
+       also one where the type implements `operator true'. 
+
+       * ecore.cs (Expression.GetOperatorTrue): New helper routine to
+       get an expression that will invoke operator true based on an
+       expression.  
+
+       (GetConversionOperators): Removed the hack that called op_True
+       here.  
+
+       (Expression.ResolveBoolean): Move this from Statement.
+
+2003-03-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (FieldExpr): do not allow initialization of initonly
+       fields on derived classes
+
+2003-03-13  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (Block.Emit): Call ig.BeginScope() and
+       ig.EndScope() when compiling with debugging info; call
+       LocalBuilder.SetLocalSymInfo _after_ opening the scope.
+
+2003-03-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Indexers): Do not construct immediately, allow
+       for new members to be appended as we go.  Fixes 38143
+
+2003-03-07  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * expression.cs: save/restore context when resolving an unchecked
+       expression.
+
+2003-03-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * cfold.cs: Catch division by zero in modulus operator during
+       constant folding.
+
+2003-03-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * interface.cs (Interface.DefineMembers): Avoid defining members
+       twice. 
+
+2003-02-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: handle the +/- options for -noconfig
+
+       * statement.cs (Unckeched.Resolve): Also track the state of
+       unchecked in the Resolve phase.
+
+2003-02-27  Martin Baulig  <martin@ximian.com>
+
+       * ecore.cs (Expression.MemberLookup): Don't create a
+       MethodGroupExpr for something which is not a method.  Fixes #38291.
+
+2003-02-25  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (MemberBase.CheckParameters): Also check that the type
+       is unmanaged if it is a pointer.
+
+       * expression.cs (SizeOf.Resolve): Add location information.
+
+       * statement.cs (Block.EmitMeta): Flag error (208) if a pointer to
+       a managed type is declared.
+
+       * expression.cs (Invocation.VerifyArgumentsCompat): Check for the
+       parameter modifiers as well.  Fixes bug 38606
+
+       * class.cs: Very sad.  Am backing out the speed up changes
+       introduced by the ArrayList -> Array in the TypeContainer, as they
+       were not actually that much faster, and introduced a bug (no error
+       reports on duplicated methods).
+
+       * assign.cs (CompoundAssign.DoLResolve): Resolve the original
+       source first, this will guarantee that we have a valid expression
+       before calling in lower levels functions that will require a
+       resolved object.  Then use this original_source in the
+       target.ResolveLValue instead of the original source that was
+       passed to us.
+
+       Another change.  Use target.Resolve instead of LValueResolve.
+       Although we are resolving for LValues, we will let the Assign code
+       take care of that (it will be called again from Resolve).  This
+       basically allows code like this:
+
+       class X { X operator + (X x, object o) {} X this [int idx] { get; set; } }
+       class Y { void A (X x) { x [0] += o; }
+
+       The problem was that the indexer was trying to resolve for
+       set_Item (idx, object o) and never finding one.  The real set_Item
+       was set_Item (idx, X).  By delaying the process we get the right
+       semantics. 
+
+       Fixes bug 36505
+       
+2003-02-23  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (Block.Emit): Override this and set ec.CurrentBlock
+       while calling DoEmit ().
+
+       * codegen.cs (EmitContext.Mark): Don't mark locations in other
+       source files; if you use the #line directive inside a method, the
+       compiler stops emitting line numbers for the debugger until it
+       reaches the end of the method or another #line directive which
+       restores the original file.
+
+2003-02-23  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (FlowBranching.UsageVector.MergeChildren): Fix bug #37708.
+
+2003-02-23  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (Block.AddChildVariableNames): We need to call this
+       recursively, not just for our immediate children.
+
+2003-02-23  Martin Baulig  <martin@ximian.com>
+
+       * class.cs (Event.Define): Always make the field private, like csc does.
+
+       * typemanager.cs (TypeManager.RealMemberLookup): Make events
+       actually work, fixes bug #37521.
+
+2003-02-23  Miguel de Icaza  <miguel@ximian.com>
+
+       * delegate.cs: When creating the various temporary "Parameters"
+       classes, make sure that we call the ComputeAndDefineParameterTypes
+       on those new parameters (just like we do with the formal ones), to
+       allow them to be resolved in the context of the DeclSpace.
+
+       This fixes the bug that Dick observed in Bugzilla #38530.
+
+2003-02-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ResolveMemberAccess): When resolving a constant,
+       do not attempt to pull a constant if the value was not able to
+       generate a valid constant.
+
+       * const.cs (LookupConstantValue): Do not report more errors than required.
+
+2003-02-19  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * expression.cs: fixes bug #38328.
+
+2003-02-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs: Changed all the various members that can be part of a
+       class from being an ArrayList to be an Array of the right type.
+       During the DefineType type_list, interface_list, delegate_list and
+       enum_list are turned into types, interfaces, delegates and enums
+       arrays.  
+
+       And during the member population, indexer_list, event_list,
+       constant_list, field_list, instance_constructor_list, method_list,
+       operator_list and property_list are turned into their real arrays.
+
+       Although we could probably perform this operation earlier, for
+       good error reporting we need to keep the lists and remove the
+       lists for longer than required.
+
+       This optimization was triggered by Paolo profiling the compiler
+       speed on the output of `gen-sample-program.pl' perl script. 
+
+       * decl.cs (DeclSpace.ResolveType): Set the ContainerType, so we do
+       not crash in methods like MemberLookupFailed that use this field.  
+
+       This problem arises when the compiler fails to resolve a type
+       during interface type definition for example.
+
+2003-02-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Indexers.GetIndexersForType): Interfaces do not
+       inherit from System.Object, so we have to stop at null, not only
+       when reaching System.Object.
+
+2003-02-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: (Indexers.GetIndexersForType): Martin's fix used
+       DeclaredOnly because the parent indexer might have had a different
+       name, but did not loop until the top of the hierarchy was reached.
+
+       The problem this one fixes is 35492: when a class implemented an
+       indexer from an interface, we were getting the interface method
+       (which was abstract) and we were flagging an error (can not invoke
+       abstract method).
+
+       This also keeps bug 33089 functioning, and test-148 functioning.
+
+       * typemanager.cs (IsSpecialMethod): The correct way of figuring
+       out if a method is special is to see if it is declared in a
+       property or event, or whether it is one of the predefined operator
+       names.   This should fix correctly #36804.
+
+2003-02-15  Miguel de Icaza  <miguel@ximian.com>
+
+       The goal here is to remove the dependency on EmptyCast.Peel ().
+       Killing it completely.
+       
+       The problem is that currently in a number of places where
+       constants are expected, we have to "probe" for an EmptyCast, and
+       Peel, which is not the correct thing to do, as this will be
+       repetitive and will likely lead to errors. 
+
+       The idea is to remove any EmptyCasts that are used in casts that
+       can be reduced to constants, so we only have to cope with
+       constants. 
+
+       This bug hunt was triggered by Bug 37363 and the desire to remove
+       the duplicate pattern where we were "peeling" emptycasts to check
+       whether they were constants.  Now constants will always be
+       constants.
+       
+       * ecore.cs: Use an enumconstant here instead of wrapping with
+       EmptyCast.  
+
+       * expression.cs (Cast.TryReduce): Ah, the tricky EnumConstant was
+       throwing me off.  By handling this we can get rid of a few hacks.
+       
+       * statement.cs (Switch): Removed Peel() code.
+
+2003-02-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs: Location information for error 508
+
+       * expression.cs (New.DoResolve): Add a guard against double
+       resolution of an expression.  
+
+       The New DoResolve might be called twice when initializing field
+       expressions (see EmitFieldInitializers, the call to
+       GetInitializerExpression will perform a resolve on the expression,
+       and later the assign will trigger another resolution
+
+       This leads to bugs (#37014)
+
+       * delegate.cs: The signature for EndInvoke should contain any ref
+       or out parameters as well.  We were not doing this in the past. 
+
+       * class.cs (Field.Define): Do not overwrite the type definition
+       inside the `volatile' group.  Turns out that volatile enumerations
+       were changing the type here to perform a validity test, which
+       broke conversions. 
+
+2003-02-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (FieldExpr.AddressOf): In the particular case of This
+       and structs, we do not want to load the instance variable
+
+       (ImplicitReferenceConversion, ImplicitReferenceConversionExists):
+       enum_type has to be handled like an object reference (implicit
+       conversions exists from this to object), but the regular IsClass
+       and IsValueType tests will never return true for this one.
+
+       Also we use TypeManager.IsValueType instead of type.IsValueType,
+       just for consistency with the rest of the code (this is only
+       needed if we ever use the construct exposed by test-180.cs inside
+       corlib, which we dont today).
+
+2003-02-12  Zoltan Varga  <vargaz@freemail.hu>
+
+       * attribute.cs (ApplyAttributes): apply all MethodImplAttributes, not
+       just InternalCall.
+
+2003-02-09  Martin Baulig  <martin@ximian.com>
+
+       * namespace.cs (Namespace..ctor): Added SourceFile argument.
+       (Namespace.DefineNamespaces): New static public method; this is
+       called when we're compiling with debugging to add all namespaces
+       to the symbol file.
+
+       * tree.cs (Tree.RecordNamespace): Added SourceFile argument and
+       pass it to the Namespace's .ctor.
+
+       * symbolwriter.cs (SymbolWriter.OpenMethod): Added TypeContainer
+       and MethodBase arguments; pass the namespace ID to the symwriter;
+       pass the MethodBase instead of the token to the symwriter.
+       (SymbolWriter.DefineNamespace): New method to add a namespace to
+       the symbol file.
+
+2003-02-09  Martin Baulig  <martin@ximian.com>
+
+       * symbolwriter.cs: New file.  This is a wrapper around
+       ISymbolWriter with a cleaner API.  We'll dynamically Invoke()
+       methods here in near future.
+
+2003-02-09  Martin Baulig  <martin@ximian.com>
+
+       * codegen.cs (EmitContext.Mark): Just pass the arguments to
+       ILGenerator.MarkSequencePoint() which are actually used by the
+       symbol writer.
+
+2003-02-09  Martin Baulig  <martin@ximian.com>
+
+       * location.cs (SourceFile): New public sealed class.  This
+       contains the name and an index which is used in the location's token.
+       (Location): Reserve an appropriate number of bits in the token for
+       the source file instead of walking over that list, this gives us a
+       really huge performance improvement when compiling with debugging.
+
+       * driver.cs (Driver.parse, Driver.tokenize_file): Take a
+       `SourceFile' argument instead of a string.
+       (Driver.ProcessFile): Add all the files via Location.AddFile(),
+       but don't parse/tokenize here, we need to generate the list of all
+       source files before we do that.
+       (Driver.ProcessFiles): New static function.  Parses/tokenizes all
+       the files.
+
+       * cs-parser.jay (CSharpParser): Take a `SourceFile' argument
+       instead of a string.
+
+       * cs-tokenizer.cs (Tokenizer): Take `SourceFile' argument instead
+       of a string.
+
+2003-02-09  Martin Baulig  <martin@ximian.com>
+
+       * cs-tokenizer.cs (Tokenizer.PreProcessLine): Also reset the
+       filename on `#line default'.
+
+Sat Feb 8 17:03:16 CET 2003 Paolo Molaro <lupus@ximian.com>
+
+       * statement.cs: don't clear the pinned var when the fixed statement
+       returns from the method (fixes bug#37752).
+
+Sat Feb 8 12:58:06 CET 2003 Paolo Molaro <lupus@ximian.com>
+
+       * typemanager.cs: fix from mathpup@mylinuxisp.com (Marcus Urban) 
+       to IsValueType.
+
+2003-02-07  Martin Baulig  <martin@ximian.com>
+
+       * driver.cs: Removed the `--debug-args' command line argument.
+
+       * codegen.cs (CodeGen.SaveSymbols): Removed, this is now done
+       automatically by the AsssemblyBuilder.
+       (CodeGen.InitializeSymbolWriter): We don't need to call any
+       initialization function on the symbol writer anymore.  This method
+       doesn't take any arguments.
+
+2003-02-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: (AddAssemblyAndDeps, LoadAssembly): Enter the types
+       from referenced assemblies as well.
+
+2003-02-02  Martin Baulig  <martin@ximian.com>
+
+       * class.cs (MethodData.Emit): Generate debugging info for external methods.
+
+2003-02-02  Martin Baulig  <martin@ximian.com>
+
+       * class.cs (Constructor.Emit): Open the symbol writer before
+       emitting the constructor initializer.
+       (ConstructorInitializer.Emit): Call ec.Mark() to allow
+       single-stepping through constructor initializers.
+
+2003-01-30  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs: Handle error 549: do not allow virtual methods in
+       sealed classes. 
+
+2003-02-01 Jackson Harper <jackson@latitudegeo.com>
+
+       * decl.cs: Check access levels when resolving types
+       
+2003-01-31 Jackson Harper <jackson@latitudegeo.com>
+
+       * statement.cs: Add parameters and locals set in catch blocks that might 
+       return to set vector
+
+2003-01-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Operator): Set the SpecialName flags for operators.
+       
+       * expression.cs (Invocation.DoResolve): Only block calls to
+       accessors and operators on SpecialName methods.
+
+       (Cast.TryReduce): Handle conversions from char constants.
+
+
+Tue Jan 28 17:30:57 CET 2003 Paolo Molaro <lupus@ximian.com>
+
+       * statement.cs: small memory and time optimization in FlowBranching.
+       
+2003-01-28  Pedro Mart  <yoros@wanadoo.es>
+
+        * expression.cs (IndexerAccess.DoResolveLValue): Resolve the same
+        problem that the last fix but in the other sid (Set).
+
+        * expression.cs (IndexerAccess.DoResolve): Fix a problem with a null
+        access when there is no indexer in the hierarchy.
+       
+2003-01-27 Jackson Harper <jackson@latitudegeo.com>
+
+       * class.cs: Combine some if statements.
+
+2003-01-27  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * driver.cs: fixed bug #37187.
+
+2003-01-27  Pedro Martinez Juliá  <yoros@wanadoo.es>
+
+       * expression.cs (IndexerAccess.DoResolve): Before trying to resolve
+       any indexer, it's needed to build a list with all the indexers in the
+       hierarchy (AllGetters), else we have problems. Fixes #35653.
+
+2003-01-23  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (MethodData.Define): It is wrong for an interface
+       implementation to be static in both cases: explicit and implicit.
+       We were only handling this in one case.
+
+       Improve the if situation there to not have negations.
+       
+       * class.cs (Field.Define): Turns out that we do not need to check
+       the unsafe bit on field definition, only on usage.  Remove the test.
+
+2003-01-22  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * driver.cs: use assembly.Location instead of Codebase (the latest
+       patch made mcs fail when using MS assemblies).
+
+2003-01-21  Tim Haynes <thaynes@openlinksw.com>
+
+       * driver.cs: use DirectorySeparatorChar instead of a hardcoded "/" to
+       get the path to *corlib.dll.
+
+2003-01-21  Nick Drochak <ndrochak@gol.com>
+
+       * cs-tokenizer.cs:
+       * pending.cs:
+       * typemanager.cs: Remove compiler warnings
+
+2003-01-20  Duncan Mak  <duncan@ximian.com>
+
+       * AssemblyInfo.cs: Bump the version number to 0.19.
+       
+2003-01-20  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * cs-tokenizer.cs: little fixes to line numbering when #line is used.
+
+2003-01-18  Zoltan Varga  <vargaz@freemail.hu>
+
+       * class.cs (Constructor::Emit): Emit debugging info for constructors.
+
+2003-01-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Small fix: we were not comparing the constructor
+       name correctly.   Thanks to Zoltan for the initial pointer.
+
+2003-01-16 Jackson Harper <jackson@latitudegeo.com>
+
+       * cs-tokenizer.cs: Set file name when specified with #line
+
+2003-01-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Only perform the constructor checks here if we
+       are named like the class;  This will help provider a better
+       error.  The constructor path is taken when a type definition is
+       not found, but most likely the user forgot to add the type, so
+       report that rather than the constructor error.
+
+Tue Jan 14 10:36:49 CET 2003 Paolo Molaro <lupus@ximian.com>
+
+       * class.cs, rootcontext.cs: small changes to avoid unnecessary memory
+       allocations.
+
+2003-01-13 Jackson Harper <jackson@latitudegeo.com>
+
+       * cs-parser.jay: Add cleanup call.
+
+2003-01-13  Duncan Mak  <duncan@ximian.com>
+
+       * cs-tokenizer.cs (Cleanup): Rename to 'cleanup' to make it more
+       consistent with other methods.
+
+2003-01-13 Jackson Harper <jackson@latitudegeo.com>
+
+       * cs-tokenizer.cs: Add Cleanup method, also fix #region error messages.
+       
+Sun Jan 12 19:58:42 CET 2003 Paolo Molaro <lupus@ximian.com>
+
+       * attribute.cs: only set GuidAttr to true when we have a
+       GuidAttribute.
+
+2003-01-09  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * ecore.cs:
+       * expression.cs:
+       * typemanager.cs: fixes to allow mcs compile corlib with the new
+       Type.IsSubclassOf fix.
+
+2003-01-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (LocalVariableReference.DoResolve): Classify a
+       constant as a value, not as a variable.   Also, set the type for
+       the variable.
+
+       * cs-parser.jay (fixed_statement): take a type instead of a
+       pointer_type, so we can produce a better error message later.
+       
+       * statement.cs (Fixed.Resolve): Flag types that are not pointers
+       as an error.  
+       
+       (For.DoEmit): Make inifinite loops have a
+       non-conditional branch back.
+
+       (Fixed.DoEmit): First populate the pinned variables, then emit the
+       statement, then clear the variables.  Before I was emitting the
+       code once for each fixed piece.
+
+
+2003-01-08  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (FlowBranching.MergeChild): A break in a
+       SWITCH_SECTION does not leave a loop.  Fixes #36155.
+
+2003-01-08  Martin Baulig  <martin@ximian.com>
+
+       * statement.cs (FlowBranching.CheckOutParameters): `struct_params'
+       lives in the same number space than `param_map'.  Fixes #36154.
+
+2003-01-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay (constructor_declaration): Set the
+       Constructor.ModFlags before probing for it.  This makes the
+       compiler report 514, 515 and 132 (the code was there, but got
+       broken). 
+
+       * statement.cs (Goto.Resolve): Set `Returns' to ALWAYS.
+       (GotoDefault.Resolve): Set `Returns' to ALWAYS.
+       (GotoCase.Resolve): Set `Returns' to ALWAYS.
+
+Tue Jan 7 18:32:24 CET 2003 Paolo Molaro <lupus@ximian.com>
+
+       * enum.cs: create the enum static fields using the enum type.
+
+Tue Jan 7 18:23:44 CET 2003 Paolo Molaro <lupus@ximian.com>
+
+       * class.cs: don't try to create the ParamBuilder for the return
+       type if it's not needed (and handle it breaking for the ms runtime
+       anyway).
+
+2003-01-06 Jackson Harper <jackson@latitudegeo.com>
+
+       * cs-tokenizer.cs: Add REGION flag to #region directives, and add checks to make sure that regions are being poped correctly
+
+2002-12-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs (get_cmd_arg): Fixups to allow \r to terminate
+       the command.   This showed up while compiling the JANET source
+       code, which used \r as its only newline separator.
+
+2002-12-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Method.Define): If we are an operator (because it
+       reuses our code), then set the SpecialName and HideBySig.  #36128
+
+2002-12-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (FieldExpr.DoResolve): Instead of throwing an
+       exception, report error 120 `object reference required'.
+
+       * driver.cs: Add --pause option, used during to measure the size
+       of the process as it goes with --timestamp.
+
+       * expression.cs (Invocation.DoResolve): Do not allow methods with
+       SpecialName to be invoked.
+
+2002-12-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs: Small fix to the parser: compute the ascii
+       number before adding it.
+
+2002-12-21  Ravi Pratap  <ravi@ximian.com>
+
+       * ecore.cs (StandardImplicitConversion): When in an unsafe
+       context, we allow conversion between void * to any other pointer
+       type. This fixes bug #35973.
+
+2002-12-20 Jackson Harper <jackson@latitudegeo.com>
+
+       * codegen.cs: Use Path.GetFileNameWithoutExtension so an exception
+       is not thrown when extensionless outputs are used 
+
+2002-12-20  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * rootcontext.cs: fixed compilation of corlib.
+
+2002-12-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs (Attributes.Contains): Add new method.
+
+       * class.cs (MethodCore.LabelParameters): if the parameter is an
+       `out' parameter, check that no attribute `[In]' has been passed.
+
+       * enum.cs: Handle the `value__' name in an enumeration.
+
+2002-12-14  Jaroslaw Kowalski <jarek@atm.com.pl>
+
+       * decl.cs: Added special case to allow overrides on "protected
+       internal" methods
+       
+2002-12-18  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs (Attributes.AddAttributeSection): Rename to this
+       since it makes much more sense.
+
+       (Attributes.ctor): Don't require a Location parameter.
+       
+       * rootcontext.cs (AddGlobalAttributeSection): Rename again.
+
+       * attribute.cs (ApplyAttributes): Remove extra Location parameters
+       since we already have that information per attribute.
+
+       * everywhere : make appropriate changes.
+
+       * class.cs (LabelParameters): Write the code which actually
+       applies attributes to the return type. We can't do this on the MS
+       .NET runtime so we flag a warning in the case an exception is
+       thrown.
+
+2002-12-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * const.cs: Handle implicit null conversions here too.
+
+2002-12-17  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (MethodCore.LabelParameters): Remove the extra
+       Type [] parameter since it is completely unnecessary. Instead
+       pass in the method's attributes so that we can extract
+       the "return" attribute.
+
+2002-12-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay (parse): Use Report.Error to flag errors instead
+       of ignoring it and letting the compile continue.
+
+       * typemanager.cs (ChangeType): use an extra argument to return an
+       error condition instead of throwing an exception.
+
+2002-12-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Unary.TryReduce): mimic the code for the regular
+       code path.  Perform an implicit cast in the cases where we can
+       implicitly convert to one of the integral types, and then reduce
+       based on that constant.   This fixes bug #35483.
+
+2002-12-14  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * typemanager.cs: fixed cut & paste error in GetRemoveMethod.
+
+2002-12-13  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * namespace.cs: fixed bug #35489.
+
+2002-12-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs: Remove some dead code.
+
+       * cs-parser.jay: Estimate the number of methods needed
+       (RootContext.MethodCount);
+
+       * cs-tokenizer.cs: Use char arrays for parsing identifiers and
+       numbers instead of StringBuilders.
+
+       * support.cs (PtrHashtable): Add constructor with initial size;
+       We can now reduce reallocations of the method table.
+
+2002-12-10  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs (ApplyAttributes): Keep track of the emitted
+       attributes on a per-target basis. This fixes bug #35413.
+
+2002-12-10  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs (MainDriver): On rotor encoding 28591 does not exist,
+       default to the Windows 1252 encoding.
+
+       (UnixParseOption): Support version, thanks to Alp for the missing
+       pointer. 
+
+       * AssemblyInfo.cs: Add nice assembly information.
+
+       * cs-tokenizer.cs: Add fix from Felix to the #if/#else handler
+       (bug 35169).
+
+       * cs-parser.jay: Allow a trailing comma before the close bracked
+       in the attribute_section production.
+
+       * ecore.cs (FieldExpr.AddressOf): Until I figure out why the
+       address of the instance was being taken, I will take this out,
+       because we take the address of the object immediately here.
+
+2002-12-09  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (AreMultipleAllowed): Take care of the most
+       obvious case where attribute type is not in the current assembly -
+       stupid me ;-)
+
+2002-12-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (SimpleName.DoResolve): First perform lookups on using
+       definitions, instead of doing that afterwards.  
+
+       Also we use a nice little hack, depending on the constructor, we
+       know if we are a "composed" name or a simple name.  Hence, we
+       avoid the IndexOf test, and we avoid 
+
+       * codegen.cs: Add code to assist in a bug reporter to track down
+       the source of a compiler crash. 
+
+2002-12-07  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs (Attribute.ApplyAttributes) : Keep track of which attribute
+       types have been emitted for a given element and flag an error
+       if something which does not have AllowMultiple set is used more
+       than once.
+
+       * typemanager.cs (RegisterAttributeAllowMultiple): Keep track of
+       attribute types and their corresponding AllowMultiple properties
+
+       (AreMultipleAllowed): Check the property for a given type.
+
+       * attribute.cs (Attribute.ApplyAttributes): Register the AllowMultiple
+       property in the case we have a TypeContainer.
+
+       (Attributes.AddAttribute): Detect duplicates and just skip on
+       adding them. This trivial fix catches a pretty gross error in our
+       attribute emission - global attributes were being emitted twice!
+
+       Bugzilla bug #33187 is now fixed.
+
+2002-12-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs (pp_expr): Properly recurse here (use pp_expr
+       instead of pp_and).
+
+       * expression.cs (Binary.ResolveOperator): I can only use the
+       Concat (string, string, string) and Concat (string, string,
+       string, string) if the child is actually a concatenation of
+       strings. 
+
+2002-12-04  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs: Small fix, because decimal_digits is used in a
+       context where we need a 2-character lookahead.
+
+       * pending.cs (PendingImplementation): Rework so we can keep track
+       of interface types all the time, and flag those which were
+       implemented by parents as optional.
+
+2002-12-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Binary.ResolveOperator): Use
+       String.Concat(string,string,string) or
+       String.Concat(string,string,string,string) when possible. 
+
+       * typemanager: More helper methods.
+
+
+Tue Dec 3 19:32:04 CET 2002 Paolo Molaro <lupus@ximian.com>
+
+       * pending.cs: remove the bogus return from GetMissingInterfaces()
+       (see the 2002-11-06 entry: the mono runtime is now fixed in cvs).
+
+2002-12-02  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * namespace.cs: avoid duplicated 'using xxx' being added to
+       using_clauses. This prevents mcs from issuing and 'ambiguous type' error
+       when we get more than one 'using' statement for the same namespace.
+       Report a CS0105 warning for it.
+
+2002-11-30  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs (consume_identifier): use read directly, instead
+       of calling getChar/putback, uses internal knowledge of it.    
+
+       (xtoken): Reorder tokenizer so most common patterns are checked
+       first.  This reduces the compilation time in another 5% (from 8.11s
+       average to 7.73s for bootstrapping mcs on my Mobile p4/1.8ghz).
+
+       The parsing time is 22% of the compilation in mcs, and from that
+       64% is spent on the tokenization process.  
+
+       I tried using a binary search for keywords, but this is slower
+       than the hashtable.  Another option would be to do a couple of
+       things:
+
+               * Not use a StringBuilder, instead use an array of chars,
+                 with a set value.  Notice that this way we could catch
+                 the 645 error without having to do it *afterwards*.
+
+               * We could write a hand-parser to avoid the hashtable
+                 compares altogether.
+
+       The identifier consumption process takes 37% of the tokenization
+       time.  Another 15% is spent on is_number.  56% of the time spent
+       on is_number is spent on Int64.Parse:
+
+               * We could probably choose based on the string length to
+                 use Int32.Parse or Int64.Parse and avoid all the 64-bit
+                 computations. 
+
+       Another 3% is spend on wrapping `xtoken' in the `token' function.
+
+       Handle 0xa0 as whitespace (#34752)
+       
+2002-11-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (IsCLRType): New routine to tell whether a type
+       is one of the builtin types.  
+
+       Maybe it needs to use TypeCodes to be faster.  Maybe we could use
+       typecode in more places instead of doing pointer comparissions.
+       We could leverage some knowledge about the way the typecodes are
+       laid out.
+
+       New code to cache namespaces in assemblies, it is currently not
+       invoked, to be used soon.
+
+       * decl.cs (DeclSpace.MakeFQN): Simple optimization.
+
+       * expression.cs (Binary.ResolveOperator): specially handle
+       strings, and do not perform user-defined operator overloading for
+       built-in types.
+
+2002-11-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs: Avoid calling Char.IsDigit which is an
+       internalcall as it is a pretty simple operation;  Avoid whenever
+       possible to call Char.IsLetter.
+
+       (consume_identifier): Cut by half the number of
+       hashtable calls by merging the is_keyword and GetKeyword behavior.
+
+       Do not short-circuit, because if we do, we
+       report errors (ie, #if false && true would produce an invalid
+       directive error);
+       
+
+2002-11-24  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (Cast.TryReduce): If we're in checked syntax,
+       check constant ranges and report a CS0221.  Fixes #33186.
+
+2002-11-24  Martin Baulig  <martin@ximian.com>
+
+       * cs-parser.jay: Make this work for uninitialized variable
+       declarations in the `for' initializer.  Fixes #32416.
+
+2002-11-24  Martin Baulig  <martin@ximian.com>
+
+       * ecore.cs (Expression.ConvertExplicit): Make casting from/to
+       System.Enum actually work.  Fixes bug #32269, added verify-6.cs.
+
+2002-11-24  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (Binary.DoNumericPromotions): Added `check_user_conv'
+       argument; if true, we also check for user-defined conversions.
+       This is only needed if both arguments are of a user-defined type.
+       Fixes #30443, added test-175.cs.
+       (Binary.ForceConversion): Pass the location argument to ConvertImplicit.
+
+       * ecore.cs (Expression.ImplicitUserConversionExists): New method.
+
+2002-11-24  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (ArrayAccess.GetStoreOpcode): New public static
+       function to get the store opcode.
+       (Invocation.EmitParams): Call ArrayAccess.GetStoreOpcode() and
+       only emit the Ldelema if the store opcode is Stobj.  You must run
+       both test-34 and test-167 to test this.  Fixes #34529.
+
+2002-11-23  Martin Baulig  <martin@ximian.com>
+
+       * ecore.cs (Expression.MemberLookup): Added additional
+       `qualifier_type' argument which is used when we're being called
+       from MemberAccess.DoResolve() and null if we're called from a
+       SimpleName lookup.
+       (Expression.MemberLookupFailed): New method to report errors; this
+       does the CS1540 check and reports the correct error message.
+
+       * typemanager.cs (MemberLookup): Added additional `qualifier_type'
+       argument for the CS1540 check and redone the way how we're dealing
+       with private members.  See the comment in the source code for details.
+       (FilterWithClosure): Reverted this back to revision 1.197; renamed
+       `closure_start_type' to `closure_qualifier_type' and check whether
+       it's not null.  It was not this filter being broken, it was just
+       being called with the wrong arguments.
+
+       * expression.cs (MemberAccess.DoResolve): use MemberLookupFinal()
+       and pass it the correct `qualifier_type'; this also does the error
+       handling for us.
+
+2002-11-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Invocation.EmitParams): If the we are dealing
+       with a non-built-in value type, load its address as well.
+
+       (ArrayCreation): Use a a pretty constant instead
+       of the hardcoded value 2.   Use 6 instead of 2 for the number of
+       static initializers.  
+
+       (ArrayCreation.EmitDynamicInitializers): Peel enumerations,
+       because they are not really value types, just glorified integers. 
+
+       * driver.cs: Do not append .exe, the CSC compiler does not do it.
+
+       * ecore.cs: Remove redundant code for enumerations, make them use
+       the same code path as everything else, fixes the casting issue
+       with enumerations in Windows.Forms.
+
+       * attribute.cs: Do only cast to string if it is a string, the
+       validation happens later.
+
+       * typemanager.cs: Temproary hack to avoid a bootstrap issue until
+       people upgrade their corlibs.
+
+       * ecore.cs: Oops, enumerations were not following the entire code path
+
+2002-11-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (FilterWithClosure): Commented out the test for
+       1540 in typemanager.cs, as it has problems when accessing
+       protected methods from a parent class (see test-174.cs). 
+
+       * attribute.cs (Attribute.ValidateGuid): new method.
+       (Attribute.Resolve): Use above.
+
+2002-11-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * enum.cs: In FindMembers, perform a recursive lookup for values. (34308)
+
+       * ecore.cs (SimpleName.SimpleNameResolve): Remove the special
+       handling for enumerations, as we only needed the TypeContainer
+       functionality to begin with (this is required for the fix below to
+       work for enums that reference constants in a container class for
+       example). 
+
+       * codegen.cs (EmitContext): Make TypeContainer a DeclSpace.
+
+       * enum.cs (Enum.Define): Use `this' instead of parent, so we have
+       a valid TypeBuilder to perform lookups on.o
+
+       * class.cs (InheritableMemberSignatureCompare): Use true in the
+       call to GetGetMethod and GetSetMethod, because we are comparing
+       the signature, and we need to get the methods *even* if they are
+       private. 
+
+       (PropertyBase.CheckBase): ditto.
+
+       * statement.cs (Switch.ResolveAndReduce, Block.EmitMeta,
+       GotoCase.Resolve): Use Peel on EmpytCasts.
+
+       * ecore.cs (EmptyCast): drop child, add Peel method.
+
+2002-11-17  Martin Baulig  <martin@ximian.com>
+
+       * ecore.cs (EmptyCast.Child): New public property.
+
+       * statement.cs (SwitchLabel.ResolveAndReduce): Check whether the
+       label resolved to an EmptyCast.  Fixes #34162.
+       (GotoCase.Resolve): Likewise.
+       (Block.EmitMeta): Likewise.
+
+2002-11-17  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (Invocation.BetterConversion): Prefer int over
+       uint; short over ushort; long over ulong for integer literals.
+       Use ImplicitConversionExists instead of StandardConversionExists
+       since we also need to check for user-defined implicit conversions.
+       Fixes #34165.  Added test-173.cs.
+
+2002-11-16  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (Binary.EmitBranchable): Eliminate comparisions
+       with the `true' and `false' literals.  Fixes #33151.
+
+2002-11-16  Martin Baulig  <martin@ximian.com>
+
+       * typemanager.cs (RealMemberLookup): Reverted Miguel's patch from
+       October 22nd; don't do the cs1540 check for static members.
+
+       * ecore.cs (PropertyExpr.ResolveAccessors): Rewrote this; we're
+       now using our own filter here and doing the cs1540 check again.
+
+2002-11-16  Martin Baulig  <martin@ximian.com>
+
+       * support.cs (InternalParameters): Don't crash if we don't have
+       any fixed parameters.  Fixes #33532.
+
+2002-11-16  Martin Baulig  <martin@ximian.com>
+
+       * decl.cs (MemberCache.AddMethods): Use BindingFlags.FlattenHierarchy
+       when looking up static methods to make this work on Windows.
+       Fixes #33773.
+
+2002-11-16  Martin Baulig  <martin@ximian.com>
+
+       * ecore.cs (PropertyExpr.VerifyAssignable): Check whether we have
+       a setter rather than using PropertyInfo.CanWrite.
+
+2002-11-15  Nick Drochak  <ndrochak@gol.com>
+
+       * class.cs: Allow acces to block member by subclasses. Fixes build
+       breaker.
+
+2002-11-14  Martin Baulig  <martin@ximian.com>
+
+       * class.cs (Constructor.Emit): Added the extern/block check.
+       Fixes bug #33678.
+
+2002-11-14  Martin Baulig  <martin@ximian.com>
+
+       * expression.cs (IndexerAccess.DoResolve): Do a DeclaredOnly
+       iteration while looking for indexers, this is needed because the
+       indexer may have a different name in our base classes.  Fixed the
+       error reporting (no indexers at all, not get accessor, no
+       overloaded match).  Fixes bug #33089.
+       (IndexerAccess.DoResolveLValue): Likewise.
+
+2002-11-14  Martin Baulig  <martin@ximian.com>
+
+       * class.cs (PropertyBase.CheckBase): Make this work for multiple
+       indexers.  Fixes the first part of bug #33089.
+       (MethodSignature.InheritableMemberSignatureCompare): Added support
+       for properties.
+
+2002-11-13  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs (Attribute.Resolve): Catch the
+       NullReferenceException and report it since it isn't supposed to
+       happen. 
+       
+2002-11-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Binary.EmitBranchable): Also handle the cases for
+       LogicalOr and LogicalAnd that can benefit from recursively
+       handling EmitBranchable.  The code now should be nice for Paolo.
+
+2002-11-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (LookupType): Added a negative-hit hashtable for
+       the Type lookups, as we perform quite a number of lookups on
+       non-Types.  This can be removed once we can deterministically tell
+       whether we have a type or a namespace in advance.
+
+       But this might require special hacks from our corlib.
+
+       * TODO: updated.
+
+       * ecore.cs (TryImplicitIntConversion): Handle conversions to float
+       and double which avoids a conversion from an integer to a double.
+
+       * expression.cs: tiny optimization, avoid calling IsConstant,
+       because it effectively performs the lookup twice.
+
+2002-11-06  Miguel de Icaza  <miguel@ximian.com>
+
+       But a bogus return here to keep the semantics of the old code
+       until the Mono runtime is fixed.
+       
+       * pending.cs (GetMissingInterfaces): New method used to remove all
+       the interfaces that are already implemented by our parent
+       classes from the list of pending methods. 
+
+       * interface.cs: Add checks for calls after ResolveTypeExpr.
+
+2002-11-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Class.Emit): Report warning 67: event not used if the
+       warning level is beyond 3.
+
+       * ecore.cs (Expression.ConvertExplicit): Missed a check for expr
+       being a NullLiteral.
+
+       * cs-parser.jay: Fix, Gonzalo reverted the order of the rank
+       specifiers. 
+
+       * class.cs (TypeContainer.GetClassBases): Cover a missing code
+       path that might fail if a type can not be resolved.
+
+       * expression.cs (Binary.Emit): Emit unsigned versions of the
+       operators. 
+
+       * driver.cs: use error 5.
+       
+2002-11-02  Gonzalo Paniagua Javier <gonzalo@gnome-db.org>
+
+       * cs-parser.jay: simplified a rule and 5 SR conflicts dissapeared.
+
+2002-11-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay (switch_section): A beautiful patch from Martin
+       Baulig that fixed 33094.
+
+2002-10-31  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (PropertyExpr.DoResolveLValue, PropertyExpr.DoResolve):
+       Check whether the base is abstract and report an error if so.
+
+       * expression.cs (IndexerAccess.DoResolveLValue,
+       IndexerAccess.DoResolve): ditto. 
+
+       (Invocation.DoResolve): ditto.
+       
+       (Invocation.FullMethodDesc): Improve the report string.
+
+       * statement.cs (Block): Eliminate IsVariableDefined as it is
+       basically just a wrapper for GetVariableInfo.
+
+       * ecore.cs (SimpleName): Use new 
+
+       * support.cs (ReflectionParamter.ParameterType): We unwrap the
+       type, as we return the actual parameter ref/unref state on a
+       different call.
+
+2002-10-30  Miguel de Icaza  <miguel@ximian.com>
+
+       * support.cs: Return proper flags REF/OUT fixing the previous
+       commit.  
+
+       * expression.cs: Reverted last patch, that was wrong.  Is_ref is
+       not used to mean `ref' but `ref or out' in ParameterReference
+       
+       * delegate.cs (FullDelegateDesc): use ParameterDesc to get the
+       full type signature instead of calling TypeManger.CSharpName
+       ourselves. 
+
+       * support.cs (InternalParameters.ParameterDesc): Do not compare
+       directly to the modflags, because REF/OUT will actually be bitsets
+       if set. 
+
+       * delegate.cs (VerifyMethod): Check also the modifiers.
+
+       * cs-tokenizer.cs: Fix bug where floating point values with an
+       exponent where a sign was missing was ignored.
+
+       * driver.cs: Allow multiple assemblies to be specified in a single
+       /r: argument
+
+2002-10-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Ugly.  We had to add a multiplicative_expression,
+       because identifiers after a parenthesis would end up in this kind
+       of production, and we needed to desamiguate it for having casts
+       like:
+
+               (UserDefinedType *) xxx
+
+2002-10-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (RealMemberLookup): when we deal with a subclass,
+       we should set on the Bindingflags.NonPublic, but not turn on
+       private_ok.  private_ok controls whether a Private member is
+       returned (this is chekced on the filter routine), while the
+       BindingFlags.NonPublic just controls whether private/protected
+       will be allowed.   This fixes the problem part of the problem of
+       private properties being allowed to be used in derived classes.
+
+       * expression.cs (BaseAccess): Provide an DoResolveLValue method,
+       so we can call the children DoResolveLValue method (this will
+       properly signal errors on lvalue assignments to base properties)
+       
+       * ecore.cs (PropertyExpr.ResolveAccessors): If both setter and
+       getter are null, and we have a property info, we know that this
+       happened because the lookup failed, so we report an error 122 for
+       protection level violation.
+
+       We also silently return if setter and getter are null in the
+       resolve functions, this condition only happens if we have flagged
+       the error before.  This is the other half of the problem. 
+
+       (PropertyExpr.ResolveAccessors): Turns out that PropertyInfo does
+       not have accessibility information, that is why we were returning
+       true in the filter function in typemanager.cs.
+
+       To properly report 122 (property is inaccessible because of its
+       protection level) correctly, we report this error in ResolveAccess
+       by failing if both the setter and the getter are lacking (ie, the
+       lookup failed). 
+
+       DoResolve and DoLResolve have been modified to check for both
+       setter/getter being null and returning silently, the reason being
+       that I did not want to put the knowledge about this error in upper
+       layers, like:
+
+       int old = Report.Errors;
+       x = new PropertyExpr (...);
+       if (old != Report.Errors)
+               return null;
+       else
+               return x;
+
+       So the property expr is returned, but it is invalid, so the error
+       will be flagged during the resolve process. 
+
+       * class.cs: Remove InheritablePropertySignatureCompare from the
+       class, as we no longer depend on the property signature to compute
+       whether it is possible to implement a method or not.
+
+       The reason is that calling PropertyInfo.GetGetMethod will return
+       null (in .NET, in Mono it works, and we should change this), in
+       cases where the Get Method does not exist in that particular
+       class.
+
+       So this code:
+
+       class X { public virtual int A { get { return 1; } } }
+       class Y : X { }
+       class Z : Y { public override int A { get { return 2; } } }
+
+       Would fail in Z because the parent (Y) would not have the property
+       defined.  So we avoid this completely now (because the alternative
+       fix was ugly and slow), and we now depend exclusively on the
+       method names.
+
+       (PropertyBase.CheckBase): Use a method-base mechanism to find our
+       reference method, instead of using the property.
+
+       * typemanager.cs (GetPropertyGetter, GetPropertySetter): These
+       routines are gone now.
+
+       * typemanager.cs (GetPropertyGetter, GetPropertySetter): swap the
+       names, they were incorrectly named.
+
+       * cs-tokenizer.cs: Return are more gentle token on failure. 
+
+       * pending.cs (PendingImplementation.InterfaceMethod): This routine
+       had an out-of-sync index variable, which caused it to remove from
+       the list of pending methods the wrong method sometimes.
+
+2002-10-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (PropertyExpr): Do not use PropertyInfo.CanRead,
+       CanWrite, because those refer to this particular instance of the
+       property, and do not take into account the fact that we can
+       override single members of a property.
+
+       Constructor requires an EmitContext.  The resolution process does
+       not happen here, but we need to compute the accessors before,
+       because the resolution does not always happen for properties.
+       
+       * typemanager.cs (RealMemberLookup): Set private_ok if we are a
+       subclass, before we did not update this flag, but we did update
+       bindingflags. 
+
+       (GetAccessors): Drop this routine, as it did not work in the
+       presence of partially overwritten set/get methods. 
+
+       Notice that this broke the cs1540 detection, but that will require
+       more thinking. 
+       
+2002-10-22  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * class.cs:
+       * codegen.cs:
+       * driver.cs: issue a warning instead of an error if we don't support
+       debugging for the platform. Also ignore a couple of errors that may
+       arise when trying to write the symbols. Undo my previous patch.
+
+2002-10-22  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * driver.cs: ignore /debug switch except for Unix platforms.
+
+2002-10-23  Nick Drochak  <ndrochak@gol.com>
+
+       * makefile: Remove mcs2.exe and mcs3.exe on 'make clean'
+
+2002-10-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Do not make mcs-debug conditional, so we do not break
+       builds that use it.
+
+       * statement.cs (UsageVector.MergeChildren): I would like Martin to
+       review this patch.  But basically after all the children variables
+       have been merged, the value of "Breaks" was not being set to
+       new_breaks for Switch blocks.  I think that it should be set after
+       it has executed.  Currently I set this to the value of new_breaks,
+       but only if new_breaks is FlowReturn.ALWAYS, which is a bit
+       conservative, but I do not understand this code very well.
+
+       I did not break anything in the build, so that is good ;-)
+
+       * cs-tokenizer.cs: Also allow \r in comments as a line separator.
+
+2002-10-20  Mark Crichton  <crichton@gimp.org>
+
+        * cfold.cs: Fixed compile blocker.  Really fixed it this time.
+
+2002-10-20  Nick Drochak  <ndrochak@gol.com>
+
+       * cfold.cs: Fixed compile blocker.
+
+2002-10-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: I was chekcing the key, not the file.
+
+2002-10-19  Ravi Pratap  <ravi@ximian.com>
+
+       * ecore.cs (UserDefinedConversion): Get rid of the bogus error
+       message that we were generating - we just need to silently return
+       a null.
+
+2002-10-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Event.Define): Change my previous commit, as this
+       breaks the debugger.  This is a temporary hack, as it seems like
+       the compiler is generating events incorrectly to begin with.
+
+       * expression.cs (Binary.ResolveOperator): Added support for 
+       "U operator - (E x, E y)"
+
+       * cfold.cs (BinaryFold): Added support for "U operator - (E x, E
+       y)".
+
+       * ecore.cs (FieldExpr.AddressOf): We had a special code path for
+       init-only variables, but this path did not take into account that
+       there might be also instance readonly variables.  Correct this
+       problem. 
+
+       This fixes bug 32253
+
+       * delegate.cs (NewDelegate.DoResolve): Catch creation of unsafe
+       delegates as well.
+
+       * driver.cs: Change the extension for modules to `netmodule'
+
+       * cs-parser.jay: Improved slightly the location tracking for
+       the debugger symbols.
+
+       * class.cs (Event.Define): Use Modifiers.FieldAttr on the
+       modifiers that were specified instead of the hardcoded value
+       (FamAndAssem).  This was basically ignoring the static modifier,
+       and others.  Fixes 32429.
+
+       * statement.cs (Switch.SimpleSwitchEmit): Simplified the code, and
+       fixed a bug in the process (32476)
+
+       * expression.cs (ArrayAccess.EmitAssign): Patch from
+       hwang_rob@yahoo.ca that fixes bug 31834.3
+
+2002-10-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Make the module extension .netmodule.
+
+2002-10-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Report an error if the resource file is not found
+       instead of crashing.
+
+       * ecore.cs (PropertyExpr.EmitAssign): Pass IsBase instead of
+       false, like Emit does.
+
+2002-10-16  Nick Drochak  <ndrochak@gol.com>
+
+       * typemanager.cs: Remove unused private member.  Also reported mcs
+       bug to report this as a warning like csc.
+
+2002-10-15  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (Statement.Emit): Made this a virtual method; emits
+       the line number info and calls DoEmit().
+       (Statement.DoEmit): New protected abstract method, formerly knows
+       as Statement.Emit().
+
+       * codegen.cs (EmitContext.Mark): Check whether we have a symbol writer.
+
+2002-10-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs: Following the comment from 2002-09-26 to AddMethod, I
+       have fixed a remaining problem: not every AddXXXX was adding a
+       fully qualified name.  
+
+       Now everyone registers a fully qualified name in the DeclSpace as
+       being defined instead of the partial name.  
+
+       Downsides: we are slower than we need to be due to the excess
+       copies and the names being registered this way.  
+
+       The reason for this is that we currently depend (on the corlib
+       bootstrap for instance) that types are fully qualified, because
+       we dump all the types in the namespace, and we should really have
+       types inserted into the proper namespace, so we can only store the
+       basenames in the defined_names array.
+
+2002-10-10  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (ArrayAccess.EmitStoreOpcode): Reverted the patch
+       from bug #31834, see the bug report for a testcase which is
+       miscompiled.
+
+2002-10-10  Martin Baulig  <martin@gnome.org>
+
+       * codegen.cs (EmitContext.Breaks): Removed, we're now using the
+       flow analysis code for this.
+
+       * statement.cs (Do, While, For): Tell the flow analysis code about
+       infinite loops.
+       (FlowBranching.UsageVector): Added support for infinite loops.
+       (Block.Resolve): Moved the dead code elimination here and use flow
+       analysis to do it.
+
+2002-10-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Field.Define): Catch cycles on struct type
+       definitions. 
+
+       * typemanager.cs (IsUnmanagedtype): Do not recursively check
+       fields if the fields are static.  We only need to check instance
+       fields. 
+
+       * expression.cs (As.DoResolve): Test for reference type.
+
+       * statement.cs (Using.ResolveExpression): Use
+       ConvertImplicitRequired, not ConvertImplicit which reports an
+       error on failture
+       (Using.ResolveLocalVariableDecls): ditto.
+
+       * expression.cs (Binary.ResolveOperator): Report errors in a few
+       places where we had to.
+
+       * typemanager.cs (IsUnmanagedtype): Finish implementation.
+
+2002-10-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: Use StoreFromPtr instead of extracting the type
+       and then trying to use Stelem.  Patch is from hwang_rob@yahoo.ca
+
+       * ecore.cs (ImplicitReferenceConversion): It is possible to assign
+       an enumeration value to a System.Enum, but System.Enum is not a
+       value type, but an class type, so we need to box.
+
+       (Expression.ConvertExplicit): One codepath could return
+       errors but not flag them.  Fix this.  Fixes #31853
+
+       * parameter.cs (Resolve): Do not allow void as a parameter type.
+
+2002-10-06  Martin Baulig  <martin@gnome.org>
+
+       * statemenc.cs (FlowBranching.SetParameterAssigned): Don't crash
+       if it's a class type and not a struct.  Fixes #31815.
+
+2002-10-06  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs: Reworked the flow analysis code a bit to make it
+       usable for dead code elimination.
+
+2002-10-06  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * cs-parser.jay: allow empty source files. Fixes bug #31781.
+
+2002-10-04  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ComposedCast.DoResolveType): A quick workaround
+       to fix the test 165, will investigate deeper.
+
+2002-10-04  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (FlowBranching.UsageVector.MergeChildren): Make
+       finally blocks actually work.
+       (Try.Resolve): We don't need to create a sibling for `finally' if
+       there is no finally block.
+
+2002-10-04  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (Constructor.Define): The default accessibility for a
+       non-default constructor is private, not public.
+
+2002-10-04  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Constructor): Make AllowedModifiers public, add
+       EXTERN.
+
+       * cs-parser.jay: Perform the modifiers test here, as the
+       constructor for the Constructor class usually receives a zero
+       because of the way we create it (first we create, later we
+       customize, and we were never checking the modifiers).
+
+       * typemanager.cs (Typemanager.LookupTypeDirect): This new function
+       is a version of LookupTypeReflection that includes the type-name
+       cache.  This can be used as a fast path for functions that know
+       the fully qualified name and are only calling into *.GetType() to
+       obtain a composed type.
+
+       This is also used by TypeManager.LookupType during its type
+       composition.
+
+       (LookupType): We now also track the real type name, as sometimes
+       we can get a quey for the real type name from things like
+       ComposedCast.  This fixes bug 31422.
+       
+       * expression.cs (ComposedCast.Resolve): Since we are obtaining a
+       complete type fullname, it does not have to go through the type
+       resolution system to obtain the composed version of the type (for
+       obtaining arrays or pointers).
+       
+       (Conditional.Emit): Use the EmitBoolExpression to
+       generate nicer code, as requested by Paolo.
+
+       (ArrayCreation.CheckIndices): Use the patch from
+       hwang_rob@yahoo.ca to validate the array initializers. 
+
+2002-10-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (ConstructorInitializer.Emit): simplify code by using
+       Invocation.EmitCall, and at the same time, fix the bugs in calling
+       parent constructors that took variable arguments. 
+
+       * ecore.cs (Expression.ConvertNumericExplicit,
+       Expression.ImplicitNumericConversion): Remove the code that
+       manually wrapped decimal (InternalTypeConstructor call is now gone
+       as well).
+
+       * expression.cs (Cast.TryReduce): Also handle decimal types when
+       trying to perform a constant fold on the type.
+
+       * typemanager.cs (IsUnmanagedtype): Partially implemented.
+
+       * parameter.cs: Removed ResolveAndDefine, as it was not needed, as
+       that only turned off an error report, and did nothing else. 
+
+2002-10-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Handle and ignore /fullpaths
+
+2002-10-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Binary.ResolveOperator): Catch the case where
+       DoNumericPromotions returns true, 
+
+       (Binary.DoNumericPromotions): Simplify the code, and the tests.
+
+2002-09-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (EventExpr.Emit): Instead of emitting an exception,
+       report error 70.
+
+2002-09-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (ConvertNumericExplicit): It is not enough that the
+       conversion exists, but it is also required that the conversion be
+       performed.  This manifested in "(Type64Enum) 2".  
+
+       * class.cs (TypeManager.AddMethod): The fix is not to change
+       AddEnum, because that one was using a fully qualified name (every
+       DeclSpace derivative does), but to change the AddMethod routine
+       that was using an un-namespaced name.  This now correctly reports
+       the duplicated name.
+
+       Revert patch until I can properly fix it.  The issue
+       is that we have a shared Type space across all namespaces
+       currently, which is wrong.
+
+       Options include making the Namespace a DeclSpace, and merge
+       current_namespace/current_container in the parser.
+
+2002-09-25  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Improve error reporting when we get a different
+       kind of expression in local_variable_type and
+       local_variable_pointer_type. 
+
+       Propagate this to avoid missleading errors being reported.
+
+       * ecore.cs (ImplicitReferenceConversion): treat
+       TypeManager.value_type as a target just like object_type.   As
+       code like this:
+
+       ValueType v = 1;
+
+       Is valid, and needs to result in the int 1 being boxed before it
+       is assigned to the value type v.
+
+       * class.cs (TypeContainer.AddEnum): Use the basename, not the name
+       to validate the enumeration name.
+
+       * expression.cs (ArrayAccess.EmitAssign): Mimic the same test from
+       EmitDynamicInitializers for the criteria to use Ldelema.  Thanks
+       to hwang_rob@yahoo.ca for finding the bug and providing a patch.
+
+       * ecore.cs (TryImplicitIntConversion): When doing an
+       implicit-enumeration-conversion, check if the type is 64-bits and
+       perform a conversion before passing to EnumConstant.
+
+2002-09-23  Miguel de Icaza  <miguel@ximian.com>
+
+       * decl.cs (Error_AmbiguousTypeReference); New routine used to
+       report ambiguous type references.  Unlike the MS version, we
+       report what the ambiguity is.   Innovation at work ;-)
+
+       (DeclSpace.FindType): Require a location argument to
+       display when we display an ambiguous error.
+
+       * ecore.cs: (SimpleName.DoResolveType): Pass location to FindType.
+
+       * interface.cs (GetInterfaceTypeByName): Pass location to FindType.
+
+       * expression.cs (EmitDynamicInitializers): Apply patch from
+       hwang_rob@yahoo.ca that fixes the order in which we emit our
+       initializers. 
+
+2002-09-21  Martin Baulig  <martin@gnome.org>
+
+       * delegate.cs (Delegate.VerifyApplicability): Make this work if the
+       delegate takes no arguments.
+
+2002-09-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * constant.cs: Use Conv_U8 instead of Conv_I8 when loading longs
+       from integers.
+
+       * expression.cs: Extract the underlying type.
+
+       * ecore.cs (StoreFromPtr): Use TypeManager.IsEnumType instad of IsEnum
+
+       * decl.cs (FindType): Sorry about this, fixed the type lookup bug.
+
+2002-09-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (TypeContainer.DefineType): We can not use the nice
+       PackingSize with the size set to 1 DefineType method, because it
+       will not allow us to define the interfaces that the struct
+       implements.
+
+       This completes the fixing of bug 27287
+
+       * ecore.cs (Expresion.ImplicitReferenceConversion): `class-type S'
+       means also structs.  This fixes part of the problem. 
+       (Expresion.ImplicitReferenceConversionExists): ditto.
+
+       * decl.cs (DeclSparce.ResolveType): Only report the type-not-found
+       error if there were no errors reported during the type lookup
+       process, to avoid duplicates or redundant errors.  Without this
+       you would get an ambiguous errors plus a type not found.  We have
+       beaten the user enough with the first error.  
+
+       (DeclSparce.FindType): Emit a warning if we have an ambiguous
+       reference. 
+
+       * ecore.cs (SimpleName.DoResolveType): If an error is emitted
+       during the resolution process, stop the lookup, this avoids
+       repeated error reports (same error twice).
+
+       * rootcontext.cs: Emit a warning if we have an ambiguous reference.
+
+       * typemanager.cs (LookupType): Redo the type lookup code to match
+       the needs of System.Reflection.  
+
+       The issue is that System.Reflection requires references to nested
+       types to begin with a "+" sign instead of a dot.  So toplevel
+       types look like: "NameSpace.TopLevelClass", and nested ones look
+       like "Namespace.TopLevelClass+Nested", with arbitrary nesting
+       levels. 
+
+2002-09-19  Martin Baulig  <martin@gnome.org>
+
+       * codegen.cs (EmitContext.EmitTopBlock): If control flow analysis
+       says that a method always returns or always throws an exception,
+       don't report the CS0161.
+
+       * statement.cs (FlowBranching.UsageVector.MergeChildren): Always
+       set `Returns = new_returns'.
+
+2002-09-19  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (MemberAccess.ResolveMemberAccess): When resolving
+       to an enum constant, check for a CS0176.
+
+2002-09-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (TypeContainer.CheckPairedOperators): Now we check
+       for operators that must be in pairs and report errors.
+
+       * ecore.cs (SimpleName.DoResolveType): During the initial type
+       resolution process, when we define types recursively, we must
+       check first for types in our current scope before we perform
+       lookups in the enclosing scopes.
+
+       * expression.cs (MakeByteBlob): Handle Decimal blobs.
+
+       (Invocation.VerifyArgumentsCompat): Call
+       TypeManager.TypeToCoreType on the parameter_type.GetElementType.
+       I thought we were supposed to always call this, but there are a
+       few places in the code where we dont do it.
+
+2002-09-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Add support in -linkres and -resource to specify the
+       name of the identifier.
+
+2002-09-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (StandardConversionExists): Sync with the conversion
+       code: allow anything-* to void* conversions.
+
+       (FindMostSpecificSource): Use an Expression argument
+       instead of a Type, because we might be handed over a Literal which
+       gets a few more implicit conversions that plain types do not.  So
+       this information was being lost.
+
+       Also, we drop the temporary type-holder expression when not
+       required.
+
+2002-09-17  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (PropertyBase.CheckBase): Don't check the base class if
+       this is an explicit interface implementation.
+
+2002-09-17  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (PropertyBase.CheckBase): Make this work for indexers with
+       different `IndexerName' attributes.
+
+       * expression.cs (BaseIndexerAccess): Rewrote this class to use IndexerAccess.
+       (IndexerAccess): Added special protected ctor for BaseIndexerAccess and
+       virtual CommonResolve().
+
+2002-09-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * enum.cs (LookupEnumValue): Use the EnumConstant declared type,
+       and convert that to the UnderlyingType.
+
+       * statement.cs (Foreach.Resolve): Indexers are just like variables
+       or PropertyAccesses.
+
+       * cs-tokenizer.cs (consume_string): Track line numbers and columns
+       inside quoted strings, we were not doing this before.
+
+2002-09-16  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (MethodGroupExpr.DoResolve): If we have an instance expression,
+       resolve it.  This is needed for the definite assignment check of the
+       instance expression, fixes bug #29846.
+       (PropertyExpr.DoResolve, EventExpr.DoResolve): Likewise.
+
+2002-09-16  Nick Drochak  <ndrochak@gol.com>
+
+       * parameter.cs: Fix compile error.  Cannot reference static member
+       from an instance object.  Is this an mcs bug?
+
+2002-09-14  Martin Baulig  <martin@gnome.org>
+
+       * decl.cs (MemberCache.SetupCacheForInterface): Don't add an interface
+       multiple times.  Fixes bug #30295, added test-166.cs.
+
+2002-09-14  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (Block.Emit): Don't emit unreachable code.
+       (Switch.SimpleSwitchEmit, Switch.TableSwitchEmit): Check for missing
+       `break' statements.
+       (Goto.Emit, Continue.Emit): Set ec.Breaks = true.
+
+2002-09-14  Martin Baulig  <martin@gnome.org>
+
+       * parameter.cs (Parameter.Attributes): Make this work if Modifier.ISBYREF
+       is set.
+
+2002-09-14  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (TypeManager.IsNestedChildOf): This must return false
+       if `type == parent' since in this case `type.IsSubclassOf (parent)' will
+       be false on the ms runtime.
+
+2002-09-13  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (SimpleName.SimpleNameResolve): Include the member name in
+       the CS0038 error message.
+
+2002-09-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (CheckedExpr, UnCheckedExpr): If we have a
+       constant inside, return it.
+
+2002-09-12  Martin Baulig  <martin@gnome.org>
+
+       * cfold.cs (ConstantFold.DoConstantNumericPromotions): Check whether an
+       implicit conversion can be done between enum types.
+
+       * enum.cs (Enum.LookupEnumValue): If the value is an EnumConstant,
+       check whether an implicit conversion to the current enum's UnderlyingType
+       exists and report an error if not.
+
+       * codegen.cs (CodeGen.Init): Delete the symbol file when compiling
+       without debugging support.
+
+       * delegate.cs (Delegate.CloseDelegate): Removed, use CloseType instead.
+       Fixes bug #30235.  Thanks to Ricardo Fernández Pascual.
+
+2002-09-12  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (TypeManager.IsNestedChildOf): New method.
+
+       * ecore.cs (IMemberExpr.DeclaringType): New property.
+       (SimpleName.SimpleNameResolve): Check whether we're accessing a
+       nonstatic member of an outer type (CS0038).
+
+2002-09-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Activate the using-error detector at warning level
+       4 (at least for MS-compatible APIs).
+
+       * namespace.cs (VerifyUsing): Small buglett fix.
+
+       * pending.cs (PendingImplementation): pass the container pointer. 
+
+       * interface.cs (GetMethods): Allow for recursive definition.  Long
+       term, I would like to move every type to support recursive
+       definitions, not the current ordering mechanism that we have right
+       now.
+
+       The situation is this: Attributes are handled before interfaces,
+       so we can apply attributes to interfaces.  But some attributes
+       implement interfaces, we will now handle the simple cases
+       (recursive definitions will just get an error).  
+
+       * parameter.cs: Only invalidate types at the end if we fail to
+       lookup all types.  
+
+2002-09-09  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (PropertyExpr.Emit): Also check for
+       TypeManager.system_int_array_get_length so this'll also work when
+       compiling corlib.  Fixes #30003.
+
+2002-09-09  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (ArrayCreation.MakeByteBlob): Added support for enums
+       and throw an exception if we can't get the type's size.  Fixed #30040,
+       added test-165.cs.
+
+2002-09-09  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (PropertyExpr.DoResolve): Added check for static properies.
+
+       * expression.cs (SizeOf.DoResolve): Sizeof is only allowed in unsafe
+       context.  Fixes bug #30027.
+
+       * delegate.cs (NewDelegate.Emit): Use OpCodes.Ldvirtftn for
+       virtual functions.  Fixes bug #30043, added test-164.cs.
+
+2002-09-08  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs : Fix a small NullRef crash thanks to my stupidity.
+
+2002-09-08  Nick Drochak  <ndrochak@gol.com>
+
+       * driver.cs: Use an object to get the windows codepage since it's not a
+       static property.
+
+2002-09-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (For.Emit): for infinite loops (test == null)
+       return whether there is a break inside, not always "true".
+
+       * namespace.cs (UsingEntry): New struct to hold the name of the
+       using definition, the location where it is defined, and whether it
+       has been used in a successful type lookup.
+       
+       * rootcontext.cs (NamespaceLookup): Use UsingEntries instead of
+       strings.
+
+       * decl.cs: ditto.
+
+2002-09-06  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs : Fix incorrect code which relied on catching
+       a NullReferenceException to detect a null being passed in
+       where an object was expected.
+
+2002-09-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Try): flag the catch variable as assigned
+
+       * expression.cs (Cast): Simplified by using ResolveType instead of
+       manually resolving.
+
+       * statement.cs (Catch): Fix bug by using ResolveType.
+
+2002-09-06  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (BetterConversion): Special case for when we have
+       a NullLiteral as the argument and we have to choose between string
+       and object types - we choose string the way csc does.
+
+       * attribute.cs (Attribute.Resolve): Catch the
+       NullReferenceException and report error #182 since the Mono
+       runtime no more has the bug and having this exception raised means
+       we tried to select a constructor which takes an object and is
+       passed a null.
+
+2002-09-05  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Invocation.OverloadResolve): Flag a nicer error
+       message (1502, 1503) when we can't locate a method after overload
+       resolution. This is much more informative and closes the bug
+       Miguel reported.
+
+       * interface.cs (PopulateMethod): Return if there are no argument
+       types. Fixes a NullReferenceException bug.
+
+       * attribute.cs (Attribute.Resolve): Ensure we allow TypeOf
+       expressions too. Previously we were checking only in one place for
+       positional arguments leaving out named arguments.
+
+       * ecore.cs (ImplicitNumericConversion): Conversion from underlying
+       type to the enum type is not allowed. Remove code corresponding to
+       that.
+
+       (ConvertNumericExplicit): Allow explicit conversions from
+       the underlying type to enum type. This precisely follows the spec
+       and closes a bug filed by Gonzalo.
+       
+2002-09-04  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * compiler.csproj:
+       * compiler.csproj.user: patch from Adam Chester (achester@bigpond.com).
+
+2002-09-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (SwitchLabel.ResolveAndReduce): In the string case,
+       it was important that we stored the right value after the
+       reduction in `converted'.
+
+2002-09-04  Martin Baulig  <martin@gnome.org>
+
+       * location.cs (Location.SymbolDocument): Use full pathnames for the
+       source files.
+
+2002-08-30  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ComposedCast): Use DeclSparce.ResolveType instead
+       of the expression resolve mechanism, because that will catch the
+       SimpleName error failures.
+
+       (Conditional): If we can not resolve the
+       expression, return, do not crash.
+
+2002-08-29  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * cs-tokenizer.cs:
+       (location): display token name instead of its number.
+
+2002-08-28  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Binary.ResolveOperator): Don't silently return
+       but return an error if an operator cannot be applied between two
+       enum types.
+
+2002-08-28  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (Constructor.Define): Set the permission attributes
+       correctly instead of making all constructors public.
+
+2002-08-28  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (Expression.DoResolve): Do a TypeManager.MemberLook
+       for private members before reporting a CS0103; if we find anything,
+       it's a CS0122.
+
+2002-08-28  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (TypeManager.FilterWithClosure): It's not enough
+       to check whether `closure_start_type == closure_invocation_type',
+       we also need to check whether `m.DeclaringType == closure_invocation_type'
+       before bypassing the permission checks.  We might be accessing
+       protected/private members from the base class.
+       (TypeManager.RealMemberLookup): Only set private_ok if private
+       members were requested via BindingFlags.NonPublic.
+
+       * ecore.cs (MethodGroupExpr.IsExplicitImpl): New property.
+
+       * expression.cs (MemberAccess.ResolveMemberAccess): Set
+       MethodGroupExpr.IsExplicitImpl if appropriate.
+       (Invocation.DoResolve): Don't report the CS0120 for explicit
+       interface implementations.
+
+2002-08-27  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Invocation.DoResolve): If this is a static
+       method and we don't have an InstanceExpression, we must report
+       a CS0120.
+
+2002-08-25  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Binary.ResolveOperator): Don't allow `!=' and
+       `==' between a valuetype and an object.
+
+2002-08-25  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (TypeExpr): Provide a ToString method.
+
+2002-08-24  Martin Baulig  <martin@gnome.org>
+
+       * codegen.cs (CodeGen.InitMonoSymbolWriter): The symbol file is
+       now called proggie.dbg and it's a binary file.
+
+2002-08-23  Martin Baulig  <martin@gnome.org>
+
+       * decl.cs (MemberCache.AddMethods): Ignore varargs methods.
+
+2002-08-23  Martin Baulig  <martin@gnome.org>
+
+       * struct.cs (MyStructInfo.ctor): Make this work with empty
+       structs; it's not allowed to use foreach() on null.
+
+2002-08-23  Martin Baulig  <martin@gnome.org>
+
+       * codegen.cs (CodeGen.InitMonoSymbolWriter): Tell the symbol
+       writer the full pathname of the generated assembly.
+
+2002-08-23  Martin Baulig  <martin@gnome.org>
+
+       * statements.cs (FlowBranching.UsageVector.MergeChildren):
+       A `finally' block never returns or breaks; improved handling of
+       unreachable code.
+
+2002-08-23  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (Throw.Resolve): Allow `throw null'.
+
+2002-08-23  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (MemberAccess.ResolveMemberAccess): If this is an
+       EventExpr, don't do a DeclaredOnly MemberLookup, but check whether
+       `ee.EventInfo.DeclaringType == ec.ContainerType'.  The
+       MemberLookup would return a wrong event if this is an explicit
+       interface implementation and the class has an event with the same
+       name.
+
+2002-08-23  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (Block.AddChildVariableNames): New public method.
+       (Block.AddChildVariableName): Likewise.
+       (Block.IsVariableNameUsedInChildBlock): Likewise.
+       (Block.AddVariable): Check whether a variable name has already
+       been used in a child block.
+
+       * cs-parser.jay (declare_local_variables): Mark all variable names
+       from the current block as being used in a child block in the
+       implicit block.
+
+2002-08-23  Martin Baulig  <martin@gnome.org>
+
+       * codegen.cs (CodeGen.InitializeSymbolWriter): Abort if we can't
+       find the symbol writer.
+
+       * driver.cs: csc also allows the arguments to /define being
+       separated by commas, not only by semicolons.
+
+2002-08-23  Martin Baulig  <martin@gnome.org>
+
+       * interface.cs (Interface.GetMembers): Added static check for events.
+
+2002-08-15  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (MethodData.EmitDestructor): In the Expression.MemberLookup
+       call, use ec.ContainerType.BaseType as queried_type and invocation_type.
+
+       * ecore.cs (Expression.MemberLookup): Added documentation and explained
+       why the MethodData.EmitDestructor() change was necessary.
+
+2002-08-20  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (TypeContainer.FindMembers): Added static check for events.
+
+       * decl.cs (MemberCache.AddMembers): Handle events like normal members.
+
+       * typemanager.cs (TypeHandle.GetMembers): When queried for events only,
+       use Type.GetEvents(), not Type.FindMembers().
+
+2002-08-20  Martin Baulig  <martin@gnome.org>
+
+       * decl.cs (MemberCache): Added a special method cache which will
+       be used for method-only searched.  This ensures that a method
+       search will return a MethodInfo with the correct ReflectedType for
+       inherited methods.      
+
+2002-08-20  Martin Baulig  <martin@gnome.org>
+
+       * decl.cs (DeclSpace.FindMembers): Made this public.
+
+2002-08-20  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * delegate.cs: fixed build on windows.
+       [FIXME:  Filed as bug #29150: MCS must report these errors.]
+
+2002-08-19  Ravi Pratap  <ravi@ximian.com>
+
+       * ecore.cs (StandardConversionExists): Return a false
+       if we are trying to convert the void type to anything else
+       since that is not allowed.
+
+       * delegate.cs (DelegateInvocation.DoResolve): Ensure that
+       we flag error 70 in the event an event is trying to be accessed
+       directly from outside the declaring type.
+
+2002-08-20  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs, decl.cs: Moved MemberList, IMemberContainer and
+       MemberCache from typemanager.cs to decl.cs.
+
+2002-08-19  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (TypeContainer): Implement IMemberContainer.
+       (TypeContainer.DefineMembers): Create the MemberCache.
+       (TypeContainer.FindMembers): Do better BindingFlags checking; only
+       return public members if BindingFlags.Public was given, check
+       whether members are static.
+
+2002-08-16  Martin Baulig  <martin@gnome.org>
+
+       * decl.cs (DeclSpace.Define): Splitted this in Define and
+       DefineMembers.  DefineMembers is called first and initializes the
+       MemberCache.
+
+       * rootcontext.cs (RootContext.DefineMembers): New function.  Calls
+       DefineMembers() on all our DeclSpaces.
+
+       * class.cs (TypeContainer.Define): Moved all code to DefineMembers(),
+       but call DefineMembers() on all nested interfaces.  We call their
+       Define() in our new Define() function.
+
+       * interface.cs (Interface): Implement IMemberContainer.
+       (Interface.Define): Moved all code except the attribute stuf to
+       DefineMembers().
+       (Interface.DefineMembers): Initialize the member cache.
+
+       * typemanager.cs (IMemberFinder): Removed this interface, we don't
+       need this anymore since we can use MemberCache.FindMembers directly.
+
+2002-08-19  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (MemberCache): When creating the cache for an
+       interface type, add all inherited members.
+       (TypeManager.MemberLookup_FindMembers): Changed `ref bool searching'
+       to `out bool used_cache' and documented it.
+       (TypeManager.MemberLookup): If we already used the cache in the first
+       iteration, we don't need to do the interfaces check.
+
+2002-08-19  Martin Baulig  <martin@gnome.org>
+
+       * decl.cs (DeclSpace.FindMembers): New abstract method.  Moved this
+       here from IMemberFinder and don't implement this interface anymore.
+       (DeclSpace.MemberCache): Moved here from IMemberFinder.
+
+       * typemanager.cs (IMemberFinder): This interface is now only used by
+       classes which actually support the member cache.
+       (TypeManager.builder_to_member_finder): Renamed to builder_to_declspace
+       since we only put DeclSpaces into this Hashtable.
+       (MemberLookup_FindMembers): Use `builder_to_declspace' if the type is
+       a dynamic type and TypeHandle.GetTypeHandle() otherwise.
+
+2002-08-16  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (ICachingMemberFinder): Removed.
+       (IMemberFinder.MemberCache): New property.
+       (TypeManager.FindMembers): Merged this with RealFindMembers().
+       This function will never be called from TypeManager.MemberLookup()
+       so we can't use the cache here, just the IMemberFinder.
+       (TypeManager.MemberLookup_FindMembers): Check whether the
+       IMemberFinder has a MemberCache and call the cache's FindMembers
+       function.
+       (MemberCache): Rewrote larger parts of this yet another time and
+       cleaned it up a bit.
+
+2002-08-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs (LoadArgs): Support quoting.
+
+       (Usage): Show the CSC-like command line arguments.
+
+       Improved a few error messages.
+
+2002-08-15  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (IMemberContainer.Type): New property.
+       (IMemberContainer.IsInterface): New property.
+
+       The following changes are conditional to BROKEN_RUNTIME, which is
+       defined at the top of the file.
+
+       * typemanager.cs (MemberCache.MemberCache): Don't add the base
+       class'es members, but add all members from TypeHandle.ObjectType
+       if we're an interface.
+       (MemberCache.AddMembers): Set the Declared flag if member.DeclaringType
+       is the current type.
+       (MemberCache.CacheEntry.Container): Removed this field.
+       (TypeHandle.GetMembers): Include inherited members.
+
+2002-08-14  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * typemanager.cs: fixed compilation and added a comment on a field that
+       is never used.
+
+2002-08-15  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (ConstructorInitializer.Resolve): In the
+       Expression.MemberLookup call, use the queried_type as
+       invocation_type.
+
+       * typemanager.cs (IMemberContainer.GetMembers): Removed the `bool
+       declared' attribute, it's always true.
+       (IMemberContainer.Parent, IMemberContainer.Name): New properties.
+       (TypeManager.MemberLookup_FindMembers): [FIXME FIXME FIXME] Added
+       temporary wrapper for FindMembers which tells MemberLookup whether
+       members from the base classes are included in the return value.
+       This will go away soon.
+       (TypeManager.MemberLookup): Use this temporary hack here; once the
+       new MemberCache is completed, we don't need to do the DeclaredOnly
+       looping here anymore since the MemberCache will take care of this.
+       (TypeManager.IsSubclassOrNestedChildOf): Allow `type == parent'.
+       (MemberCache): When creating the MemberCache for a class, get
+       members from the current class and all its base classes.
+       (MemberCache.CacheEntry.Container): New field.  This is a
+       temporary hack until the Mono runtime is fixed to distinguish
+       between ReflectedType and DeclaringType.  It allows us to use MCS
+       with both the MS runtime and the unfixed Mono runtime without
+       problems and without accecting performance.
+       (MemberCache.SearchMembers): The DeclaredOnly looping from
+       TypeManager.MemberLookup is now done here.      
+
+2002-08-14  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (MyStructInfo.MyStructInfo): Don't call
+       Type.GetFields on dynamic types but get the fields from the
+       corresponding TypeContainer.
+       (MyStructInfo.GetStructInfo): Added check for enum types.
+
+       * typemanager.cs (MemberList.IsSynchronized): Implemented.
+       (MemberList.SyncRoot): Implemented.
+       (TypeManager.FilterWithClosure): No need to check permissions if
+       closure_start_type == closure_invocation_type, don't crash if
+       closure_invocation_type is null.
+
+2002-08-13  Martin Baulig  <martin@gnome.org>
+
+       Rewrote TypeContainer.FindMembers to use a member cache.  This
+       gives us a speed increase of about 35% for the self-hosting MCS
+       build and of about 15-20% for the class libs (both on GNU/Linux).
+
+       * report.cs (Timer): New class to get enhanced profiling.  This
+       whole class is "TIMER" conditional since it remarkably slows down
+       compilation speed.
+
+       * class.cs (MemberList): New class.  This is an IList wrapper
+       which we're now using instead of passing MemberInfo[]'s around to
+       avoid copying this array unnecessarily.
+       (IMemberFinder.FindMember): Return a MemberList, not a MemberInfo [].
+       (ICachingMemberFinder, IMemberContainer): New interface.
+       (TypeManager.FilterWithClosure): If `criteria' is null, the name
+       has already been checked, otherwise use it for the name comparision.
+       (TypeManager.FindMembers): Renamed to RealMemberFinder and
+       provided wrapper which tries to use ICachingMemberFinder.FindMembers
+       if possible.  Returns a MemberList, not a MemberInfo [].
+       (TypeHandle): New class, implements IMemberContainer.  We create
+       one instance of this class per type, it contains a MemberCache
+       which is used to do the member lookups.
+       (MemberCache): New class.  Each instance of this class contains
+       all members of a type and a name-based hash table.
+       (MemberCache.FindMembers): This is our new member lookup
+       function.  First, it looks up all members of the requested name in
+       the hash table.  Then, it walks this list and sorts out all
+       applicable members and returns them.
+
+2002-08-13  Martin Baulig  <martin@gnome.org>
+
+       In addition to a nice code cleanup, this gives us a performance
+       increase of about 1.4% on GNU/Linux - not much, but it's already
+       half a second for the self-hosting MCS compilation.
+
+       * typemanager.cs (IMemberFinder): New interface.  It is used by
+       TypeManager.FindMembers to call FindMembers on a TypeContainer,
+       Enum, Delegate or Interface.
+       (TypeManager.finder_to_member_finder): New PtrHashtable.
+       (TypeManager.finder_to_container): Removed.
+       (TypeManager.finder_to_delegate): Removed.
+       (TypeManager.finder_to_interface): Removed.
+       (TypeManager.finder_to_enum): Removed.
+
+       * interface.cs (Interface): Implement IMemberFinder.
+
+       * delegate.cs (Delegate): Implement IMemberFinder.
+
+       * enum.cs (Enum): Implement IMemberFinder.
+
+       * class.cs (TypeContainer): Implement IMemberFinder.
+
+2002-08-12  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (TypeExpr.DoResolveType): Mark this as virtual.
+
+2002-08-12  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (ITypeExpression): New interface for expressions which
+       resolve to a type.
+       (TypeExpression): Renamed to TypeLookupExpression.
+       (Expression.DoResolve): If we're doing a types-only lookup, the
+       expression must implement the ITypeExpression interface and we
+       call DoResolveType() on it.
+       (SimpleName): Implement the new ITypeExpression interface.
+       (SimpleName.SimpleNameResolve): Removed the ec.OnlyLookupTypes
+       hack, the situation that we're only looking up types can't happen
+       anymore when this method is called.  Moved the type lookup code to
+       DoResolveType() and call it.
+       (SimpleName.DoResolveType): This ITypeExpression interface method
+       is now doing the types-only lookup.
+       (TypeExpr, TypeLookupExpression): Implement ITypeExpression.
+       (ResolveFlags): Added MaskExprClass.
+
+       * expression.cs (MemberAccess): Implement the ITypeExpression
+       interface.
+       (MemberAccess.DoResolve): Added support for a types-only lookup
+       when we're called via ITypeExpression.DoResolveType().
+       (ComposedCast): Implement the ITypeExpression interface.
+
+       * codegen.cs (EmitContext.OnlyLookupTypes): Removed.  Call
+       Expression.Resolve() with ResolveFlags.Type instead.
+
+2002-08-12  Martin Baulig  <martin@gnome.org>
+
+       * interface.cs (Interface.Define): Apply attributes.
+
+       * attribute.cs (Attribute.ApplyAttributes): Added support for
+       interface attributes.
+
+2002-08-11  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (Block.Emit): Only check the "this" variable if we
+       do not always throw an exception.
+
+       * ecore.cs (PropertyExpr.DoResolveLValue): Implemented, check
+       whether the property has a set accessor.
+
+2002-08-11  Martin Baulig  <martin@gnome.org>
+
+       Added control flow analysis support for structs.
+
+       * ecore.cs (ResolveFlags): Added `DisableFlowAnalysis' to resolve
+       with control flow analysis turned off.
+       (IVariable): New interface.
+       (SimpleName.SimpleNameResolve): If MemberAccess.ResolveMemberAccess
+       returns an IMemberExpr, call DoResolve/DoResolveLValue on it.
+       (FieldExpr.DoResolve): Resolve the instance expression with flow
+       analysis turned off and do the definite assignment check after the
+       resolving when we know what the expression will resolve to.
+
+       * expression.cs (LocalVariableReference, ParameterReference):
+       Implement the new IVariable interface, only call the flow analysis
+       code if ec.DoFlowAnalysis is true.
+       (This): Added constructor which takes a Block argument.  Implement
+       the new IVariable interface.
+       (MemberAccess.DoResolve, MemberAccess.DoResolveLValue): Call
+       DoResolve/DoResolveLValue on the result of ResolveMemberLookup().
+       This does the definite assignment checks for struct members.
+
+       * class.cs (Constructor.Emit): If this is a non-static `struct'
+       constructor which doesn't have any initializer, call
+       Block.AddThisVariable() to tell the flow analysis code that all
+       struct elements must be initialized before control returns from
+       the constructor.
+
+       * statement.cs (MyStructInfo): New public class.
+       (UsageVector.this [VariableInfo vi]): Added `int field_idx'
+       argument to this indexer.  If non-zero, check an individual struct
+       member, not the whole struct.
+       (FlowBranching.CheckOutParameters): Check struct members.
+       (FlowBranching.IsVariableAssigned, SetVariableAssigned): Added
+       overloaded versions of these methods which take an additional
+       `int field_idx' argument to check struct members.
+       (FlowBranching.IsParameterAssigned, SetParameterAssigned): Added
+       overloaded versions of these methods which take an additional
+       `string field_name' argument to check struct member.s
+       (VariableInfo): Implement the IVariable interface.
+       (VariableInfo.StructInfo): New public property.  Returns the
+       MyStructInfo instance of the variable if it's a struct or null.
+       (Block.AddThisVariable): New public method.  This is called from
+       Constructor.Emit() for non-static `struct' constructor which do
+       not have any initializer.  It creates a special variable for the
+       "this" instance variable which will be checked by the flow
+       analysis code to ensure that all of the struct's fields are
+       initialized before control returns from the constructor.
+       (UsageVector): Added support for struct members.  If a
+       variable/parameter is a struct with N members, we reserve a slot
+       in the usage vector for each member.  A struct is considered fully
+       initialized if either the struct itself (slot 0) or all its
+       members are initialized.
+
+2002-08-08  Martin Baulig  <martin@gnome.org>
+
+       * driver.cs (Driver.MainDriver): Only report an error CS5001
+       if there were no compilation errors.
+
+       * codegen.cs (EmitContext.EmitContext): Use the DeclSpace's
+       `UnsafeContext' property to determine whether the parent is in
+       unsafe context rather than checking the parent's ModFlags:
+       classes nested in an unsafe class are unsafe as well.
+
+2002-08-08  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (UsageVector.MergeChildren): Distinguish between
+       `Breaks' and `Returns' everywhere, don't set `Breaks' anymore if
+       we return.  Added test17() and test18() to test-154.cs.
+
+2002-08-08  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (TypeManager.FilterWithClosure): If we have
+       Family access, make sure the invoking type isn't a subclass of the
+       queried type (that'd be a CS1540).
+
+       * ecore.cs (Expression.MemberLookup): Added overloaded version of
+       this method which takes an additional `Type invocation_type'.
+
+       * expression.cs (BaseAccess.DoResolve): Use the base type as
+       invocation and query type.
+       (MemberAccess.DoResolve): If the lookup failed and we're about to
+       report a CS0122, try a lookup with the ec.ContainerType - if this
+       succeeds, we must report a CS1540.
+
+2002-08-08  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (IMemberExpr): Added `bool IsInstance' property.
+       (MethodGroupExpr): Implement the IMemberExpr interface.
+
+       * expression (MemberAccess.ResolveMemberAccess): No need to have
+       any special code for MethodGroupExprs anymore, they're now
+       IMemberExprs.   
+
+2002-08-08  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (TypeManager.FilterWithClosure): Check Assembly,
+       Family, FamANDAssem and FamORAssem permissions.
+       (TypeManager.IsSubclassOrNestedChildOf): New public method.
+
+2002-08-08  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (FlowBranchingType): Added LOOP_BLOCK.
+       (UsageVector.MergeChildren): `break' breaks unless we're in a switch
+       or loop block.
+
+Thu Aug 8 10:28:07 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * driver.cs: implemented /resource option to embed managed resources.
+
+2002-08-07  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (FieldBase.Initializer): Renamed to `init' and made private.
+       (FieldBase.HasFieldInitializer): New public property.
+       (FieldBase.GetInitializerExpression): New public method.  Resolves and
+       returns the field initializer and makes sure it is only resolved once.
+       (TypeContainer.EmitFieldInitializers): Call
+       FieldBase.GetInitializerExpression to get the initializer, this ensures
+       that it isn't resolved multiple times.
+
+       * codegen.cs (EmitContext): Added `bool IsFieldInitialier'.  This tells
+       the resolving process (SimpleName/MemberLookup) that we're currently
+       emitting a field initializer (which must not access any instance members,
+       this is an error CS0236).
+
+       * ecore.cs (SimpleName.Error_ObjectRefRequired): Added EmitContext
+       argument, if the `IsFieldInitializer' flag is set, we must report and
+       error CS0236 and not an error CS0120.   
+
+2002-08-07  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (IMemberExpr): New public interface.
+       (FieldExpr, PropertyExpr, EventExpr): Implement IMemberExpr.
+       (SimpleName.SimpleNameResolve): Call MemberAccess.ResolveMemberAccess
+       if the expression is an IMemberExpr.
+
+       * expression.cs (MemberAccess.ResolveMemberAccess): Allow `left'
+       to be null, implicitly default to `this' if we're non-static in
+       this case.  Simplified the code a lot by using the new IMemberExpr
+       interface.  Also fixed bug #28176 here.
+
+2002-08-06  Martin Baulig  <martin@gnome.org>
+
+       * cs-parser.jay (SimpleLookup): Removed.  We need to create
+       ParameterReferences during semantic analysis so that we can do a
+       type-only search when resolving Cast, TypeOf and SizeOf.
+       (block): Pass the `current_local_parameters' to the Block's
+       constructor.
+
+       * class.cs (ConstructorInitializer): Added `Parameters parameters'
+       argument to the constructor.
+       (ConstructorInitializer.Resolve): Create a temporary implicit
+       block with the parameters.
+
+       * ecore.cs (SimpleName.SimpleNameResolve): Resolve parameter
+       references here if we aren't doing a type-only search.
+
+       * statement.cs (Block): Added constructor which takes a
+       `Parameters parameters' argument.
+       (Block.Parameters): New public property.
+
+       * support.cs (InternalParameters.Parameters): Renamed `parameters'
+       to `Parameters' and made it public readonly.
+
+2002-08-06  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (Expression.Warning): Made this public as well.
+
+       * report.cs (Report.Debug): Print the contents of collections.
+
+2002-08-06  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (Expression.ResolveFlags): New [Flags] enum.  This is
+       used to tell Resolve() which kinds of expressions it may return.
+       (Expression.Resolve): Added overloaded version of this method which
+       takes a `ResolveFlags flags' argument.  This can be used to tell
+       Resolve() which kinds of expressions it may return.  Reports a
+       CS0118 on error.
+       (Expression.ResolveWithSimpleName): Removed, use Resolve() with
+       ResolveFlags.SimpleName.
+       (Expression.Error118): Added overloaded version of this method which
+       takes a `ResolveFlags flags' argument.  It uses the flags to determine
+       which kinds of expressions are allowed.
+
+       * expression.cs (Argument.ResolveMethodGroup): New public method.
+       Resolves an argument, but allows a MethodGroup to be returned.
+       This is used when invoking a delegate.
+
+       * TODO: Updated a bit.
+
+2002-08-06  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       Fixed compilation with csc.
+
+       * ecore.cs: Expression.Error made public. Is this correct? Should
+       Warning be made public too?
+
+       * expression.cs: use ea.Location instead of ea.loc.
+       [FIXME:  Filed as bug #28607: MCS must report these errors.]
+
+2002-08-06  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (Expression.loc): Moved the location here instead of
+       duplicating it in all derived classes.
+       (Expression.Location): New public property.
+       (Expression.Error, Expression.Warning): Made them non-static and
+       removed the location argument.
+       (Expression.Warning): Added overloaded version which takes an
+       `int level' argument.
+       (Expression.Error118): Make this non-static and removed the
+       expression and location arguments.
+       (TypeExpr): Added location argument to the constructor.
+
+       * expression.cs (StaticCallExpr): Added location argument to
+       the constructor.
+       (Indirection, PointerArithmetic): Likewise.
+       (CheckedExpr, UnCheckedExpr): Likewise.
+       (ArrayAccess, IndexerAccess, UserCast, ArrayPtr): Likewise.
+       (StringPtr): Likewise.
+
+
+2002-08-05  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (BaseAccess.DoResolve): Actually report errors.
+
+       * assign.cs (Assign.DoResolve): Check whether the source
+       expression is a value or variable.
+
+       * statement.cs (Try.Resolve): Set ec.InTry/InCatch/InFinally
+       while resolving the corresponding blocks.
+
+       * interface.cs (Interface.GetInterfaceTypeByName): Actually report
+       an error, don't silently return null.
+
+       * statement.cs (Block.AddVariable): Do the error reporting here
+       and distinguish between CS0128 and CS0136.
+       (Block.DoResolve): Report all unused labels (warning CS0164).
+       (LabeledStatement): Pass the location to the constructor.
+       (LabeledStatement.HasBeenReferenced): New property.
+       (LabeledStatement.Resolve): Set it to true here.
+
+       * statement.cs (Return.Emit): Return success even after reporting
+       a type mismatch error (CS0126 or CS0127), this is what csc does and
+       it avoids confusing the users with any consecutive errors.
+
+2002-08-05  Martin Baulig  <martin@gnome.org>
+
+       * enum.cs (Enum.LookupEnumValue): Catch circular definitions.
+
+       * const.cs (Const.LookupConstantValue): Catch circular definitions.
+
+       * expression.cs (MemberAccess.DoResolve): Silently return if an
+       error has already been reported.
+
+       * ecore.cs (Expression.MemberLookupFinal): Silently return if an
+       error has already been reported.
+
+2002-08-05  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (UsageVector): Only initialize the `parameters'
+       vector if we actually have any "out" parameters.
+
+2002-08-05  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Binary.ResolveOperator): When combining delegates,
+       they must have the same type.
+
+2002-08-05  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (TypeManager.GetArgumentTypes): Don't call
+       PropertyInfo.GetIndexParameters() on dynamic types, this doesn't
+       work with the ms runtime and we also don't need it: if we're a
+       PropertyBuilder and not in the `indexer_arguments' hash, then we
+       are a property and not an indexer.
+
+       * class.cs (TypeContainer.AsAccessible): Use Type.IsArray,
+       Type.IsPointer and Type.IsByRef instead of Type.HasElementType
+       since the latter one doesn't work with the ms runtime.
+
+2002-08-03  Martin Baulig  <martin@gnome.org>
+
+       Fixed bugs #27998 and #22735.
+
+       * class.cs (Method.IsOperator): New public field.
+       (Method.CheckBase): Report CS0111 if there's already a method
+       with the same parameters in the current class.  Report CS0508 when
+       attempting to change the return type of an inherited method.
+       (MethodData.Emit): Report CS0179 if a method doesn't have a body
+       and it's not marked abstract or extern.
+       (PropertyBase): New abstract base class for Property and Indexer.
+       (PropertyBase.CheckBase): Moved here from Property and made it work
+       for indexers.
+       (PropertyBase.Emit): Moved here from Property.Emit, Indexer.Emit is
+       the same so we can reuse it there.
+       (Property, Indexer): Derive from PropertyBase.
+       (MethodSignature.inheritable_property_signature_filter): New delegate
+       to find properties and indexers.
+
+       * decl.cs (MemberCore.CheckMethodAgainstBase): Added `string name'
+       argument and improved error reporting.
+
+       * parameter.cs (Parameters.GetEmptyReadOnlyParameters): Renamed to
+       EmptyReadOnlyParameters and made it a property.
+
+       * typemanager.cs (TypeManager.GetArgumentTypes): Added overloaded
+       version of this method which takes a `PropertyInfo indexer'.
+       (TypeManager.RegisterIndexer): New method.
+
+       * class.cs: Added myself as author of this file :-)
+
+2002-08-03  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * class.cs: fixed compilation on windoze.
+
+2002-08-03  Martin Baulig  <martin@gnome.org>
+
+       * interface.cs (Interface.GetInterfaceBases): Check whether all
+       base interfaces are at least as accessible than the current one.
+
+       * class.cs (TypeContainer.GetClassBases): Check whether base types
+       are at least as accessible than the current type.
+       (TypeContainer.AsAccessible): Implemented and made non-static.
+       (MemberBase.CheckParameters): Report errors if the accessibility
+       checks fail.
+
+       * delegate.cs (Delegate.Delegate): The default visibility is
+       internal for top-level types and private for nested types.
+       (Delegate.Define): Report errors if the accessibility checks fail.
+
+       * enum.cs (Enum.Enum): The default visibility is internal for
+       top-level types and private for nested types.
+       (Enum.DefineType): Compute the correct visibility.
+
+       * modifiers.cs (Modifiers.TypeAttr): Added a version of this
+       function which takes a `bool is_toplevel' instead of a TypeContainer.
+
+       * typemanager.cs (TypeManager.IsBuiltinType): `void' is also a
+       builtin type.
+
+2002-08-02  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (LocalVariableReferenc): Added constructor which
+       takes additional `VariableInfo vi' and `bool is_readonly' arguments.
+       (LocalVariableReference.IsReadOnly): New property.
+       (LocalVariableReference.DoResolveLValue): Report a CS1604 if the
+       variable is readonly, use our own readonly flag to do this; you can
+       use the new constructor to get a writable reference to a read-only
+       variable.
+
+       * cs-parser.jay (foreach_statement, using_statement): Get a writable
+       reference to the local variable.
+
+2002-08-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs (ResolveCore): Also include System.Exception
+
+       * statement.cs (Block.Emit): Do not emit the dead-code warnings if
+       we reach an EmptyStatement.
+
+       (Catch.DoResolve, Throw.DoResolve): Throwing the System.Exception
+       is also fine.
+
+       * expression.cs (Binary.ResolveOperator): Check error result in
+       two places.
+
+       use brtrue/brfalse directly and avoid compares to null.
+
+2002-08-02  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (TypeContainer.Define): Define all nested interfaces here.
+       Fixes bug #28407, added test-155.cs.
+
+2002-08-01  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (Event.EmitDefaultMethod): Make this work with static
+       events.  Fixes #28311, added verify-3.cs.
+
+2002-08-01  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (ForeachHelperMethods): Added `enumerator_type' and
+       `is_disposable' fields.
+       (Foreach.GetEnumeratorFilter): Set `hm.enumerator_type' and
+       `hm.is_disposable' if we're using the collection pattern.
+       (Foreach.EmitCollectionForeach): Use the correct type for the
+       enumerator's local variable, only emit the try/finally block if
+       necessary (fixes #27713).
+
+2002-08-01  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (Expression.report118): Renamed to Error118 and made
+       it public static.
+
+       * statement.cs (Throw.Resolve): Check whether the expression is of
+       the correct type (CS0118) and whether the type derives from
+       System.Exception (CS0155).
+       (Catch.Resolve): New method.  Do the type lookup here and check
+       whether it derives from System.Exception (CS0155).
+       (Catch.CatchType, Catch.IsGeneral): New public properties.
+
+       * typemanager.cs (TypeManager.exception_type): Added.
+
+2002-07-31  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Updated About function.
+
+2002-07-31  Martin Baulig  <martin@gnome.org>
+
+       Implemented Control Flow Analysis.
+
+       * codegen.cs (EmitContext.DoFlowAnalysis): New public variable.
+       (EmitContext.CurrentBranching): Added.
+       (EmitContext.StartFlowBranching): Added.
+       (EmitContext.EndFlowBranching): Added.
+       (EmitContext.KillFlowBranching): Added.
+       (EmitContext.IsVariableAssigned): Added.
+       (EmitContext.SetVariableAssigned): Added.
+       (EmitContext.IsParameterAssigned): Added.
+       (EmitContext.SetParameterAssigned): Added.
+       (EmitContext.EmitTopBlock): Added `InternalParameters ip' argument.
+       Added control flow analysis stuff here.
+
+       * expression.cs (Unary.DoResolve): If the operator is Oper.AddressOf,
+       resolve the expression as lvalue.
+       (LocalVariableReference.DoResolve): Check whether the variable has
+       already been assigned.
+       (ParameterReference.DoResolveLValue): Override lvalue resolve to mark
+       the parameter as assigned here.
+       (ParameterReference.DoResolve): Check whether the parameter has already
+       been assigned.
+       (Argument.Resolve): If it's a `ref' or `out' argument, resolve the
+       expression as lvalue.
+
+       * statement.cs (FlowBranching): New class for the flow analysis code.
+       (Goto): Resolve the label in Resolve, not in Emit; added flow analysis.
+       (LabeledStatement.IsDefined): New public property.
+       (LabeledStatement.AddUsageVector): New public method to tell flow
+       analyis that the label may be reached via a forward jump.
+       (GotoCase): Lookup and resolve the label in Resolve, not in Emit; added
+       flow analysis.
+       (VariableInfo.Number): New public field.  This is used by flow analysis
+       to number all locals of a block.
+       (Block.CountVariables): New public property.  This is the number of
+       local variables in this block (including the locals from all parent
+       blocks).
+       (Block.EmitMeta): Number all the variables.
+
+       * statement.cs: Added flow analysis support to all classes.
+
+2002-07-31  Martin Baulig  <martin@gnome.org>
+
+       * driver.cs: Added "--mcs-debug" argument if MCS_DEBUG is defined.
+       To get debugging messages, compile mcs with /define:MCS_DEBUG and
+       then use this argument.
+
+       * report.cs (Report.Debug): Renamed to conditional to "MCS_DEBUG".
+
+       * makefile.gnu (MCS_FLAGS): Include $(MCS_DEFINES), the user may
+       use this to specify /define options.
+
+2002-07-29  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (Fixed): Moved all code that does variable lookups
+       and resolvings from Emit to Resolve.
+
+       * statement.cs (For): Moved all code that does variable lookups
+       and resolvings from Emit to Resolve.
+
+       * statement.cs (Using): Moved all code that does variable lookups
+       and resolvings from Emit to Resolve.
+
+2002-07-29  Martin Baulig  <martin@gnome.org>
+
+       * attribute.cs (Attribute.Resolve): Explicitly catch a
+       System.NullReferenceException when creating the
+       CustromAttributeBuilder and report a different warning message.
+
+2002-07-29  Martin Baulig  <martin@gnome.org>
+
+       * support.cs (ParameterData.ParameterName): Added method to
+       get the name of a parameter.
+
+       * typemanager.cs (TypeManager.IsValueType): New public method.
+
+2002-07-29  Martin Baulig  <martin@gnome.org>
+
+       * parameter.cs (Parameter.Modifier): Added `ISBYREF = 8'.  This
+       is a flag which specifies that it's either ref or out.
+       (Parameter.GetParameterInfo (DeclSpace, int, out bool)): Changed
+       the out parameter to `out Parameter.Modifier mod', also set the
+       Parameter.Modifier.ISBYREF flag on it if it's either ref or out.
+
+       * support.cs (InternalParameters.ParameterModifier): Distinguish
+       between Parameter.Modifier.OUT and Parameter.Modifier.REF, set the
+       Parameter.Modifier.ISBYREF flag if it's either ref or out.
+
+       * expression.cs (Argument.GetParameterModifier): Distinguish
+       between Parameter.Modifier.OUT and Parameter.Modifier.REF, set the
+       Parameter.Modifier.ISBYREF flag if it's either ref or out.
+
+2002-07-29  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (ParameterReference.ParameterReference): Added
+       `Location loc' argument to the constructor.
+
+       * cs-parser.jay: Pass location to ParameterReference.
+
+2002-07-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Try): Initialize the location.
+
+       * cs-parser.jay: pass location to Try.
+
+       * expression.cs (Unary.Reduce): Change the prototype to return
+       whether a constant fold could be performed or not.  The result is
+       returned in an out parameters.  In the case of Indirection and
+       AddressOf, we want to perform the full tests.
+
+2002-07-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Statement.Emit): Flag dead code.
+
+2002-07-27  Andrew Birkett  <andy@nobugs.org>
+
+       * expression.cs (Unary.Reduce): Handle AddressOf and Indirection.
+
+2002-07-27  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (MethodData.Define): Put back call to
+       TypeManager.AddMethod(), accidentally commented this out.
+
+       * report.cs (Debug): New public method to print debugging information,
+       this is `[Conditional ("DEBUG")]'.
+
+2002-07-26  Martin Baulig  <martin@gnome.org>
+
+       * cs-parser.jay (CSharpParser): Added `Stack switch_stack'.
+       (switch_statement): Push the current_block to the switch_stack and
+       pop it again when we're done with the switch.
+       (switch_section): The new block is a child of the current_block.
+       Fixes bug #24007, added test-152.cs.
+
+2002-07-27  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Invocation.EmitArguments): When calling a varargs
+       function with only its fixed arguments, we need to pass an empty
+       array.
+
+2002-07-27  Martin Baulig  <martin@gnome.org>
+
+       Mono 0.13 has been released.
+
+2002-07-25  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Rename --resource to --linkres, because that is what
+       we do currently, we dont support --resource yet.
+
+       * cs-tokenizer.cs: Fix test for reporting endif mismatches.
+
+2002-07-25  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (MethodData): New public class.  This is a `method builder'
+       class for a method or one accessor of a Property/Indexer/Event.
+       (MethodData.GetMethodFlags): Moved here from MemberBase.
+       (MethodData.ApplyAttributes): Likewise.
+       (MethodData.ApplyObsoleteAttribute): Likewise.
+       (MethodData.ApplyConditionalAttribute): Likewise.
+       (MethodData.ApplyDllImportAttribute): Likewise.
+       (MethodData.CheckAbstractAndExternal): Likewise.
+       (MethodData.Define): Formerly knows as MemberBase.DefineMethod().
+       (MethodData.Emit): Formerly known as Method.Emit().
+       (MemberBase): Moved everything which was specific to a single
+       accessor/method to MethodData.
+       (Method): Create a new MethodData and call Define() and Emit() on it.
+       (Property, Indexer, Event): Create a new MethodData objects for each
+       accessor and call Define() and Emit() on them.
+
+2002-07-25  Martin Baulig  <martin@gnome.org>
+
+       Made MethodCore derive from MemberBase to reuse the code from there.
+       MemberBase now also checks for attributes.
+
+       * class.cs (MethodCore): Derive from MemberBase, not MemberCore.
+       (MemberBase.GetMethodFlags): Moved here from class Method and marked
+       as virtual.
+       (MemberBase.DefineAccessor): Renamed to DefineMethod(), added
+       `CallingConventions cc' and `Attributes opt_attrs' arguments.
+       (MemberBase.ApplyAttributes): New virtual method; applies the
+       attributes to a method or accessor.
+       (MemberBase.ApplyObsoleteAttribute): New protected virtual method.
+       (MemberBase.ApplyConditionalAttribute): Likewise.
+       (MemberBase.ApplyDllImportAttribute): Likewise.
+       (MemberBase.CheckAbstractAndExternal): Likewise.
+       (MethodCore.ParameterTypes): This is now a property instead of a
+       method, it's initialized from DoDefineParameters().
+       (MethodCore.ParameterInfo): Removed the set accessor.
+       (MethodCore.DoDefineParameters): New protected virtual method to
+       initialize ParameterTypes and ParameterInfo.
+       (Method.GetReturnType): We can now simply return the MemberType.
+       (Method.GetMethodFlags): Override the MemberBase version and add
+       the conditional flags.
+       (Method.CheckBase): Moved some code from Define() here, call
+       DoDefineParameters() here.
+       (Method.Define): Use DoDefine() and DefineMethod() from MemberBase
+       here to avoid some larger code duplication.
+       (Property.Emit, Indexer.Emit): Call CheckAbstractAndExternal() to
+       ensure that abstract and external accessors don't declare a body.
+
+       * attribute.cs (Attribute.GetValidPieces): Make this actually work:
+       `System.Attribute.GetCustomAttributes (attr.Type)' does a recursive
+       lookup in the attribute's parent classes, so we need to abort as soon
+       as we found the first match.
+       (Attribute.Obsolete_GetObsoleteMessage): Return the empty string if
+       the attribute has no arguments.
+
+       * typemanager.cs (TypeManager.AddMethod): Now takes a MemberBase instead
+       of a Method.
+
+2002-07-24  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * cs-parser.jay: reverted previous patch.
+
+2002-07-24  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * cs-parser.jay: fixed bug #22119.
+
+2002-07-24  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * attribute.cs: fixed compilation. The error was:
+       "attribute.cs(571,17): error CS0177: The out parameter 'is_error' must 
+       be assigned to before control leaves the current method."
+       [FIXME:  Filed as bug #28186: MCS must report this error.]
+
+2002-07-25  Martin Baulig  <martin@gnome.org>
+
+       * attribute.cs (Attribute.Conditional_GetConditionName): New static
+       method to pull the condition name ouf of a Conditional attribute.
+       (Attribute.Obsolete_GetObsoleteMessage): New static method to pull
+       the obsolete message and error flag out of an Obsolete attribute.
+
+       * class.cs (Method.GetMethodFlags): New public method to get the
+       TypeManager.MethodFlags for this method.
+       (Method.ApplyConditionalAttribute, Method.ApplyObsoleteAttribute): New
+       private methods.
+       (Method.Define): Get and apply the Obsolete and Conditional attributes;
+       if we're overriding a virtual function, set the new private variable
+       `parent_method'; call the new TypeManager.AddMethod().
+
+       * typemanager.cs (TypeManager.AddMethod): New static method.  Stores
+       the MethodBuilder and the Method in a PtrHashtable.
+       (TypeManager.builder_to_method): Added for this purpose.
+       (TypeManager.MethodFlags): Added IsObsoleteError.
+       (TypeManager.GetMethodFlags): Added `Location loc' argument.  Lookup
+       Obsolete and Conditional arguments in MethodBuilders.  If we discover
+       an Obsolete attribute, emit an appropriate warning 618 / error 619 with
+       the message from the attribute.
+
+2002-07-24  Martin Baulig  <martin@gnome.org>
+
+       * cs-tokenizer.cs: Eat up trailing whitespaces and one-line comments in
+       preprocessor directives, ensure that the argument to #define/#undef is
+       exactly one identifier and that it's actually an identifier.
+
+       Some weeks ago I did a `#define DEBUG 1' myself and wondered why this
+       did not work ....
+
+2002-07-24  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (Foreach.ForeachHelperMethods): Added `Type element_type',
+       initialize it to TypeManager.object_type in the constructor.
+       (Foreach.GetEnumeratorFilter): Set `hm.element_type' to the return type
+       of the `hm.get_current' method if we're using the collection pattern.
+       (Foreach.EmitCollectionForeach): Use `hm.element_type' as the source type
+       for the explicit conversion to make it work when we're using the collection
+       pattern and the `Current' property has a different return type than `object'.
+       Fixes #27713.
+
+2002-07-24  Martin Baulig  <martin@gnome.org>
+
+       * delegate.cs (Delegate.VerifyMethod): Simply return null if the method
+       does not match, but don't report any errors.  This method is called in
+       order for all methods in a MethodGroupExpr until a matching method is
+       found, so we don't want to bail out if the first method doesn't match.
+       (NewDelegate.DoResolve): If none of the methods in the MethodGroupExpr
+       matches, report the 123.  Fixes #28070.
+
+2002-07-24  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (ArrayAccess.EmitStoreOpcode): Moved the
+       TypeManager.TypeToCoreType() to the top of the method so the
+       following equality checks will work.  Fixes #28107.
+
+2002-07-24  Martin Baulig  <martin@gnome.org>
+
+       * cfold.cs (ConstantFold.DoConstantNumericPromotions): "If either
+       operand is of type uint, and the other operand is of type sbyte,
+       short or int, the operands are converted to type long." -
+       Actually do what this comment already told us.  Fixes bug #28106,
+       added test-150.cs.
+
+2002-07-24  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (MethodBase): New abstract class.  This is now a base
+       class for Property, Indexer and Event to avoid some code duplication
+       in their Define() and DefineMethods() methods.
+       (MethodBase.DoDefine, MethodBase.DefineAccessor): Provide virtual
+       generic methods for Define() and DefineMethods().
+       (FieldBase): Derive from MemberBase, not MemberCore.
+       (Property): Derive from MemberBase, not MemberCore.
+       (Property.DefineMethod): Moved all the code from this method to the
+       new MethodBase.DefineAccessor(), just call it with appropriate
+       argumetnts.
+       (Property.Define): Call the new Property.DoDefine(), this does some
+       sanity checks and we don't need to duplicate the code everywhere.
+       (Event): Derive from MemberBase, not MemberCore.
+       (Event.Define): Use the new MethodBase.DefineAccessor() to define the
+       accessors, this will also make them work with interface events.
+       (Indexer): Derive from MemberBase, not MemberCore.
+       (Indexer.DefineMethod): Removed, call MethodBase.DefineAccessor() insstead.
+       (Indexer.Define): Use the new MethodBase functions.
+
+       * interface.cs (InterfaceEvent.InterfaceEvent): Added `Location loc'
+       argument to the constructor.
+       (Interface.FindMembers): Added support for interface events.
+       (Interface.PopluateEvent): Implemented.
+
+       Added test-149.cs for this.  This also fixes bugs #26067 and #24256.
+
+2002-07-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (TypeContainer.AddMethod): Adding methods do not use IsValid,
+       but this is required to check for a method name being the same as
+       the containing class.  
+
+       Handle this now.
+
+2002-07-22  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * interface.cs: initialize variable.
+
+2002-07-23  Martin Baulig  <martin@gnome.org>
+
+       Implemented the IndexerName attribute in interfaces.
+
+       * class.cs (TypeContainer.DefineIndexers): Don't set the indexer
+       name if this is an explicit interface implementation.
+       (Indexer.InterfaceIndexerName): New public variable.  If we're
+       implementing an interface indexer, this is the IndexerName in that
+       interface.  Otherwise, it's the IndexerName.
+       (Indexer.DefineMethod): If we're implementing interface indexer,
+       set InterfaceIndexerName.  Use the new Pending.IsInterfaceIndexer
+       and Pending.ImplementIndexer methods.
+       (Indexer.Define): Also define the PropertyBuilder if we're
+       implementing an interface indexer and this is neither an explicit
+       interface implementation nor do the IndexerName match the one in
+       the interface.
+
+       * pending.cs (TypeAndMethods): Added `MethodInfo [] need_proxy'.
+       If a method is defined here, then we always need to create a proxy
+       for it.  This is used when implementing interface indexers.
+       (Pending.IsInterfaceIndexer): New public method.
+       (Pending.ImplementIndexer): New public method.
+       (Pending.InterfaceMethod): Added `MethodInfo need_proxy' argument.
+       This is used when implementing interface indexers to define a proxy
+       if necessary.
+       (Pending.VerifyPendingMethods): Look in the `need_proxy' array and
+       define a proxy if necessary.
+
+       * interface.cs (Interface.IndexerName): New public variable.
+       (Interface.PopulateIndexer): Set the IndexerName.
+       (Interface.DefineIndexers): New private method.  Populate all the
+       indexers and make sure their IndexerNames match.
+
+       * typemanager.cs (IndexerPropertyName): Added support for interface
+       indexers.
+
+2002-07-22  Martin Baulig  <martin@gnome.org>
+
+       * codegen.cs (EmitContext.HasReturnLabel): New public variable.
+       (EmitContext.EmitTopBlock): Always mark the ReturnLabel and emit a
+       ret if HasReturnLabel.
+       (EmitContext.TryCatchLevel, LoopBeginTryCatchLevel): New public
+       variables.
+
+       * statement.cs (Do.Emit, While.Emit, For.Emit, Foreach.Emit): Save
+       and set the ec.LoopBeginTryCatchLevel.
+       (Try.Emit): Increment the ec.TryCatchLevel while emitting the block.
+       (Continue.Emit): If the ec.LoopBeginTryCatchLevel is smaller than
+       the current ec.TryCatchLevel, the branch goes out of an exception
+       block.  In this case, we need to use Leave and not Br.
+
+2002-07-22  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (Try.Emit): Emit an explicit ret after the end of the
+       block unless the block does not always return or it is contained in
+       another try { ... } catch { ... } block.  Fixes bug #26506.
+       Added verify-1.cs to the test suite.
+
+2002-07-22  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (Switch.TableSwitchEmit): If we don't have a default,
+       then we do not always return.  Fixes bug #24985.
+
+2002-07-22  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Invocation.OverloadedResolve): Do the BetterFunction()
+       lookup on a per-class level; ie. walk up the class hierarchy until we
+       found at least one applicable method, then choose the best among them.
+       Fixes bug #24463 and test-29.cs.
+
+2002-07-22  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (TypeManager.ArrayContainsMethod): Don't check the
+       return types of the methods.  The return type is not part of the
+       signature and we must not check it to make the `new' modifier work.
+       Fixes bug #27999, also added test-147.cs.
+       (TypeManager.TypeToCoreType): Added TypeManager.type_type.
+
+       * expression.cs (Invocation.DoResolve): Call TypeManager.TypeToCoreType()
+       on the method's return type.
+
+2002-07-21  Martin Baulig  <martin@gnome.org>
+
+       * assign.cs: Make this work if the rightmost source is a constant and
+       we need to do an implicit type conversion.  Also adding a few more tests
+       to test-38.cs which should have caught this.
+
+       * makefile.gnu: Disable debugging, there's already the mcs-mono2.exe
+       target in the makefile for this.  The makefile.gnu is primarily intended
+       for end-users who don't want to debug the compiler.
+
+2002-07-21  Martin Baulig  <martin@gnome.org>
+
+       * assign.cs: Improved the Assign class so it can now handle embedded
+       assignments (X = Y = Z = something).  As a side-effect this'll now also
+       consume less local variables.  test-38.cs now passes with MCS, added
+       a few new test cases to that test.
+
+2002-07-20  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Binary.EmitBranchable): Emit correct unsigned branch
+       instructions.  Fixes bug #27977, also added test-146.cs.
+
+2002-07-19  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * cs-tokenizer.cs: fixed getHex ().
+
+2002-07-19  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Invocation.EmitParams): Use TypeManager.LookupType(),
+       not Type.GetType() to lookup the array type.  This is needed when
+       we're constructing an array of a user-defined type.
+       (ArrayAccess.EmitDynamicInitializers): Only emit the Ldelema for
+       single-dimensional arrays, but also for single-dimensial arrays of
+       type decimal.
+
+2002-07-19  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (New.DoEmit): Create a new LocalTemporary each time
+       this function is called, it's not allowed to share LocalBuilders
+       among ILGenerators.
+
+2002-07-19  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Argument.Resolve): Report an error 118 when trying
+       to pass a type as argument.
+
+2002-07-18  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (Expression.ImplicitNumericConversion): Don't emit a
+       Conv_R_Un for the signed `long' type.
+
+2002-07-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (MemberAccess.DoResolve): Do not reuse the field
+       `expr' for the temporary result, as that will fail if we do
+       multiple resolves on the same expression.
+
+2002-07-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (SimpleNameResolve): Use ec.DeclSpace instead of
+       ec.TypeContainer for looking up aliases. 
+
+       * class.cs (TypeContainer): Remove LookupAlias from here.
+
+       * decl.cs (DeclSpace); Move here.
+
+2002-07-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (FindMembers): Only call filter if the constructor
+       bulider is not null.
+
+       Also handle delegates in `NestedTypes' now.  Now we will perform
+       type lookups using the standard resolution process.  This also
+       fixes a bug.
+
+       * decl.cs (DeclSpace.ResolveType): New type resolution routine.
+       This uses Expressions (the limited kind that can be parsed by the
+       tree) instead of strings.
+
+       * expression.cs (ComposedCast.ToString): Implement, used to flag
+       errors since now we have to render expressions.
+
+       (ArrayCreation): Kill FormElementType.  Use ComposedCasts in
+       FormArrayType. 
+
+       * ecore.cs (SimpleName.ToString): ditto.
+
+       * cs-parser.jay: Instead of using strings to assemble types, use
+       Expressions to assemble the type (using SimpleName, ComposedCast,
+       MemberAccess).  This should fix the type lookups in declarations,
+       because we were using a different code path for this.
+
+       * statement.cs (Block.Resolve): Continue processing statements
+       even when there is an error.
+
+2002-07-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Event.Define): Also remove the `remove' method from
+       the list of pending items.
+
+       * expression.cs (ParameterReference): Use ldarg.N (0..3) to
+       generate more compact code. 
+
+2002-07-17  Martin Baulig  <martin@gnome.org>
+
+       * const.cs (Const.LookupConstantValue): Add support for constant
+       `unchecked' and `checked' expressions.
+       Also adding test case test-140.cs for this.
+
+2002-07-17  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (Foreach.GetEnumeratorFilter): When compiling corlib,
+       check whether mi.ReturnType implements the IEnumerator interface; the
+       `==' and the IsAssignableFrom() will fail in this situation.
+
+2002-07-16  Ravi Pratap  <ravi@ximian.com>
+
+       * ecore.cs (SimpleName.SimpleNameResolve) : Apply Gonzalo's fix 
+       here too.
+
+2002-07-16  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * expression.cs: fixed bug #27811.
+
+2002-07-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ParameterReference.AddressOf): Patch from Paolo
+       Molaro: when we are a ref, the value already contains a pointer
+       value, do not take the address of it.
+
+2002-07-14 Rafael Teixeira <rafaelteixeirabr@hotmail.com>
+       * removed mb-parser.jay and mb-tokenizer.cs
+
+Sat Jul 13 19:38:03 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * expression.cs: check against the building corlib void type.
+
+Sat Jul 13 19:35:58 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * ecore.cs: fix for valuetype static readonly fields: when 
+       initializing them, we need their address, not the address of a copy.
+
+Sat Jul 13 17:32:53 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * typemanager.cs: register also enum_type in corlib.
+
+Sat Jul 13 15:59:47 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * class.cs: allow calling this (but not base) initializers in structs.
+
+Sat Jul 13 15:12:06 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * ecore.cs: make sure we compare against the building base types
+       in GetTypeSize ().
+
+Sat Jul 13 15:10:32 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * typemanager.cs: fix TypeToCoreType() to handle void and object
+       (corlib gets no more typerefs after this change).
+
+2002-07-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ArrayCreation.EmitArrayArguments): use
+       Conv.Ovf.U4 for unsigned and Conv.Ovf.I4 for signed.
+
+       (ArrayAccess.LoadArrayAndArguments): Use Conv_Ovf_I and
+       Conv_Ovf_I_Un for the array arguments.  Even if C# allows longs as
+       array indexes, the runtime actually forbids them.
+
+       * ecore.cs (ExpressionToArrayArgument): Move the conversion code
+       for array arguments here.
+
+       * expression.cs (EmitLoadOpcode): System.Char is a U2, use that
+       instead of the default for ValueTypes.
+
+       (New.DoEmit): Use IsValueType instead of
+       IsSubclassOf (value_type)
+       (New.DoResolve): ditto.
+       (Invocation.EmitCall): ditto.
+
+       * assign.cs (Assign): ditto.
+
+       * statement.cs (Unsafe): Ok, so I got the semantics wrong.
+       Statements *are* currently doing part of their resolution during
+       Emit.  
+
+       Expressions do always resolve during resolve, but statements are
+       only required to propagate resolution to their children.
+
+2002-07-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs (CSCParseOption): Finish the /r: and /lib: support.
+
+       (LoadAssembly): Do not add the dll if it is already specified
+       
+       (MainDriver): Add the System directory to the link path at the end,
+       after all the other -L arguments. 
+
+       * expression.cs (ArrayAccess.EmitLoadOpcode): I was using the
+       wrong opcode for loading bytes and bools (ldelem.i1 instead of
+       ldelem.u1) and using the opposite for sbytes.
+
+       This fixes Digger, and we can finally run it.
+
+       * driver.cs (UnixParseOption): Move the option parsing here.  
+       (CSCParseOption): Implement CSC-like parsing of options.
+
+       We now support both modes of operation, the old Unix way, and the
+       new CSC-like way.  This should help those who wanted to make cross
+       platform makefiles.
+
+       The only thing broken is that /r:, /reference: and /lib: are not
+       implemented, because I want to make those have the same semantics
+       as the CSC compiler has, and kill once and for all the confussion
+       around this.   Will be doing this tomorrow.
+
+       * statement.cs (Unsafe.Resolve): The state is checked during
+       resolve, not emit, so we have to set the flags for IsUnsfe here.
+
+2002-07-10  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (MemberAccess.ResolveMemberAccess): Since we can
+       not catch the Error_ObjectRefRequired in SimpleName (as it is
+       possible to have a class/instance variable name that later gets
+       deambiguated), we have to check this here.      
+
+2002-07-10  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (TypeContainer.GetFieldFromEvent): Move away from here,
+       make static and put into Expression.
+
+       (Event.Define): Register the private field of the event with the 
+       TypeManager so that GetFieldFromEvent can get at it.
+
+       (TypeManager.RegisterPrivateFieldOfEvent): Implement to
+       keep track of the private field associated with an event which
+       has no accessors.
+
+       (TypeManager.GetPrivateFieldOfEvent): Implement to get at the
+       private field.
+
+       * ecore.cs (GetFieldFromEvent): RE-write to use the above methods.
+       
+2002-07-10  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Binary.EmitBranchable): this routine emits the
+       Binary expression in a branchable context.  This basically means:
+       we need to branch somewhere, not just get the value on the stack.
+
+       This works together with Statement.EmitBoolExpression.
+
+       * statement.cs (Statement.EmitBoolExpression): Use
+       EmitBranchable. 
+
+2002-07-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (For): Reduce the number of jumps in loops.
+
+       (For): Implement loop inversion for the For statement.
+
+       (Break): We can be breaking out of a Try/Catch controlled section
+       (foreach might have an implicit try/catch clause), so we need to
+       use Leave instead of Br.
+
+       * ecore.cs (FieldExpr.AddressOf): Fix for test-139 (augmented
+       now).  If the instace expression supports IMemoryLocation, we use
+       the AddressOf method from the IMemoryLocation to extract the
+       address instead of emitting the instance.
+
+       This showed up with `This', as we were emitting the instance
+       always (Emit) instead of the Address of This.  Particularly
+       interesting when This is a value type, as we dont want the Emit
+       effect (which was to load the object).
+       
+2002-07-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs: Pass the entry point to the DefinePInvokeMethod
+
+       * statement.cs (Checked): Set the CheckedState during the resolve
+       process too, as the ConvCast operations track the checked state on
+       the resolve process, and not emit.
+
+       * cs-parser.jay (namespace_member_declaration): Flag that we have
+       found a declaration when we do.  This is used to flag error 1529
+
+       * driver.cs: Report ok when we display the help only.
+
+2002-07-06  Andrew Birkett  <adb@tardis.ed.ac.uk>
+
+       * cs-tokenizer.cs (xtoken): Improve handling of string literals.
+
+2002-07-04  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs (define): We also have to track locally the
+       defines.  AllDefines is just used for the Conditional Attribute,
+       but we also need the local defines for the current source code. 
+
+2002-07-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (While, For, Do): These loops can exit through a
+       Break statement, use this information to tell whether the
+       statement is the last piece of code.
+
+       (Break): Flag that we break.
+
+       * codegen.cs (EmitContexts): New `Breaks' state variable.
+
+2002-07-03  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (TypeContainer.MethodModifiersValid): Allow override
+       modifiers in method declarations in structs.  Otherwise, you won't
+       be able to override things like Object.Equals().
+
+2002-07-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Method, Property, Indexer): Do not allow the public
+       modifier to be used in explicit interface implementations.
+
+       (TypeContainer.MethodModifiersValid): Catch virtual, abstract and
+       override modifiers in method declarations in structs
+
+2002-07-02   Andrew Birkett <adb@tardis.ed.ac.uk>
+
+       * cs-tokenizer.cs (adjust_int, adjust_real): Do not abort on
+       integer or real overflow, report an error
+
+2002-07-02  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (TypeManager.InitCoreTypes): When compiling
+       corlib, dynamically call AssemblyBuilder.SetCorlibTypeBuilders()
+       to tell the runtime about our newly created System.Object and
+       System.ValueType types.
+
+2002-07-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (This): Use Stobj/Ldobj when we are a member of a
+       struct instead of Ldarg/Starg.
+
+2002-07-02  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Indirection.Indirection): Call
+       TypeManager.TypeToCoreType() on `expr.Type.GetElementType ()'.
+
+2002-07-02  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (ArrayAccess.EmitStoreOpcode): If the type is a
+       ValueType, call TypeManager.TypeToCoreType() on it.
+       (Invocations.EmitParams): Call TypeManager.TypeToCoreType() on
+       the OpCodes.Newarr argument.
+
+2002-07-02  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Invocation.EmitCall): When compiling corlib,
+       replace all calls to the system's System.Array type to calls to
+       the newly created one.
+
+       * typemanager.cs (TypeManager.InitCodeHelpers): Added a few more
+       System.Array methods.
+       (TypeManager.InitCoreTypes): When compiling corlib, get the methods
+       from the system's System.Array type which must be replaced.
+
+Tue Jul 2 19:05:05 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * typemanager.cs: load unverifiable_code_ctor so we can build
+       corlib using the correct type. Avoid using GetTypeCode() with
+       TypeBuilders.
+       * rootcontext.cs: uses TypeManager.unverifiable_code_ctor and
+       TypeManager.object_type to allow building corlib.
+
+Tue Jul 2 19:03:19 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * ecore.cs: handle System.Enum separately in LoadFromPtr().
+
+2002-07-01  Martin Baulig  <martin@gnome.org>
+
+       * class.cs: Make the last change actually work, we need to check
+       whether `ifaces != null' to avoid a crash.
+
+Mon Jul 1 16:15:03 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * class.cs: when we build structs without fields that implement
+       interfaces, we need to add the interfaces separately, since there is
+       no API to both set the size and add the interfaces at type creation
+       time.
+
+Mon Jul 1 14:50:47 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * expression.cs: the dimension arguments to the array constructors
+       need to be converted if they are a long.
+
+Mon Jul 1 12:26:12 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * class.cs: don't emit ldarg.0 if there is no parent constructor
+       (fixes showstopper for corlib).
+
+2002-06-29  Martin Baulig  <martin@gnome.org>
+
+       MCS now compiles corlib on GNU/Linux :-)
+
+       * attribute.cs (Attribute.ApplyAttributes): Treat Accessors like Method,
+       ie. check for MethodImplOptions.InternalCall.
+
+       * class.cs (TypeContainer.DefineType): When compiling corlib, both parent
+       and TypeManager.attribute_type are null, so we must explicitly check
+       whether parent is not null to find out whether it's an attribute type.
+       (Property.Emit): Always call Attribute.ApplyAttributes() on the GetBuilder
+       and SetBuilder, not only if the property is neither abstract nor external.
+       This is necessary to set the MethodImplOptions on the accessor methods.
+       (Indexer.Emit): Call Attribute.ApplyAttributes() on the GetBuilder and
+       SetBuilder, see Property.Emit().
+
+       * rootcontext.cs (RootContext.PopulateTypes): When compiling corlib, don't
+       populate "System.Object", "System.ValueType" and "System.Attribute" since
+       they've already been populated from BootCorlib_PopulateCoreTypes().
+
+2002-06-29  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (Expression.ImplicitReferenceConversionExists): If expr
+       is the NullLiteral, we also need to make sure that target_type is not
+       an enum type.   
+
+2002-06-29  Martin Baulig  <martin@gnome.org>
+
+       * rootcontext.cs (RootContext.ResolveCore): We must initialize
+       `TypeManager.multicast_delegate_type' and `TypeManager.delegate_type'
+       before calling BootstrapCorlib_ResolveDelegate ().
+
+2002-06-27  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * statement.cs: fixed build-breaker. All tests passed ok.
+
+2002-06-27  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (TypeManager.VerifyUnManaged): Added explicit check
+       for System.Decimal when compiling corlib.
+
+2002-06-27  Martin Baulig  <martin@gnome.org>
+
+       * statement.cs (Switch.TableSwitchEmit): Make this work with empty
+       switch blocks which contain nothing but a default clause.
+
+2002-06-26  Andrew  <adb@tardis.ed.ac.uk>
+
+       * ../errors/cs1501-3.cs: Added new test for struct ctr typechecks.
+
+2002-06-27  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (PropertyExpr.PropertyExpr): Call
+       TypeManager.TypeToCoreType() on the `pi.PropertyType'.
+
+       * typemanager.cs (TypeManager.TypeToCoreType): Return if the type
+       is already a TypeBuilder.
+
+2002-06-27  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (Expression.ImplicitReferenceConversionExists): Use
+       `target_type == TypeManager.array_type', not IsAssignableFrom() in
+       the "from an array-type to System.Array" case.  This makes it work
+       when compiling corlib.
+
+2002-06-27  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (Expression.SimpleNameResolve): If the expression is a
+       non-static PropertyExpr, set its InstanceExpression.  This makes
+       the `ICollection.Count' property work in System/Array.cs.
+
+2002-06-25  Andrew Birkett  <adb@tardis.ed.ac.uk>
+
+       * driver.cs: Made error handling more consistent.  Errors now
+       tracked by Report class, so many methods which used to return int
+       now return void.  Main() now prints success/failure and 
+       errors/warnings message.
+
+       Renamed '--probe' compiler argument to '--expect-error'.  Removed
+       the magic number return values (123 and 124).  Now, if the
+       expected error occurs, the compiler exits with success (exit value
+       0).  If the compilation completes without seeing that particular
+       error, the compiler exits with failure (exit value 1).  The
+       makefile in mcs/errors has been changed to handle the new behaviour.
+
+       * report.cs: Made 'expected error' number a property and renamed
+       it from 'Probe' to 'ExpectedError'.
+
+       * genericparser.cs: Removed error handling support, since it is
+       now all done by Report class.
+
+       * cs-parser.jay, mb-parser.jay: Errors are tracked by Report
+       class, so parse() no longer returns an int.
+
+       * namespace.cs: Use Report.Error instead of GenericParser.error
+
+2002-06-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (TypeContainer.AddMethod, TypeContainer.AddIndexer,
+       TypeContainer.AddOperator): At the front of the list put the
+       explicit implementations, so they get resolved/defined first. 
+
+2002-06-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (TypeContainer.VerifyImplements): Verifies that a given
+       interface type is implemented by this TypeContainer.  Used during
+       explicit interface implementation.
+
+       (Property.Define, Indexer.Define, Method.Define): Validate that
+       the given interface in the explicit implementation is one of the
+       base classes for the containing type.
+
+       Also if we are explicitly implementing an interface, but there is
+       no match in the pending implementation table, report an error.
+
+       (Property.Define): Only define the property if we are
+       not explicitly implementing a property from an interface.  Use the
+       correct name also for those properties (the same CSC uses,
+       although that is really not needed).
+       
+       (Property.Emit): Do not emit attributes for explicitly implemented
+       properties, as there is no TypeBuilder.
+
+       (Indexer.Emit): ditto.
+
+       Hiding then means that we do not really *implement* a pending
+       implementation, which makes code fail.
+
+2002-06-22  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (Expression.Constantify): Call TypeManager.TypeToCoreType() on
+       the return value of Object.GetType().  [FIXME: we need to do this whenever
+       we get a type back from the reflection library].
+
+Fri Jun 21 13:37:57 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * typemanager.cs: make ExpandInterfaces() slip duplicated interfaces.
+
+2002-06-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs: Return null if we can not look up the type.
+
+       * class.cs (TypeContainer.GetClassBases): Use ExpandInterfaces on
+       the interface types found.
+
+       * interface.cs (Interface.GetInterfaceBases): Use ExpandInterfaces on the
+       interface types found.
+
+       * typemanager.cs (GetInterfaces): Make this routine returns alll
+       the interfaces and work around the lame differences between
+       System.Type and System.Reflection.Emit.TypeBuilder in the results
+       result for GetInterfaces.
+       
+       (ExpandInterfaces): Given an array of interface types, expand and
+       eliminate repeated ocurrences of an interface.  This expands in
+       context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
+       be IA, IB, IC.
+       
+2002-06-21  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (TypeManager.EnumToUnderlying): It's now safe to call this function
+       on System.Enum.
+
+2002-06-21  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (TypeManager.TypeToCoreType): New function.  When compiling corlib
+       and called with one of the core types, return the corresponding typebuilder for
+       that type.
+
+       * expression.cs (ArrayAccess.DoResolve): Call TypeManager.TypeToCoreType() on the
+       element type.
+
+2002-06-21  Martin Baulig  <martin@gnome.org>
+
+       * ecore.cs (Expression.ExplicitReferenceConversionExists): Use
+       `target_type.IsArray' instead of `target_type.IsSubclassOf (TypeManager.array_type)'.
+       (Expression.ConvertReferenceExplicit): Likewise.
+
+       * expression.cs (ElementAccess.DoResolve): Likewise.
+       (ElementAccess.DoResolveLValue): Likewise.
+
+2002-06-10  Martin Baulig  <martin@gnome.org>
+
+       * interface.cs (Interface.PopulateIndexer): When creating the setter, we need to
+       add the "value" parameter to the parameter list.
+
+       * statement.cs (Fixed.Emit): Pass the return value of the child block's Emit()
+       to our caller.
+
+2002-06-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ArrayCreation.ExpressionToArrayArgument): Convert
+       the argument to an int, uint, long or ulong, per the spec.  Also
+       catch negative constants in array creation.
+
+Thu Jun 20 17:56:48 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * class.cs: do not allow the same interface to appear twice in
+       the definition list.
+
+Wed Jun 19 22:33:37 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * ecore.cs: don't use ldlen with System.Array.
+
+Wed Jun 19 20:57:40 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * ecore.cs: stobj requires a type argument. Handle indirect stores on enums.
+
+Wed Jun 19 20:17:59 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * modifiers.cs: produce correct field attributes for protected
+       internal. Easy fix so miguel can work on ther harder stuff:-)
+
+2002-06-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * pending.cs: New file.  Move the code from class.cs here.
+       Support clearning the pending flag for all methods (when not doing
+       explicit interface implementation).
+
+Tue Jun 18 10:36:22 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * rootcontext.cs: added a couple more types needed to bootstrap.
+
+2002-06-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (GetConstructor): Use DeclaredOnly to look the
+       constructor in the type, instead of any constructor in the type
+       hierarchy.  Thanks to Paolo for finding this bug (it showed up as
+       a bug in the Mono runtime when applying the params attribute). 
+
+2002-06-16  Rafael Teixeira  <rafaelteixeirabr@hotmail.com>
+       * changed namespace.cs to use "GenericParser.error(...)" instead of "CSharpParser.error(...)"
+
+2002-06-14  Rachel Hestilow  <hestilow@ximian.com>
+
+       * expression.cs (Unary.ResolveOperator): Use TypeManager
+       to resolve the type.
+       
+2002-06-13  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (enum_member_declaration): Pass in the attributes
+       attached.
+
+       * enum.cs (AddEnumMember): Add support to store the attributes associated 
+       with each member too.
+
+       * attribute.cs (CheckAttribute, ApplyAttributes): Update to handle
+       field builders too - this takes care of the enum member case.
+
+2002-06-10  Rachel Hestilow  <hestilow@ximian.com>
+
+       * typemanager.cs (TypeManager.VerifyUnManaged): Allow
+       address-of operator on both value types and pointers.
+       
+2002-06-10  Martin Baulig  <martin@gnome.org>
+
+       * interface.cs (Interface.PopulateIndexer): Add the indexer's
+       PropertyBuilder to the `property_builders' list.
+
+       * expression.cs (Indexers.GetIndexersForTypeOrInterface): New private method.
+       (Indexers.GetIndexersForType): Call GetIndexersForTypeOrInterface() on the
+       `lookup_type' and all its interfaces.  Unfortunately, Type.FindMembers() won't
+       find any indexers which are inherited from an interface.
+
+2002-06-09  Martin Baulig  <martin@gnome.org>
+
+       * const.cs (Const.LookupConstantValue): Convert `Expr' to a literal of
+       the same type as the constant if necessary.  There's also a test-130.cs
+       for this.
+
+       * enum.cs (Enum.ChangeEnumType): Moved to typemanager.cs and made public.
+
+       * typemanager.cs (TypeManager.ChangeType): Previously known as
+       Enum.ChangeEnumType().
+
+2002-06-09  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Cast.TryReduce): Added support for consts.
+
+2002-06-08  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Accessor): Hold attributes information so we can pass
+       it along.
+
+       * cs-parser.jay (get_accessor_declaration, set_accessor_declaration):
+       Modify to pass in attributes attached to the methods.
+
+       (add_accessor_declaration, remove_accessor_declaration): Ditto.
+
+       * attribute.cs (ApplyAttributes, CheckAttribute): Update accordingly
+       to handle the Accessor kind :-)
+
+       * class.cs (Property.Emit, Event.Emit): Apply attributes to the accessors
+       
+2002-06-08  Martin Baulig  <martin@gnome.org>
+
+       * expression.cs (Unary.TryReduceNegative): Added support for
+       ULongConstants.
+
+2002-06-08  Martin Baulig  <martin@gnome.org>
+
+       * enum.cs (Enum.LookupEnumValue): Don't report an error if the
+       name can't be found in the `defined_names' - the caller will do a
+       MemberLookup in this case and thus find methods in System.Enum
+       such as Enum.IsDefined().
+
+2002-06-08  Martin Baulig  <martin@gnome.org>
+
+       * enum.cs (Enum.ChangeEnumType): This is a custom version of
+       Convert.ChangeType() which works with TypeBuilder created types.
+       (Enum.LookupEnumValue, Enum.Define): Use it here.
+
+       * class.cs (TypeContainer.RegisterRequiredImplementations): Added
+       `TypeBuilder.BaseType != null' check.
+       (TypeContainer.FindMembers): Only lookup parent members if we
+       actually have a parent.
+       (Method.EmitDestructor): Added `ec.ContainerType.BaseType != null' check.
+       (ConstructorInitializer.Resolve): Likewise.
+
+       * interface.cs (Interface.FindMembers): Added
+       `TypeBuilder.BaseType != null' check.
+
+       * rootcontext.cs (RootContext.ResolveCore): Added
+       "System.Runtime.CompilerServices.IndexerNameAttribute" to
+       classes_second_stage.
+
+       * typemanager.cs (TypeManager.InitCoreTypes): Don't initialize
+       debug_type and trace_type when compiling with --nostdlib.       
+
+2002-06-07  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (TypeContainer): Added `have_nonstatic_fields' field.
+       (AddField): Set it to true when adding a non-static field.
+       (DefineType): Use `have_nonstatic_fields' to find out whether we
+       have non-static fields, not `Fields != null'.
+
+2002-06-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (SimpleNameResolve): Removed simple bug (we were
+       dereferencing a null on the static-field code path)
+
+2002-05-30  Martin Baulig  <martin@gnome.org>
+
+       * codegen.cs (InitMonoSymbolWriter): Added `string[] args' argument
+       to take command line arguments.  Use reflection to call the new
+       custom `Initialize' function on the symbol writer and pass it the
+       command line arguments.
+
+       * driver.cs (--debug-args): New command line argument to pass command
+       line arguments to the symbol writer.
+
+2002-05-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * assign.cs (DoResolve): Forgot to do the implicit conversion to
+       the target type for indexers and properties.  Thanks to Joe for
+       catching this.
+
+2002-05-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (MethodFlags): returns the method flags
+       (Obsolete/ShouldIgnore) that control warning emission and whether
+       the invocation should be made, or ignored. 
+
+       * expression.cs (Invocation.Emit): Remove previous hack, we should
+       not do this on matching a base type, we should do this based on an attribute
+
+       Only emit calls to System.Diagnostics.Debug and
+       System.Diagnostics.Trace if the TRACE and DEBUG defines are passed
+       on the command line.
+
+       * rootcontext.cs: Global settings for tracing and debugging.
+
+       * cs-tokenizer.cs (define): New utility function to track
+       defines.   Set the global settings for TRACE and DEBUG if found.
+
+2002-05-25  Ravi Pratap  <ravi@ximian.com>
+
+       * interface.cs (Populate*): Pass in the TypeContainer as well as
+       the DeclSpace as parameters so that we can create EmitContexts and
+       then use that to apply attributes etc.
+
+       (PopulateMethod, PopulateEvent, PopulateProperty)
+       (PopulateIndexer): Apply attributes everywhere.
+
+       * attribute.cs (CheckAttribute): Include InterfaceMethod, InterfaceEvent
+       etc.
+
+       (ApplyAttributes): Update accordingly.
+
+       We now apply interface attributes for all members too.
+
+2002-05-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Indexer.Define); Correctly check if we are explicit
+       implementation (instead of checking the Name for a ".", we
+       directly look up if the InterfaceType was specified).
+
+       Delay the creation of the PropertyBuilder.
+
+       Only create the PropertyBuilder if we are not an explicit
+       interface implementation.   This means that explicit interface
+       implementation members do not participate in regular function
+       lookups, and hence fixes another major ambiguity problem in
+       overload resolution (that was the visible effect).
+
+       (DefineMethod): Return whether we are doing an interface
+       implementation. 
+       
+       * typemanager.cs: Temporary hack until we get attributes in
+       interfaces (Ravi is working on that) and we get IndexerName
+       support in interfaces.
+
+       * interface.cs: Register the indexers as properties.
+
+       * attribute.cs (Attribute.Resolve): Catch the error, and emit a
+       warning, I have verified that this is a bug in the .NET runtime
+       (JavaScript suffers of the same problem).
+
+       * typemanager.cs (MemberLookup): When looking up members for
+       interfaces, the parent of an interface is the implicit
+       System.Object (so we succeed in searches of Object methods in an
+       interface method invocation.  Example:  IEnumerable x;  x.ToString
+       ()) 
+
+2002-05-25  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Event): Events should also register if they do
+       implement the methods that an interface requires.
+
+       * typemanager.cs (MemberLookup); use the new GetInterfaces
+       method. 
+
+       (GetInterfaces): The code used to lookup interfaces for a type is
+       used in more than one place, factor it here. 
+
+       * driver.cs: Track the errors at the bottom of the file, we kept
+       on going.
+
+       * delegate.cs (NewDelegate.Emit): We have to emit a null as the
+       instance if the method we are calling is static!
+
+2002-05-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs (ApplyAttributes): Make this function filter out
+       the IndexerName attribute (as that attribute in reality is never
+       applied) and return the string constant for the IndexerName
+       attribute. 
+
+       * class.cs (TypeContainer.Emit): Validate that all the indexers
+       have the same IndexerName attribute, and if so, set the
+       DefaultName attribute on the class. 
+
+       * typemanager.cs: The return value might contain other stuff (not
+       only methods).  For instance, consider a method with an "Item"
+       property and an Item method.
+
+       * class.cs: If there is a problem with the parameter types,
+       return. 
+
+2002-05-24  Ravi Pratap  <ravi@ximian.com>
+
+       * ecore.cs (ImplicitConversionExists): Wrapper function which also
+       looks at user defined conversion after making a call to 
+       StandardConversionExists - we need this for overload resolution.
+
+       * expression.cs : Update accordingly the various method calls.
+
+       This fixes 2 bugs filed against implicit user defined conversions 
+
+2002-05-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs: Track the result of the assignment.
+
+2002-05-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (MemberAccess): Improved error reporting for
+       inaccessible members.
+
+2002-05-22  Martin Baulig  <martin@gnome.org>
+
+       * makefile (mcs-mono2.exe): New target.  This is mcs compiled with
+       itself with debugging support.
+
+2002-05-22  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs ("System.Runtime.InteropServices.StructLayoutAttribute"):
+       Removed, this isn't needed anymore.
+
+2002-05-20  Martin Baulig  <martin@gnome.org>
+
+       * typemanager.cs (InitEnumUnderlyingTypes): "System.Char" can't
+       be underlying type for an enum.
+
+2002-05-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (InitEnumUnderlyingTypes): New helper function
+       that splits out the loading of just the core types.
+
+       * rootcontext.cs (ResolveCore): Split the struct resolution in
+       two, so we can load the enumeration underlying types before any
+       enums are used.
+
+       * expression.cs (Is): Bandaid until we fix properly Switch (see
+       bug #24985 for details).
+
+       * typemanager.cs (ImplementsInterface): The hashtable will contain
+       a null if there are no interfaces implemented.
+
+2002-05-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay (indexer_declarator): It is fine to have array
+       parameters
+
+2002-05-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs: (RegisterBuilder): New function used to register
+       TypeBuilders that implement interfaces.  Since
+       TypeBuilder.GetInterfaces (as usual) does not work with lame
+       Reflection.Emit. 
+       (AddUserType): register interfaces.
+
+       (ImplementsInterface): Use the builder_to_ifaces hash if we are
+       dealing with TypeBuilder.  Also, arrays are showing up as
+       SymbolTypes, which are not TypeBuilders, but whose GetInterfaces
+       methods can not be invoked on them!
+
+       * ecore.cs (ExplicitReferenceConversionExists): Made public.
+       (ImplicitReferenceConversionExists): Split out from
+       StandardConversionExists. 
+
+       * expression.cs (As): We were only implementing one of the three
+       cases for the as operator.  We now implement them all.
+       (Is): Implement the various other cases for Is as well.
+
+       * typemanager.cs (CACHE): New define used to control if we want or
+       not the FindMembers cache.  Seems to have a negative impact on
+       performance currently
+
+       (MemberLookup): Nested types have full acess to
+       enclosing type members
+
+       Remove code that coped with instance/static returns for events, we
+       now catch this in RealFindMembers.
+
+       (RealFindMembers): only perform static lookup if the instance
+       lookup did not return a type or an event.  
+
+2002-05-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * assign.cs (CompoundAssign): We pass more semantic information
+       now to Compound Assignments than we did before: now we have all
+       the information at hand, and now we resolve the target *before* we
+       do the expression expansion, which allows the "CacheValue" method
+       to have the effect we intended (before, a [x] += 1 would generate
+       two differen ArrayAccess expressions from the ElementAccess,
+       during the resolution process).
+
+       (CompoundAssign.DoResolve): Resolve target and original_source here.
+
+2002-05-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ArrayAccess): dropped debugging information. 
+
+       * typemanager.cs: Small bug fix: I was always returning i_members,
+       instead of one of i_members or s_members (depending on which had
+       the content).
+
+       * assign.cs (IAssignMethod.CacheTemporaries): New method.  This
+       method is invoked before any code generation takes place, and it
+       is a mechanism to inform that the expression will be invoked more
+       than once, and that the method should use temporary values to
+       avoid having side effects
+
+       (Assign.Emit): Call CacheTemporaries in the IAssignMethod.
+       
+       * ecore.cs (Expression.CacheTemporaries): Provide empty default
+       implementation.
+
+       * expression.cs (Indirection, ArrayAccess): Add support for
+       CacheTemporaries in these two bad boys. 
+
+       * ecore.cs (LoadFromPtr): figure out on our own if we need to use
+       ldobj or ldind_ref.  
+       (StoreFromPtr): Handle stobj as well.
+
+       * expression.cs (UnaryMutator): Share more code.
+       
+       * typemanager.cs (FindMembers): Thanks to Paolo for tracking this
+       down: I was not tracking the Filter function as well, which
+       was affecting the results of the cache.
+
+2002-05-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs: Remove the hack to handle the CharSet property on
+       StructLayouts. 
+
+2002-05-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs (DoResolve): More uglyness, we now only try to
+       resolve the attribute partially, to extract the CharSet
+       information (only if we are a StructLayout attribute).  Otherwise 
+
+       (GetExtraTypeInfo): Add some code to conditionally kill in the
+       future this.   I am more and more convinced that the .NET
+       framework has special code to handle the attribute setting on
+       certain elements.
+
+       * expression.cs (IsParamsMethodApplicable): Revert my previous
+       foreach change here, it was wrong.
+
+2002-05-13  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs: (pp_primary): Eat the ')' at the end.
+       (pp_expr): do not abort on unknown input, just return.
+       (eval): abort if there are pending chars.
+
+       * attribute.cs (Attribute.Resolve): Positional parameters are
+       optional.  Deal with that case.
+
+       * class.cs (DefineType): Call Attribute.GetExtraTypeInfo to fetch
+       the Ansi/Unicode/Auto information for the type.
+
+       (TypeContainer.DefineType): instantiate the EmitContext here, as
+       we will be using it during the type definition (to resolve
+       attributes) and during the emit phase.
+
+       * attribute.cs (Attribute.GetExtraTypeInfo): This routine is used
+       to pull type information out of the attributes
+
+       (Attribute.Resolve): track the constructor builder, and allow for
+       multiple invocations (structs and classes will use this).
+
+       * ecore.cs (MemberLookupFinal): new version with all the
+       parameters customizable.
+
+       * expression.cs (New.DoResolve): Use MemberLookupFinal to locate
+       constructors.  Return if the result value is null (as the error
+       would have been flagged already by MemberLookupFinal)
+
+       Do not allow instances of abstract classes or interfaces to be
+       created.
+       
+       * class.cs: (MethodSignature.InheritableMemberSignatureCompare):
+       We have to compare the assembly property here when dealing with
+       FamANDAssem and Assembly access modifiers, because we might be
+       creating an assembly from *modules* (that means that we are not
+       getting TypeBuilders for types defined in other modules that are
+       part of this assembly).
+
+       (Method.Emit): If the method is marked abstract and has a body,
+       emit an error. 
+
+       (TypeContainer.DefineMembers): If both the defined member and the
+       parent name match are methods, then do not emit any warnings: let
+       the Method.Define routine take care of flagging warnings.  But if
+       there is a mismatch (method overrides something else, or method is
+       overriwritten by something, then emit warning).
+
+       (MethodSignature.MemberSignatureCompare): If the sig.ret_type is
+       set to null, this means `do not check for the return type on the
+       signature'. 
+
+       (Method.Define): set the return type for the method signature to
+       null, so that we get methods with the same name and parameters and
+       different return types.  This is used to flag warning 114 (you are
+       hiding a method, and you probably want to use the new/override
+       keywords instead).
+
+       * typemanager.cs (MemberLookup): Implemented proper access
+       control, closing a long standing set of bug reports.  The problem
+       was that the Framework only has two bits: Public and NonPublic,
+       and NonPublic includes private and protected methods, but we need
+       to enforce the FamANDAssem, FamOrAssem and Family. 
+
+2002-05-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (GotoCase): Return true: Ammounts to giving up
+       knowledge on whether we return or not, and letting the other case
+       be responsible for it.
+
+2002-05-10  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Do not load directories for each file processed, only
+       do it if there is a pattern.
+
+       * ecore.cs: Report readonly assigns here as well, as we might have
+       been resolved only by MemberAccess.
+
+       (SimpleName.SimpleNameResolve): Also be useful for LValue
+       resolution.   We need this to propagate assign to local readonly variables
+
+       * typemanager.cs: Use a ptrhashtable for the criteria, because we
+       do not want to reuse potential criteria memory.
+
+       * class.cs (MyEventBuilder): Set reflected_type;
+
+       * ecore.cs (Constantify): Added support for constifying bools.
+
+       (RootContext.LookupType): Added a cache for values looked up in
+       the declaration space.
+
+       * typemanager.cs (FindMembers): Now is a front-end to
+       RealFindMembers, and provides a two-level hashtable-based cache to
+       the request.  
+
+       15% performance improvement: from 22.5 to 19.2 seconds.
+
+       * expression.cs (IsParamsMethodApplicable): use foreach.
+       (Invocation.DoResolve): ditto.
+       (New.DoResolve): ditto.
+       (ArrayCreation.DoResolve): ditto.
+
+       * ecore.cs (FindMostEncompassingType): use foreach.
+
+       * delegate.cs (NewDelegate.DoResolve): Use foreach
+
+       * ecore.cs (Expression.FindMostSpecificSource): Use foreach.
+       (RemoveMethods): use foreach.
+
+       * expression.cs (Invocation.MakeUnionSet): Optimization: Use two
+       nested foreach statements instead of for, and also break out of
+       the inner loop once a match is found.
+       
+       (Invocation.OverloadResolve): Use foreach, simplify the code. 
+
+2002-05-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * cfold.cs (BinaryFold): During an enumeration evaluation context,
+       we actually unwrap the expression to allow for extra information
+       to be extracted. 
+
+       * expression.cs: Use Shr_Un on unsigned operations. 
+
+2002-05-08  Ravi Pratap  <ravi@ximian.com>
+
+       * ecore.cs (FindMostEncompass*): Fix trivial bug where the set of 
+       applicable operators was not being considered correctly. This closes
+       the bug Miguel reported.
+
+Wed May 8 16:40:50 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * attribute.cs: check that the type derives from System.Attribute
+       and report the correct error in that case (moved the duplicate code to
+       its own method, too).
+
+Wed May 8 11:50:31 CEST 2002 Paolo Molaro <lupus@ximian.com>
+
+       * attribute.cs: lookup attribute type name as the spec says: first the
+       bare attribute name and then name + "Attribute" (nant compiles with
+       mcs after this fix).
+
+2002-05-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Unary.TryReduceNegative): Ah!  Tricky!  Tricky!
+       Because of the way we parse things, we should try to see if a
+       UIntConstant can fit in an integer.
+
+2002-05-07  Ravi Pratap  <ravi@ximian.com>
+
+       * ecore.cs (GetConversionOperators): Do not pick up op_True operators
+       when we are in an explicit context.
+
+       (ConvertReferenceExplicit): When converting from Iface type S to Class
+       T make sure the rules are implemented as an OR.
+
+       * parameter.cs (ParameterType): Make it a property for now although the
+       purpose really isn't anything immediate.
+       
+       * expression.cs (Is*Applicable): Do better checking on the parameter type
+       of a ref/out parameter. The ones from the system assemblies are already 
+       marked with the correct type so we don't need to do any correction.
+
+       * ecore.cs (StandardConversionExists): Conversion from Interface types to 
+       the object type is standard too so include that.
+
+2002-05-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (StandardConversionExists): Augment with missing code:
+       deal with IntConstant, LongConstants and Enumerations.
+
+       * assign.cs: Report the error, instead of failing silently
+
+       * rootcontext.cs (AddGlobalAttributes): Track attributes on the
+       typecontainer that they are declared, because the
+       typecontainer/namespace will have the list of using clauses that
+       need to be applied.
+
+       Assembly Attributes were escaping the normal registration
+       mechanism. 
+
+       (EmitCode): Apply attributes within an EmitContext that represents
+       the container they were declared on.
+       
+       * cs-parser.jay: Track bases for structs.  How did I get this wrong?
+
+2002-05-06  Ravi Pratap  <ravi@ximian.com>
+
+       * ecore.cs (FindMostEncompassingType, FindMostEncompassedType):
+       Revamp completely - make much cleaner as we now operate only
+       on a set of Types.
+
+       (FindMostSpecificSource, FindMostSpecificTarget): New methods
+       to implement the logic detailed in the spec more correctly.
+
+       (UserDefinedConversion): Update accordingly.
+
+2002-05-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs: Return flow analysis information up.
+
+       * cs-tokenizer.cs (adjust_real): Share code between LITERAL_DOUBLE
+       and the default.
+
+       (token): Do not consume an extra character before calling
+       decimal_digits.
+
+2002-05-06  Piers Haken        <piersh@friskit.com>
+
+       * cs-parser.jay: add 'override' attribute to System.Object.Finalize
+
+2002-05-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Constructor.Emit): Set the IsStatic flag in the
+       EmitContext during the instance constructor initializer
+       resolution, to stop access to instance variables.
+
+       This is mandated by the spec, last paragraph of the `constructor
+       initializers' section. 
+
+2002-05-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay, class.cs (Accessor): new class used to represent
+       an accessor (get or set).  In the past we used `null' to represent
+       a missing accessor.  But this is ambiguous because there was no
+       way to tell in abstract indexers/properties if one of them was
+       specified.
+
+       Now there is a way of addressing that.
+
+       * expression.cs (Indexers.GetIndexersForType): Use TypeManager.MemberLookup
+       instead of FindMembers.
+
+       * class.cs (TypeContainer.EmitFieldInitializer): Do not typecast
+       the result of Assign.Resolve as Assign, but rather as ExpressionStatement.
+
+       * attribute.cs: Treat indexers and properties as the same in terms
+       of applying attributes
+
+       * ecore.cs (FindMostEncompassedType): Use statically initialized
+       EmptyExpressions()s like we do elsewhere to avoid creating useless
+       objects (and we take this out of the tight loop).
+
+       (GetConversionOperators): Move the code to extract the actual
+       operators to a separate routine to clean things up.
+
+2002-05-04  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (FieldExpr): Remove un-needed tests for null, since now
+       events are always registered FieldBuilders.
+       
+       * class.cs (FieldBase): New class shared by Fields 
+
+       * delegate.cs: If we are a toplevel delegate, use our full name.
+       If we are a nested delegate, then only use our tail name.
+
+2002-05-02  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (IsApplicable): Ensure that we add the "&" to
+       ref/out types before comparing it with the type of the argument.
+
+       (IsParamsMethodApplicable): Ditto.
+
+       (Argument.Type): Use TypeManager.LookupType instead of Type.GetType - 
+       silly me ;-)
+
+       * delegate.cs : Handle the case when we have more than one applicable
+       method. Flag an error only when we finish checking all.
+
+2002-05-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: Add support for boolean static initializers.
+
+2002-05-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs: Use proper cast for Events, since we use a MyEventBuilder.
+
+       * parameter.cs (ComputeParameterTypes,
+       ComputeAndDefineParameterTypes): Better error handling: now we
+       clear the `types' cache if we fail during any of the type lookups.
+       We also return the status code correctly to our caller
+
+       * delegate.cs: If we fail to define a delegate, abort the extra
+       steps. 
+
+       * expression.cs (Binary.ResolveOperator): for
+       operator==(object,object) and operator !=(object, object) we also
+       have to verify that there is an implicit conversion from one to
+       the other.
+
+       (ArrayAccess.DoResolve): Array Access can operate on
+       non-variables. 
+
+2002-04-30  Miguel de Icaza  <miguel@ximian.com>
+
+       * assign.cs (CompoundAssign): A new class used as a "flag" that
+       the assignment actually is happening as part of a compound
+       assignment operator.
+
+       During compound assignment, a few new rules exist to enable things
+       like:
+
+       byte b |= 1 + 2
+
+       From the spec:
+       
+       x op= y can be evaluated as x = (T) (x op y) (ie, an explicit cast
+       to the type of x) if y is implicitly convertible to the type of x,
+       and the operator is a builtin operator and the return type of the
+       operator is explicitly convertible to the type of x. 
+
+       * rootcontext.cs: Reset warning level to 2.  4 catches various
+       "interesting" features in mcs, we must clean this up at some
+       point, but currently am trying to kill other bugs ;-)
+
+       * ecore.cs (SimpleName.SimpleNameResolve): Perform member lookups
+       in container classes as well.  
+
+       * expression.cs (Binary.ResolveOperator): Handle string case
+       before anything else (as operator overloading does emit an error
+       before doing anything else).
+
+       This code could go away when we move to a table driven model, but
+       i could not come up with a good plan last night.
+       
+2002-04-30  Lawrence Pit <loz@cable.a2000.nl>
+
+       * typemanager.cs (CSharpName): reimplementation using regex.
+       * class.cs: added null check for fields in Emit
+       * rootcontext.cs: set warninglevel to 4
+
+2002-04-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (CSharpName): reimplemented with Lupus
+       suggestion.
+
+2002-04-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (If): correclty implement Resolve, because we were
+       not catching sem errors in there.  The same process is needed
+       everywhere else. 
+       (Return, StatementExpression, For, While, Do, Throw, Lock): Implement Resolve
+       
+
+       (Statement.Warning_DeadCodeFound): Factorize code.
+       (While): Report dead code here too.
+
+       (Statement): Added Resolve virtual method to allow
+       for resolution split from the emit code.
+
+2002-04-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (EmitBoolExpression): No longer try to resolve the
+       expression here.    
+       (MakeBoolean): New utility function that resolve, implicitly
+       converts to boolean and tags the expression. 
+       
+
+       (If, Do): Implement dead code elimination.
+       (While): Implement loop inversion
+
+       (Do, While, For, If): Resolve the expression prior to calling our
+       code generation.
+
+2002-04-22  Lawrence Pit <loz@cable.a2000.nl>
+
+       * class.cs:
+         - added method Report28 (warning: program has more than one entry point)
+         - added method IsEntryPoint, implements paragraph 10.1 of the spec
+         - modified method Method.Define, the part at the end of the method
+
+       * rootcontext.cs: added static public Location EntryPointLocation;
+         
+       * ../errors/cs0028.cs : Add test case for the above warning.              
+
+       * typemanager.cs:
+         - modified method CSharpName to allow arrays of primitive type to
+           be printed nicely (e.g. instead of System.Int32[][] it now prints
+           int[][])
+         - added method CSharpSignature: returns the signature of a method
+           in string format to be used in reporting errors, warnings, etc.
+
+       * support.cs: InternalParameters.ParameterDesc variable tmp initialized
+       with String.Empty.
+       
+2002-04-26  Ravi Pratap  <ravi@ximian.com>
+
+       * delegate.cs (Define): Fix extremely silly bug where I was
+       setting the type of the 'object' parameter of the BeginInvoke
+       method to System.IAsyncResult instead of System.Object ;-)
+
+2002-04-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (ConstructorInitializer.Resolve): Also use DeclaredOnly
+       here. 
+
+       (Constructor.Emit): return if we fail to initialize the
+       constructor.  Another door closed!  
+
+       * expression.cs (New.DoResolve): Improve error message (from -6 to
+       1501).  Use DeclaredOnly lookup to find the exact constructor.
+
+       * typemanager.cs (MemberLookup): If DeclaredOnly is set, do not
+       loop.  This is useful.
+
+       * cs-parser.jay: Adjust the default parameters so that destructors
+       have the proper signature.
+
+2002-04-26  Martin Baulig  <martin@gnome.org>
+
+       * driver.cs (LoadAssembly): If `assembly' contains any characters
+       which are only valid in path names and not in assembly names
+       (currently slash, backslash and point), use Assembly.LoadFrom ()
+       instead of Assembly.Load () on the `assembly' (before iteration
+       over the link_paths).
+
+2002-04-26  Martin Baulig  <martin@gnome.org>
+
+       * cs-tokenizer.cs (is_hex): Correctly handle lowercase chars.
+
+2002-04-25  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Property): use the new typemanager.MemberLookup
+
+       (TypeContainer.MemberLookup): Implement using the
+       TypeManager.MemberLookup now. 
+       
+       * typemanager.cs: Make MemberLookup a function of the TypeManager,
+       and return MemberInfos, so that these can be used without an
+       EmitContext (what we had before).
+
+2002-04-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: Fix the case where the argument to params if the
+       type of the params.  I omitted handling this before.   Fixed
+
+2002-04-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Call BootCorlib_PopulateCoreType
+
+       * class.cs (Property.CheckBase): Check for properties only, not
+       for all members. 
+
+       * interface.cs: Temporary hack: try/catch around the
+       CustomAttributeBuilder, because I am getting an exception that I
+       do not understand.
+
+       * rootcontext.cs (BootCorlib_PopulateCoreType): Populate some
+       types whose definitions are required to be there (attributes are
+       defined before standard types).
+
+       Compute definitions as we boot the various types, as they are used
+       immediately (value_type class will need object_type, but if we do
+       not initialize object_type, we will pass a null, which will let
+       the runtime pick the System.Object from the existing corlib, which
+       is not what we want).
+
+2002-04-22  Patrik Torstensson <totte@labs2.com>
+
+       * cs-tokenizer.cs: fixed a number of trim() issues.
+
+2002-04-22  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Argument.Type): Ensure that we return the correct
+       type when we have out or ref parameters [in which case we 
+       append a "&"].
+       
+2002-04-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Property, Indexer): Allow extern modifier in there. 
+
+       * typemanager.cs (InitBaseTypes): Initializes object_type and
+       value_type, since those will be used early on during the bootstrap
+       process to compile corlib.
+
+       (InitCoreTypes): Move code from here to InitBaseTypes.
+
+2002-04-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (PropertyExpr): Optimize calls to Array::get_Length on
+       single-dimension arrays as using the ldlen opcode.  
+
+       Daniel Lewis discovered this optimization.  
+
+       * typemanager.cs: Add signature for System.Array::get_Length
+
+2002-04-20  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * statement.cs: report the error when the foreach does not apply to an
+       array nor a collection.
+
+2002-04-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: Add implicit conversions to the operator ~.
+
+       * constant.cs (DecimalConstant.Emit): Emit decimal value.
+
+       * typemanager.cs: Locate the decimal constructor.
+
+2002-04-17  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * attribute.cs: use the new property of TypeOf.
+       * expression.cs: added 'get' property around typearg.
+
+       These changes fix a build breaker reported by NickD. Is this the
+       correct way to fix?  If not, please, revert my changes and make it
+       work :-).
+
+2002-04-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * attribute.cs: Add support for typeof in attribute invocations.
+       I am not sure that this is right though.
+
+2002-04-14  Duncan Mak  <duncan@ximian.com>
+
+       * cfold.cs (BinaryFold): Catch DivideByZeroException in the
+       Binary.Operator.Division case.
+
+2002-04-13  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (DefineType): Ensure that we do a proper check on
+       attribute types and also register it with the TypeManager.
+
+       (TypeContainer.Targets): The default for attribute types is
+       AttributeTargets.All.
+       
+       * attribute.cs (ApplyAttributes): Registering the attribute type
+       is done elsewhere, not when we discover we have a Usage attribute.
+
+2002-04-12  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (VerifyArgumentsCompat): Implement Miguel's suggestion
+       and get rid of is_delegate parameter.
+
+       * everywhere : update.
+       
+2002-04-12  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (compilation_unit): Revamp completely to use
+       some new ideas that I got from Rhys' grammar to solve the problems
+       with assembly level attributes.
+
+       (outer_declaration): New grammar production.
+
+       (attribute_sections): Add.
+
+       (opt_attributes): Base on attribute_sections
+
+       (namespace_declaration): Allow opt_attributes to tackle the case
+       when we have assembly level attributes - we are clever in this
+       regard now ;-)
+
+       * attribute.cs (ApplyAttributes): Do not worry about assembly 
+       attributes in the non-global context.
+
+       * rootcontext.cs (AddGlobalAttributes): Go back to using this
+       instead of SetGlobalAttributes.
+
+       * class.cs, rootcontext.cs : Ensure we define and generate 
+       attribute types before anything else.
+
+       * attribute.cs (CheckAttribute and GetValidPlaces): Handle the exception
+       and flag the new error -20 for the case when the attribute type
+       does not have valid targets specified. csc does not catch this.
+
+       * ../errors/errors.txt : update for error # -20
+
+2002-04-11  Ravi Pratap  <ravi@ximian.com>
+
+       * support.cs (InternalParameters.ParameterModifier): Do some null
+       checking and return sane values.
+
+       * class.cs (Method.Define): If we are a PInvoke method, ensure
+       that we are static and extern. Report error # 601
+
+       * ../errors/cs0601.cs : Add test case for the above error.
+
+2002-04-07  Ravi Pratap  <ravi@ximian.com>
+
+       * rootcontext.cs (attribute_types): We need to keep type of
+       all attribute types separately and emit code for them first.
+
+       (RegisterAttribute) : Implement.
+
+       * class.cs (DefineType): Check if the current Type is a custom
+       attribute type and register it accordingly.
+
+       * rootcontext.cs (AddGlobalAttributes): Fix silly bug where we were
+       adding the first attribute twice and rename to
+
+       (SetGlobalAttributes): this.
+
+       * rootcontext.cs (NamespaceLookup): Run through the aliases too and perform
+       lookups.
+
+       * attribute.cs (ApplyAttributes): Take an additional argument telling us
+       if we are processing global arguments. Hmm, I am unsure of this.
+
+2002-04-12  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+       * expression.cs: added static array of strings to avoid calling
+       Enum.ToString () for Operator in Binary. Significant recover of
+       performance.
+
+2002-04-10  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (FindMembers): Allow the Builders of the various
+       members to be null.  If they are skip them.  This only happens
+       during the PInvoke declaration.
+
+2002-04-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * parameter.cs (Parameters.ComputeParameterTypes): Flag the
+       failure, so we do not keep going afterwards.
+
+       * expression.cs: (Invocation.OverloadResolve): I believe Ravi
+       wanted to pass `false' as the `is_delegate' argument.  If this is
+       the case, why not use delegate_type == null to mean `is_delegate =
+       false' and anything else as is_delegate = true.
+
+Tue Apr  9 05:40:12  2002 Piers Haken <piersh@friskit.com>
+
+       * statement.cs: fixed SimpleSwitchEmit to make 'goto case' goto the
+       code for the section, not the beginning of the tests.
+
+2002-04-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * cfold.cs: Handle operator + (Enum x, Underlying x) 
+
+       * expression.cs (Binary): same.  Warn about errors where we have
+       Enum/Enum in operator + as well.
+
+Mon Apr  8 06:29:03  2002 Piers Haken <piersh@friskit.com>
+
+       * statement.cs:
+               - added support for switch(bool)
+               - optimize loading of I8/U8 constants (ldc.i4, iconv_i8)
+               - add TableSwitchEmit() to handle table-based switch statements
+
+2002-04-05  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Invocation.OverloadResolve): Factor out code which
+       does parameter compatibility checking with arguments so that we can 
+       re-use the code even from Delegate.VerifyApplicability
+
+       (VerifyArgumentsCompat): Move above code here.
+
+       * delegate.cs (VerifyApplicability): Get rid of duplicate code
+       and instead make a call to the above method.
+
+2002-03-31  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (attribute_type): Corresponds to System.Attribute.
+       We use it to keep track of classes which are attribute types.
+
+2002-04-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * delegate.cs (Delegate.Define): Correctly define the types in the
+       presence of fixed and array parameters.
+
+       * class.cs (TypeContainers.FindMembers): Use NonPublic flag while
+       doing FindMembers.
+
+       * ecore.cs (Expression.MemberLookup): Reset binding flags to not
+       include NonPublic after the first iteration.
+
+       * class.cs (Indexer.CheckBase): Only check if both parents are
+       non-null. 
+       
+       * cs-parser.jay (accessor_body): If empty, set to null.
+
+       * ecore.cs (SimpleName.SimpleNameResolve): We did not have the
+       same code path here to resolve constants names that we did have in
+       MemberAccess.DoResolve.  There is too much code duplicated here.
+
+2002-04-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs, makefile: Drop Statementcollection and just use ArrayLists
+
+       * ecore.cs: Optimize UserDefinedConversion by minimizing the calls
+       to MakeUnionSet.
+
+       * cs-tokenizer.cs: Reuse a single StringBuilder for assembling
+       tokens, numbers and strings.
+
+       * ecore.cs (MethodGroupExpr): Make Emit warn about missing
+       parenthesis.
+
+       * delegate.cs: Use ComputeAndDefineParameterTypes for both the
+       asyncronous parameters and the regular parameters.  
+
+       * codegen.cs (CodeGen.Init): Use the constructor that allows us to
+       specify the target directory.
+
+       * expression.cs: (This.DoResolve): Simplify
+       (As.Emit): Optimize, do not generate IsInst if the expression is
+       always of the given type.
+
+       (Is.DoResolve): Bug fix, we were reporting both always/never for
+       the is expression.
+
+       * (Invocation.MakeUnionSet): Simplify vastly and optimize, we were
+       creating too many unnecessary arrays.
+
+2002-03-31  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (EmitFieldInitializer): Use Assign expression to assign
+       fields instead of rolling our own initializer.   Takes care of all
+       implicit conversions, and drops unnecessary static checks/argument.
+
+2002-03-31  Dick Porter  <dick@ximian.com>
+
+       * driver.cs: use the GetDirectories() return values properly, and
+       use "/" as path separator.
+
+2002-03-30  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Unary): Optimize - - expr into expr.
+       (Binary): Optimize a + (-b) into a -b.
+
+       * codegen.cs (CodeGen): Made all methods static.
+
+2002-03-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs: 
+
+       * decl.cs: Rename `definition' into `TypeBuilder' and drop the
+       TypeBuilder property.
+
+       * cs-parser.jay: Drop the use of RecordXXX and use RecordDecl
+       instead. 
+
+       * tree.cs: Removed the various RecordXXXX, and replaced with a
+       single RecordDecl.  Removed all the accessor methods, and just
+       left a single access point Type 
+
+       * enum.cs: Rename DefineEnum to DefineType.
+
+       * decl.cs: New abstract method `DefineType' used to unify the
+       Defines for Enumerations, Interfaces, TypeContainers and
+       Delegates.
+
+       (FindType): Moved LookupInterfaceOrClass here.  Moved the
+       LookupBaseClasses method that used to live in class.cs and
+       interface.cs here, and renamed to FindType.
+       
+       * delegate.cs: Implement DefineType.  Take advantage of the
+       refactored pattern for locating the parent builder without taking
+       the parent_builder argument (which we know does not work if we are
+       nested, and triggering a toplevel definition).
+
+2002-03-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * decl.cs (MemberCore.CheckMethodAgainstBase): Test if the
+       accessibility of a member has changed during override and report
+       an error if so.
+
+       * class.cs (Method.Define, Property.Define): Only complain on
+       overrides if the method is private, any other accessibility is
+       fine (and since we just checked the permission is the same, we are
+       good to go).
+
+       * cs-tokenizer.cs: only line, region, endregion, if, endif, else
+       and elif are processed always.  The other pre-processing
+       directives are only processed if we are "taking" the path
+
+2002-03-29  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (Method.Emit): Only emit symbolic debugging info if the
+       current location is not Null.
+
+       * codegen.cs (CodeGen.SaveSymbols): Split out symbol writing code into
+       a separate method so we can profile it.
+
+       * driver.cs (ShowTime): We need to use `(int) span.TotalSeconds' since
+       `span.Seconds' are just seconds, but no minutes or hours.
+       (MainDriver): Profile the CodeGen.SaveSymbols calls.
+
+2002-03-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Method.Define), (Property.Define), (Indexer.Define):
+       Remove the gratuitous set of Final:
+
+                               // If an interface implementation, then we can set Final.
+                               if (((flags & MethodAttributes.Abstract) == 0) &&
+                                   implementing.DeclaringType.IsInterface)
+                                       flags |= MethodAttributes.Final;
+
+        I do not know what I was smoking when I used that.
+       
+
+       * cs-parser.jay, delegate.cs: Make Delegate be a DeclSpace, first
+       step into fixing the name resolution issues for delegates and
+       unifying the toplevel name resolution.
+
+2002-03-28  Martin Baulig  <martin@gnome.org>
+
+       * class.cs (Method.Emit): If we have a symbol writer, call its
+       OpenMethod(), CloseMethod() and SetMethodSourceRange() methods to
+       tell it about the current method.
+
+       * codegen.cs (EmitContext.Mark): New public method. Tell the symbol
+       writer that we're going to emit the first byte of IL code for a new
+       statement (a new source line).
+       (EmitContext.EmitTopBlock): If we have a symbol writer, call
+       EmitContext.Mark() before emitting any code.
+
+       * location.cs (SymbolDocument): Return null when we're Null.
+
+       * statement.cs (Statement): Moved the `Location loc' variable here.
+       (Statement.EmitBoolExpression): If we have a symbol writer, call
+       ec.Mark() before emitting any code to tell it that we're at the
+       beginning of a new statement.
+       (StatementExpression): Added `Location' argument to the constructor.
+       (Block): Added public readonly variable `StartLocation' and public
+       variable `EndLocation'.  The latter is to be set using SetEndLocation().
+       (Block): Added constructor which takes a start and end location.
+       (Block.SetEndLocation): New method. This sets the end location.
+       (Block.EmitMeta): If we have a symbol writer, tell it the names of the
+       local variables we create.
+       (Block.Emit): If we have a symbol writer, call ec.Mark() before emitting
+       each statement and do also mark the begin and end of the block.
+
+       * cs-parser.jay (block : OPEN_BRACE): Use the new `Block' constructor to
+       tell it the current lexer.Location, use Location.Null for the end of the
+       block.
+       (block : OPEN_BRACE opt_statement_list CLOSE_BRACE): When closing the
+       current block, set its end location using SetEndLocation().
+       (statement_expression): StatementExpression constructor now takes the
+       lexer.Location as additional argument.
+       (for_statement, declare_local_variables): Likewise.
+       (declare_local_variables): When creating a new implicit block, use the
+       new Block constructor and pass it the lexer.Location.
+
+2002-03-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (Expression.MemberLookup): On interfaces, lookup
+       members also on the parent interfaces recursively.
+
+2002-03-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * report.cs: Use new formats, since Gonzalo finished the missing
+       bits. 
+
+       * expression.cs (Binary.ResolveOperator): added missing operator|
+       operator& and operator^ for bool/bool.
+
+       * cs-parser.jay: CheckDef now takes a Location argument that is
+       used to report errors more precisly (instead of reporting the end
+       of a definition, we try to track something which is a lot closer
+       to the source of the problem).
+
+       * cs-tokenizer.cs: Track global token use, so we can properly flag
+       the use of #define/#undef after the first token has been seen.
+
+       Also, rename the reportXXXX to Error_DescriptiveName
+
+       * decl.cs (DeclSpace.IsTopLevel): Move property here from
+       TypeContainer, so that Enum and Interface can use this too.
+
+       * class.cs (TypeContainer.LookupInterfaceOrClass,
+       GetInterfaceOrClass, GetClassBases, DefineType): Drop the
+       `builder' argument.  Typically this was used to pass the parent
+       builder (a ModuleBuilder or a TypeBuilder from whoever triggered
+       the definition).  
+
+       The problem is that a nested class could trigger the definition of
+       a toplevel class, and the builder would be obviously wrong in that
+       case. 
+
+       So we drop this argument, and we compute dynamically the
+       TypeBuilder/ModuleBuilder (the correct information was available
+       to us anyways from DeclSpace.Parent)
+
+       * interface.cs (Interface.DefineInterface): Drop builder
+       parameter cleanup like class.cs
+
+       * enum.cs (Enum.DefineEnum): Drop builder parameter.  Clean up
+       like class.cs
+
+       * statement.cs (Switch.EmitObjectInteger): Emit short/ushort
+       values. 
+
+       (Try.Emit): Propagate the returns value from the statement.
+
+       (Return.Emit): Even if we are leavning 
+
+       * driver.cs: Catch IOExpcetion for Directory.GetFiles as well.
+
+       * modifiers.cs: Fix the computation of MethodAttributes flags.
+
+Tue Mar 26 21:14:36 CET 2002 Paolo Molaro <lupus@ximian.com>
+
+       * driver.cs: allow compilation of files that start with '/'.
+       Add a default case when checking the argument of --target.
+
+2002-03-25  Miguel de Icaza  <miguel@ximian.com>
+
+       * interface.cs: Implement the same search algorithm for types in
+       the interface code.
+
+       * delegate.cs: Do not allow multiple definition.
+
+       * Recovered ChangeLog that got accidentally amputated
+
+       * interface.cs (Interface.DefineInterface): Prevent from double definitions.
+
+       * rootcontext.cs: Load manually enum to allow core classes to
+       contain enumerations.
+
+       * enum.cs, ecore.cs, driver.cs, attribute.cs, class.cs, expression.cs:
+       Update to new static methods in TypeManager.
+
+       * typemanager.cs (GetMethod, GetConstructor): Use our
+       implementation of FindMembers to find the members, since during
+       corlib compilation, the types are TypeBuilders and GetMethod and
+       GetConstructor do not work.
+
+       Make all methods in TypeManager static.
+
+       (InitCodeHelpers): Split the functionality from
+       the InitCodeTypes function.
+
+       * driver.cs: Call InitCodeHelpers after we have populated the
+       types. 
+
+       * cs-parser.jay (delegate_declaration): we did not used to compute
+       the delegate name correctly for void delegates.
+
+2002-03-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs (RootContext): Init the interface_resolve_order
+       and type_container_resolve_order always.
+
+       (ResolveCore, BootstrapCorlib_ResolveClass,
+       BootstrapCorlib_ResolveStruct): New functions to bootstrap the
+       compiler when compiling with --nostdlib
+
+       * class.cs (TypeContainer.DefineType): Check that our parent is
+       not null.  This test is most important when we are bootstraping
+       the core types.
+
+       * codegen.cs: Split out the symbol writing code.
+
+2002-03-25  Martin Baulig  <martin@gnome.org>
+
+       * driver.cs (-g): Made -g an alias for --debug.
+
+2002-03-24  Martin Baulig  <martin@gnome.org>
+
+       * codegen.cs (SymbolWriter): New public variable. Returns the
+       current symbol writer.
+       (CodeGen): Added `bool want_debugging_support' argument to the
+        constructor. If true, tell the ModuleBuild that we want debugging
+       support and ask it for the ISymbolWriter.
+       (Save): If we have a symbol writer, call it's Close() method after
+       saving the assembly.
+
+       * driver.c (--debug): New command line argument to create a
+       debugger information file.
+
+       * location.cs (SymbolDocument): New public property. Returns an
+       ISymbolDocumentWriter object for the current source file or null
+       if we don't have a symbol writer.
+
+2002-03-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs (LoadAssembly): Correctly return when all the paths
+       have been tried and not before.
+
+       * statement.cs (Switch.Emit): return the actual coverage for this
+       statement (returns/not-returns)
+
+       (Switch.SimpleSwitchEmit): Do not generate jumps to the end of the
+       switch of the statement if we are the last switch section.  That
+       kills two problems: try/catch problems (we used to emit an empty
+       nop at the end) and switch statements where all branches would
+       return. 
+
+2002-03-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Add default assemblies (the equivalent to the
+       Microsoft CSC.RSP file)
+
+       * cs-tokenizer.cs: When updating `cols and setting it to zero,
+       also update tokens_seen and set it to false.
+
+       * driver.cs: Implement --recurse for Mike.
+
+       * driver.cs (SplitPathAndPattern): Small bug fix, I was not
+       correctly splitting out the paths.
+
+2002-03-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * interface.cs (Interface.PopulateProperty): Instead of using
+       `parent' as the declaration space for the set parameters, use
+       `this' 
+
+       * support.cs (InternalParameters): InternalParameters constructor
+       takes a DeclSpace instead of a TypeContainer.
+
+       * expression.cs (ArrayCreation.EmitDynamicInitializers): If value
+       types are being initialized, load the address of it before calling
+       the function.  
+
+       (New): Provide a mechanism to disable the generation of local
+       value type temporaries when the caller will be providing us with
+       an address to store it.
+
+       (ArrayCreation.EmitDynamicInitializers): Use it.
+
+2002-03-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Invocation.EmitArguments): Only probe for array
+       property if there is more than one argument.  Sorry about that.
+
+       * class.cs (Invocation.EmitArguments): Fix to emit arguments for
+       empty param arrays.
+       
+       * class.cs (Method.LabelParameters): Fix incorrect code path that
+       prevented the `ParamArrayAttribute' from being applied to the
+       params attribute.
+
+2002-03-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * support.cs (ReflectionParameters): Correctly compute whether the
+       last argument is a params array.  Fixes the problem with
+       string.Split ('a')
+
+       * typemanager.cs: Make the assemblies array always be non-null
+       (empty, but non-null)
+
+       * tree.cs (RecordDecl): New function that abstracts the recording
+       of names.  This reports error 101, and provides a pointer to the
+       previous declaration.  Fixes a crash in the compiler.
+
+       * cs-parser.jay (constructor_declaration): Update to new grammar,
+       and provide a constructor_body that can be empty.
+
+2002-03-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Add support for --resources.
+
+       * expression.cs: (FetchGetMethod, FetchAddressMethod, EmitAssign):
+       Make all types for the various array helper methods be integer.
+
+       * ecore.cs (Expression.ConvertNumericExplicit): Pass the
+       CheckState to ConvCast.
+
+       (ConvCast): Now it takes a `checked' state argument, to avoid
+       depending on the emit context for the conversion, and just using
+       the resolve time setting.
+
+       * expression.cs (ArrayCreation.EmitArrayArguments): New function,
+       instead of Invocation.EmitArguments.  We do not emit the original
+       arguments, instead we emit those which have been converted to
+       unsigned int expressions.
+
+       * statement.cs (Block.EmitMeta): Drop tracking of indexes.
+
+       * codegen.cs: ditto.
+
+       * expression.cs (LocalVariableReference): Drop the use of the
+       Store function that depended on the variable index.
+
+       * statement.cs (VariableInfo): Drop the `Idx' property from this
+       class, as this is not taking into account the indexes for
+       temporaries tat we generate during the execution, getting the
+       indexes wrong.
+
+       * class.cs: First emit class initializers, then call the parent
+       constructor. 
+
+       * expression.cs (Binary): Fix opcode emision.
+       (UnaryMutator.EmitCode): Support checked code generation
+
+       * ecore.cs (MemberLookup): TypeManager.FindMembers will return
+       matches for events for both the Static and Instance scans,
+       pointing to the same element.   Fix that.
+
+2002-03-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs (ResolveTree): Always set the
+       interface_resolve_order, because nested interfaces will be calling
+       into us.
+
+       * class.cs (GetInterfaceOrClass): Track the same resolution
+       process used by TypeManager.LookupType.  This fixes the nested
+       type lookups in class declarations (separate path from
+       LookupType). 
+
+       (TypeContainer.DefineType): Also define nested interfaces.
+       (TypeContainer.RegisterOrder): New public function used to
+       register the order in which child interfaces need to be closed.
+
+       Nested interfaces need to be closed after their parents have been
+       created. 
+       
+       * interface.cs (InterfaceAttr): Put all the logic for computing
+       the interface attribute here. 
+
+       (DefineInterface): Register our interface order with the
+       RootContext or with the TypeContainer depending on the case.
+
+2002-03-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: rework foreach statement to work with the new
+       changes to the policy on SimpleNames.
+       
+       * report.cs: support Stacktrace on warnings as well.
+
+       * makefile: drop --unsafe and /unsafe from the compile.
+
+2002-03-13  Ravi Pratap  <ravi@ximian.com>
+
+       * ecore.cs (StandardConversionExists): Modify to take an Expression
+       as the first parameter. Ensure we do null -> reference type conversion
+       checking.
+
+       * Everywhere : update calls accordingly, making use of MyEmptyExpr to store
+       temporary Expression objects.
+
+Wed Mar 13 12:32:40 CET 2002 Paolo Molaro <lupus@ximian.com>
+
+       * interface.cs: workaround bug in method overloading resolution
+       (there is already a bugzilla bug for it).
+
+2002-03-12  Miguel de Icaza  <miguel@ximian.com>
+
+       We could also solve this problem by having a separate path for
+       performing type lookups, instead of DoResolve, we could have a
+       ResolveType entry point, and only participating pieces of the
+       production (simplename, deref, array) would implement this. 
+       
+       * codegen.cs (EmitContext): New field OnlyLookupTypes used to
+       signal SimpleName to only resolve type names and not attempt to
+       resolve anything else.
+
+       * expression.cs (Cast): Set the flag.
+
+       * ecore.cs (SimpleName): Use the OnlyLookupTypes flag
+
+       * class.cs: Only report 108 if there is no `new' modifier.
+
+       * cs-parser.jay: rework foreach statement to work with the new
+       changes to the policy on SimpleNames.
+       
+       * report.cs: support Stacktrace on warnings as well.
+
+       * makefile: drop --unsafe and /unsafe from the compile.
+
+2002-03-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (SimpleName.SimpleNameResolve): Perform local variable
+       lookups here, instead of doing that at parse time.  This means
+       that our grammar will not introduce `LocalVariableReferences' as
+       expressions at this point.  That solves the problem of code like
+       this:
+
+       class X {
+          static void Main ()
+          { int X = 1;
+           { X x = null }}}
+
+       This is only half the fix.  The full fix requires parameters to
+       also be handled in this way.
+
+       * Everywhere: Use ec.DeclSpace on calls to LookupType, as this
+       makes the use more obvious of the DeclSpace.  The
+       ec.TypeContainer.TypeBuilder is now only used to pull the
+       TypeBuilder for it.
+
+       My theory is that I can get rid of the TypeBuilder completely from
+       the EmitContext, and have typecasts where it is used (from
+       DeclSpace to where it matters).  
+
+       The only pending problem is that the code that implements Aliases
+       is on TypeContainer, and probably should go in DeclSpace.
+
+       * ecore.cs (SimpleName.SimpleNameResolve): Perform local variable
+       lookups here, instead of doing that at parse time.  This means
+       that our grammar will not introduce `LocalVariableReferences' as
+       expressions at this point.  That solves the problem of code like
+       this:
+
+       class X {
+          static void Main ()
+          { int X = 1;
+           { X x = null }}}
+
+       This is only half the fix.  The full fix requires parameters to
+       also be handled in this way.
+
+       * class.cs (Property.DefineMethod): When implementing an interface
+       method, set newslot, when implementing an abstract method, do not
+       set the flag (before we tried never setting it, or always setting
+       it, which is the difference).
+       (Indexer.DefineMethod): same.
+       (Method.DefineMethod): same.
+
+       * ecore.cs: Only set the status used flag if we get back a Field.
+
+       * attribute.cs: Temporary hack, so Paolo can keep working.
+
+2002-03-08  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs (Attribute.UnmanagedType): This is to keep track of
+       the unmanaged type in the case we have a MarshalAs attribute.
+
+       (Resolve): Handle the case when we are parsing the special MarshalAs
+       attribute [we need to store the unmanaged type to use later]
+       
+       * typemanager.cs (marshal_as_attr_type): Built in type for the 
+       MarshalAs Attribute.
+
+       * attribute.cs (ApplyAttributes): Recognize the MarshalAs attribute 
+       on parameters and accordingly set the marshalling info.
+       
+2002-03-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs: Optimizing slightly by removing redundant code after
+       we switched to the `NoTypes' return value.
+       (Property.DefineMethod): use NoTypes here too.
+
+       This fixes the bug I introduced in my last batch of changes.
+
+2002-03-05  Ravi Pratap  <ravi@ximian.com>
+
+       * tree.cs (RecordEnum): Add. We now keep track of enums too.
+
+       * class.cs (LookupInterfaceOrClass): Check against the list of recorded
+       Enums since those are types too. 
+
+       * cs-parser.jay (enum_declaration): Record enums as we parse them.
+       
+       * enum.cs (DefineEnum): Return if the TypeBuilder has already been defined 
+       thanks to a call during the lookup process.
+
+2002-03-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Foreach): Lots of work to accomodate a particular
+       kind of foreach statement that I had not kept in mind.  It is
+       possible to have foreachs on classes that provide a GetEnumerator
+       method that return objects that implement the "pattern" for using
+       a foreach, there is no need to support GetEnumerator
+       specifically. 
+
+       This is needed to compile nant.
+
+       * decl.cs: Only report 114 if the member is not `Finalize' and if
+       the warning level is at least 2.
+
+       * class.cs: Moved the compare function from Method to
+       MethodSignature. 
+
+       (MethodSignature.InheritableMemberSignatureCompare): Add new
+       filter function that is used to extract inheritable methods from a
+       class. 
+
+       (Method.Define): Use the new `inheritable_method_signature_filter'
+       delegate
+
+       * cs-tokenizer.cs (get_cmd_arg): Do not add white space to the
+       command. 
+
+2002-03-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (Expression.ConvertReferenceExplicit): Removed dead code.
+
+       * cs-parser.jay: Add opt_semicolon to the interface declaration.
+
+       * expression.cs: Pass location information to
+       ConvertImplicitStandard. 
+
+       * class.cs: Added debugging code to track return values from
+       interfaces. 
+
+2002-03-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Is.DoResolve): If either side of the `is' is an
+       interface, do not flag the warning.
+
+       * ecore.cs (ImplicitReferenceConversion): We need a separate test
+       for interfaces
+
+       * report.cs: Allow for --fatal to be used with --probe.
+       
+       * typemanager.cs (NoTypes): Move the definition for the empty Type
+       array here. 
+
+       * class.cs (TypeContainer.FindMembers): Also look for methods defined by
+       properties. 
+       (TypeContainer.DefineProxy): New function used to proxy to parent
+       implementations when implementing interfaces.
+       (TypeContainer.ParentImplements): used to lookup if our parent
+       implements a public function that is required by an interface.
+       (TypeContainer.VerifyPendingMethods): Hook this up.
+
+       * typemanager.cs (TypeManager, AddModule, AddAssembly): Make the
+       `modules' and `assemblies' arraylists into arrays.  We only grow
+       these are the very early start up of the program, so this improves
+       the speedof LookupType (nicely measured).
+
+       * expression.cs (MakeByteBlob): Replaced unsafe code with
+       BitConverter, as suggested by Paolo.
+
+       * cfold.cs (ConstantFold.Binary): Special case: perform constant
+       folding of string concatenation, but if either side is a string,
+       and the other is not, then return null, and let the runtime use
+       the concatenation on the string plus the object (using
+       `Object.ToString'). 
+
+2002-03-04  Miguel de Icaza  <miguel@ximian.com>
+
+       Constant Folding has been implemented now.
+       
+       * expression.cs (Unary.Reduce): Do not throw an exception, catch
+       the error instead on types that are not supported in one's
+       complement. 
+
+       * constant.cs (Constant and all children): New set of functions to
+       perform implict and explicit conversions.
+       
+       * ecore.cs (EnumConstant): Implement the new functions to perform
+       conversion by proxying to the child expression.
+
+       * codegen.cs: (ConstantCheckState): Constant evaluation has its
+       own separate setting that can not be turned off from the command
+       line using --unchecked or --checked and is only controlled using
+       the checked/unchecked statements and expressions.  This setting is
+       used by the constant folder to flag errors.
+
+       * expression.cs (CheckedExpr, UncheckedExpr): Set the
+       ConstantCheckState as well.   
+
+       During Resolve, they also have to flag the state, because the
+       constant folder runs completely in the Resolve phase.
+
+       * statement.cs (Checked, Unchecked): Set the ConstantCheckState as
+       well.
+
+2002-03-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * cfold.cs: New file, this file contains the constant folder.
+       
+       * ecore.cs (IMemoryLocation.AddressOf): Now takes an extra
+       argument to track whether we are using the resulting address to
+       load or store a value and provide better error messages. 
+
+       (FieldExpr.Emit, FieldExpr.EmitAssign, FieldExpr.AddressOf): Use
+       new AddressOf arguments.
+
+       * statement.cs (Foreach.EmitCollectionForeach): Update
+
+       * expression.cs (Argument.Emit): Call AddressOf with proper
+       arguments to track usage.
+
+       (New.DoEmit): Call AddressOf with new arguments.
+
+       (Unary.Emit): Adjust AddressOf call.
+
+2002-03-01  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (member_access): Change the case for pre-defined types
+       to use a MemberAccess instead of a SimpleName. Thanks to Felix again for 
+       this suggestion.
+
+       * class.cs (Operator::Emit): If we are abstract or extern, we don't have
+       a method body.
+
+       * attribute.cs (CheckAttribute, ApplyAttribute): Ensure that we treat operators
+       essentially like methods and apply attributes like MethodImplOptions to them too.
+
+       * ecore.cs (SimpleName.SimpleNameResolve): Perform a check on ec.TypeContainer.TypeBuilder
+       not being null.
+
+       * codegen.cs (EmitContext): The constructor now takes in an extra argument specifying the
+       DeclSpace as the distinction is important. We provide sane defaults as usually the TypeContainer
+       is the DeclSpace.
+
+       * Update code everywhere accordingly.
+
+       * ecore.cs : Change references to ec.TypeContainer to ec.DeclSpace where appropriate.
+
+       * cs-parser.jay (enum_declaration): Set the current namespace of the enum.
+
+2002-02-28  Ravi Pratap  <ravi@ximian.com>
+
+       * rootcontext.cs (LookupType): As we cycle through the chain of namespaces
+       try performing lookups against those instead of jumping straight into using
+       the 'using' clauses.
+
+       (ImplicitParent): Add. Thanks to Felix Arrese-Igor for this idea.
+
+       (LookupType): Perform lookups in implicit parents too.
+
+       * class.cs (GetInterfaceOrClass): Modify to perform the exact same lookup
+       sequence as RootContext.LookupType. 
+
+       * rootcontext.cs (NamespaceLookup): Split out code from LookupType which tries 
+       the various cases of namespace lookups into this method.
+
+2002-03-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Add support for [Attribute ()] (empty arguments
+       in positional arguments)
+
+       * class.cs (Operator): Update the AllowedModifiers to contain
+       extern. 
+
+       * cs-parser.jay: Update operator declaration to allow for the
+       operator body to be empty.
+
+       * cs-tokenizer.cs: Added '\u' unicode support in strings and hex
+       values. 
+
+2002-02-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Method.Emit): Label parameters.
+
+       * driver.cs: Return 1 or 0 as the program exit code.
+
+2002-02-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: Special case the `null' object when trying to
+       auto-compute the type, as anything can be explicitly converted to
+       that. 
+
+       * ecore.cs (Expression.ConvertExplicit): Bug fix, thanks for
+       spotting this Paolo.
+
+       (Expression.ImplicitNumericConversion): Perform comparissions of
+       the type using the underlying type in the case of an enumeration
+       rather than using the enumeration type for the compare.
+
+       Cope with the underlying == type case, which is not possible to
+       catch before. 
+
+       (Expression.ConvertNumericExplicit): Perform comparissions of
+       the type using the underlying type in the case of an enumeration
+       rather than using the enumeration type for the compare.
+
+       * driver.cs: If the user does not supply an extension, assume .exe
+
+       * cs-parser.jay (if_statement): Rewrote so that we can track the
+       location for the if statement.
+
+       * expression.cs (Binary.ConstantFold): Only concat strings when
+       the operation is "+", not everything ;-)
+
+       * statement.cs (Statement.EmitBoolExpression): Take a location
+       argument. 
+       (If, While, Do): Track location.
+
+       * expression.cs (Binary.ResolveOperator): In the object + string
+       case, I was missing a call to ConvertImplicit
+
+2002-02-25  Ravi Pratap  <ravi@ximian.com>
+
+       * parameter.cs (Parameter.ExternalType): Take in extra DeclSpace and
+       Location arguments. Ensure we use RootContext.LookupType to do our work
+       and not try to do a direct Type.GetType and ModuleBuilder.GetType
+
+       * interface.cs (PopulateMethod): Handle the type of the parameter being
+       null gracefully.
+
+       * expression.cs (Invocation.BetterFunction): Handle the case when we 
+       have a params method with no fixed arguments and a call is made with no
+       arguments.
+
+2002-02-25  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs: Add support for the quote-escape-sequence in
+       the verbatim-string-literal
+
+       * support.cs (InternalParameters.ParameterModifier): handle null
+       fixed parameters.
+       (InternalParameters.ParameterType): ditto.
+
+       * parameter.cs (VerifyArgs): Also check if the fixed parameter is
+       duplicating the name of the variable parameter.
+       (GetParameterByName): Fix bug where we were not looking up array
+       paramters if they were the only present (thanks Paolo!).
+       (GetParameterInfo): We only have an empty set of types if both
+       fixed and array are set to null.
+       (GetParameterInfo-idx): Handle FixedParameter == null
+
+       * cs-parser.jay: Handle the case where there is no catch
+       statements (missing null test).
+
+2002-02-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs (MainDriver): Be conservative on our command line
+       handling.
+
+       Catch DirectoryNotFoundException when calling GetFiles.
+       
+       (SplitPathAndPattern): Used to split the input specification into
+       a path and a pattern that we can feed to Directory.GetFiles.
+
+2002-02-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Fixed): Implement the last case of the Fixed
+       statement (string handling).
+
+       * expression.cs (StringPtr): New class used to return a char * to
+       a string;  Used by the Fixed statement.
+
+       * typemanager.cs: Add char_ptr_type.  Add get_OffsetToStringData method.
+
+       * expression.cs (Binary.ResolveOperator): Remove redundant
+       MemberLookup pn parent type.
+       Optimize union call, we do not need a union if the types are the same.
+       (Unary.ResolveOperator): REmove redundant MemberLookup on parent
+       type.
+
+       Specialize the use of MemberLookup everywhere, instead of using
+       the default settings. 
+
+       (StackAlloc): Implement stackalloc keyword.
+
+       * cs-parser.jay: Add rule to parse stackalloc.
+       
+       * driver.cs: Handle /h, /help, /?
+
+       * expression.cs (MakeByteBlob): Removed the hacks we had in place
+       before we supported unsafe code.
+       
+       * makefile: add --unsafe to the self compilation of mcs.
+
+2002-02-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (PointerArithmetic): New class that is used to
+       perform pointer arithmetic.
+       (Binary.Resolve): Handle pointer arithmetic
+       Handle pointer comparission.
+       (ArrayPtr): Utility expression class that is used to take the
+       address of an array.
+
+       (ElementAccess): Implement array access for pointers
+       
+       * statement.cs (Fixed): Implement fixed statement for arrays, we
+       are missing one more case before we are done.
+
+       * expression.cs (Indirection): Implement EmitAssign and set the
+       ExprClass to Variable.  This allows pointer dereferences to be
+       treated as variables, and to have values assigned to them.
+       
+       * ecore.cs (Expression.StoreFromPtr): New utility function to
+       store values dereferencing.
+
+2002-02-20  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Binary.ResolveOperator): Ensure that we are
+       not trying to operate on a void type - this fixes the reported
+       bug.
+
+       * decl.cs (CheckMethodAgainstBase): Do not allow overriding if
+       the parent implementation is sealed.
+
+       * ../errors/cs0239.cs : Add.
+
+       * attribute.cs (ApplyAttributes): Handle Modulebuilders too.
+
+       * typemanager.cs (unverifiable_code_type): Corresponds to 
+       System.Security.UnverifiableCodeAttribute. We need to emit this for modules
+       which have unsafe code in them.
+
+       * rootcontext.cs (EmitCode): Emit the above attribute when we are in an 
+       unsafe context.
+
+2002-02-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs: Add support for @"litreal strings"
+
+       Make tokenizer accept pre-processor directives
+       on any column (remove the old C-like limitation). 
+
+       * rootcontext.cs (EmitCode): Emit any global attributes.
+       (AddGlobalAttributes): Used to keep track of assembly attributes. 
+
+       * attribute.cs (ApplyAttributes): Support AssemblyAttributes.
+
+       * cs-parser.jay: Add support for global attributes.  
+
+2002-02-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Indirection): New helper class.  Unary will
+       create Indirection classes to be able to implement the
+       IMemoryLocation interface on it.
+
+2002-02-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay (fixed_statement): reference the right statement.
+
+       * statement.cs (Fixed.Emit): Finish implementing the fixed
+       statement for the &x case.
+
+2002-02-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Property.Define, Method.Define): Remove newslot when
+       `implementing'.  
+
+       * modifiers.cs: My use of NewSlot when `Abstract' was set was
+       wrong.  NewSlot should only be used if the `new' keyword is present.
+
+       * driver.cs (GetSystemDir): Use CodeBase instead of FullName for
+       locating our system dir.  Sorry about this.
+
+2002-02-13  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs (GetSystemDir): Compute correctly the location of our
+       system assemblies.  I was using the compiler directory instead of
+       the library directory.
+
+2002-02-13  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (BetterFunction): Put back in what Miguel commented out
+       since it is the correct fix. The problem is elsewhere ;-)
+
+       (IsParamsMethodApplicable): Fix bug where we were not checking that the fixed
+       parameters of the parms method are themselves compatible or not !
+
+       (StandardConversionExists): Fix very dangerous bug where we were forgetting
+       to check that a class implements an interface before saying that an implicit
+       conversion was allowed. Use ImplementsInterface to do the checking.
+
+2002-02-13  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Method.Define): Track whether we are an explicit
+       implementation or not.  And only call DefineMethodOverride if we
+       are an explicit implementation.
+
+       (Property.DefineMethod): Ditto.
+
+2002-02-11  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (BetterFunction): Catch hideous bug which was
+        preventing us from detecting ambiguous calls due to implicit casts i.e
+       cs0121.
+
+2002-01-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * support.cs (Pair): Remove un-needed method.  I figured why I was
+       getting the error in cs-parser.jay, the variable in a foreach loop
+       is readonly, and the compiler does not really treat this as a variable.
+
+       * cs-parser.jay (fixed_statement): Fix grammar.  Use ASSIGN
+       instead of EQUALS in grammar.  
+
+       * typemanager.cs (VerifyUnmanaged): Report correct error (208)
+
+       * expression.cs (Unary.DoResolve): Check whether the argument is
+       managed or not.
+
+2002-01-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * support.cs: Api for Pair to set a value.  Despite the fact that
+       the variables are public the MS C# compiler refuses to compile
+       code that accesses the field if the variable is part of a foreach
+       statement. 
+
+       * statement.cs (Fixed): Begin implementation of the fixed
+       statement.
+
+       (Block.AddVariable): Return the VariableInfo on success and null
+       on failure instead of true/false. 
+
+       * cs-parser.jay (foreach): Catch errors on variables already
+       defined (we were ignoring this value before) and properly unwind
+       the block hierarchy
+
+       (fixed_statement): grammar for the fixed statement.
+
+2002-01-25  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (UnaryMutator.IsIncrementableNumber): Allow also
+       pointer types to be incretemented.
+
+       (SizeOf): Implement.
+
+       * cs-parser.jay (pointer_member_access): Implement
+       expr->IDENTIFIER production.
+
+       * expression.cs (IndexerAccess.DoResolve, ArrayAccess.DoResolve,
+       MemberAccess.DoResolve, Invocation.DoResolve): Check for pointers
+       on safe contexts.
+
+       (Unary): Implement indirection.
+
+       * ecore.cs (Expression.UnsafeError): Reports error 214 (pointer
+       use in non-unsafe context).
+
+       (SimpleName.DoResolve): Check for pointers in field access on safe
+       contexts. 
+
+       (Expression.LoadFromPtr): Factor the load-indirect code in this
+       function.  This was duplicated in UnboxCast and ParameterReference
+
+2002-01-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ComposedCast): report an error if a pointer cast
+       is used in a safe region.
+
+       * ecore.cs (Expression.ConvertExplicit): Add rules for implicit
+       pointer type casts in unsafe context.
+
+       * codegen.cs (EmitContext): Set up IsUnsafe.
+
+       * cs-parser.jay (non_expression_type): Add productions for pointer
+       casts. 
+
+       * expression.cs (Invocation.EmitCall): Remove chunk of buggy
+       code.  We should not use force into static mode if the method is
+       not virtual.  Fixes bug in MIS
+
+       * statement.cs (Do.Emit, While.Emit, For.Emit,
+       Statement.EmitBoolExpression): Add support to Do and While to
+       propagate infinite loop as `I do return' semantics.
+
+       Improve the For case to also test for boolean constants.
+
+       * attribute.cs (Attribute.ApplyAttributes): Add ParameterBuilder
+       to the list of attributes we can add.
+
+       Remove `EmitContext' argument.
+
+       * class.cs (Method.Define): Apply parameter attributes.
+       (Constructor.Define): Apply parameter attributes.
+       (MethodCore.LabelParameters): Move here the core of labeling
+       parameters. 
+
+       * support.cs (ReflectionParameters.ParameterModifier,
+       InternalParameters.ParameterModifier): Use IsByRef on the type and
+       only return the OUT bit for these parameters instead of in/out/ref
+       flags.
+
+       This is because I miss-understood things.  The ParameterInfo.IsIn
+       and IsOut represent whether the parameter has the [In] and [Out]
+       attributes set.  
+
+2002-01-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (FieldExpr.Emit): Release temporaries.
+
+       * assign.cs (LocalTemporary.Release): new function.
+
+       * codegen.cs (EmitContext.GetTemporaryStorage,
+       EmitContext.FreeTemporaryStorage): Rework the way we deal with
+       temporary storage.  Now we can "put back" localbuilders when we
+       are done with them
+
+2002-01-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (FieldExpr.Emit): Handle initonly fields specially: we
+       need to make a copy of the variable to generate verifiable code.
+
+2002-01-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Compute dynamically the system directory.
+
+       * ecore.cs (CopyNewMethods): reworked, exposed, made public.
+       Slower, but more generally useful.  Used by the abstract
+       registering implementation. 
+
+       * expression.cs (ResolveMemberAccess): Reorder the way we evaluate
+       the rules for the special rule on Type/instances.  First check if
+       we have the same name, and if so, try that special static path
+       rather than the instance path.
+       
+2002-01-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Emit 642 (warning: possible empty statement) for
+       for, while and if.
+
+       * class.cs (TypeBuilder.DefineType): Do not allow inheritance from
+       Enum, ValueType, Delegate or Array for non-corlib compiles.
+
+       * cs-tokenizer.cs: Catch long identifiers (645)
+
+       * typemanager.cs (IndexerPropetyName): Ravi never tested this
+       piece of code.
+
+       * class.cs (TypeContainer.RegisterRequiredImplementations): Bug
+       fix, we were returning too early, so we were not registering
+       pending methods from abstract classes.
+
+       Do not register pending methods if the class is abstract.
+
+       * expression.cs (Conditional.DoResolve): Report circular implicit
+       conversions when we neecd to compute it for conditional
+       expressions. 
+
+       (Is.DoResolve): If the expression is always of the provided type,
+       flag warning 183.  If the expression can not ever be of the
+       provided type flag warning 184.
+
+       * class.cs: Catch 169 as well.
+
+       * ecore.cs (FieldExpr): For now in AddressOf mark as assigned and
+       read. 
+
+2002-01-18  Nick Drochak  <ndrochak@gol.com>
+
+       * makefile: remove path to beta2 csc.exe.  path to csc.exe must be in PATH instead.
+
+2002-01-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * interface.cs: (PopulateMethod): Check for pointers being defined
+       only if the unsafe context is active.
+       (PopulateProperty): ditto.
+       (PopulateIndexer): ditto.
+
+       * class.cs (Method, Method.Define): Allow `unsafe' modifier to be
+       specified.  If pointers are present, make sure that they are
+       present in an unsafe context.
+       (Constructor, Constructor.Define): ditto.
+       (Field, Field.Define): ditto.
+       (Property, Property.Define): ditto.
+       (Event, Event.Define): ditto.
+
+       * interface.cs (Interface.GetInterfaceTypeByName): Only lookup the
+       hashtable if there are classes or structs defined.
+
+       * expression.cs (LocalVariableReference.DoResolve): Simplify this
+       code, as the constant resolution moved.
+
+       * statement.cs (Block.EmitMeta): Resolve all constants as we emit
+       the metadata, so we can flag error 133. 
+
+       * decl.cs (MemberCore.UnsafeOK): New function to test that a
+       pointer is being declared in an unsafe context.
+
+2002-01-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * modifiers.cs (Modifiers.Check): Require a Location argument.
+       Report error 227 for Unsafe use.
+
+       * typemanager.cs: Remove IsPointerType, we should be using Type.IsPointer
+
+       * statement.cs (For.Emit): If the test is null, then report that
+       we do `return', as we wont reach anything afterwards.
+
+       (Switch.SwitchGoverningType): Track the expression that matched
+       the conversion.
+
+       * driver.cs: Allow negative numbers as an error code to flag.
+
+       * cs-parser.jay: Handle 1551.
+
+       * namespace.cs: Add 1537 checking (repeated using alias namespaces).
+
+2002-01-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Report 1518 (type declaration can only contain
+       class, struct, interface, enum or delegate)
+
+       (switch_label): Report 1523 (keywords `case' or `default' must
+       preced code)
+
+       (opt_switch_sections): Report 1522 (empty switch)
+
+       * driver.cs: Report 1515 (response file specified multiple times)
+       Report 1516 (Source file specified multiple times).
+
+       * expression.cs (Argument.Resolve): Signal 1510
+
+       (BaseAccess.Resolve, BaseIndexer.Resolve): Signal 1511 (base
+       access not allowed in static code)
+
+2002-01-11  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (IsPointerType): Utility method which we are going
+       to need a lot.
+
+       * ecore.cs (ImplicitReferenceConversion): A pointer type cannot be cast to
+       the object type, so we take care of that.
+
+       * expression.cs (FullMethodDesc): Also include the return type in descriptions.
+       
+       * support.cs (ParameterDesc): Fix minor bug which was causing params tags to be
+       added to non-params parameters :-)
+
+       * typemanager.cs (CSharpName): Include 'void' type too. 
+
+       (void_ptr_type): Include in the set of core types.
+
+       * ecore.cs (ConvertImplicit): Make use of ConvertImplicitStandard instead of 
+       duplicating code.
+
+       (ConvertImplicitStandard): Handle standard implicit pointer conversions when we have 
+       an unsafe context.
+
+       * cs-parser.jay (local_variable_pointer_type): Add support for 'void *' as I had 
+       completely forgotten about it.
+
+2002-01-10  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (pointer_type): Add. This begins our implementation
+       of parsing rules for unsafe code.
+
+       (unsafe_statement): Implement.
+
+       (embedded_statement): Modify to include the above.
+
+       * statement.cs (Unsafe): Implement new class for unsafe blocks.
+
+       * codegen.cs (EmitContext.InUnsafe): Add. This determines
+       if the current context is an unsafe one.
+
+       * cs-parser.jay (local_variable_pointer_type): Since local variable types
+       are handled differently, we need separate rules for them.
+
+       (local_variable_declaration): Update to use local_variable_pointer_type
+       to allow variable declarations of unmanaged pointer types.
+
+       * expression.cs (Unary.ResolveOperator): Ensure that the '&' operator is used only
+       in unsafe contexts.
+
+       * ../errors/cs0214.cs : Add.
+
+2002-01-16  Nick Drochak  <ndrochak@gol.com>
+
+       * makefile: remove 'response' file when cleaning.
+
+2002-01-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Report 1524.
+
+2002-01-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (RegisterMethod): drop checking if we have
+       registered this from here
+
+2002-01-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Method.EmitDestructor): Implement calling our base
+       destructor. 
+
+       * statement.cs (Try.Emit): Fix to reset the InFinally to the old
+       value of InFinally.
+
+       * codegen.cs (EmitContext.EmitTopBlock): Destructors will call
+       this routine and will wrap the call in a try/catch block.  Deal
+       with the case.
+
+2002-01-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (Expression.MemberLookup): instead of taking a
+       parameter `same_type' that was used to tell whether we could
+       access private members we compute our containing type from the
+       EmitContext.
+
+       (FieldExpr): Added partial support for volatile fields.  This does
+       not work for volatile fields exposed from assemblies, as I can not
+       figure out how to extract the modreq from it.
+
+       Updated all the source files to use this.
+
+       * codegen.cs (EmitContext): Compute ContainerType ahead of time,
+       because it is referenced by MemberLookup very often. 
+
+2002-01-09  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (IndexerPropertyName): If we have a TypeBuilder, use
+       TypeBuilder.GetCustomAttributes to retrieve what we need.
+
+       Get rid of redundant default_member_attr_type as this is the same as
+       default_member_type which already exists.
+
+       * interface.cs, attribute.cs : Update accordingly.
+       
+2002-01-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs: Enable IndexerPropertyName again.  It does not
+       work for TYpeBuilders though.  Ravi, can you please fix this?
+
+       * cs-tokenizer.cs: Accept _ as a name in pp-expressions.
+
+       * expression.cs (Argument.Emit): Handle the case of ref objects
+       being passed to ref functions;  
+
+       (ParameterReference.EmitLoad): Loads the content of the pointer
+       without dereferencing.
+
+2002-01-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs: Implemented the pre-processing expressions.
+
+2002-01-08  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Indexer.DefineMethod): Incorporate the interface
+       type in the name of the method if we are doing explicit interface
+       implementation.
+
+       * expression.cs (ConversionExists): Remove as it is completely obsolete.
+
+       (BetterConversion): Fix extremely trivial bug where we were referring to
+       ConversionExists instead of StandardConversionExists ! Hooray, things are fine
+       again !
+
+       * ../errors/bug16.cs : Add although we have fixed it.
+
+2002-01-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (BaseIndexer): Begin implementation.
+
+       * class.cs (TypeContainer.IsInterfaceMethod): Bug fix.
+
+       * cs-parser.jay (indexer_declarator): Use qualified_identifier
+       production directly to remove a shift/reduce, and implement
+       explicit interface implementation.
+
+       * cs-tokenizer.cs: Fix tokenizer, it was consuming one extra char
+       after a floating point suffix.
+
+       * expression.cs (DoNumericPromotions): Improved the conversion for
+       uint/uint.  If we have a constant, we avoid doing a typecast to a
+       larger type.
+
+       * class.cs (Indexer): Implement explicit interface implementation
+       for indexers.
+       
+Sat Jan 5 16:08:23 CET 2002 Paolo Molaro <lupus@ximian.com>
+
+       * class.cs: make the default instance constructor public and hidebysig.
+
+2001-01-03  Ravi Pratap  <ravi@ximian.com>
+
+       * interface.cs (EmitDefaultMemberAttr): Make this helper method static
+       so we can call it from elsewhere.
+
+       * class.cs (TypeContainer.Emit): Emit the attribute here too. The rule is that
+       we emit it internally if the class has a defined indexer; otherwise the user
+       emits it by decorating the class definition with the DefaultMemberAttribute.
+
+       * attribute.cs (ApplyAttributes): Perform checks to see that the DefaultMember
+       attribute is not used on a type which defines an indexer.
+
+       * cs-tokenizer.cs (get_cmd_arg): Ensure we trim whitespace and also include the tab
+       character when we skip whitespace.
+
+       * ../errors/cs0646.cs : Add.
+
+2002-01-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (SimpleName.ResolveSimpleName): Report error 120
+       again. 
+
+       * makefile: Add practical target `mcs3.exe' which builds the third
+       generation compiler. 
+
+       * expression.cs (New): Fix structures constructor calling.
+
+       * class.cs (Property, Method, Indexer): Emit Final flag on the
+       method if we are an interface implementation and we are not
+       abstract. 
+
+       * ecore.cs (PropertyExpr): New public field `IsBase', tells
+       whether this property is referencing a `base' method.
+
+       * expression.cs (Invocation.EmitCall): take an extra argument:
+       is_base, this is used to determine whether the `call' or
+       `callvirt' opcode should be used.
+
+       
+       * delegate.cs: update EmitCall.
+
+       * class.cs (Method.Define): Set NewSlot for the cases where we are
+       not implementing an interface method.
+
+       (Property.Define): ditto.
+
+2002-01-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs: (Tokenizer.escape): Escape '\r' as '\r' not as
+       'r'.  Allows mcs to parse itself fully.
+
+2002-01-02  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (ArrayCreation.num_automatic_initializers): Keep track
+       of the number of initializers that require the InitializeArray method.
+
+       (CheckIndices): Store the Expression in all cases - not the plain value. Also
+       update the above field where necessary.
+
+       (MakeByteBlob): Update accordingly.
+
+       (DoEmit): Call EmitStaticInitializers only if the number of initializers is 
+       greater than 2.
+
+       (EmitDynamicInitializers): Update in accordance with the new optimization.
+
+       (ArrayAccess.EmitStoreOpcode): Include char type along with short and ushort - the
+       same OpCode applies.
+
+       * cs-parser.jay : Fix some glaring errors I introduced.
+
+2002-01-01  Ravi Pratap  <ravi@ximian.com> 
+
+       * parameters.cs (AddVariable, AddConstant): Pass in current_local_parameters
+       so that we can check for name clashes there too.
+
+       * typemanager.cs (default_member_attr_type): The attribute that we need to emit
+       for interface indexers.
+
+       * interfaces.cs (Define): Emit the default member attribute.
+
+       * expression.cs (MakeByteBlob): Fix extremely trivial bug where the wrong
+       variable was being referred to while setting the value ;-)
+
+2002-01-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (MakeByteBlob): Optimize: we do not need to fill
+       byte-by-byte information when we know the data is zero.
+
+       Make the block always a multiple of 4, because
+       DefineInitializedData has a bug.
+
+       * assign.cs: Fix, we should assign from the temporary, not from
+       the source. 
+
+       * expression.cs (MakeByteBlob): Fix my incorrect code.
+
+2001-12-31  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (EnumToUnderlying): This function is used to get
+       the underlying type from an enumeration, because it does not
+       always work. 
+
+       * constant.cs: Use the I4_S form for values between -128 and 127.
+
+       * statement.cs (Block.LookupLabel): Looks up a label.
+       (Block): Drop support for labeled blocks.
+
+       (LabeledStatement): New kind of statement that represents a label
+       only.
+
+       (Goto): Finally implement this bad boy.
+       
+       * cs-parser.jay: Update to reflect new mechanism to implement
+       labels.
+
+2001-12-30  Miguel de Icaza  <miguel@ximian.com>
+
+       * codegen.cs (EmitContext.This): a codegen property that keeps the
+       a single instance of this instead of creating many different this
+       instances. 
+
+       * delegate.cs (Delegate.DoResolve): Update to use the property;
+
+       * ecore.cs (SimpleName.SimpleNameResolve): Ditto
+
+       * expression.cs (BaseAccess.DoResolve): Ditto.
+
+2001-12-29  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (methodimpl_attr_type): Add to hold the type
+       corresponding to System.Runtime.CompilerServices.MethodImplAttribute.
+
+       (InitCoreTypes): Update accordingly.
+
+       * attribute.cs (Resolve): Remember if the attribute is a MethodImplAttribute
+       so we can quickly store the state.
+
+       (ApplyAttributes): Set the correct implementation flags
+       for InternalCall methods.
+
+2001-12-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (EmitCall): if a method is not virtual, then do
+       not use callvirt on it.
+
+       (ArrayAccess.EmitAssign): storing non-builtin value types (ie,
+       user defined stuff) requires the use of stobj, which takes an
+       address on the stack instead of an array and an index.  So emit
+       the Ldelema operation for it.
+
+       (EmitStoreOpcode): Use stobj for valuetypes.
+
+       (UnaryMutator.EmitCode): Use the right 1 value depending on
+       whether we are dealing with int64/uint64, float or doubles.
+
+       * class.cs (TypeContainer.AddConstructor): Fix the logic to define
+       constructors that I implemented last night.
+
+       (Constructor.IsDefault): Fix to work properly for static
+       constructors.
+
+       * cs-parser.jay (CheckDef): report method signature errors.
+       Update error number 103 to be 132.
+
+       * decl.cs: New AdditionResult enumeration value: MethodExists.
+       Although we do this check for methods later on in the semantic
+       analysis, catching repeated default constructors is so easy that
+       we catch these here. 
+       
+       * expression.cs (Binary.DoNumericPromotions): Fix the uint64 type
+       promotions code.
+
+       (ParameterReference.EmitAssign, Emit): handle
+       bools as bytes.
+
+       (ArrayAccess.EmitLoadOpcode): Handle bool type here.
+       (ArrayAccess.EmitStoreOpcode): ditto.
+
+       * cs-tokenizer.cs (is_punct): Eliminated empty computation.
+
+       * expression.cs (MakeByteBlob): Complete all the missing types
+       (uint, short, ushort, byte, sbyte)
+
+       * class.cs: Only init instance field initializers on instance
+       constructors. 
+
+       Rename `constructors' to instance_constructors. 
+
+       (TypeContainer.AddConstructor): Only add constructors to the list
+       if it is not static.
+
+       Make sure that we handle default_static_constructor independently
+       everywhere where we handle instance_constructors
+
+2001-12-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs: Do not lookup or create a base initializer for a
+       static constructor.
+
+       (ConstructorInitializer.Resolve): use the proper type to lookup
+       for constructors.
+
+       * cs-parser.jay: Report error 1585 (modifiers between type and name).
+
+       * enum.cs, interface.cs: Remove CloseType, this is taken care by
+       in DeclSpace. 
+
+       * decl.cs: CloseType is now an virtual method, the default
+       implementation just closes this type.
+       
+2001-12-28  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs (DefinePInvokeMethod): Set the implementation flags
+       to PreserveSig by default. Also emit HideBySig on such methods.
+
+       Basically, set the defaults to standard values.
+
+       * expression.cs (Invocation.BetterFunction): We need to make sure that for each
+       argument, if candidate is better, it can't be worse than the best !
+
+       (Invocation): Re-write bits to differentiate between methods being
+       applicable in their expanded form and their normal form - for params
+       methods of course.
+
+       Get rid of use_standard everywhere as only standard conversions are allowed
+       in overload resolution. 
+
+       More spec conformance.
+       
+2001-12-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Add --timestamp, to see where the compiler spends
+       most of its time.
+
+       * ecore.cs (SimpleName.DoResolve): Do not create an implicit
+       `this' in static code.
+
+       (SimpleName.DoResolve): Implement in terms of a helper function
+       that allows static-references to be passed upstream to
+       MemberAccess.
+
+       (Expression.ResolveWithSimpleName): Resolve specially simple
+       names when called by MemberAccess to implement the special
+       semantics. 
+
+       (Expression.ImplicitReferenceConversion): Handle conversions from
+       Null to reference types before others, as Null's type is
+       System.Object. 
+
+       * expression.cs (Invocation.EmitCall): Handle the special case of
+       calling methods declared on a reference type from a ValueType
+       (Base classes System.Object and System.Enum)
+
+       (MemberAccess.Resolve): Only perform lookups on Enumerations if
+       the left hand side is a TypeExpr, not on every enumeration. 
+
+       (Binary.Resolve): If types are reference types, then do a cast to
+       object on operators != and == of both arguments.
+       
+       * typemanager.cs (FindMembers): Extract instance and static
+       members if requested.
+
+       * interface.cs (PopulateProperty): Use void_type instead of null
+       as the return type for the setter method.
+
+       (PopulateIndexer): ditto.
+
+2001-12-27  Ravi Pratap  <ravi@ximian.com>
+
+       * support.cs (ReflectionParameters): Fix minor bug where we
+       were examining the wrong parameter for the ParamArray attribute.
+
+       Cope with requests for the type of the parameter at position
+       greater than the params parameter's. We now return the element
+       type of the params array as that makes more sense.
+
+       * expression.cs (Invocation.IsParamsMethodApplicable): Update 
+       accordingly as we no longer have to extract the element type
+       ourselves.
+
+       (Invocation.OverloadResolve): Update.
+
+2001-12-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Foreach.GetEnumeratorFilter): Do not compare
+       against IEnumerator, test whether the return value is a descendant
+       of the IEnumerator interface.
+
+       * class.cs (Indexer.Define): Use an auxiliary method to implement
+       the other bits of the method definition.  Begin support for
+       explicit interface implementation.
+
+       (Property.DefineMethod): Use TypeManager.void_type instead of null
+       for an empty return value.
+
+2001-12-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (MemberAccess.ResolveMemberAccess): if we are
+       dealing with a FieldExpr which is composed of a FieldBuilder, in
+       the code path we did extract the constant, but we should have
+       obtained the underlying value to be able to cast it (otherwise we
+       end up in an infinite loop, this is what Ravi was running into).
+
+       (ArrayCreation.UpdateIndices): Arrays might be empty.
+
+       (MemberAccess.ResolveMemberAccess): Add support for section
+       14.5.4.1 that deals with the special case of E.I when E is a type
+       and something else, that I can be a reference to a static member.
+
+       (ArrayCreation.MakeByteBlob): It is not an error to not be able to
+       handle a particular array type to create byte blobs, it is just
+       something we dont generate byteblobs for.
+
+       * cs-tokenizer.cs (get_cmd_arg): Ignore \r in commands and
+       arguments. 
+
+       * location.cs (Push): remove the key from the hashtable that we
+       are about to add.   This happens for empty files.
+
+       * driver.cs: Dispose files after we have parsed them.
+
+       (tokenize): new function that only runs the tokenizer on its
+       input, for speed testing.
+
+2001-12-26  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Event.Define): Define the private field only if there
+       are no accessors defined.
+
+       * expression.cs (ResolveMemberAccess): If there is no associated
+       field with the event, that means we have an event defined with its
+       own accessors and we should flag error cs0070 since transforming
+       ourselves into a field is not valid in that case.
+
+       * ecore.cs (SimpleName.DoResolve): Same as above.
+
+       * attribute.cs (DefinePInvokeMethod): Set the default calling convention
+       and charset to sane values.
+
+2001-12-25  Ravi Pratap  <ravi@ximian.com>
+
+       * assign.cs (DoResolve): Perform check on events only if they 
+       are being accessed outside the declaring type.
+
+       * cs-parser.jay (event_declarations): Update rules to correctly
+       set the type of the implicit parameter etc.
+
+       (add_accessor, remove_accessor): Set current local parameters.
+
+       * expression.cs (Binary): For delegate addition and subtraction,
+       cast the return value from the method into the appropriate delegate
+       type.
+
+2001-12-24  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (RegisterDelegateData, GetDelegateData): Get rid
+       of these as the workaround is unnecessary.
+
+       * delegate.cs (NewDelegate.DoResolve): Get rid of bits which registered
+       delegate data - none of that is needed at all.
+
+       Re-write bits to extract the instance expression and the delegate method
+       correctly.
+
+       * expression.cs (Binary.ResolveOperator): Handle the '-' binary operator 
+       on delegates too.
+
+       * attribute.cs (ApplyAttributes): New method to take care of common tasks
+       of attaching attributes instead of duplicating code everywhere.
+
+       * everywhere : Update code to do attribute emission using the above method.
+
+2001-12-23  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (IsParamsMethodApplicable): if there are not
+       parameters, return immediately.
+
+       * ecore.cs: The 0 literal can be implicity converted to an enum
+       type. 
+
+       (SimpleName.DoResolve): First lookup the type, then lookup the
+       members. 
+
+       (FieldExpr.Emit): If the InstanceExpression is a ValueType, we
+       want to get its address.  If the InstanceExpression is not
+       addressable, store the result in a temporary variable, then get
+       the address of it.
+
+       * codegen.cs: Only display 219 errors on warning level or above. 
+
+       * expression.cs (ArrayAccess): Make it implement the
+       IMemoryLocation interface.
+
+       (Binary.DoResolve): handle the operator == (object a, object b)
+       and operator != (object a, object b) without incurring into a
+       BoxedCast (because 5 != o should never be performed).
+
+       Handle binary enumerator operators.
+
+       (EmitLoadOpcode): Use Ldelema if the object we are loading is a
+       value type, otherwise use Ldelem_ref.
+
+       Use precomputed names;
+
+       (AddressOf): Implement address of
+
+       * cs-parser.jay (labeled_statement): Fix recursive block
+       addition by reworking the production.
+
+       * expression.cs (New.DoEmit): New has a special case:
+               
+                If we are dealing with a ValueType, we have a few
+                situations to deal with:
+               
+                   * The target of New is a ValueType variable, that is
+                     easy, we just pass this as the variable reference
+               
+                   * The target of New is being passed as an argument,
+                     to a boxing operation or a function that takes a
+                     ValueType.
+               
+                     In this case, we need to create a temporary variable
+                     that is the argument of New.
+
+
+2001-12-23  Ravi Pratap  <ravi@ximian.com>
+
+       * rootcontext.cs (LookupType): Check that current_type is not null before
+       going about looking at nested types.
+
+       * ecore.cs (EventExpr.EmitAddOrRemove): Rename from EmitAssign as we do
+       not implement the IAssignMethod interface any more.
+
+       * expression.cs (MemberAccess.ResolveMemberAccess): Handle EventExprs specially
+       where we tranform them into FieldExprs if they are being resolved from within
+       the declaring type.
+
+       * ecore.cs (SimpleName.DoResolve): Do the same here.
+
+       * assign.cs (DoResolve, Emit): Clean up code considerably. 
+
+       * ../errors/bug10.cs : Add.
+
+       * ../errors/cs0070.cs : Add.
+
+       * typemanager.cs : Use PtrHashtable for Delegate data hashtable etc.
+
+       * assign.cs : Get rid of EventIsLocal everywhere.
+       
+2001-12-23  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (ConvertIntLiteral): finished the implementation.
+
+       * statement.cs (SwitchLabel): Convert the value we are using as a
+       key before looking up the table.
+
+2001-12-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * codegen.cs (EmitTopBlock): Require a Location argument now.
+
+       * cs-parser.jay (constructor_declarator): We need to setup
+       current_local_parameters before we parse the
+       opt_constructor_initializer, to allow the variables to be bound
+       to the constructor arguments.
+
+       * rootcontext.cs (LookupType): First lookup nested classes in our
+       class and our parents before we go looking outside our class.
+
+       * expression.cs (ConstantFold): Extract/debox the values at the
+       beginnning. 
+
+       * rootcontext.cs (EmitCode): Resolve the constants first before we
+       resolve the types.  This is not really needed, but it helps debugging.
+
+       * statement.cs: report location.
+       
+       * cs-parser.jay: pass location to throw statement.
+
+       * driver.cs: Small bug fix.
+
+       * report.cs: Updated format to be 4-zero filled digits.
+
+2001-12-22  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (CheckIndices): Fix minor bug where the wrong
+       variable was being referred to ;-)
+
+       (DoEmit): Do not call EmitStaticInitializers when the 
+       underlying type is System.Object.
+
+2001-12-21  Ravi Pratap  <ravi@ximian.com>
+
+       * ecore.cs (EventExpr.Resolve): Implement to correctly set the type
+       and do the usual workaround for SRE.
+
+       * class.cs (MyEventBuilder.EventType): New member to get at the type
+       of the event, quickly.
+
+       * expression.cs (Binary.ResolveOperator): Handle delegate addition.
+
+       * assign.cs (Assign.DoResolve): Handle the case when the target
+       is an EventExpr and perform the necessary checks.
+
+       * ecore.cs (EventExpr.EmitAssign): Implement the IAssignMethod
+       interface.
+
+       (SimpleName.MemberStaticCheck): Include check for EventExpr.
+
+       (EventExpr): Set the type in the constructor itself since we 
+       are meant to be born fully resolved.
+
+       (EventExpr.Define): Revert code I wrote earlier.
+               
+       * delegate.cs (NewDelegate.Resolve): Handle the case when the MethodGroup's
+       instance expression is null. The instance expression is a This in that case
+       or a null, depending on whether it is a static method or not.
+
+       Also flag an error if the reference to a method is ambiguous i.e the MethodGroupExpr
+       refers to more than one method.
+
+       * assign.cs (DoResolve): Check whether the event belongs to the same Type container
+       and accordingly flag errors.
+
+2001-12-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Throw.Emit): Add support for re-throwing exceptions.
+
+2001-12-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * location.cs (ToString): Provide useful rutine.
+
+2001-12-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (Expression.ConvertIntLiteral): Do not return Constant
+       objects, return the actual integral boxed.
+
+       * statement.cs (SwitchLabel): define an ILLabel for each
+       SwitchLabel. 
+       
+       (Switch.CheckSwitch): If the value is a Literal, extract
+       the underlying literal.
+       
+       Also in the unused hashtable we had, add the SwitchLabel so we can
+       quickly look this value up.
+
+       * constant.cs: Implement a bunch of new constants.  Rewrite
+       Literal based on this.  Made changes everywhere to adapt to this.
+       
+       * expression.cs (Expression.MakeByteBlob): Optimize routine by
+       dereferencing array only once, and also copes with enumrations.
+
+       bytes are two bytes wide, not one.
+
+       (Cast): Perform constant conversions.
+       
+       * ecore.cs (TryImplicitIntConversion): Return literals instead of
+       wrappers to the literals here.
+
+       * expression.cs (DoNumericPromotions): long literals can converted
+       to ulong implicity (this is taken care of elsewhere, but I was
+       missing this spot).
+
+       * ecore.cs (Expression.Literalize): Make the return type Literal,
+       to improve type checking.
+
+       * rootcontext.cs: Lookup for nested classes in our class hierarchy.
+
+2001-12-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * literal.cs: Revert code from ravi that checked the bounds.  The
+       bounds are sane by the definition of the type itself. 
+
+       * typemanager.cs: Fix implementation of ImplementsInterface.  We
+       need to actually look up in our parent hierarchy for interfaces
+       implemented. 
+
+       * const.cs: Use the underlying type for enumerations
+
+       * delegate.cs: Compute the basename for the delegate creation,
+       that should fix the delegate test case, and restore the correct
+       Type Lookup semantics in rootcontext
+
+       * rootcontext.cs: Revert Ravi's last patch.  The correct way of
+       referencing a nested type with the Reflection API is using the "+"
+       sign. 
+
+       * cs-parser.jay: Do not require EOF token at the end.
+
+2001-12-20  Ravi Pratap  <ravi@ximian.com>
+
+       * rootcontext.cs (LookupType): Concatenate type names with
+       a '.' instead of a '+' The test suite passes again.
+
+       * enum.cs (Enum.DefineEnum): Set RTSpecialName on the 'value__'
+       field of the enumeration.
+
+       * expression.cs (MemberAccess.ResolveMemberAccess): Add support for
+       the case when the member is an EventExpr.
+
+       * ecore.cs (EventExpr.InstanceExpression): Every event which is not
+       static has an associated instance expression.
+
+       * typemanager.cs (RegisterEvent): The usual workaround, now for events.
+
+       (GetAddMethod, GetRemoveMethod): Workarounds, as usual.
+
+       * class.cs (Event.Define): Register event and perform appropriate checks
+       for error #111.
+
+       We define the Add and Remove methods even if the use provides none because
+       in that case, we provide default implementations ourselves.
+
+       Define a private field of the type of the event. This is done by the CSC compiler
+       and we should be doing it too ;-)
+
+       * typemanager.cs (delegate_combine_delegate_delegate, delegate_remove_delegate_delegate):
+       More methods we use in code we generate.
+
+       (multicast_delegate_type, delegate_type): Two separate types since the distinction
+       is important.
+
+       (InitCoreTypes): Update accordingly for the above.
+
+       * class.cs (Event.Emit): Generate code for default accessors that we provide
+
+       (EmitDefaultMethod): Do the job in the above.
+
+       * delegate.cs (DefineDelegate): Use TypeManager.multicast_delegate_type in the 
+       appropriate place.
+
+2001-12-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Indexer.Define): Fix bug, we were setting both Get/Set
+       builders even if we were missing one.
+
+       * interface.cs, class.cs, enum.cs: When calling DefineNestedType
+       pass the Basename as our class name instead of the Name.  The
+       basename will be correctly composed for us.
+
+       * parameter.cs (Paramters): Now takes a Location argument.
+
+       * decl.cs (DeclSpace.LookupType): Removed convenience function and
+       make all the code call directly LookupType in RootContext and take
+       this chance to pass the Location information everywhere.
+
+       * Everywhere: pass Location information.
+
+2001-12-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Constructor.Define): Updated way of detecting the
+       length of the parameters.
+
+       (TypeContainer.DefineType): Use basename as the type name for
+       nested types.
+
+       (TypeContainer.Define): Do not recursively define types here, as
+       definition is taken care in order by the RootContext.
+
+       * tree.cs: Keep track of namespaces in a per-file basis.
+
+       * parameter.cs (Parameter.ComputeSignature): Update to use
+       DeclSpace. 
+
+       (Parameters.GetSignature): ditto.
+
+       * interface.cs (InterfaceMethod.GetSignature): Take a DeclSpace
+       instead of a TypeContainer.
+
+       (Interface.SemanticAnalysis): Use `this' instead of our parent to
+       resolve names.  Because we need to be resolve in our context, not
+       our parents.
+       
+       * driver.cs: Implement response files.
+
+       * class.cs (TypeContainer.DefineType): If we are defined, do not
+       redefine ourselves.
+       
+       (Event.Emit): Emit the code for add/remove handlers.
+       (Event.Define): Save the MethodBuilders for add/remove.
+
+       * typemanager.cs: Use pair here too.
+
+       * cs-parser.jay: Replaced use of DictionaryEntry for Pair because
+       DictionaryEntry requires the first argument to be non-null.  
+       
+       (enum_declaration): Compute full name for registering the
+       enumeration.
+       
+       (delegate_declaration): Instead of using
+       formal_parameter_list, use opt_formal_parameter_list as the list
+       can be empty.
+
+       * cs-tokenizer.cs (PropertyParsing): renamed from `properties'
+       (EventParsing): New property that controls whether `add' and
+       `remove' are returned as tokens or identifiers (for events);
+
+2001-12-19  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Event.Define): Revamp use of EventBuilder completely. We now
+       use MyEventBuilder only and let it wrap the real builder for us.
+
+       (MyEventBuilder): Revamp constructor etc.
+
+       Implement all operations that we perform on EventBuilder in precisely the same
+       way here too.
+
+       (FindMembers): Update to use the EventBuilder member.
+
+       (Event.Emit): Update accordingly.
+
+2001-12-18  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (MyEventBuilder.Set*): Chain to the underlying builder
+       by calling the appropriate methods.
+
+       (GetCustomAttributes): Make stubs as they cannot possibly do anything
+       useful.
+
+       (Event.Emit): Use MyEventBuilder everywhere - even to set attributes.
+
+2001-12-17  Ravi Pratap  <ravi@ximian.com>
+
+       * delegate.cs (Delegate.Populate): Check that the return type
+       and various parameters types are indeed accessible.
+
+       * class.cs (Constructor.Define): Same here.
+
+       (Field.Define): Ditto.
+
+       (Event.Define): Ditto.
+
+       (Operator.Define): Check that the underlying Method defined itself
+       correctly - so it's MethodBuilder should not be null.
+
+       * delegate.cs (DelegateInvocation.DoResolve): Bale out if the type of the Instance
+       expression happens to be null.
+
+       * class.cs (MyEventBuilder): Workaround for SRE lameness. Implement various abstract
+       members but as of now we don't seem to be able to do anything really useful with it.
+
+       (FindMembers): Handle events separately by returning the MyEventBuilder of the event,
+       not the EventBuilder.
+
+2001-12-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs: Add support for defines.
+       Add support for #if, #elif, #else, #endif
+       
+       (eval_var): evaluates a variable.
+       (eval): stubbed for evaluating functions.
+
+       * cs-parser.jay: Pass the defines information
+
+       * driver.cs: Add --define command line option.
+
+       * decl.cs: Move MemberCore here.
+
+       Make it the base class for DeclSpace.  This allows us to catch and
+       report 108 and 109 for everything now.
+
+       * class.cs (TypeContainer.Define): Extract all the members
+       before populating and emit the warning 108 (new keyword required
+       to override) instead of having each member implement this.
+
+       (MemberCore.Define): New abstract method, we will be using this in
+       the warning reporting engine in Populate.
+       
+       (Operator.Define): Adjust to new MemberCore protocol. 
+
+       * const.cs (Const): This does not derive from Expression, it is a
+       temporary object we use to create fields, it is a MemberCore. 
+
+       * class.cs (Method.Define): Allow the entry point to be in a
+       specific class.
+
+       * driver.cs: Rewrite the argument handler to clean it up a bit.
+
+       * rootcontext.cs: Made it just an auxiliary namespace feature by
+       making everything static.
+
+       * driver.cs: Adapt code to use RootContext type name instead of
+       instance variable.
+
+       * delegate.cs: Remove RootContext argument.
+
+       * class.cs: (Struct, TypeContainer, Class): Remove RootContext
+       argument. 
+
+       * class.cs (Event.Define): The lookup can fail.
+       
+       * cs-tokenizer.cs: Begin implementation of pre-procesor. 
+
+       * expression.cs: Resolve the this instance before invoking the code.
+
+2001-12-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Add a production in element_access that allows
+       the thing to become a "type" reference.  This way we can parse
+       things like "(string [])" as a type.
+
+       Note that this still does not handle the more complex rules of
+       casts. 
+       
+
+       * delegate.cs (Delegate.Populate): Register the delegage constructor builder here. 
+
+       * ecore.cs: (CopyNewMethods): new utility function used to
+       assemble the list of methods from running FindMembers.
+
+       (MemberLookup): Rework FindMembers so that 
+
+2001-12-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (TypeContainer): Remove Delegates who fail to be
+       defined.
+
+       * delegate.cs (Populate): Verify that we dont get null return
+       values.   TODO: Check for AsAccessible.
+
+       * cs-parser.jay: Use basename to emit error 574 (destructor should
+       have the same name as container class), not the full name.
+
+       * cs-tokenizer.cs (adjust_int): Fit the integer in the best
+       possible representation.  
+
+       Also implements integer type suffixes U and L.
+
+2001-12-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ArrayCreation.DoResolve): We need to do the
+       argument resolution *always*.
+
+       * decl.cs: Make this hold the namespace.  Hold the root context as
+       well.
+       (LookupType): Move here.
+
+       * enum.cs, class.cs, interface.cs: Adapt to new hierarchy.
+
+       * location.cs (Row, Name): Fixed the code, it was always returning
+       references to the first file.
+
+       * interface.cs: Register properties defined through interfaces.
+
+       * driver.cs: Add support for globbing on the command line
+
+       * class.cs (Field): Make it derive from MemberCore as well.
+       (Event): ditto.
+
+2001-12-15  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Event::Define): Check that the type of the event is a delegate
+       type else flag error #66.
+
+       Also, re-use TypeContainer.MethodModifiersValid here too as the rules are the
+       same.
+
+       * attribute.cs (DefinePInvokeMethod): Handle named arguments and process
+       values of EntryPoint, CharSet etc etc.
+
+       Pass in the values to TypeBuilder.DefinePInvokeMethod; determine Type etc neatly.
+
+       * class.cs (FindMembers): If a method is in transit, its MethodBuilder will
+       be null and we should ignore this. I am not sure if this is really clean. Apparently,
+       there's no way of avoiding hitting this because the call is coming from SimpleName.DoResolve,
+       which needs this to do its work.
+
+       * ../errors/cs0066.cs : Add.
+
+2001-12-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs: (GetPropertyGetter, GetPropertyGetter): New
+       helper functions.
+
+       * class.cs: (MethodSignature.MethodSignature): Removed hack that
+       clears out the parameters field.
+       (MemberSignatureCompare): Cleanup
+
+       (MemberCore): New base class used to share code between MethodCore
+       and Property.
+
+       (RegisterRequiredImplementations) BindingFlags.Public requires
+       either BindingFlags.Instace or Static.  Use instance here.
+
+       (Property): Refactored code to cope better with the full spec.
+
+       * parameter.cs (GetParameterInfo): Return an empty array instead
+       of null on error.
+
+       * class.cs (Property): Abstract or extern properties have no bodies.
+
+       * parameter.cs (GetParameterInfo): return a zero-sized array.
+
+       * class.cs (TypeContainer.MethodModifiersValid): Move all the
+       method modifier validation to the typecontainer so we can reuse
+       this on properties.
+
+       (MethodCore.ParameterTypes): return an empty sized array of types.
+
+       (Property.Define): Test property modifier validity.
+
+       Add tests for sealed/override too.
+
+       (Method.Emit): abstract or extern methods have no bodies.
+
+2001-12-14  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Method.IsPInvoke): Get rid of it as it is an expensive
+       thing.
+
+       (Method::Define, ::Emit): Modify accordingly.
+
+       * expression.cs (Invocation::OverloadResolve): Handle error # 121.
+
+       (ArrayCreation::MakeByteBlob): Handle floats and doubles.
+
+       * makefile: Pass in /unsafe.
+
+2001-12-13  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (MakeKey): Kill routine.
+       
+       * class.cs (TypeContainer.Define): Correctly define explicit
+       method implementations (they require the full interface name plus
+       the method name).
+
+       * typemanager.cs: Deply the PtrHashtable here and stop using the
+       lame keys.  Things work so much better.
+
+       This of course broke everyone who depended on `RegisterMethod' to
+       do the `test for existance' test.  This has to be done elsewhere.
+
+       * support.cs (PtrHashtable): A hashtable that avoid comparing with
+       the object stupid Equals method (because, that like fails all over
+       the place).  We still do not use it.
+
+       * class.cs (TypeContainer.SetRequiredInterface,
+       TypeContainer.RequireMethods): Killed these two routines and moved
+       all the functionality to RegisterRequiredImplementations.
+
+       (TypeContainer.RegisterRequiredImplementations): This routine now
+       registers all the implementations required in an array for the
+       interfaces and abstract methods.  We use an array of structures
+       which can be computed ahead of time to reduce memory usage and we
+       also assume that lookups are cheap as most classes will not
+       implement too many interfaces.
+
+       We also avoid creating too many MethodSignatures.
+
+       (TypeContainer.IsInterfaceMethod): Update and optionally does not
+       clear the "pending" bit if we find that there are problems with
+       the declaration.
+
+       (TypeContainer.VerifyPendingMethods): Update to report errors of
+       methods that look like implementations but are not.
+
+       (TypeContainer.Define): Add support for explicit interface method
+       implementation. 
+       
+2001-12-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs: Keep track of the parameters here instead of
+       being a feature of the TypeContainer.
+
+       * class.cs: Drop the registration of parameters here, as
+       InterfaceMethods are also interface declarations.
+
+       * delegate.cs: Register methods with the TypeManager not only with
+       the TypeContainer.  This code was buggy.
+
+       * interface.cs: Full registation here.
+
+2001-12-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: Remove reducer for binary expressions, it can not
+       be done this way.
+
+       * const.cs: Put here the code that used to go into constant.cs
+
+       * constant.cs: Put here the code for constants, this is a new base
+       class for Literals.
+
+       * literal.cs: Make Literal derive from Constant.
+
+2001-12-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Return.Emit): Report error 157 if the user
+       attempts to return from a finally block.
+
+       (Return.Emit): Instead of emitting a return, jump to the end of
+       the function.
+
+       * codegen.cs (EmitContext): ReturnValue, ReturnLabel: new
+       LocalBuilder to store the result of the function.  ReturnLabel is
+       the target where we jump.
+       
+
+2001-12-09  Radek Doulik  <rodo@ximian.com>
+
+       * cs-parser.jay: remember alias in current namespace
+
+       * ecore.cs (SimpleName::DoResolve): use aliases for types or
+       namespaces
+
+       * class.cs (LookupAlias): lookup alias in my_namespace
+
+       * namespace.cs (UsingAlias): add alias, namespace_or_type pair to
+       aliases hashtable
+       (LookupAlias): lookup alias in this and if needed in parent
+       namespaces
+
+2001-12-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * support.cs: 
+
+       * rootcontext.cs: (ModuleBuilder) Made static, first step into
+       making things static.  I need this to avoid passing the
+       TypeContainer when calling ParameterType.
+
+       * support.cs (InternalParameters.ParameterType): Remove ugly hack
+       that did string manipulation to compute the type and then call
+       GetType.  Use Parameter.ParameterType instead.
+
+       * cs-tokenizer.cs: Consume the suffix for floating values.
+
+       * expression.cs (ParameterReference): figure out whether this is a
+       reference parameter or not.  Kill an extra variable by computing
+       the arg_idx during emission.
+
+       * parameter.cs (Parameters.GetParameterInfo): New overloaded
+       function that returns whether a parameter is an out/ref value or not.
+
+       (Parameter.ParameterType): The type of the parameter (base,
+       without ref/out applied).
+       
+       (Parameter.Resolve): Perform resolution here.
+       (Parameter.ExternalType): The full type (with ref/out applied).
+
+       * statement.cs (Using.Emit, Using.EmitExpression): Implement
+       support for expressions on the using statement.
+
+2001-12-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Using.EmitLocalVariableDecls): Split the
+       localvariable handling of the using statement.
+
+       (Block.EmitMeta): Keep track of variable count across blocks.  We
+       were reusing slots on separate branches of blocks.
+
+       (Try.Emit): Emit the general code block, we were not emitting it. 
+
+       Check the type of the declaration to be an IDisposable or
+       something that can be implicity converted to it. 
+
+       Emit conversions if required.
+
+       * ecore.cs (EmptyExpression): New utility class.
+       (Expression.ImplicitConversionExists): New utility function.
+
+2001-12-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Using): Implement.
+
+       * expression.cs (LocalVariableReference): Support read only variables.
+
+       * statement.cs: Remove the explicit emit for the Leave opcode.
+       (VariableInfo): Add a readonly field.
+
+2001-12-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (ConvCast): new class used to encapsulate the various
+       explicit integer conversions that works in both checked and
+       unchecked contexts.
+
+       (Expression.ConvertNumericExplicit): Use new ConvCast class to
+       properly generate the overflow opcodes.
+
+2001-12-04  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs: The correct type for the EmptyExpression is the
+       element_type, not the variable type.  Ravi pointed this out.
+
+2001-12-04  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Method::Define): Handle PInvoke methods specially
+       by using DefinePInvokeMethod instead of the usual one.
+
+       * attribute.cs (DefinePInvokeMethod): Implement as this is what is called
+       above to do the task of extracting information and defining the method.
+       
+2001-12-04  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (ArrayCreation::EmitStaticInitializers): Get rid
+       of the condition for string type.
+
+       (Emit): Move that here. 
+
+       (ArrayCreation::CheckIndices): Keep string literals in their expression
+       form.
+
+       (EmitDynamicInitializers): Handle strings appropriately.
+
+2001-12-04  Miguel de Icaza  <miguel@ximian.com>
+
+       * codegen.cs (EmitContext): Replace multiple variables with a
+       single pointer to the current Switch statement.
+
+       * statement.cs (GotoDefault, Switch): Adjust to cleaned up
+       EmitContext.
+
+2001-12-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs 
+
+       * statement.cs (GotoDefault), cs-parser.jay: Implement `goto
+       default'.
+       
+       (Foreach.Emit): Foreach on arrays was not setting
+       up the loop variables (for break/continue).
+
+       (GotoCase): Semi-implented.
+       
+2001-12-03  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs (CheckAttribute): Handle system attributes by using
+       Attribute.GetAttributes to examine information we need.
+
+       (GetValidPlaces): Same here.
+
+       * class.cs (Method::Define): Catch invalid use of extern and abstract together.
+
+       * typemanager.cs (dllimport_type): Core type for System.DllImportAttribute.
+
+       * class.cs (Method.IsPinvoke): Used to determine if we are a PInvoke method.
+
+       (Method::Define): Set appropriate flags if we have a DllImport attribute.
+
+       (Method::Emit): Handle the case when we are a PInvoke method.
+
+2001-12-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: Use ResolveWithSimpleName on compound names.
+
+2001-12-02  Ravi Pratap  <ravi@ximian.com>
+
+       * constant.cs (EmitConstant): Make sure we resolve the associated expression
+       before trying to reduce it.
+
+       * typemanager.cs (RegisterConstant, LookupConstant): Implement.
+
+       * constant.cs (LookupConstantValue): Implement.
+
+       (EmitConstant): Use the above in emitting the constant.
+
+       * expression.cs (MemberAccess::ResolveMemberAccess): Handle constants
+       that are user-defined by doing a LookupConstantValue on them.
+
+       (SimpleName::DoResolve): When we have a FieldExpr, cope with constants
+       too, like above.
+
+2001-11-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (BaseAccess, BaseIndexer): Also split this out.
+
+       (BaseAccess.DoResolve): Implement.
+
+       (MemberAccess.DoResolve): Split this routine into a
+       ResolveMemberAccess routine that can be used independently
+
+2001-11-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Probe, Is, As): Split Probe in two classes Is and
+       As that share bits of the implementation.  Is returns a boolean,
+       while As returns the Type that is being probed.
+
+2001-12-01  Ravi Pratap  <ravi@ximian.com>
+
+       * enum.cs (LookupEnumValue): Re-write various bits, return an object value
+       instead of a Literal - much easier.
+
+       (EnumInTransit): Remove - utterly useless :-)
+
+       (Populate): Re-write bits - remove duplicate code etc. The code is much neater now.
+
+       * expression.cs (MemberLookup): Cope with user-defined enums when they are in transit.
+
+       * enum.cs (LookupEnumValue): Auto-compute next values by going down the dependency
+       chain when we have no associated expression.
+
+2001-11-30  Ravi Pratap  <ravi@ximian.com>
+
+       * constant.cs (Define): Use Location while reporting the errror.
+
+       Also emit a warning when 'new' is used and there is no inherited
+       member to hide.
+
+       * enum.cs (EnumInTransit): Used to tell if an enum type is in the process of being 
+       populated.
+
+       (LookupEnumValue): Implement to lookup an enum member's value and define it
+       if necessary.
+
+       (Populate): Re-write accordingly to use the above routine.
+
+2001-11-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (This): Fix prototype for DoResolveLValue to
+       override the base class DoResolveLValue.
+
+       * cs-parser.cs: Report errors cs574 and cs575 (destructor
+       declarations) 
+
+       * ecore.cs (FieldExpr.EmitAssign): Handle value types specially
+       (we need to load the address of the field here).  This fixes
+       test-22. 
+       
+       (FieldExpr.DoResolveLValue): Call the DoResolve
+       function to initialize the Instance expression.
+       
+       * statement.cs (Foreach.Emit): Fix the bug where we did not invoke
+       correctly the GetEnumerator operation on a value type.
+
+       * cs-parser.jay: Add more simple parsing error catches.
+
+       * statement.cs (Switch): Add support for string switches.
+       Handle null specially.
+
+       * literal.cs (NullLiteral): Make NullLiteral objects singletons. 
+
+2001-11-28  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (local_constant_declaration): Use declare_local_constant.
+
+       (declare_local_constant): New helper function.
+
+       * statement.cs (AddConstant): Keep a separate record of constants
+
+       (IsConstant): Implement to determine if a variable is a constant.
+
+       (GetConstantExpression): Implement.
+
+       * expression.cs (LocalVariableReference): Handle the case when it is a constant.
+
+       * statement.cs (IsVariableDefined): Re-write.
+
+2001-11-27  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (TypeContainer::FindMembers): Look for constants
+       in the case when we are looking for MemberTypes.Field
+
+       * expression.cs (MemberAccess::DoResolve): Check that in the
+       case we are a FieldExpr and a Literal, we are not being accessed
+       by an instance reference.
+
+       * cs-parser.jay (local_constant_declaration): Implement.
+
+       (declaration_statement): Implement for constant declarations.
+
+2001-11-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Switch): Catch double defaults.
+
+       (Switch): More work on the switch() statement
+       implementation.  It works for integral values now, need to finish
+       string support.
+
+
+2001-11-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * ecore.cs (Expression.ConvertIntLiteral): New function to convert
+       integer literals into other integer literals.  To be used by
+       switch. 
+
+2001-11-24  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (ArrayCreation): Get rid of ArrayExprs : we save
+       some memory.
+
+       (EmitDynamicInitializers): Cope with the above since we extract data
+       directly from ArrayData now.
+
+       (ExpectInitializers): Keep track of whether initializers are mandatory
+       or not.
+
+       (Bounds): Make it a hashtable to prevent the same dimension being 
+       recorded for every element in that dimension.
+
+       (EmitDynamicInitializers): Fix bug which prevented the Set array method
+       from being found.
+
+       Also fix bug which was causing the indices to be emitted in the reverse
+       order.
+
+2001-11-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ArrayCreation): Implement the bits that Ravi left
+       unfinished.  They do not work, because the underlying code is
+       sloppy.
+
+2001-11-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Remove bogus fixme.
+
+       * statement.cs (Switch, SwitchSection, SwithLabel): Started work
+       on Switch statement.
+       
+2001-11-23  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (IsDelegateType, IsEnumType): Fix logic to determine
+       the same. 
+       
+       * expression.cs (ArrayCreation::CheckIndices): Get rid of the require_constant
+       parameter. Apparently, any expression is allowed. 
+
+       (ValidateInitializers): Update accordingly.
+
+       (CheckIndices): Fix some tricky bugs thanks to recursion.
+
+       * delegate.cs (NewDelegate::DoResolve): Re-write large portions as 
+       I was being completely brain-dead.
+
+       (VerifyMethod, VerifyApplicability, VerifyDelegate): Make static
+       and re-write acordingly.
+
+       (DelegateInvocation): Re-write accordingly.
+
+       * expression.cs (ArrayCreation::Emit): Handle string initialization separately.
+
+       (MakeByteBlob): Handle types more correctly.
+
+       * expression.cs (ArrayCreation:Emit): Write preliminary code to do
+       initialization from expressions but it is incomplete because I am a complete
+       Dodo :-|
+
+2001-11-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (If.Emit): Fix a bug that generated incorrect code
+       on If.  Basically, we have to return `true' (ie, we do return to
+       our caller) only if both branches of the if return.
+
+       * expression.cs (Binary.Emit): LogicalOr and LogicalAnd are
+       short-circuit operators, handle them as short circuit operators. 
+
+       (Cast.DoResolve): Resolve type.
+       (Cast.Cast): Take an expression as the target type.
+
+       * cs-parser.jay (cast_expression): Remove old hack that only
+       allowed a limited set of types to be handled.  Now we take a
+       unary_expression and we resolve to a type during semantic
+       analysis.
+
+       Use the grammar productions from Rhys to handle casts (this is
+       not complete like Rhys syntax yet, we fail to handle that corner
+       case that C# has regarding (-x), but we will get there.
+       
+2001-11-22  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (EmitFieldInitializer): Take care of the case when we have a
+       field which is an array type.
+
+       * cs-parser.jay (declare_local_variables): Support array initialization too.
+
+       * typemanager.cs (MakeKey): Implement.
+
+       (everywhere): Use the above appropriately.
+
+       * cs-parser.jay (for_statement): Update for array initialization while
+       declaring variables.
+
+       * ecore.cs : The error message was correct, it's the variable's names that
+       were misleading ;-) Make the code more readable.
+
+       (MemberAccess::DoResolve): Fix the code which handles Enum literals to set
+       the correct type etc.
+
+       (ConvertExplicit): Handle Enum types by examining the underlying type.
+
+2001-11-21  Ravi Pratap  <ravi@ximian.com>
+
+       * parameter.cs (GetCallingConvention): Always return
+       CallingConventions.Standard for now.
+
+2001-11-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Binary.ResolveOperator): Update the values of `l'
+       and `r' after calling DoNumericPromotions.
+
+       * ecore.cs: Fix error message (the types were in the wrong order).
+
+       * statement.cs (Foreach.ProbeCollectionType): Need to pass
+       BindingFlags.Instance as well 
+
+       * ecore.cs (Expression.TryImplicitIntConversion): Wrap the result
+       implicit int literal conversion in an empty cast so that we
+       propagate the right type upstream.
+
+       (UnboxCast): new class used to unbox value types.
+       (Expression.ConvertExplicit): Add explicit type conversions done
+       by unboxing.
+
+       (Expression.ImplicitNumericConversion): Oops, forgot to test for
+       the target type before applying the implicit LongLiterals to ULong
+       literal cast.
+
+2001-11-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay (for_statement): Reworked the way For works: now
+       we declare manually any variables that are introduced in
+       for_initializer to solve the problem of having out-of-band code
+       emition (that is what got for broken).
+
+       (declaration_statement): Perform the actual variable declaration
+       that used to be done in local_variable_declaration here.
+
+       (local_variable_declaration): Do not declare anything, just pass
+       the information on a DictionaryEntry
+
+2001-11-20  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (ArrayCreation::CheckIndices): The story continues :-) Complete
+       re-write of the logic to now make it recursive.
+
+       (UpdateIndices): Re-write accordingly.
+
+       Store element data in a separate ArrayData list in the above methods.
+
+       (MakeByteBlob): Implement to dump the array data into a byte array.
+
+2001-11-19  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (ArrayCreation): Factor out some code from ValidateInitializers
+       into CheckIndices.
+
+       * constant.cs (Define): Implement.
+
+       (EmitConstant): Re-write fully.
+
+       Pass in location info.
+
+       * class.cs (Populate, Emit): Call Constant::Define and Constant::EmitConstant
+       respectively.
+
+       * cs-parser.jay (constant_declarator): Use VariableDeclaration instead of
+       DictionaryEntry since we need location info too.
+
+       (constant_declaration): Update accordingly.
+
+       * expression.cs (ArrayCreation): Make ValidateInitializers simpler by factoring
+       code into another method : UpdateIndices.
+
+2001-11-18  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (ArrayCreation::ValidateInitializers): Update to perform
+       some type checking etc.
+
+2001-11-17  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (ArrayCreation::ValidateInitializers): Implement
+       bits to provide dimension info if the user skips doing that.
+
+       Update second constructor to store the rank correctly.
+
+2001-11-16  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (ArrayCreation::ValidateInitializers): Poke around
+       and try to implement.
+
+       * ../errors/cs0150.cs : Add.
+
+       * ../errors/cs0178.cs : Add.
+
+2001-11-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs: Implement foreach on multi-dimensional arrays. 
+
+       * parameter.cs (Parameters.GetParameterByName): Also lookup the
+       name of the params argument.
+
+       * expression.cs: Use EmitStoreOpcode to get the right opcode while
+       initializing the array.
+
+       (ArrayAccess.EmitStoreOpcode): move the opcode generation here, so
+       we can use this elsewhere.
+
+       * statement.cs: Finish implementation of foreach for single
+       dimension arrays.
+
+       * cs-parser.jay: Use an out-of-band stack to pass information
+       around, I wonder why I need this.
+
+       foreach_block: Make the new foreach_block the current_block.
+
+       * parameter.cs (Parameters.GetEmptyReadOnlyParameters): New
+       function used to return a static Parameters structure.  Used for
+       empty parameters, as those are created very frequently.
+
+       * cs-parser.jay, class.cs: Use GetEmptyReadOnlyParameters
+
+2001-11-15  Ravi Pratap  <ravi@ximian.com>
+
+       * interface.cs : Default modifier is private, not public. The
+       make verify test passes again.
+
+2001-11-15  Ravi Pratap  <ravi@ximian.com>
+
+       * support.cs (ReflectionParameters): Fix logic to determine
+       whether the last parameter is a params one. Test 9 passes again.
+
+       * delegate.cs (Populate): Register the builders we define with
+       RegisterParameterForBuilder. Test 19 passes again.
+
+       * cs-parser.jay (property_declaration): Reference $6 instead
+       of $$ to get at the location.
+
+       (indexer_declaration): Similar stuff.
+
+       (attribute): Ditto.
+
+       * class.cs (Property): Register parameters for the Get and Set methods
+       if they exist. Test 23 passes again.
+
+       * expression.cs (ArrayCreation::Emit): Pass null for the method in the
+       call to EmitArguments as we are sure there aren't any params arguments. 
+       Test 32 passes again.
+
+       * suppor.cs (ParameterDesc, ParameterModifier): Fix trivial bug causing
+       IndexOutOfRangeException. 
+
+       * class.cs (Property::Define): Register property using TypeManager.RegisterProperty
+       Test 33 now passes again.
+       
+2001-11-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Kill horrendous hack ($??? = lexer.Location) that
+       broke a bunch of things.  Will have to come up with a better way
+       of tracking locations.
+
+       * statement.cs: Implemented foreach for single dimension arrays.
+
+2001-11-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * enum.cs (Enum.Emit): Delay the lookup of loc until we run into
+       an error.  This removes the lookup from the critical path.
+
+       * cs-parser.jay: Removed use of temporary_loc, which is completely
+       broken. 
+
+2001-11-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * support.cs (ReflectionParameters.ParameterModifier): Report
+       whether the argument is a PARAMS argument or not.
+
+       * class.cs: Set the attribute `ParamArrayAttribute' on the
+       parameter argument.
+
+       * typemanager.cs: Define param_array_type (ParamArrayAttribute)
+       and cons_param_array_attribute (ConstructorInfo for
+       ParamArrayAttribute)., 
+
+       * codegen.cs: Emit the return using the `Return' statement, that
+       way we can report the error correctly for missing return values. 
+
+       * class.cs (Method.Emit): Clean up.
+
+       * expression.cs (Argument.Resolve): Take another argument: the
+       location where this argument is used.  Notice that this is not
+       part of the "Argument" class as to reduce the size of the
+       structure (we know the approximate location anyways).
+
+       Test if the argument is a variable-reference, if not, then
+       complain with a 206.
+
+       (Argument.Emit): Emit addresses of variables.
+
+       (Argument.FullDesc): Simplify.
+
+       (Invocation.DoResolve): Update for Argument.Resolve.
+
+       (ElementAccess.DoResolve): ditto.
+
+       * delegate.cs (DelegateInvocation.Emit): Invocation of Invoke
+       method should be virtual, as this method is always virtual.
+
+       (NewDelegate.DoResolve): Update for Argument.Resolve.
+
+       * class.cs (ConstructorInitializer.DoResolve): ditto.
+       
+       * attribute.cs (Attribute.Resolve): ditto.
+
+2001-11-13  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Foreach.Emit): Use EmitAssign instead of Store.
+
+       * expression.cs (ParameterReference): Drop IStackStorage and implement
+       IAssignMethod instead. 
+
+       (LocalVariableReference): ditto.
+       
+       * ecore.cs (FieldExpr): Drop IStackStorage and implement
+       IAssignMethod instead. 
+
+2001-11-13  Miguel de Icaza <miguel@ximian.com>
+
+       * parameter.cs, expression.cs, class.cs, ecore.cs: Made all
+       enumerations that are used in heavily used structures derive from
+       byte in a laughable and pathetic attempt to reduce memory usage.
+       This is the kind of pre-optimzations that you should not do at
+       home without adult supervision.
+
+       * expression.cs (UnaryMutator): New class, used to handle ++ and
+       -- separatedly from the other unary operators.  Cleans up the
+       code, and kills the ExpressionStatement dependency in Unary.
+
+       (Unary): Removed `method' and `Arguments' from this class, making
+       it smaller, and moving it all to SimpleCall, so I can reuse this
+       code in other locations and avoid creating a lot of transient data
+       strucutres when not required.
+
+       * cs-parser.jay: Adjust for new changes.
+
+2001-11-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * enum.cs (Enum.Populate): If there is a failure during
+       definition, return
+
+       * cs-parser.jay (opt_enum_base): we used to catch type errors
+       here, but this is really incorrect.  The type error should be
+       catched during semantic analysis.
+
+2001-12-11  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (operator_declarator, conversion_operator_declarator): Set
+       current_local_parameters as expected since I, in my stupidity, had forgotten
+       to do this :-)
+
+       * attribute.cs (GetValidPlaces): Fix stupid bug.
+
+       * class.cs (Method::Emit): Perform check on applicability of attributes.
+
+       (Constructor::Emit): Ditto.
+
+       (Field::Emit): Ditto.
+
+       (Field.Location): Store location information.
+
+       (Property, Event, Indexer, Operator): Ditto.
+
+       * cs-parser.jay (field_declaration): Pass in location for each field.
+
+       * ../errors/cs0592.cs : Add.
+
+2001-11-12  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (attribute_usage_type): New static member for System.AttributeUsage.
+
+       (InitCoreTypes): Update accordingly.
+
+       (RegisterAttrType, LookupAttr): Implement.
+
+       * attribute.cs (Attribute.Targets, AllowMultiple, Inherited): New fields to hold
+       info about the same.
+
+       (Resolve): Update to populate the above as necessary.
+
+       (Error592): Helper.
+
+       (GetValidPlaces): Helper to the above.
+
+       (CheckAttribute): Implement to perform validity of attributes on declarative elements.
+
+       * class.cs (TypeContainer::Emit): Update attribute emission code to perform checking etc.
+
+2001-11-12  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs (Attribute::Resolve): Expand to handle named arguments too.
+
+       * ../errors/cs0617.cs : Add.
+
+2001-11-11  Ravi Pratap  <ravi@ximian.com>
+
+       * enum.cs (Emit): Rename to Populate to be more consistent with what
+       we expect it to do and when exactly it is called.
+
+       * class.cs, rootcontext.cs : Update accordingly.
+
+       * typemanager.cs (RegisterField, GetValue): Workarounds for the fact that
+       FieldInfo.GetValue does not work on dynamic types ! S.R.E lameness strikes again !
+
+       * enum.cs (Populate): Register fields with TypeManager.RegisterField.
+
+       * expression.cs (MemberAccess.DoResolve): Adjust code to obtain the value
+       of a fieldinfo using the above, when dealing with a FieldBuilder.
+
+2001-11-10  Ravi Pratap  <ravi@ximian.com>
+
+       * ../errors/cs0031.cs : Add.
+
+       * ../errors/cs1008.cs : Add.
+
+       * ../errrors/cs0543.cs : Add.
+
+       * enum.cs (DefineEnum): Check the underlying type and report an error if not a valid
+       enum type.
+
+       (FindMembers): Implement.
+
+       * typemanager.cs (FindMembers): Re-write to call the appropriate methods for
+       enums and delegates too.
+
+       (enum_types): Rename to builder_to_enum.
+
+       (delegate_types): Rename to builder_to_delegate.
+
+       * delegate.cs (FindMembers): Implement.
+
+2001-11-09  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (IsEnumType): Implement.
+
+       * enum.cs (Emit): Re-write parts to account for the underlying type
+       better and perform checking etc.
+
+       (GetNextDefaultValue): Helper to ensure we don't overshoot max value
+       of the underlying type.
+
+       * literal.cs (GetValue methods everywhere): Perform bounds checking and return
+       value
+
+       * enum.cs (error31): Helper to report error #31.
+
+       * cs-parser.jay (enum_declaration): Store location of each member too.
+
+       * enum.cs (member_to_location): New hashtable. 
+
+       (AddEnumMember): Update location hashtable.
+
+       (Emit): Use the location of each member while reporting errors.
+
+2001-11-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: A for_initializer if is a
+       local_variable_declaration really ammount to have an implicit
+       block with the variable declaration and no initializer for for.
+
+       * statement.cs (For.Emit): Cope with null initializers.
+
+       This fixes the infinite loop on for initializers.
+
+2001-11-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * enum.cs: More cleanup.
+
+       * ecore.cs: Remove dead code.
+
+       * class.cs (Property.Emit): More simplification.
+       (Event.Emit): ditto.
+
+       Reworked to have less levels of indentation.
+       
+2001-11-08  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Property): Emit attributes.
+
+       (Field): Ditto.
+       
+       (Event): Ditto.
+
+       (Indexer): Ditto.
+
+       (Operator): Ditto.
+
+       * enum.cs (Emit): Ditto.
+
+       * rootcontext.cs (ResolveTree, EmitCode, CloseTypes): Do the same for
+       Enums too.
+
+       * class.cs (Field, Event, etc.): Move attribute generation into the
+       Emit method everywhere.
+
+       * enum.cs (Enum): Revamp to use the same definition semantics as delegates so
+       we have a DefineEnum, CloseEnum etc. The previous way of doing things was not right
+       as we had no way of defining nested enums !
+
+       * rootcontext.cs : Adjust code accordingly.
+
+       * typemanager.cs (AddEnumType): To keep track of enum types separately.
+
+2001-11-07  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (EvalConstantExpression): Move into ecore.cs
+       
+       * enum.cs (Enum): Rename some members and make them public and readonly
+       according to our convention.
+
+       * modifiers.cs (EnumAttr): Implement as we need to set only visibility flags,
+       nothing else.
+
+       * enum.cs (Enum::Define): Use the above instead of TypeAttr.
+
+       (Enum::Emit): Write a simple version for now which doesn't try to compute
+       expressions. I shall modify this to be more robust in just a while.
+
+       * class.cs (TypeContainer::Emit): Make sure we include Enums too.
+
+       (TypeContainer::CloseType): Create the Enum types too.
+
+       * attribute.cs (Resolve): Use the new Reduce method instead of EvalConstantExpression.
+
+       * expression.cs (EvalConstantExpression): Get rid of completely.
+
+       * enum.cs (Enum::Emit): Use the new expression reducer. Implement assigning
+       user-defined values and other cases.
+
+       (IsValidEnumLiteral): Helper function.
+
+       * expression.cs (ExprClassfromMemberInfo): Modify to not do any literalizing 
+       out there in the case we had a literal FieldExpr.
+
+       (MemberAccess:DoResolve): Do the literalizing of the FieldExpr here.
+
+       (Literalize): Revamp a bit to take two arguments.
+       
+       (EnumLiteral): New class which derives from Literal to wrap enum literals.
+       
+2001-11-06  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (compilation_unit): Remove extra opt_attributes for now.
+
+       * expression.cs (ArrayCreation::ValidateInitializers): Implement.
+
+       (Resolve): Use the above to ensure we have proper initializers.
+
+2001-11-05  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Expression::EvalConstantExpression): New method to 
+       evaluate constant expressions.
+
+       * attribute.cs (Attribute::Resolve): Modify bits to use the above function.
+
+2001-11-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ArrayCreation.Emit): Some bits to initialize data
+       in an array.
+
+       (Binary.ResolveOperator): Handle operator != (object a, object b)
+       and operator == (object a, object b);
+
+       (Binary.DoNumericPromotions): Indicate whether the numeric
+       promotion was possible.
+
+       (ArrayAccess.DoResolve, ArrayAccess.Emit, ArrayAccess.EmitAssign):
+       Implement.  
+
+       Made the ArrayAccess implement interface IAssignMethod instead of
+       IStackStore as the order in which arguments are passed reflects
+       this.
+
+       * assign.cs: Instead of using expr.ExprClass to select the way of
+       assinging, probe for the IStackStore/IAssignMethod interfaces.
+
+       * typemanager.cs: Load InitializeArray definition.
+
+       * rootcontext.cs (RootContext.MakeStaticData): Used to define
+       static data that can be used to initialize arrays. 
+
+2001-11-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: Handle operator== and operator!= for booleans.
+
+       (Conditioal.Reduce): Implement reducer for the ?: operator.
+
+       (Conditional.Resolve): Implement dead code elimination.
+
+       (Binary.Resolve): Catch string literals and return a new
+       concatenated string.
+
+       (Unary.Reduce): Implement reduction of unary expressions.
+
+       * ecore.cs: Split out the expression core handling here.
+
+       (Expression.Reduce): New method used to perform constant folding
+       and CSE.  This is needed to support constant-expressions. 
+       
+       * statement.cs (Statement.EmitBoolExpression): Pass true and false
+       targets, and optimize for !x.
+
+2001-11-04  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs (Attribute::Resolve): Implement guts. Note that resolution
+       of an attribute gives us a CustomAttributeBuilder which we use accordingly to
+       set custom atttributes.
+
+       * literal.cs (Literal::GetValue): New abstract method to return the actual
+       value of the literal, cast as an object.
+
+       (*Literal): Implement GetValue method.
+
+       * cs-parser.jay (positional_argument_list, named_argument_list): Add not just plain
+       expressions to the arraylist but objects of type Argument.
+
+       * class.cs (TypeContainer::Emit): Emit our attributes too.
+
+       (Method::Emit, Constructor::Emit): Ditto.
+
+       * cs-parser.jay (constructor_declaration): Set attributes too, which we seemed
+       to be ignoring earlier.
+
+2001-11-03  Ravi Pratap  <ravi@ximian.com>
+
+       * attribute.cs (AttributeSection::Define): Implement to do the business
+       of constructing a CustomAttributeBuilder.
+
+       (Attribute): New trivial class. Increases readability of code.  
+
+       * cs-parser.jay : Update accordingly.
+
+       (positional_argument_list, named_argument_list, named_argument): New rules
+
+       (attribute_arguments): Use the above so that we are more correct.
+       
+2001-11-02  Ravi Pratap  <ravi@ximian.com>
+       
+       * expression.cs (Invocation::IsParamsMethodApplicable): Implement
+       to perform all checks for a method with a params parameter.
+
+       (Invocation::OverloadResolve): Update to use the above method and therefore
+       cope correctly with params method invocations.
+
+       * support.cs (InternalParameters::ParameterDesc): Provide a desc for 
+       params too.
+
+       * class.cs (ConstructorInitializer::Resolve): Make sure we look for Non-public
+       constructors in our parent too because we can't afford to miss out on 
+       protected ones ;-)
+
+       * attribute.cs (AttributeSection): New name for the class Attribute
+
+       Other trivial changes to improve readability.
+
+       * cs-parser.jay (opt_attributes, attribute_section etc.): Modify to
+       use the new class names.
+       
+2001-11-01  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Method::Define): Complete definition for params types too
+
+       (Indexer::Define): Ditto.
+
+       * support.cs (InternalParameters::ParameterType, ParameterDesc, ParameterModifier):
+       Cope everywhere with a request for info about the array parameter.
+
+2001-11-01  Ravi Pratap  <ravi@ximian.com>
+
+       * tree.cs (RecordNamespace): Fix up to check for the correct key.
+
+       * cs-parser.jay (GetQualifiedIdentifier): New Helper method used in 
+       local_variable_type to extract the string corresponding to the type.
+
+       (local_variable_type): Fixup the action to use the new helper method.
+
+       * codegen.cs : Get rid of RefOrOutParameter, it's not the right way to 
+       go.
+
+       * expression.cs : Clean out code which uses the above.
+
+2001-10-31  Ravi Pratap  <ravi@ximian.com>
+       
+       * typemanager.cs (RegisterMethod): Check if we already have an existing key
+       and bale out if necessary by returning a false.
+
+       (RegisterProperty): Ditto.
+
+       * class.cs (everywhere): Check the return value from TypeManager.RegisterMethod
+       and print out appropriate error messages.
+
+       * interface.cs (everywhere): Ditto.
+
+       * cs-parser.jay (property_declaration, event_declaration, indexer_declaration): Pass
+       location to constructor.
+
+       * class.cs (Property, Event, Indexer): Update accordingly.
+
+       * ../errors/cs111.cs : Added.
+
+       * expression.cs (Invocation::IsApplicable): New static method to determine applicability
+       of a method, as laid down by the spec.
+
+       (Invocation::OverloadResolve): Use the above method.
+
+2001-10-31  Ravi Pratap  <ravi@ximian.com>
+
+       * support.cs (InternalParameters): Get rid of crap taking in duplicate info. We
+       now take a TypeContainer and a Parameters object.
+
+       (ParameterData): Modify return type of ParameterModifier method to be 
+       Parameter.Modifier and not a string.
+
+       (ReflectionParameters, InternalParameters): Update accordingly.
+
+       * expression.cs (Argument::GetParameterModifier): Same here.
+
+       * support.cs (InternalParameters::ParameterType): Find a better way of determining
+       if we are a ref/out parameter. Actually, the type shouldn't be holding the '&'
+       symbol in it at all so maybe this is only for now.
+
+2001-10-30  Ravi Pratap  <ravi@ximian.com>
+
+       * support.cs (InternalParameters): Constructor now takes an extra argument 
+       which is the actual Parameters class.
+
+       (ParameterDesc): Update to provide info on ref/out modifiers.
+
+       * class.cs (everywhere): Update call to InternalParameters to pass in
+       the second argument too.
+
+       * support.cs (ParameterData): Add ParameterModifier, which is a method 
+       to return the modifier info [ref/out etc]
+
+       (InternalParameters, ReflectionParameters): Implement the above.
+
+       * expression.cs (Argument::ParameterModifier): Similar function to return
+       info about the argument's modifiers.
+
+       (Invocation::OverloadResolve): Update to take into account matching modifiers 
+       too.
+
+       * class.cs (Indexer::Define): Actually define a Parameter object and put it onto
+       a new SetFormalParameters object which we pass to InternalParameters.
+
+2001-10-30  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (NewArray): Merge into the ArrayCreation class.
+
+2001-10-29  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (NewArray): Merge classes NewBuiltinArray and 
+       NewUserdefinedArray into one as there wasn't much of a use in having
+       two separate ones.
+
+       * expression.cs (Argument): Change field's name to ArgType from Type.
+
+       (Type): New readonly property which returns the proper type, taking into 
+       account ref/out modifiers.
+
+       (everywhere): Adjust code accordingly for the above.
+
+       * codegen.cs (EmitContext.RefOrOutParameter): New field to determine
+       whether we are emitting for a ref or out parameter.
+
+       * expression.cs (Argument::Emit): Use the above field to set the state.
+
+       (LocalVariableReference::Emit): Update to honour the flag and emit the
+       right stuff.
+
+       * parameter.cs (Attributes): Set the correct flags for ref parameters.
+
+       * expression.cs (Argument::FullDesc): New function to provide a full desc.
+
+       * support.cs (ParameterData): Add method ParameterDesc to the interface.
+
+       (ReflectionParameters, InternalParameters): Implement the above method.
+
+       * expression.cs (Invocation::OverloadResolve): Use the new desc methods in
+       reporting errors.
+
+       (Invocation::FullMethodDesc): Ditto. 
+
+2001-10-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Add extra production for the second form of array
+       creation. 
+
+       * expression.cs (ArrayCreation): Update to reflect the above
+       change. 
+
+       * Small changes to prepare for Array initialization.
+
+2001-10-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (ImplementsInterface): interface might be null;
+       Deal with this problem;
+
+       Also, we do store negative hits on the cache (null values), so use
+       this instead of calling t.GetInterfaces on the type everytime.
+
+2001-10-28  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (IsBuiltinType): New method to help determine the same.
+
+       * expression.cs (New::DoResolve): Get rid of array creation code and instead
+       split functionality out into different classes.
+
+       (New::FormArrayType): Move into NewBuiltinArray.
+
+       (Invocation::EmitArguments): Get rid of the MethodBase argument. Appears
+       quite useless.
+
+       (NewBuiltinArray): New class to handle creation of built-in arrays.
+
+       (NewBuiltinArray::DoResolve): Implement guts of array creation. Also take into
+       account creation of one-dimensional arrays.
+
+       (::Emit): Implement to use Newarr and Newobj opcodes accordingly.
+
+       (NewUserdefinedArray::DoResolve): Implement.
+
+       * cs-parser.jay (local_variable_type): Fix up to add the rank to the variable too.
+
+       * typemanager.cs (AddModule): Used to add a ModuleBuilder to the list of modules
+       we maintain inside the TypeManager. This is necessary to perform lookups on the
+       module builder.
+
+       (LookupType): Update to perform GetType on the module builders too.     
+
+       * driver.cs (Driver): Add the ModuleBuilder to the list maintained by the TypeManager.
+
+       * exprssion.cs (NewUserdefinedArray::Emit): Implement.
+
+2001-10-23  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (New::DoResolve): Implement guts of array creation.
+
+       (New::FormLookupType): Rename to FormArrayType and modify ever so slightly.
+       
+2001-10-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: Fix bug I introduced lsat night that broke
+       Delegates. 
+
+       (Expression.Resolve): Report a 246 error (can not resolve name)
+       if we find a SimpleName in the stream.
+       
+       (Expression.ResolveLValue): Ditto.
+       
+       (Expression.ResolveWithSimpleName): This function is a variant of
+       ResolveName, this one allows SimpleNames to be returned without a
+       warning.  The only consumer of SimpleNames is MemberAccess
+
+2001-10-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Invocation::DoResolve): Catch SimpleNames that
+       might arrive here.  I have my doubts that this is correct.
+
+       * statement.cs (Lock): Implement lock statement.
+
+       * cs-parser.jay: Small fixes to support `lock' and `using'
+
+       * cs-tokenizer.cs: Remove extra space
+
+       * driver.cs: New flag --checked, allows to turn on integer math
+       checking. 
+
+       * typemanger.cs: Load methodinfos for Threading.Monitor.Enter and
+       Threading.Monitor.Exit 
+       
+2001-10-23  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (IndexerAccess::DoResolveLValue): Set the
+       Expression Class to be IndexerAccess.
+
+       Notice that Indexer::DoResolve sets the eclass to Value.
+
+2001-10-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (TypeContainer::Emit): Emit code for indexers.
+
+       * assign.cs (IAssignMethod): New interface implemented by Indexers
+       and Properties for handling assignment.
+
+       (Assign::Emit): Simplify and reuse code. 
+       
+       * expression.cs (IndexerAccess, PropertyExpr): Implement
+       IAssignMethod, clean up old code. 
+
+2001-10-22  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (ImplementsInterface): New method to determine if a type
+       implements a given interface. Provides a nice cache too.
+
+       * expression.cs (ImplicitReferenceConversion): Update checks to use the above
+       method.
+
+       (ConvertReferenceExplicit): Ditto.
+
+       * delegate.cs (Delegate::Populate): Update to define the parameters on the 
+       various methods, with correct names etc.
+
+       * class.cs (Operator::OpType): New members Operator.UnaryPlus and 
+       Operator.UnaryNegation.
+
+       * cs-parser.jay (operator_declarator): Be a little clever in the case where
+       we have a unary plus or minus operator.
+
+       * expression.cs (Unary): Rename memebers of Operator enum to UnaryPlus and 
+       UnaryMinus.
+
+       * everywhere : update accordingly.
+
+       * everywhere : Change Negate and BitComplement to LogicalNot and OnesComplement
+       respectively.
+
+       * class.cs (Method::Define): For the case where we are implementing a method
+       inherited from an interface, we need to set the MethodAttributes.Final flag too. 
+       Also set MethodAttributes.NewSlot and MethodAttributes.HideBySig.
+       
+2001-10-21  Ravi Pratap  <ravi@ximian.com>
+
+       * interface.cs (FindMembers): Implement to work around S.R.E
+       lameness.
+
+       * typemanager.cs (IsInterfaceType): Implement.
+
+       (FindMembers): Update to handle interface types too.
+
+       * expression.cs (ImplicitReferenceConversion): Re-write bits which
+       use IsAssignableFrom as that is not correct - it doesn't work.
+
+       * delegate.cs (DelegateInvocation): Derive from ExpressionStatement
+       and accordingly override EmitStatement.
+
+       * expression.cs (ConvertReferenceExplicit): Re-write similary, this time
+       using the correct logic :-)
+
+2001-10-19  Ravi Pratap  <ravi@ximian.com>
+
+       * ../errors/cs-11.cs : Add to demonstrate error -11 
+
+2001-10-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * assign.cs (Assign::Resolve): Resolve right hand side first, and
+       then pass this as a hint to ResolveLValue.
+       
+       * expression.cs (FieldExpr): Add Location information
+
+       (FieldExpr::LValueResolve): Report assignment to readonly
+       variable. 
+       
+       (Expression::ExprClassFromMemberInfo): Pass location information.
+
+       (Expression::ResolveLValue): Add new method that resolves an
+       LValue. 
+
+       (Expression::DoResolveLValue): Default invocation calls
+       DoResolve. 
+
+       (Indexers): New class used to keep track of indexers in a given
+       Type. 
+
+       (IStackStore): Renamed from LValue, as it did not really describe
+       what this did.  Also ResolveLValue is gone from this interface and
+       now is part of Expression.
+
+       (ElementAccess): Depending on the element access type
+       
+       * typemanager.cs: Add `indexer_name_type' as a Core type
+       (System.Runtime.CompilerServices.IndexerNameAttribute)
+
+       * statement.cs (Goto): Take a location.
+       
+2001-10-18  Ravi Pratap  <ravi@ximian.com>
+
+       * delegate.cs (Delegate::VerifyDelegate): New method to verify
+       if two delegates are compatible.
+
+       (NewDelegate::DoResolve): Update to take care of the case when
+       we instantiate a delegate from another delegate.
+
+       * typemanager.cs (FindMembers): Don't even try to look up members
+       of Delegate types for now.
+
+2001-10-18  Ravi Pratap  <ravi@ximian.com>
+
+       * delegate.cs (NewDelegate): New class to take care of delegate
+       instantiation.
+
+       * expression.cs (New): Split the delegate related code out into 
+       the NewDelegate class.
+
+       * delegate.cs (DelegateInvocation): New class to handle delegate 
+       invocation.
+
+       * expression.cs (Invocation): Split out delegate related code into
+       the DelegateInvocation class.
+
+2001-10-17  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (New::DoResolve): Implement delegate creation fully
+       and according to the spec.
+
+       (New::DoEmit): Update to handle delegates differently.
+
+       (Invocation::FullMethodDesc): Fix major stupid bug thanks to me
+       because of which we were printing out arguments in reverse order !
+
+       * delegate.cs (VerifyMethod): Implement to check if the given method
+       matches the delegate.
+
+       (FullDelegateDesc): Implement.
+
+       (VerifyApplicability): Implement.
+
+       * expression.cs (Invocation::DoResolve): Update to accordingly handle
+       delegate invocations too.
+
+       (Invocation::Emit): Ditto.
+
+       * ../errors/cs1593.cs : Added.
+
+       * ../errors/cs1594.cs : Added.
+
+       * delegate.cs (InstanceExpression, TargetMethod): New properties.
+
+2001-10-16  Ravi Pratap  <ravi@ximian.com>
+
+       * typemanager.cs (intptr_type): Core type for System.IntPtr
+
+       (InitCoreTypes): Update for the same.
+
+       (iasyncresult_type, asynccallback_type): Ditto.
+
+       * delegate.cs (Populate): Fix to use System.Intptr as it is indeed
+       correct.
+
+       * typemanager.cs (AddDelegateType): Store a pointer to the Delegate class
+       too.
+
+       * delegate.cs (ConstructorBuilder, InvokeBuilder, ...): New members to hold
+       the builders for the 4 members of a delegate type :-)
+
+       (Populate): Define the BeginInvoke and EndInvoke methods on the delegate
+       type.
+
+       * expression.cs (New::DoResolve): Implement guts for delegate creation.
+
+       * ../errors/errors.txt : Update for an error (-11) which only we catch :-)
+
+2001-10-15  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Break::Emit): Implement.   
+       (Continue::Emit): Implement.
+
+       (For::Emit): Track old being/end loops;  Set Begin loop, ack end loop
+       (While::Emit): Track old being/end loops;  Set Begin loop, ack end loop
+       (Do::Emit): Track old being/end loops;  Set Begin loop, ack end loop
+       (Foreach::Emit): Track old being/end loops;  Set Begin loop, ack
+       end loop
+       
+       * codegen.cs (EmitContext::LoopEnd, EmitContext::LoopBegin): New
+       properties that track the label for the current loop (begin of the
+       loop and end of the loop).
+
+2001-10-15  Ravi Pratap  <ravi@ximian.com>
+
+       * delegate.cs (Emit): Get rid of it as there doesn't seem to be any ostensible
+       use of emitting anything at all.
+
+       * class.cs, rootcontext.cs : Get rid of calls to the same.
+
+       * delegate.cs (DefineDelegate): Make sure the class we define is also sealed.
+
+       (Populate): Define the constructor correctly and set the implementation
+       attributes.
+
+       * typemanager.cs (delegate_types): New hashtable to hold delegates that
+       have been defined.
+
+       (AddDelegateType): Implement.
+
+       (IsDelegateType): Implement helper method.
+
+       * delegate.cs (DefineDelegate): Use AddDelegateType instead of AddUserType.
+
+       * expression.cs (New::DoResolve): Check if we are trying to instantiate a delegate type
+       and accordingly handle it.
+
+       * delegate.cs (Populate): Take TypeContainer argument.
+       Implement bits to define the Invoke method. However, I still haven't figured out
+       how to take care of the native int bit :-(
+
+       * cs-parser.jay (delegate_declaration): Fixed the bug that I had introduced :-) 
+       Qualify the name of the delegate, not its return type !
+
+       * expression.cs (ImplicitReferenceConversion): Implement guts of implicit array
+       conversion.
+
+       (StandardConversionExists): Checking for array types turns out to be recursive.
+
+       (ConvertReferenceExplicit): Implement array conversion.
+
+       (ExplicitReferenceConversionExists): New method to determine precisely that :-)
+       
+2001-10-12  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (delegate_declaration): Store the fully qualified
+       name as it is a type declaration.
+
+       * delegate.cs (ReturnType, Name): Rename members to these. Make them 
+       readonly.
+
+       (DefineDelegate): Renamed from Define. Does the same thing essentially,
+       as TypeContainer::DefineType.
+
+       (Populate): Method in which all the definition of the various methods (Invoke)
+       etc is done.
+
+       (Emit): Emit any code, if necessary. I am not sure about this really, but let's
+       see.
+       
+       (CloseDelegate): Finally creates the delegate.
+
+       * class.cs (TypeContainer::DefineType): Update to define delegates.
+       (Populate, Emit and CloseType): Do the same thing here too.
+
+       * rootcontext.cs (ResolveTree, PopulateTypes, EmitCode, CloseTypes): Include
+       delegates in all these operations.
+
+2001-10-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: LocalTemporary: a new expression used to
+       reference a temporary that has been created.
+
+       * assign.cs: Handle PropertyAccess back here, so that we can
+       provide the proper semantic access to properties.
+
+       * expression.cs (Expression::ConvertReferenceExplicit): Implement
+       a few more explicit conversions. 
+
+       * modifiers.cs: `NEW' modifier maps to HideBySig.
+
+       * expression.cs (PropertyExpr): Make this into an
+       ExpressionStatement, and support the EmitStatement code path. 
+
+       Perform get/set error checking, clean up the interface.
+
+       * assign.cs: recognize PropertyExprs as targets, and if so, turn
+       them into toplevel access objects.
+
+2001-10-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: PropertyExpr::PropertyExpr: use work around the
+       SRE.
+
+       * typemanager.cs: Keep track here of our PropertyBuilders again to
+       work around lameness in SRE.
+
+2001-10-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (LValue::LValueResolve): New method in the
+       interface, used to perform a second resolution pass for LValues. 
+       
+       (This::DoResolve): Catch the use of this in static methods.
+
+       (This::LValueResolve): Implement.
+
+       (This::Store): Remove warning, assigning to `this' in structures
+       is 
+
+       (Invocation::Emit): Deal with invocation of
+       methods on value types.  We need to pass the address to structure
+       methods rather than the object itself.  (The equivalent code to
+       emit "this" for structures leaves the entire structure on the
+       stack instead of a pointer to it). 
+
+       (ParameterReference::DoResolve): Compute the real index for the
+       argument based on whether the method takes or not a `this' pointer
+       (ie, the method is static).
+
+       * codegen.cs (EmitContext::GetTemporaryStorage): Used to store
+       value types returned from functions when we need to invoke a
+       method on the sturcture.
+       
+
+2001-10-11  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (TypeContainer::DefineType): Method to actually do the business of
+       defining the type in the Modulebuilder or Typebuilder. This is to take
+       care of nested types which need to be defined on the TypeBuilder using
+       DefineNestedMethod.
+
+       (TypeContainer::GetClassBases): Implement. Essentially the code from the 
+       methods in RootContext, only ported to be part of TypeContainer.
+
+       (TypeContainer::GetInterfaceOrClass): Ditto.
+
+       (TypeContainer::LookupInterfaceOrClass, ::MakeFQN): Ditto.
+
+       * interface.cs (Interface::DefineInterface): New method. Does exactly
+       what RootContext.CreateInterface did earlier, only it takes care of nested types 
+       too.
+
+       (Interface::GetInterfaces): Move from RootContext here and port.
+
+       (Interface::GetInterfaceByName): Same here.
+
+       * rootcontext.cs (ResolveTree): Re-write.
+
+       (PopulateTypes): Re-write.
+
+       * class.cs (TypeContainer::Populate): Populate nested types too.
+       (TypeContainer::Emit): Emit nested members too.
+
+       * typemanager.cs (AddUserType): Do not make use of the FullName property,
+       instead just use the name argument passed in as it is already fully
+       qualified.
+
+       (FindMembers): Check in the Builders to TypeContainer mapping instead of the name
+       to TypeContainer mapping to see if a type is user-defined.
+
+       * class.cs (TypeContainer::CloseType): Implement. 
+
+       (TypeContainer::DefineDefaultConstructor): Use Basename, not Name while creating
+       the default constructor.
+       
+       (TypeContainer::Populate): Fix minor bug which led to creating default constructors
+       twice.
+
+       (Constructor::IsDefault): Fix up logic to determine if it is the default constructor
+
+       * interface.cs (CloseType): Create the type here.
+       
+       * rootcontext.cs (CloseTypes): Re-write to recursively close types by running through
+       the hierarchy.
+
+       Remove all the methods which are now in TypeContainer.
+
+2001-10-10  Ravi Pratap  <ravi@ximian.com>
+
+       * delegate.cs (Define): Re-write bits to define the delegate
+       correctly.
+
+2001-10-10  Miguel de Icaza  <miguel@ximian.com>
+
+       * makefile: Renamed the compiler to `mcs.exe' instead of compiler.exe
+
+       * expression.cs (ImplicitReferenceConversion): handle null as well
+       as a source to convert to any reference type.
+
+       * statement.cs (Return): Perform any implicit conversions to
+       expected return type.  
+
+       Validate use of return statement.  
+
+       * codegen.cs (EmitContext): Pass the expected return type here.
+
+       * class.cs (Method, Constructor, Property): Pass expected return
+       type to EmitContext.
+
+2001-10-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: Make DoResolve take an EmitContext instead of a
+       TypeContainer.
+
+       Replaced `l' and `location' for `loc', for consistency.
+       
+       (Error, Warning): Remove unneeded Tc argument.
+
+       * assign.cs, literal.cs, constant.cs: Update to new calling
+       convention. 
+       
+       * codegen.cs: EmitContext now contains a flag indicating whether
+       code is being generated in a static method or not.
+
+       * cs-parser.jay: DecomposeQI, new function that replaces the old
+       QualifiedIdentifier.  Now we always decompose the assembled
+       strings from qualified_identifier productions into a group of
+       memberaccesses.
+
+2001-10-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs: Deal with field-less struct types correctly now
+       by passing the size option to Define Type.
+
+       * class.cs: Removed hack that created one static field. 
+
+2001-10-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs: Moved most of the code generation here. 
+
+2001-10-09  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (New::DoResolve): Revert changes for array creation, doesn't
+       seem very right.
+
+       (ElementAccess): Remove useless bits for now - keep checks as the spec
+       says.
+
+2001-10-08  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (ElementAccess::DoResolve): Remove my crap code
+       and start performing checks according to the spec.
+
+2001-10-07  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (type_suffix*): Remove - they are redundant. Use
+       rank_specifiers instead.
+
+       (rank_specifiers): Change the order in which the rank specifiers are stored
+
+       (local_variable_declaration): Use opt_rank_specifier instead of type_suffixes.
+
+       * expression.cs (ElementAccess): Implement the LValue interface too.
+       
+2001-10-06  Ravi Pratap  <ravi@ximian.com>
+       
+       * expression.cs (ConvertExplicitStandard): Add. Same as ConvertExplicit
+       except that user defined conversions are not included.
+
+       (UserDefinedConversion): Update to use the ConvertExplicitStandard to 
+       perform the conversion of the return type, if necessary.
+
+       (New::DoResolve): Check whether we are creating an array or an object
+       and accordingly do the needful.
+
+       (New::Emit): Same here.
+
+       (New::DoResolve): Implement guts of array creation.
+
+       (New::FormLookupType): Helper function.
+
+2001-10-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * codegen.cs: Removed most of the code generation here, and move the
+       corresponding code generation bits to the statement classes. 
+
+       Added support for try/catch/finalize and throw.
+       
+       * cs-parser.jay: Added support for try/catch/finalize.
+
+       * class.cs: Catch static methods having the flags override,
+       virtual or abstract.
+
+       * expression.cs (UserCast): This user cast was not really doing
+       what it was supposed to do.  Which is to be born in fully resolved
+       state.  Parts of the resolution were being performed at Emit time! 
+
+       Fixed this code.
+
+2001-10-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs: Implicity convert the result from UserCast.
+
+2001-10-05  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Expression::FindMostEncompassingType): Fix bug which
+       prevented it from working correctly. 
+
+       (ConvertExplicit): Make the first try, a call to ConvertImplicitStandard, not
+       merely ConvertImplicit.
+
+2001-10-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs: Make the LookupTypeContainer function static,
+       and not per-instance.  
+
+       * class.cs: Make static FindMembers (the one that takes a Type
+       argument). 
+
+       * codegen.cs: Add EmitForeach here.
+
+       * cs-parser.jay: Make foreach a toplevel object instead of the
+       inline expansion, as we need to perform semantic analysis on it. 
+
+2001-10-05  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Expression::ImplicitUserConversion): Rename to
+       UserDefinedConversion.
+
+       (Expression::UserDefinedConversion): Take an extra argument specifying 
+       whether we look for explicit user conversions too.
+
+       (Expression::ImplicitUserConversion): Make it a call to UserDefinedConversion.
+
+       (UserDefinedConversion): Incorporate support for user defined explicit conversions.
+
+       (ExplicitUserConversion): Make it a call to UserDefinedConversion
+       with the appropriate arguments.
+
+       * cs-parser.jay (cast_expression): Record location too.
+
+       * expression.cs (Cast): Record location info.
+
+       (Expression::ConvertExplicit): Take location argument.
+
+       (UserImplicitCast): Change name to UserCast. Take an extra constructor argument
+       to determine if we are doing explicit conversions.
+
+       (UserCast::Emit): Update accordingly.
+
+       (Expression::ConvertExplicit): Report an error if everything fails.
+
+       * ../errors/cs0030.cs : Add.
+
+2001-10-04  Miguel de Icaza  <miguel@ximian.com>
+
+       * modifiers.cs: If the ABSTRACT keyword is present, also set the
+       virtual and newslot bits. 
+
+       * class.cs (TypeContainer::RegisterRequiredImplementations):
+       Record methods we need.
+
+       (TypeContainer::MakeKey): Helper function to make keys for
+       MethodBases, since the Methodbase key is useless.
+
+       (TypeContainer::Populate): Call RegisterRequiredImplementations
+       before defining the methods.   
+
+       Create a mapping for method_builders_to_methods ahead of time
+       instead of inside a tight loop.
+
+       (::RequireMethods):  Accept an object as the data to set into the
+       hashtable so we can report interface vs abstract method mismatch.
+
+2001-10-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * report.cs: Make all of it static.
+
+       * rootcontext.cs: Drop object_type and value_type computations, as
+       we have those in the TypeManager anyways.
+
+       Drop report instance variable too, now it is a global.
+
+       * driver.cs: Use try/catch on command line handling.
+
+       Add --probe option to debug the error reporting system with a test
+       suite. 
+
+       * report.cs: Add support for exiting program when a probe
+       condition is reached.
+
+2001-10-03  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Binary::DoNumericPromotions): Fix the case when
+       we do a forcible conversion regardless of type, to check if 
+       ForceConversion returns a null.
+
+       (Binary::error19): Use location to report error.
+
+       (Unary::error23): Use location here too.
+
+       * ../errors/cs0019.cs : Check in.
+
+       * ../errors/cs0023.cs : Check in.
+
+       * expression.cs (Expression.MemberLookup): Return null for a rather esoteric
+       case of a non-null MethodInfo object with a length of 0 !
+
+       (Binary::ResolveOperator): Flag error if overload resolution fails to find
+       an applicable member - according to the spec :-)
+       Also fix logic to find members in base types.
+
+       (Unary::ResolveOperator): Same here.
+
+       (Unary::report23): Change name to error23 and make first argument a TypeContainer
+       as I was getting thoroughly confused between this and error19 :-)
+       
+       * expression.cs (Expression::ImplicitUserConversion): Re-write fully
+       (::FindMostEncompassedType): Implement.
+       (::FindMostEncompassingType): Implement.
+       (::StandardConversionExists): Implement.
+
+       (UserImplicitCast): Re-vamp. We now need info about most specific
+       source and target types so that we can do the necessary conversions.
+
+       (Invocation::MakeUnionSet): Completely re-write to make sure we form a proper
+       mathematical union with no duplicates.
+
+2001-10-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs (RootContext::PopulateTypes): Populate containers
+       in order from base classes to child classes, so that we can in
+       child classes look up in our parent for method names and
+       attributes (required for handling abstract, virtual, new, override
+       constructs: we need to instrospect our base class, and if we dont
+       populate the classes in order, the introspection might be
+       incorrect.  For example, a method could query its parent before
+       the parent has any methods and would determine that the parent has
+       no abstract methods (while it could have had them)).
+
+       (RootContext::CreateType): Record the order in which we define the
+       classes.
+
+2001-10-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (TypeContainer::Populate): Also method definitions can
+       fail now, keep track of this.
+
+       (TypeContainer::FindMembers): Implement support for
+       DeclaredOnly/noDeclaredOnly flag.
+
+       (Constructor::Emit) Return the ConstructorBuilder.
+
+       (Method::Emit) Return the MethodBuilder. 
+       Check for abstract or virtual methods to be public.
+
+       * rootcontext.cs (RootContext::CreateType): Register all the
+       abstract methods required for the class to be complete and the
+       interface methods that must be implemented. 
+
+       * cs-parser.jay: Report error 501 (method requires body if it is
+       not marked abstract or extern).
+
+       * expression.cs (TypeOf::Emit): Implement.
+
+       * typemanager.cs: runtime_handle_type, new global type.
+
+       * class.cs (Property::Emit): Generate code for properties.
+
+2001-10-02  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Unary::ResolveOperator): Find operators on base type
+       too - we now conform exactly to the spec.
+
+       (Binary::ResolveOperator): Same here.
+
+       * class.cs (Operator::Define): Fix minor quirk in the tests.
+
+       * ../errors/cs0215.cs : Added.
+
+       * ../errors/cs0556.cs : Added.
+
+       * ../errors/cs0555.cs : Added.
+
+2001-10-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-tokenizer.cs: Reimplemented Location to be a struct with a
+       single integer which is really efficient
+
+2001-10-01  Ravi Pratap  <ravi@ximian.com>
+
+       *  expression.cs (Expression::ImplicitUserConversion): Use location
+        even in the case when we are examining True operators.
+        * class.cs (Operator::Define): Perform extensive checks to conform
+        with the rules for operator overloading in the spec.
+
+       * expression.cs (Expression::ImplicitReferenceConversion): Implement
+       some of the other conversions mentioned in the spec.
+
+       * typemanager.cs (array_type): New static member for the System.Array built-in
+       type.
+
+       (cloneable_interface): For System.ICloneable interface.
+
+       * driver.cs (Driver::Driver): Initialize TypeManager's core types even before
+       we start resolving the tree and populating types.
+
+       * ../errors/errors.txt : Update for error numbers -7, -8, -9, -10
+2001-10-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Expression::ExprClassFromMemberInfo,
+       Expression::Literalize): Create literal expressions from
+       FieldInfos which are literals.
+
+       (ConvertNumericExplicit, ImplicitNumericConversion): Fix a few
+       type casts, because they were wrong.  The test suite in tests
+       caught these ones.
+
+       (ImplicitNumericConversion): ushort to ulong requires a widening
+       cast. 
+
+       Int32 constant to long requires widening cast as well.
+
+       * literal.cs (LongLiteral::EmitLong): Do not generate i4 constants
+       for integers because the type on the stack is not i4.
+
+2001-09-30  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (report118): require location argument. 
+
+       * parameter.cs: Do not dereference potential null value.
+
+       * class.cs: Catch methods that lack the `new' keyword when
+       overriding a name.  Report warnings when `new' is used without
+       anything being there to override.
+
+       * modifiers.cs: Handle `NEW' as MethodAttributes.NewSlot.
+
+       * class.cs: Only add constructor to hashtable if it is non-null
+       (as now constructors can fail on define).
+
+       (TypeManager, Class, Struct): Take location arguments.
+
+       Catch field instance initialization in structs as errors.
+
+       accepting_filter: a new filter for FindMembers that is static so
+       that we dont create an instance per invocation.
+
+       (Constructor::Define): Catch errors where a struct constructor is
+       parameterless 
+
+       * cs-parser.jay: Pass location information for various new
+       constructs. 
+       
+       * delegate.cs (Delegate): take a location argument.
+
+       * driver.cs: Do not call EmitCode if there were problesm in the
+       Definition of the types, as many Builders wont be there. 
+
+       * decl.cs (Decl::Decl): Require a location argument.
+
+       * cs-tokenizer.cs: Handle properly hex constants that can not fit
+       into integers, and find the most appropiate integer for it.
+
+       * literal.cs: Implement ULongLiteral.
+
+       * rootcontext.cs: Provide better information about the location of
+       failure when CreateType fails.
+       
+2001-09-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs (RootContext::PopulateTypes): Populates structs
+       as well.
+
+       * expression.cs (Binary::CheckShiftArguments): Add missing type
+       computation.
+       (Binary::ResolveOperator): Add type to the logical and and logical
+       or, Bitwise And/Or and Exclusive Or code paths, it was missing
+       before.
+
+       (Binary::DoNumericPromotions): In the case where either argument
+       is ulong (and most signed types combined with ulong cause an
+       error) perform implicit integer constant conversions as well.
+
+2001-09-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (UserImplicitCast): Method should always be
+       non-null. 
+       (Invocation::BetterConversion): Simplified test for IntLiteral.
+
+       (Expression::ImplicitNumericConversion): Split this routine out.
+       Put the code that performs implicit constant integer conversions
+       here. 
+
+       (Expression::Resolve): Become a wrapper around DoResolve so we can
+       check eclass and type being set after resolve.
+
+       (Invocation::Badness): Remove this dead function
+
+       (Binary::ResolveOperator): Do not compute the expensive argumnets
+       unless we have a union for it.
+
+       (Probe::Emit): Is needs to do an isinst and then
+       compare against null.
+
+       (::CanConvert): Added Location argument.  If the Location argument
+       is null (Location.Null), then we do not report errors.  This is
+       used by the `probe' mechanism of the Explicit conversion.  We do
+       not want to generate an error for something that the user
+       explicitly requested to be casted.  But the pipeline for an
+       explicit cast first tests for potential implicit casts.
+
+       So for now, if the Location is null, it means `Probe only' to
+       avoid adding another argument.   Might have to revise this
+       strategy later.
+
+       (ClassCast): New class used to type cast objects into arbitrary
+       classes (used in Explicit Reference Conversions).
+
+       Implement `as' as well.
+
+       Reverted all the patches from Ravi below: they were broken:
+
+               * The use of `level' as a mechanism to stop recursive
+                 invocations is wrong.  That was there just to catch the
+                 bug with a strack trace but not as a way of addressing
+                 the problem.
+
+                 To fix the problem we have to *understand* what is going
+                 on and the interactions and come up with a plan, not
+                 just get things going.
+
+               * The use of the type conversion cache that I proposed
+                 last night had an open topic: How does this work across
+                 protection domains.  A user defined conversion might not
+                 be public in the location where we are applying the
+                 conversion, a different conversion might be selected
+                 (ie, private A->B (better) but public B->A (worse),
+                 inside A, A->B applies, but outside it, B->A will
+                 apply).
+
+               * On top of that (ie, even if the above is solved),
+                 conversions in a cache need to be abstract.  Ie, `To
+                 convert from an Int to a Short use an OpcodeCast', not
+                 `To convert from an Int to a Short use the OpcodeCast on
+                 the variable 5' (which is what this patch was doing).
+       
+2001-09-28  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Invocation::ConversionExists): Re-write to use
+       the conversion cache
+       
+       (Expression::ConvertImplicit): Automatic bailing out if level != 0. Also
+       cache all conversions done, not just user-defined ones.
+
+       (Invocation::BetterConversion): The real culprit. Use ConversionExists
+       to determine if a conversion exists instead of acutually trying to 
+       perform the conversion. It's faster too.
+
+       (Expression::ConvertExplicit): Modify to use ConversionExists to check
+       and only then attempt the implicit conversion.
+
+2001-09-28  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (ConvertImplicit): Use a cache for conversions
+       already found. Check level of recursion and bail out if necessary.
+       
+2001-09-28  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (string_concat_string_string, string_concat_object_object):
+       Export standard methods that we expect for string operations.
+       
+       * statement.cs (Block::UsageWarning): Track usage of variables and
+       report the errors for not used variables.
+
+       * expression.cs (Conditional::Resolve, ::Emit): Implement ?:
+       operator. 
+
+2001-09-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * codegen.cs: remove unnneded code 
+
+       * expression.cs: Removed BuiltinTypeAccess class
+
+       Fix the order in which implicit conversions are
+       done.  
+
+       The previous fixed dropped support for boxed conversions (adding a
+       test to the test suite now)
+
+       (UserImplicitCast::CanConvert): Remove test for source being null,
+       that code is broken.  We should not feed a null to begin with, if
+       we do, then we should track the bug where the problem originates
+       and not try to cover it up here.
+
+       Return a resolved expression of type UserImplicitCast on success
+       rather than true/false.  Ravi: this is what I was talking about,
+       the pattern is to use a static method as a "constructor" for
+       objects. 
+
+       Also, do not create arguments until the very last minute,
+       otherwise we always create the arguments even for lookups that
+       will never be performed. 
+
+       (UserImplicitCast::Resolve): Eliminate, objects of type
+       UserImplicitCast are born in a fully resolved state. 
+       
+       * typemanager.cs (InitCoreTypes): Init also value_type
+       (System.ValueType). 
+
+       * expression.cs (Cast::Resolve): First resolve the child expression.
+
+       (LValue): Add new method AddressOf to be used by
+       the `&' operator.  
+
+       Change the argument of Store to take an EmitContext instead of an
+       ILGenerator, because things like FieldExpr need to be able to call
+       their children expression to generate the instance code. 
+
+       (Expression::Error, Expression::Warning): Sugar functions for
+       reporting errors.
+
+       (Expression::MemberLookup): Accept a TypeContainer instead of a
+       Report as the first argument.
+
+       (Expression::ResolvePrimary): Killed.  I still want to improve
+       this as currently the code is just not right.
+
+       (Expression::ResolveMemberAccess): Simplify, but it is still
+       wrong. 
+
+       (Unary::Resolve): Catch errors in AddressOf operators.
+
+       (LocalVariableReference::Emit, ::Store, ::AddressOf): typecast
+       index to a byte for the short-version, or the compiler will choose
+       the wrong Emit call, which generates the wrong data.
+
+       (ParameterReference::Emit, ::Store): same.
+
+       (FieldExpr::AddressOf): Implement.
+       
+       * typemanager.cs: TypeManager: made public variable instead of
+       property.
+       
+       * driver.cs: document --fatal.
+
+       * report.cs (ErrorMessage, WarningMessage): new names for the old
+       Error and Warning classes.
+
+       * cs-parser.jay (member_access): Turn built-in access to types
+       into a normal simplename
+
+2001-09-27  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Invocation::BetterConversion): Fix to cope
+       with q being null, since this was introducing a bug.
+
+       * expression.cs (ConvertImplicit): Do built-in conversions first.
+
+2001-09-27  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (UserImplicitCast::Resolve): Fix bug.
+
+2001-09-27  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (TypeContainer::AddConstructor): Fix a stupid bug
+       I had introduced long ago (what's new ?).
+
+       * expression.cs (UserImplicitCast::CanConvert): Static method to do 
+       the work of all the checking. 
+       (ConvertImplicit): Call CanConvert and only then create object if necessary.
+       (UserImplicitCast::CanConvert, ::Resolve): Re-write.
+
+       (Unary::Operator): Rename Add and Subtract to Addition and Subtraction because
+       that is the right way. 
+
+       (Invocation::MakeUnionSet): Convenience function to make unions of sets for 
+       overloading resolution. Use everywhere instead of cutting and pasting code.
+
+       (Binary::ResolveOperator): Use MakeUnionSet.
+
+       (UserImplicitCast::CanConvert, ::Resolve): Update to take care of the case when 
+       we have to convert to bool types. Not complete yet.
+       
+2001-09-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (TypeManager::CSharpName): support ushort.
+
+       * expression.cs (Expression::TryImplicitIntConversion): Attempts
+       to provide an expression that performsn an implicit constant int
+       conversion (section 6.1.6).
+       (Expression::ConvertImplicitRequired): Reworked to include
+       implicit constant expression conversions.
+
+       (Expression::ConvertNumericExplicit): Finished.
+
+       (Invocation::Emit): If InstanceExpression is null, then it means
+       that we perform a call on this.
+       
+2001-09-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Unary::Emit): Remove some dead code.
+       (Probe): Implement Resolve and Emit for `is'.
+       (Expression::ConvertImplicitRequired): Attempt to do constant
+       expression conversions here.  Maybe should be moved to
+       ConvertImplicit, but I am not sure.
+       (Expression::ImplicitLongConstantConversionPossible,
+       Expression::ImplicitIntConstantConversionPossible): New functions
+       that tell whether is it possible to apply an implicit constant
+       expression conversion.
+
+       (ConvertNumericExplicit): Started work on explicit numeric
+       conversions.
+
+       * cs-parser.jay: Update operator constants.
+
+       * parameter.cs (Parameters::GetParameterInfo): Hook up VerifyArgs
+       (Parameters::GetSignature): Hook up VerifyArgs here.
+       (Parameters::VerifyArgs): Verifies that no two arguments have the
+       same name. 
+
+       * class.cs (Operator): Update the operator names to reflect the
+       ones that the spec expects (as we are just stringizing the
+       operator names).
+       
+       * expression.cs (Unary::ResolveOperator): Fix bug: Use
+       MethodInfo's ReturnType instead of LookupMethodByBuilder as the
+       previous usage did only work for our methods.
+       (Expression::ConvertImplicit): Handle decimal implicit numeric
+       conversions as well.
+       (Expression::InternalTypeConstructor): Used to invoke constructors
+       on internal types for default promotions.
+
+       (Unary::Emit): Implement special handling for the pre/post
+       increment/decrement for overloaded operators, as they need to have
+       the same semantics as the other operators.
+
+       (Binary::ResolveOperator): ditto.
+       (Invocation::ConversionExists): ditto.
+       (UserImplicitCast::Resolve): ditto.
+       
+2001-09-26  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Unary::Emit and Binary::Emit): If we have an overloaded
+       operator, return after emitting body. Regression tests pass again !
+
+       * expression.cs (ConvertImplicit): Take TypeContainer as first argument
+       (Unary::ForceConversion, Binary::ForceConversion): Ditto.
+       (Invocation::OverloadResolve): Ditto.
+       (Invocation::BetterFunction, BetterConversion, ConversionExists): Ditto.
+
+       * everywhere : update calls to the above methods accordingly.
+
+2001-09-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * assign.cs (Assign): Make it inherit from ExpressionStatement.
+
+       * expression.cs (ExpressionStatement): New base class used for
+       expressions that can appear in statements, so that we can provide
+       an alternate path to generate expression that do not leave a value
+       on the stack.
+
+       (Expression::Emit, and all the derivatives): We no longer return
+       whether a value is left on the stack or not.  Every expression
+       after being emitted leaves a single value on the stack.
+
+       * codegen.cs (EmitContext::EmitStatementExpression): Use the
+       facilties of ExpressionStatement if possible.
+
+       * cs-parser.jay: Update statement_expression.
+
+2001-09-25  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Change the wording of message
+
+2001-09-25  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Binary::ResolveOperator): Had forgottten to set 
+       the type of the expression to the return type of the method if
+       we have an overloaded operator match ! The regression tests pass again !
+       (Unary::ResolveOperator): Ditto.
+
+       * expression.cs (Invocation::ConversionExists): Correct the member lookup
+       to find "op_Implicit", not "implicit" ;-)
+       (UserImplicitCast): New class to take care of user-defined implicit conversions.
+       (ConvertImplicit, ForceConversion): Take TypeContainer argument
+
+       * everywhere : Correct calls to the above accordingly.
+
+       * expression.cs (UserImplicitCast::Resolve, ::Emit): Implement.
+       (ConvertImplicit): Do user-defined conversion if it exists.
+
+2001-09-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * assign.cs: track location.
+       (Resolve): Use implicit conversions on assignment.
+
+       * literal.cs: Oops.  Not good, Emit of short access values should
+       pass (Bytes) or the wrong argument will be selected.
+
+       * expression.cs (Unary::Emit): Emit code for -expr.
+       
+       (Unary::ResolveOperator): Handle `Substract' for non-constants
+       (substract from zero from the non-constants).
+       Deal with Doubles as well. 
+       
+       (Expression::ConvertImplicitRequired): New routine that reports an
+       error if no implicit conversion exists. 
+
+       (Invocation::OverloadResolve): Store the converted implicit
+       expressions if we make them
+       
+2001-09-24  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (ConstructorInitializer): Take a Location argument.
+       (ConstructorBaseInitializer): Same here.
+       (ConstructorThisInitializer): Same here.
+
+       * cs-parser.jay : Update all calls accordingly.
+
+       * expression.cs (Unary, Binary, New): Take location argument.
+       Update accordingly everywhere.
+
+       * cs-parser.jay : Update all calls to the above to take a location
+       argument.
+
+       * class.cs : Ditto.
+
+2001-09-24  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Invocation::BetterFunction): Take TypeContainer argument
+       (Invocation::BetterConversion): Same here
+       (Invocation::ConversionExists): Ditto.
+
+       (Invocation::ConversionExists): Implement.
+
+2001-09-22  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (OverloadResolve): Improve some more to catch errors 1502 and 1503
+       Also take an additional TypeContainer argument.
+
+       * All over : Pass in TypeContainer as argument to OverloadResolve.
+
+       * typemanager.cs (CSharpName): Update to check for the string type and return
+       that too.
+
+       * expression.cs (Invocation::FullMethodDesc): New static method to return a string fully describing
+       a given method.
+       
+2001-09-21  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Invocation::OverloadResolve): Re-write to conform more to the spec.
+       (Invocation::BetterFunction): Implement.
+       (Invocation::BetterConversion): Implement.
+       (Invocation::ConversionExists): Skeleton, no implementation yet.
+
+       Okay, things work fine !
+
+2001-09-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs: declare and load enum_type, delegate_type and
+       void_type. 
+
+       * expression.cs (Expression::Emit): Now emit returns a value that
+       tells whether a value is left on the stack or not.  This strategy
+       might be reveted tomorrow with a mechanism that would address
+       multiple assignments.
+       (Expression::report118): Utility routine to report mismatches on
+       the ExprClass.
+
+       (Unary::Report23): Report impossible type/operator combination
+       utility function.
+
+       (Unary::IsIncrementableNumber): Whether the type can be
+       incremented or decremented with add.
+       (Unary::ResolveOperator): Also allow enumerations to be bitwise
+       complemented. 
+       (Unary::ResolveOperator): Implement ++, !, ~,
+
+       (Invocation::Emit): Deal with new Emit convetion.
+       
+       * All Expression derivatives: Updated their Emit method to return
+       whether they leave values on the stack or not.
+       
+       * codegen.cs (CodeGen::EmitStatement): Pop values left on the
+       stack for expressions that are statements. 
+
+2001-09-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (LValue): New interface.  Must be implemented by
+       LValue objects.
+       (LocalVariableReference, ParameterReference, FieldExpr): Implement
+       LValue interface.
+       
+       * assign.cs (Assign::Emit, Assign::Resolve): Use new LValue
+       interface for generating code, simplifies the code.
+
+2001-09-20  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (everywhere): Comment out return statements in ::Resolve
+       methods to avoid the warnings.
+
+2001-09-20  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs (parse): Report error 2001 if we can not open the
+       source file.
+
+       * expression.cs (SimpleName::ResolveSimpleName): Error if we can
+       not resolve it.
+
+       * cs-parser.jay (QualifierIdentifier): Pass location to SimpleName
+       object. 
+
+       * statement.cs (Block::EmitMeta): Reuse the count across all the variables,
+       otherwise nested blocks end up with the same index.
+
+       * codegen.cs (CodeGen::EmitTopBlock): Pass initial sequence
+
+       * expression.cs:  Instead of having FIXMEs in the Resolve
+       functions, throw exceptions so it is obvious that we are facing a
+       bug. 
+
+       * cs-parser.jay (invocation_expression): Pass Location information.
+
+       * codegen.cs (CodeGen::Save, CodeGen::CodeGen, CodeGen::Basename):
+       Use a basename for those routines because .NET does not like paths
+       on them. 
+
+       * class.cs (TypeContainer::AddMethod): Do not call DefineName if the name was
+       already defined.
+
+2001-09-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (TypeManager::CoreLookupType): A function to make sure that we
+       are loading the correct data types (throws an exception if not).
+       (TypeManager::InitCoreTypes): Use CoreLookupType
+
+       * expression.cs (Unary::ResolveOperator): return the child
+       expression for expressions which are just +expr.
+       (Unary::ResolveOperator): Return negative literals for -LITERAL
+       expressions (otherwise they are Unary {Literal}).
+       (Invocation::Badness): Take into account `Implicit constant
+       expression conversions'.
+
+       * literal.cs (LongLiteral): Implement long literal class.
+       (IntLiteral): export the `Value' of the intliteral. 
+
+2001-09-19  Ravi Pratap  <ravi@ximian.com>
+
+       * expression.cs (Binary::Emit): Finally get the emission right ! Woo!
+
+       * class.cs (Operator::Define): Change the methodname prefix to 'op_' 
+       instead of 'Operator'
+
+       * expression.cs (Binary::ResolveOperator): Update accordingly.
+       (Unary::Operator): Change names to 'Add' and 'Subtract' instead 'Plus'
+       and 'Minus'
+
+       * cs-parser.jay (unary_expression): Update to use the new names.
+
+       * gen-treedump.cs (GetUnary): Same here.
+
+       * expression.cs (Unary::Resolve): Implement.
+       (Binary::ResolveOperator): Re-write bits to quietly continue if no overloaded 
+       operators are found instead of making noise ;-)
+       (Unary::ResolveOperator): New method to do precisely the same thing which
+       Binary::ResolveOperator does for Binary expressions.
+       (Unary.method, .Arguments): Add.
+       (Unary::OperName): Implement.   
+       (Unary::ForceConversion): Copy and Paste !
+
+       * class.cs (Operator::Define): Fix a small bug for the case when we have 
+       a unary operator.
+
+       * expression.cs (Unary::Emit): Implement. Need to find the right Opcodes
+       for the inbuilt operators. Only overloading works for now ;-)
+
+2001-09-18  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (CheckedExpr::Resolve, CheckedExpr::Emit,
+       UnCheckedExpr::Resolve, UnCheckedExpr::Emit): Implement.
+
+       * expression.cs (This::Emit): Implement. 
+       (This::Resolve): Implement.
+       (TypeOf:Resolve): Implement.
+       (Expression::ResolveSimpleName): Add an implicit this to instance
+       field references. 
+       (MemberAccess::Resolve): Deal with Parameters and Fields. 
+       Bind instance variable to Field expressions.
+       (FieldExpr::Instance): New field used to track the expression that
+       represents the object instance.
+       (FieldExpr::Resolve): Track potential errors from MemberLookup not
+       binding 
+       (FieldExpr::Emit): Implement.
+
+       * codegen.cs (EmitIf, EmitStatement, EmitBlock): Propagate whether
+       the last instruction contains a return opcode to avoid generating
+       the last `ret' instruction (this generates correct code, and it is
+       nice to pass the peverify output).
+
+       * class.cs (TypeContainer::EmitFieldInitializers): Implement field
+       initializer for static and instance variables.
+       (Constructor::Emit): Allow initializer to be null in the case of
+       static constructors.  Only emit initializer for instance
+       constructors. 
+
+       (TypeContainer::FindMembers): Return a null array if there are no
+       matches.
+
+       Also fix the code for the MemberTypes.Method branch, as it was not
+       scanning that for operators (or tried to access null variables before).
+
+       * assign.cs (Assign::Emit): Handle instance and static fields. 
+
+       * TODO: Updated.
+
+       * driver.cs: Stop compilation if there are parse errors.
+
+       * cs-parser.jay (constructor_declaration): Provide default base
+       initializer for non-static constructors.
+       (constructor_declarator): Do not provide a default base
+       initializers if none was specified.
+       Catch the fact that constructors should not have parameters.
+
+       * class.cs: Do not emit parent class initializers for static
+       constructors, that should be flagged as an error.
+
+2001-09-18  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (RegisterMethodBuilder): Remove : it's unnecessary.
+       Move back code into TypeContainer::Populate.
+
+2001-09-18  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (TypeContainer::AddConstructor): Fix the check to
+       compare against Name, not Basename. 
+       (Operator::OpType): Change Plus and Minus to Add and Subtract.
+
+       * cs-parser.jay : Update accordingly.
+
+       * class.cs (TypeContainer::FindMembers): For the case where we are searching
+       for methods, don't forget to look into the operators too.
+       (RegisterMethodBuilder): Helper method to take care of this for
+       methods, constructors and operators.
+       (Operator::Define): Completely revamp.
+       (Operator.OperatorMethod, MethodName): New fields.
+       (TypeContainer::Populate): Move the registering of builders into
+       RegisterMethodBuilder.
+       (Operator::Emit): Re-write.
+
+       * expression.cs (Binary::Emit): Comment out code path to emit method
+       invocation stuff for the case when we have a user defined operator. I am
+       just not able to get it right !
+       
+2001-09-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Expression::OverloadResolve): Drop TypeContainer
+       argument. 
+
+       (Expression::MemberLookup): Provide a version that allows to
+       specify the MemberTypes and BindingFlags. 
+
+       * statement.cs (Block::GetVariableInfo): Forgot to recurse here,
+       so it was not fetching variable information from outer blocks.
+
+       * modifiers.cs: (Modifiers::TypeAttr): Invert condition on
+       Beforefieldinit as it was buggy.
+
+       * rootcontext.cs (::LookupInterfaceOrClass): Removed an Error -200
+       that Ravi put here.  
+
+       * class.cs (Constructor::Emit): Only emit if block is not null.
+       (TypeContainer::EmitDefaultConstructor): Removed routine, now we
+       deal with this by semantically definining it as if the user had
+       done it.
+
+       (TypeContainer::FindMembers): Removed ad-hoc hack to deal with
+       constructors as we now "emit" them at a higher level.
+
+       (TypeContainer::DefineDefaultConstructor): Used to define the
+       default constructors if none was provided.
+
+       (ConstructorInitializer): Add methods Resolve and Emit. 
+       
+       * expression.cs: Cast to ConstructorInfo instead of MethodInfo
+
+2001-09-17  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (TypeContainer::EmitDefaultConstructor): Register
+       the default constructor builder with our hashtable for methodbuilders
+       to methodcores.
+
+       * expression.cs (Invocation::OverloadResolve): Add a check for pd == null
+       and argument_count is 0 in which case we have a match.
+       (Binary::ResolveOperator): More null checking and miscellaneous coding
+       style cleanup.
+
+2001-09-17  Ravi Pratap  <ravi@ximian.com>
+
+       * rootcontext.cs (IsNameSpace): Compare against null.
+
+       * everywhere : Correct spelling to 'Greater' and to 'Subtract'
+
+       * class.cs (Operator::OpType): Change names to match the ones in Binary::Operator
+       and Unary::Operator.
+
+       * cs-parser.jay (operator_declaration, CheckBinaryOperator, CheckUnaryOperator): Update
+       accordingly.
+
+       * expression.cs (Binary::method): New member to hold the MethodBase for the case when
+       we have overloaded operators.
+       (Binary::ResolveOperator): Implement the part which does the operator overload
+       resolution.
+
+       * class.cs (Operator::Emit): Implement.
+       (TypeContainer::Emit): Emit the operators we have too.
+
+       * expression.cs (Binary::Emit): Update to emit the appropriate code for
+       the case when we have a user-defined operator.
+       
+2001-09-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs: Fix bug: tree.Namespaces might be null.
+
+2001-09-16  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (EmitStaticFieldInitializers, EmitFieldInitializers): Make public.
+       (TypeContainer::EmitConstructor): Remove and move code into Contructor::Emit.
+       (Constructor::Emit): Implement.
+       (EmitStaticFieldInitializers, EmitFieldInitializers): Ensure we return immediately
+       if we have no work to do. 
+       (TypeContainer::Emit): Pass in TypeContainer as argument to the constructor's 
+       Emit method.
+
+       * interface.cs (Interface::InterfaceAttr): Re-write to be more correct and complete.
+       (Interface::IsTopLevel): Add. Same as TypeContainer::IsTopLevel.
+
+       * class.cs (TypeContainer::IsTopLevel): Modify to use parent.Parent instead
+       of parent.parent.
+
+2001-09-15  Ravi Pratap  <ravi@ximian.com>
+
+       * tree.cs (Tree::namespaces): New hashtable to keep track of namespaces
+       in the source.
+       (Tree::RecordNamespace): Method to do what the name says ;-)
+       (Tree::Namespaces): Property to get at the namespaces hashtable.
+
+       * cs-parser.jay (namespace_declaration): Call RecordNamespace to 
+       keep track.
+
+       * rootcontext.cs (IsNamespace): Fixed it :-)
+
+2001-09-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (TypeContainer::FindMembers): Add support for
+       constructors. 
+       (MethodCore): New class that encapsulates both the shared aspects
+       of a Constructor and a Method.  
+       (Method, Constructor): Factored pieces into MethodCore.
+
+       * driver.cs: Added --fatal which makes errors throw exceptions.
+       Load System assembly as well as part of the standard library.
+
+       * report.cs: Allow throwing exceptions on errors for debugging.
+
+       * modifiers.cs: Do not use `parent', instead use the real type
+       container to evaluate permission settings.
+
+       * class.cs: Put Ravi's patch back in.  He is right, and we will
+       have to cope with the
+
+2001-09-14  Ravi Pratap  <ravi@ximian.com>
+
+       * modifiers.cs (TypeAttr, MethodAttr, FieldAttr): Map protected internal to
+       FamORAssem, not FamANDAssem.
+       
+2001-09-14  Miguel de Icaza  <miguel@ximian.com>
+
+       * driver.cs: Added --parse option that only parses its input files
+       and terminates.
+
+       * class.cs: Reverted last change from Ravi to IsTopLevel.  That is
+       incorrect.  IsTopLevel is not used to tell whether an object is
+       root_types or not (that can be achieved by testing this ==
+       root_types).  But to see if this is a top-level *class* (not
+       necessarly our "toplevel" container). 
+
+2001-09-14  Ravi Pratap  <ravi@ximian.com>
+
+       * enum.cs (Enum::Define): Modify to call the Lookup method on the
+       parent instead of a direct call to GetType.
+
+2001-09-14  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (TypeContainer::TypeAttr): Remove property code and move it into
+       Modifiers.TypeAttr. This should just be a call to that method.
+
+       * modifiers.cs (TypeAttr): Re-write and take an extra argument, the TypeContainer
+       object so that we can determine if we are top-level or not.
+
+       * delegate.cs (Delegate::Define): Update call to TypeAttr method to pass in the 
+       TypeContainer too.
+
+       * enum.cs (Enum::Define): Ditto.
+
+       * modifiers.cs (FieldAttr): Re-write.
+
+       * class.cs (TypeContainer::IsTopLevel): Change accessibility to public.
+       (TypeContainer::HaveStaticConstructor): New property to provide access
+       to precisely that info.
+
+       * modifiers.cs (MethodAttr): Re-write.
+       (EventAttr): Remove altogether as there seems to be no ostensible use for it.
+
+       * class.cs (TypeContainer::IsTopLevel): Re-write. root_types doesn't seem to be the parent
+       of top-level types as claimed.
+       
+2001-09-13  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (MemberLookup): Fruitless attempt to lookup
+       constructors.  Maybe I need to emit default constructors?  That
+       might be it (currently .NET emits this for me automatically).
+       (Invocation::OverloadResolve): Cope with Arguments == null.
+       (Invocation::EmitArguments): new function, shared by the new
+       constructor and us.
+       (Invocation::Emit): Handle static and instance methods.  Emit
+       proper call instruction for virtual or non-virtual invocations.
+       (New::Emit): Implement.
+       (New::Resolve): Implement.
+       (MemberAccess:Resolve): Implement.
+       (MethodGroupExpr::InstanceExpression): used conforming to the spec
+       to track instances.
+       (FieldExpr::Resolve): Set type.
+
+       * support.cs: Handle empty arguments.
+               
+       * cs-parser.jay (CompositeLookup, QualifierIdentifier,
+       SimpleLookup): Auxiliary routines to help parse a qualifier
+       identifier.  
+
+       Update qualifier_identifier rule.
+
+       * codegen.cs: Removed debugging messages.
+
+       * class.cs: Make this a global thing, this acts just as a "key" to
+       objects that we might have around.
+
+       (Populate): Only initialize method_builders_to_methods once.
+
+       * expression.cs (PropertyExpr): Initialize type from the
+       PropertyType. 
+
+       * codegen.cs (EmitContext::EmitBoolExpression): Use propper
+       Resolve pattern.  Attempt to implicitly convert value to boolean.
+       Emit code.
+
+       * expression.cs: Set the type for the int32/int32 argument case.
+       (Binary::ResolveOperator): Set the return type to boolean for
+       comparission operators
+
+       * typemanager.cs: Remove debugging print code.
+
+       (Invocation::Resolve): resolve type.
+
+       * class.cs: Allocate a MemberInfo of the correct size, as the code
+       elsewhere depends on the test to reflect the correct contents.
+
+       (Method::) Keep track of parameters, due to System.Reflection holes
+
+       (TypeContainer::Populate): Keep track of MethodBuilders to Method
+       mapping here.
+
+       (TypeContainer::FindMembers): Use ArrayList and then copy an array
+       of the exact size and return that.
+
+       (Class::LookupMethodByBuilder): New function that maps
+       MethodBuilders to its methods.  Required to locate the information
+       on methods because System.Reflection bit us again.
+
+       * support.cs: New file, contains an interface ParameterData and
+       two implementations: ReflectionParameters and InternalParameters
+       used to access Parameter information.  We will need to grow this
+       as required.
+
+       * expression.cs (Invocation::GetParameterData): implement a cache
+       and a wrapper around the ParameterData creation for methods. 
+       (Invocation::OverloadResolve): Use new code.
+
+2001-09-13  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (TypeContainer::EmitField): Remove and move into 
+       (Field::Define): here and modify accordingly.
+       (Field.FieldBuilder): New member.
+       (TypeContainer::Populate): Update accordingly.
+       (TypeContainer::FindMembers): Implement.
+
+2001-09-13  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs: (VariableInfo::VariableType): New field to be
+       initialized with the full type once it is resolved. 
+
+2001-09-12  Miguel de Icaza  <miguel@ximian.com>
+
+       * parameter.cs (GetParameterInfo): Use a type cache to compute
+       things only once, and to reuse this information
+
+       * expression.cs (LocalVariableReference::Emit): Implement.
+       (OpcodeCast::Emit): fix.
+
+       (ParameterReference::Resolve): Implement.
+       (ParameterReference::Emit): Implement.
+
+       * cs-parser.jay: Fix bug introduced by Ravi, variable initializers
+       that are expressions need to stay as Expressions.
+
+       * typemanager.cs (CSharpName): Returns the C# name of a type if
+       possible. 
+
+       * expression.cs (Expression::ConvertImplicit): New function that
+       implements implicit type conversions.
+
+       (Expression::ImplicitReferenceConversion): Implements implicit
+       reference conversions.
+
+       (EmptyCast): New type for transparent casts.
+
+       (OpcodeCast): New type for casts of types that are performed with
+       a sequence of bytecodes.
+       
+       (BoxedCast): New type used for casting value types into reference
+       types.  Emits a box opcode.
+
+       (Binary::DoNumericPromotions): Implements numeric promotions of
+       and computation of the Binary::Type.
+
+       (Binary::EmitBranchable): Optimization.
+
+       (Binary::Emit): Implement code emission for expressions.
+       
+       * typemanager.cs (TypeManager): Added two new core types: sbyte
+       and byte.
+
+2001-09-12  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (TypeContainer::FindMembers): Method which does exactly
+       what Type.FindMembers does, only we don't have to use reflection. No
+       implementation yet.
+
+       * typemanager.cs (typecontainers): New hashtable to hold the corresponding
+       typecontainer objects as we need to get at them.
+       (TypeManager::AddUserType): Overload to take an extra argument, the TypeContainer.
+
+       * rootcontext.cs : Correspondingly modify called to AddUserType to pass the
+       typecontainer object.
+
+       * expression.cs (MemberLookup): Modify signature to take a RootContext object instead
+       of just a Report object.
+
+2001-09-11  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Event::Define): Go back to using the prefixes "add_" and
+       "remove_"
+       (TypeContainer::Populate): Now define the delegates of the type too.
+       (TypeContainer.Delegates): Property to access the list of delegates defined
+       in the type.
+
+       * delegates.cs (Delegate::Define): Implement partially.
+
+       * modifiers.cs (TypeAttr): Handle more flags.
+
+2001-09-11  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Indexer::Define): Fix for loop iteration condition to be just <
+       and not <=
+       (Operator::Define): Re-write logic to get types by using the LookupType method
+       instead of blindly doing a Type.GetType ! How stupid can I get ;-) ?
+       (Indexer::Define): Ditto.
+       (Event::Define): Ditto.
+       (Property::Define): Ditto.
+       
+2001-09-10  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (TypeContainer::Populate): Now define operators too. 
+       (TypeContainer.Operators): New property to access the list of operators
+       in a type.
+       (Operator.OperatorMethodBuilder): New member to hold the method builder
+       for the operator we are defining.
+       (Operator::Define): Implement.
+
+2001-09-10  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Event::Define): Make the prefixes of the accessor methods
+       addOn_ and removeOn_ 
+
+       * genericparser.cs (GenericParser::error): Overloaded method to handle the case
+       of the location being passed in too. Ideally, this should go later since all
+       error reporting should be done through the Report object.
+
+       * class.cs (TypeContainer.Indexers): New property to access the list of indexers.
+       (Populate): Iterate thru the indexers we have and define them too.
+       (Indexer.GetMethodBuilder, .SetMethodBuilder): New members to hold the method builders
+       for the get and set accessors.
+       (Indexer::Define): Implement.
+       
+2001-09-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (Binary::Resolve): Beginning of it.  I scratched
+       my previous implementation, did not work.
+
+       * typemanager.cs: Add a couple of missing types (the longs).
+
+       * literal.cs: Use TypeManager.bool_type instead of getting it.
+
+       * expression.cs (EventExpr): New kind of expressions.
+       (Expressio::ExprClassFromMemberInfo): finish
+
+2001-09-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * assign.cs: Emit stores to static fields differently.
+
+2001-09-08  Ravi Pratap  <ravi@ximian.com>
+
+       * Merge in changes and adjust code to tackle conflicts. Backed out my
+       code in Assign::Resolve ;-) 
+
+2001-09-08  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (CheckAttributeTarget): Modify call to error to use
+       instead Report.Error and also pass in the location.
+       (CSharpParser::Lexer): New readonly property to return the reference
+       to the Tokenizer object.
+       (declare_local_variables): Use Report.Error with location instead of plain 
+       old error.
+       (CheckDef): Ditto.
+
+       * class.cs (Operator::CheckUnaryOperator): Move into cs-parser.jay.
+       (Operator.CheckBinaryOperator): Ditto.
+
+       * cs-parser.jay (operator_declarator): Update accordingly.
+
+       * cs-parser.jay (CheckUnaryOperator): Modify to use Report.Error
+       (CheckBinaryOperator): Same here.
+
+       * rootcontext.cs (LookupType): Add an extra lookup which simply does a lookup
+       on the name without any prefixes of namespace names etc. This is because we
+       already might have something already fully qualified like 
+       'System.Console.WriteLine'
+
+       * assign.cs (Resolve): Begin implementation. Stuck ;-)
+
+2001-09-07  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-tokenizer.cs (location): Return a string which also contains
+       the file name.
+
+       * expression.cs (ElementAccess): New class for expressions of the
+       type 'element access.'
+       (BaseAccess): New class for expressions of the type 'base access.'
+       (CheckedExpr, UnCheckedExpr): New classes for Checked and Unchecked expressions
+       respectively.
+       
+       * cs-parser.jay (element_access): Implement action.
+       (base_access): Implement actions.
+       (checked_expression, unchecked_expression): Implement.
+
+       * cs-parser.jay (local_variable_type): Correct and implement.
+       (type_suffixes, type_suffix_list, type_suffix): Implement actions.
+
+       * cs-tokenizer.cs (real_type_suffix): Comment out the extra getchar.
+
+       * cs-parser.jay (rank_specifiers): Remove space while concatenating the type's
+       name and the specifiers.
+
+       * interface.cs (InterfaceAttr): New property to return the corresponding TypeAttributes
+       
+       * rootcontext.cs (CreateInterface): Use the InterfaceAttr property instead of 
+       making them all public ;-)
+
+       * cs-parser.jay (error): Remove entirely as we have an implementation in the base
+       class anyways.
+       
+2001-09-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * expression.cs (ExprClassFromMemberInfo): Return FieldExpr and
+       PropertyExprs.
+       (FieldExpr, PropertyExprs): New resolved expressions.
+       (SimpleName::MemberStaticCheck): Perform static checks for access
+       to non-static fields on static methods. Maybe this should be
+       generalized for MemberAccesses. 
+       (SimpleName::ResolveSimpleName): More work on simple name
+       resolution. 
+
+       * cs-parser.jay (primary_expression/qualified_identifier): track
+       the parameter index.
+
+       * codegen.cs (CodeGen::Save): Catch save exception, report error.
+       (EmitContext::EmitBoolExpression): Chain to expression generation
+       instead of temporary hack.
+       (::EmitStatementExpression): Put generic expression code generation.
+
+       * assign.cs (Assign::Emit): Implement variable assignments to
+       local variables, parameters and fields.
+
+2001-09-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs (Block::GetVariableInfo): New method, returns the
+       VariableInfo for a variable name in a block.
+       (Block::GetVariableType): Implement in terms of GetVariableInfo
+
+       * literal.cs (IntLiteral::Emit, FloatLiteral::Emit,
+       DoubleLiteral::Emit, CharLiteral::Emit, BoolLiteral::Emit): Implement
+
+2001-09-06  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (operator_declaration): Continue on my quest : update
+       to take attributes argument.
+       (event_declaration): Ditto.
+       (enum_declaration): Ditto.
+       (indexer_declaration): Ditto.
+       
+       * class.cs (Operator::Operator): Update constructor accordingly.
+       (Event::Event): Ditto.
+
+       * delegate.cs (Delegate::Delegate): Same here.
+
+       * enum.cs (Enum::Enum): Same here.
+       
+2001-09-05  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (CheckAttributeTarget): Update to use the right error number.
+
+       * ../tests/cs0658.cs : New file to demonstrate error 0658.
+
+       * attribute.cs (Attributes): New class to encapsulate all attributes which were
+       being passed around as an arraylist.
+       (Attributes::AddAttribute): Method to add attribute sections.
+
+       * cs-parser.jay (opt_attributes): Modify actions to use the new Attributes class.
+       (struct_declaration): Update accordingly.
+       (constant_declaration): Update.
+       (field_declaration): Update.
+       (method_header): Update.
+       (fixed_parameter): Update.
+       (parameter_array): Ditto.
+       (property_declaration): Ditto.
+       (destructor_declaration): Ditto.
+       
+       * class.cs (Struct::Struct): Update constructors accordingly.
+       (Class::Class): Ditto.
+       (Field::Field): Ditto.
+       (Method::Method): Ditto.
+       (Property::Property): Ditto.
+       (TypeContainer::OptAttribute): update property's return type.
+       
+       * interface.cs (Interface.opt_attributes): New member.
+       (Interface::Interface): Update to take the extra Attributes argument.
+
+       * parameter.cs (Parameter::Parameter): Ditto.
+
+       * constant.cs (Constant::Constant): Ditto.
+
+       * interface.cs (InterfaceMemberBase): New OptAttributes field.
+       (InterfaceMemberBase::InterfaceMemberBase): Update constructor to take 
+       the attributes as a parameter.
+       (InterfaceProperty): Update constructor call.
+       (InterfaceEvent): Ditto.
+       (InterfaceMethod): Ditto.
+       (InterfaceIndexer): Ditto.
+
+       * cs-parser.jay (interface_indexer_declaration): Update call to constructor to 
+       pass the attributes too.
+       (interface_event_declaration): Ditto.
+       (interface_property_declaration): Ditto.
+       (interface_method_declaration): Ditto.
+       (interface_declaration): Ditto.
+
+2001-09-05  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (Method::Define): Track the "static Main" definition to
+       create an entry point. 
+
+       * rootcontext.cs (RootContext::EntryPoint): MethodInfo that holds the
+       EntryPoint if we find it. 
+
+       * codegen.cs (EmitContext::EmitInvocation): Emit invocations.
+       (EmitContext::ig): Make this variable public.
+
+       * driver.cs: Make the default output file be the first file name
+       with the .exe extension.  
+
+       Detect empty compilations
+
+       Handle various kinds of output targets.  Handle --target and
+       rename -t to --dumper.
+
+       * expression.cs, literal.cs, assign.cs, constant.cs: All `Resolve'
+       methods inherited from Expression return now an Expression.  This
+       will is used during the tree rewriting as we resolve them during
+       semantic analysis.
+
+       (Expression::MemberLookup): Implements the MemberLookup (7.3) from
+       the spec.  Missing entirely is the information about
+       accessability of elements of it.
+
+       (Expression::ExprClassFromMemberInfo): New constructor for
+       Expressions that creates a fully initialized Expression based on
+       a MemberInfo that is one of Eventinfo, FieldINfo, PropertyInfo or
+       a Type.
+
+       (Invocation::Resolve): Begin implementing resolution of invocations.
+       
+       * literal.cs (StringLiteral):  Implement Emit.
+
+2001-09-05  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (error): Add new modifier because we are hiding an inherited
+       member.
+       
+2001-09-04  Ravi Pratap  <ravi@ximian.com>
+
+       * cs-parser.jay (attribute_arguments): Implement actions.
+       (attribute): Fix bug in production. Implement action.
+       (attribute_list): Implement.
+       (attribute_target): Implement.
+       (attribute_target_specifier, opt_target_specifier): Implement
+       (CheckAttributeTarget): New method to check if the attribute target
+       is valid.
+       (attribute_section): Implement.
+       (opt_attributes): Implement.
+
+       * attribute.cs : New file to handle attributes.
+       (Attribute): Class to hold attribute info.
+
+       * cs-parser.jay (opt_attribute_target_specifier): Remove production
+       (attribute_section): Modify production to use 2 different rules to 
+       achieve the same thing. 1 s/r conflict down !
+       Clean out commented, useless, non-reducing dimension_separator rules.
+       
+       * class.cs (TypeContainer.attributes): New member to hold list
+       of attributes for a type.
+       (Struct::Struct): Modify to take one more argument, the attribute list.
+       (Class::Class): Ditto.
+       (Field::Field): Ditto.
+       (Method::Method): Ditto.
+       (Property::Property): Ditto.
+       
+       * cs-parser.jay (struct_declaration): Update constructor call to
+       pass in the attributes too.
+       (class_declaration): Ditto.
+       (constant_declaration): Ditto.
+       (field_declaration): Ditto.
+       (method_header): Ditto.
+       (fixed_parameter): Ditto.
+       (parameter_array): Ditto.
+       (property_declaration): Ditto.
+
+       * constant.cs (Constant::Constant): Update constructor similarly.
+       Use System.Collections.
+
+       * parameter.cs (Parameter::Parameter): Update as above.
+
+2001-09-02  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (TypeContainer::AddDelegate): New method to add a delegate.
+       (TypeContainer.delegates): New member to hold list of delegates.
+
+       * cs-parser.jay (delegate_declaration): Implement the action correctly 
+       this time as I seem to be on crack ;-)
+
+2001-09-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs (RootContext::IsNamespace): new function, used to
+       tell whether an identifier represents a namespace.
+
+       * expression.cs (NamespaceExpr): A namespace expression, used only
+       temporarly during expression resolution.
+       (Expression::ResolveSimpleName, ::ResolvePrimary, ::ResolveName):
+       utility functions to resolve names on expressions.
+
+2001-09-01  Miguel de Icaza  <miguel@ximian.com>
+
+       * codegen.cs: Add hook for StatementExpressions. 
+
+       * class.cs: Fix inverted test for static flag in methods.
+
+2001-09-02  Ravi Pratap  <ravi@ximian.com>
+
+       * class.cs (Operator::CheckUnaryOperator): Correct error number used
+       to make it coincide with MS' number.
+       (Operator::CheckBinaryOperator): Ditto.
+
+       * ../errors/errors.txt : Remove error numbers added earlier.
+
+       * ../errors/cs1019.cs : Test case for error # 1019
+
+       * ../errros/cs1020.cs : Test case for error # 1020
+
+       * cs-parser.jay : Clean out commented cruft.
+       (dimension_separators, dimension_separator): Comment out. Ostensibly not
+       used anywhere - non-reducing rule.
+       (namespace_declarations): Non-reducing rule - comment out.
+
+       * enum.cs (Enum::AddEnum): Rename to AddEnumMember as I was getting confused
+       with TypeContainer::AddEnum.
+
+       * delegate.cs : New file for delegate handling classes.
+       (Delegate): Class for declaring delegates.
+
+       * makefile : Update.
+
+       * cs-parser.jay (delegate_declaration): Implement.
+
+2001-09-01  Ravi Pratap  <ravi@che.iitm.ac.in>
+
+       * class.cs (Event::Define): Implement.
+       (Event.EventBuilder): New member.
+
+       * class.cs (TypeContainer::Populate): Update to define all enums and events
+       we have.
+       (Events): New property for the events arraylist we hold. Shouldn't we move to using
+       readonly fields for all these cases ?
+
+2001-08-31  Ravi Pratap  <ravi@che.iitm.ac.in>
+
+       * class.cs (Property): Revamp to use the convention of making fields readonly.
+       Accordingly modify code elsewhere.
+
+       * class.cs : Apply patch from Mr. Mandar <go_mono@hotmail.com> for implementing
+       the Define method of the Property class.
+
+       * class.cs : Clean up applied patch and update references to variables etc. Fix 
+       trivial bug.
+       (TypeContainer::Populate): Update to define all the properties we have. Also
+       define all enumerations.
+
+       * enum.cs (Define): Implement.
+       
+2001-08-31  Ravi Pratap  <ravi@che.iitm.ac.in>
+
+       * cs-parser.jay (overloadable_operator): The semantic value is an
+       enum of the Operator class.
+       (operator_declarator): Implement actions.
+       (operator_declaration): Implement.
+
+       * class.cs (Operator::CheckUnaryOperator): New static method to help in checking
+       validity of definitions.
+       (Operator::CheckBinaryOperator): Static method to check for binary operators
+       (TypeContainer::AddOperator): New method to add an operator to a type.
+
+       * cs-parser.jay (indexer_declaration): Added line to actually call the
+       AddIndexer method so it gets added ;-)
+
+       * ../errors/errors.txt : Update to include new error numbers. Are these numbers 
+       already taken care of by the MS compiler ?  
+
+2001-08-29  Ravi Pratap  <ravi@che.iitm.ac.in>
+
+       * class.cs (Operator): New class for operator declarations.
+       (Operator::OpType): Enum for the various operators.
+
+2001-08-29  Ravi Pratap  <ravi@che.iitm.ac.in>
+
+       * class.cs (TypeContainer::AddIndexer): Remove FIXME comment. We
+       ostensibly handle this in semantic analysis.
+
+       * cs-parser.jay (general_catch_clause): Comment out
+       (specific_catch_clauses, specific_catch_clause): Ditto.
+       (opt_general_catch_clause, opt_specific_catch_clauses): Ditto
+       (catch_args, opt_catch_args): New productions.
+       (catch_clause): Rewrite to use the new productions above
+       (catch_clauses): Modify accordingly.
+       (opt_catch_clauses): New production to use in try_statement
+       (try_statement): Revamp. Basically, we get rid of one unnecessary rule
+       and re-write the code in the actions to extract the specific and
+       general catch clauses by being a little smart ;-)
+
+       * ../tests/try.cs : Fix. It's not 'finalize' my friend, it's 'finally' !
+       Hooray, try and catch statements parse fine !
+       
+2001-08-28  Ravi Pratap  <ravi@che.iitm.ac.in>
+
+       * statement.cs (Block::GetVariableType): Fix logic to extract the type
+       string from the hashtable of variables.
+
+       * cs-parser.jay (event_accessor_declarations): Trivial fix. Man, how did
+       I end up making that mistake ;-)
+       (catch_clauses): Fixed gross error which made Key and Value of the 
+       DictionaryEntry the same : $1 !!
+
+2001-08-28  Ravi Pratap  <ravi@che.iitm.ac.in>
+
+       * cs-tokenizer.cs (initTokens): Add keywords 'add' and 'remove'
+
+       * cs-parser.jay (event_declaration): Correct to remove the semicolon
+       when the add and remove accessors are specified. 
+
+2001-08-28  Ravi Pratap  <ravi@che.iitm.ac.in>
+
+       * cs-parser.jay (IndexerDeclaration): New helper class to hold
+       information about indexer_declarator.
+       (indexer_declarator): Implement actions.
+       (parsing_indexer): New local boolean used to keep track of whether
+       we are parsing indexers or properties. This is necessary because 
+       implicit_parameters come into picture even for the get accessor in the 
+       case of an indexer.
+       (get_accessor_declaration, set_accessor_declaration): Correspondingly modified.
+
+       * class.cs (Indexer): New class for indexer declarations.
+       (TypeContainer::AddIndexer): New method to add an indexer to a type.
+       (TypeContainer::indexers): New member to hold list of indexers for the
+       type.
+
+2001-08-27  Ravi Pratap  <ravi@che.iitm.ac.in>
+
+       * cs-parser.jay (add_accessor_declaration): Implement action.
+       (remove_accessor_declaration): Implement action.
+       (event_accessors_declaration): Implement
+       (variable_declarators): swap statements for first rule - trivial.
+
+       * class.cs (Event): New class to hold information about event
+       declarations.
+       (TypeContainer::AddEvent): New method to add an event to a type
+       (TypeContainer::events): New member to hold list of events.
+
+       * cs-parser.jay (event_declaration): Implement actions.
+
+2001-08-27  Ravi Pratap  <ravi@che.iitm.ac.in>
+
+       * cs-parser.jay (dim_separators): Implement. Make it a string
+       concatenating all the commas together, just as they appear.
+       (opt_dim_separators): Modify accordingly
+       (rank_specifiers): Update accordingly. Basically do the same
+       thing - instead, collect the brackets here.
+       (opt_rank_sepcifiers): Modify accordingly.
+       (array_type): Modify to actually return the complete type string
+       instead of ignoring the rank_specifiers.
+       (expression_list): Implement to collect the expressions
+       (variable_initializer): Implement. We make it a list of expressions
+       essentially so that we can handle the array_initializer case neatly too.
+       (variable_initializer_list): Implement.
+       (array_initializer): Make it a list of variable_initializers
+       (opt_array_initializer): Modify accordingly.
+
+       * expression.cs (New::NType): Add enumeration to help us
+       keep track of whether we have an object/delegate creation
+       or an array creation.
+       (New:NewType, New::Rank, New::Indices, New::Initializers): New
+       members to hold data about array creation.
+       (New:New): Modify to update NewType
+       (New:New): New Overloaded contructor for the array creation
+       case.
+
+       * cs-parser.jay (array_creation_expression): Implement to call
+       the overloaded New constructor.
+       
+2001-08-26  Ravi Pratap  <ravi@che.iitm.ac.in>
+
+       * class.cs (TypeContainer::Constructors): Return member
+       constructors instead of returning null.
+
+2001-08-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * typemanager.cs (InitCoreTypes): Initialize the various core
+       types after we have populated the type manager with the user
+       defined types (this distinction will be important later while
+       compiling corlib.dll)
+
+       * expression.cs, literal.cs, assign.cs, constant.cs: Started work
+       on Expression Classification.  Now all expressions have a method
+       `Resolve' and a method `Emit'.
+
+       * codegen.cs, cs-parser.jay: Fixed the bug that stopped code
+       generation from working.     Also add some temporary debugging
+       code. 
+       
+2001-08-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * codegen.cs: Lots of code generation pieces.  This is only the
+       beginning, will continue tomorrow with more touches of polish.  We
+       handle the fundamentals of if, while, do, for, return.  Others are
+       trickier and I need to start working on invocations soon.
+       
+       * gen-treedump.cs: Bug fix, use s.Increment here instead of
+       s.InitStatement. 
+
+       * codegen.cs (EmitContext): New struct, used during code
+       emission to keep a context.   Most of the code generation will be
+       here. 
+
+       * cs-parser.jay: Add embedded blocks to the list of statements of
+       this block.  So code generation proceeds in a top down fashion.
+
+2001-08-23  Miguel de Icaza  <miguel@ximian.com>
+
+       * statement.cs: Add support for multiple child blocks.
+
+2001-08-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * codegen.cs (EmitCode): New function, will emit the code for a
+       Block of code given a TypeContainer and its ILGenerator. 
+
+       * statement.cs (Block): Standard public readonly optimization.
+       (Block::Block constructors): Link children. 
+       (Block::Child): Child Linker.
+       (Block::EmitVariables): Emits IL variable declarations.
+
+       * class.cs: Drop support for MethodGroups here, delay until
+       Semantic Analysis.
+       (Method::): Applied the same simplification that I did before, and
+       move from Properties to public readonly fields.
+       (Method::ParameterTypes): Returns the parameter types for the
+       function, and implements a cache that will be useful later when I
+       do error checking and the semantic analysis on the methods is
+       performed.
+       (Constructor::GetCallingConvention): Renamed from CallingConvetion
+       and made a method, optional argument tells whether this is a class
+       or a structure to apply the `has-this' bit.
+       (Method::GetCallingConvention): Implement, returns the calling
+       convention. 
+       (Method::Define): Defines the type, a second pass is performed
+       later to populate the methods.
+
+       (Constructor::ParameterTypes): implement a cache similar to the
+       one on Method::ParameterTypes, useful later when we do semantic
+       analysis. 
+
+       (TypeContainer::EmitMethod):  New method.  Emits methods.
+
+       * expression.cs: Removed MethodGroup class from here.
+       
+       * parameter.cs (Parameters::GetCallingConvention): new method.
+
+2001-08-21  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (TypeContainer::Populate): Drop RootContext from the
+       argument. 
+
+       (Constructor::CallingConvention): Returns the calling convention.
+       (Constructor::ParameterTypes): Returns the constructor parameter
+       types. 
+       
+       (TypeContainer::AddConstructor): Keep track of default constructor
+       and the default static constructor.
+
+       (Constructor::) Another class that starts using `public readonly'
+       instead of properties. 
+
+       (Constructor::IsDefault): Whether this is a default constructor. 
+
+       (Field::) use readonly public fields instead of properties also.
+
+       (TypeContainer::TypeAttr, TypeContainer::AddConstructor): Keep
+       track of static constructors;  If none is used, turn on
+       BeforeFieldInit in the TypeAttributes. 
+
+       * cs-parser.jay (opt_argument_list): now the return can be null
+       for the cases where there are no arguments. 
+
+       (constructor_declarator): If there is no implicit `base' or
+       `this', then invoke the default parent constructor. 
+       
+       * modifiers.cs (MethodAttr): New static function maps a set of
+       modifiers flags into a MethodAttributes enum
+       (FieldAttr): renamed from `Map'.  So now we have FieldAttr,
+       MethodAttr, TypeAttr to represent the various mappings where the
+       modifiers are used.
+       (FieldAttr): Map also `readonly' to `FieldAttributes.InitOnly'  
+
+2001-08-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * parameter.cs (GetParameterInfo): Fix bug where there would be no
+       method arguments.
+
+       * interface.cs (PopulateIndexer): Implemented the code generator
+       for interface indexers.
+
+2001-08-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * interface.cs (InterfaceMemberBase): Now we track the new status
+       here.  
+
+       (PopulateProperty): Implement property population.  Woohoo!  Got
+       Methods and Properties going today. 
+
+       Removed all the properties for interfaces, and replaced them with
+       `public readonly' fields. 
+
+2001-08-16  Miguel de Icaza  <miguel@ximian.com>
+
+       * interface.cs (AddEvent, AddMethod, AddIndexer, AddProperty):
+       initialize their hashtables/arraylists only when they are needed
+       instead of doing this always.
+
+       * parameter.cs: Handle refs and out parameters.
+
+       * cs-parser.jay: Use an ArrayList to construct the arguments
+       instead of the ParameterCollection, and then cast that to a
+       Parameter[] array.
+
+       * parameter.cs: Drop the use of ParameterCollection and use
+       instead arrays of Parameters.
+
+       (GetParameterInfo): Use the Type, not the Name when resolving
+       types. 
+
+2001-08-13  Miguel de Icaza  <miguel@ximian.com>
+
+       * parameter.cs: Eliminate the properties Name, Type and ModFlags,
+       and instead use public readonly fields.
+
+       * class.cs: Put back walking code for type containers.
+
+2001-08-11  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (MakeConstant): Code to define constants.
+
+       * rootcontext.cs (LookupType): New function.  Used to locate types 
+
+       
+2001-08-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs: OH MY!  My trick works!   It is amazing how nice
+       this System.Reflection code is.  Kudos to Microsoft
+       
+       * typemanager.cs: Implement a type cache and avoid loading all
+       types at boot time.  Wrap in LookupType the internals.  This made
+       the compiler so much faster.  Wow.  I rule!
+       
+       * driver.cs: Make sure we always load mscorlib first (for
+       debugging purposes, nothing really important).
+
+       * Renamespaced things that were on `CSC' to `CIR'.  Maybe I should
+       have moved to `CSC' rather than `CIR'.  Oh man!  The confussion!  
+
+       * rootcontext.cs: Lookup types on their namespace;  Lookup types
+       on namespaces that have been imported using the `using' keyword.
+
+       * class.cs (TypeContainer::TypeAttr): Virtualize.
+       (Class::TypeAttr): Return attributes suitable for this bad boy.
+       (Struct::TypeAttr): ditto.
+       Handle nested classes.
+       (TypeContainer::) Remove all the type visiting code, it is now
+       replaced with the rootcontext.cs code
+
+       * rootcontext.cs (GetClassBases): Added support for structs. 
+
+2001-08-06  Miguel de Icaza  <miguel@ximian.com>
+
+       * interface.cs, statement.cs, class.cs, parameter.cs,
+       rootcontext.cs, gen-treedump.cs, enum.cs, cs-parse.jay:
+       Drop use of TypeRefs, and use strings instead.
+
+2001-08-04  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs: 
+
+       * class.cs (Struct::Struct): set the SEALED flags after
+       checking the modifiers.
+       (TypeContainer::TypeAttr): new property, returns the
+       TypeAttributes for a class.  
+
+       * cs-parser.jay (type_list): Oops, list production was creating a
+       new list of base types.
+
+       * rootcontext.cs (StdLib): New property.
+       (GetInterfaceTypeByName): returns an interface by type name, and
+       encapsulates error handling here.
+       (GetInterfaces): simplified.
+       (ResolveTree): Encapsulated all the tree resolution here.
+       (CreateClass, GetClassBases, GetInterfaceOrClass): Create class
+       types. 
+       
+       * driver.cs: Add support for --nostdlib, to avoid loading the
+       default assemblies.
+       (Main): Do not put tree resolution here. 
+
+       * rootcontext.cs: Beginning of the class resolution.
+
+2001-08-03  Miguel de Icaza  <miguel@ximian.com>
+
+       * rootcontext.cs: Provide better error reporting. 
+
+       * cs-parser.jay (interface_base): set our $$ to be interfaces.
+
+       * rootcontext.cs (CreateInterface): Handle the case where there
+       are no parent interfaces.
+       
+       (CloseTypes): Routine to flush types at the end.
+       (CreateInterface): Track types.
+       (GetInterfaces): Returns an array of Types from the list of
+       defined interfaces.
+
+       * typemanager.c (AddUserType): Mechanism to track user types (puts
+       the type on the global type hash, and allows us to close it at the
+       end). 
+       
+2001-08-02  Miguel de Icaza  <miguel@ximian.com>
+
+       * tree.cs: Removed RecordType, added RecordClass, RecordStruct and
+       RecordInterface instead.
+
+       * cs-parser.jay: Updated to reflect changes above.
+
+       * decl.cs (Definition): Keep track of the TypeBuilder type that
+       represents this type here.  Not sure we will use it in the long
+       run, but wont hurt for now.
+
+       * driver.cs: Smaller changes to accomodate the new code.
+
+       Call ResolveInterfaceBases, Call ResolveClassBases, Save assembly
+       when done. 
+
+       * rootcontext.cs (CreateInterface):  New method, used to create
+       the System.TypeBuilder type for interfaces.
+       (ResolveInterfaces): new entry point to resolve the interface
+       hierarchy. 
+       (CodeGen): Property, used to keep track of the code generator.
+
+2001-07-26  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Add a second production for delegate_declaration
+       with `VOID'.
+
+       (enum_body): Put an opt_comma here instead of putting it on
+       enum_body or enum_member_declarations so we can handle trailing
+       commas on enumeration members.  Gets rid of a shift/reduce.
+       
+       (type_list): Need a COMMA in the middle.
+
+       (indexer_declaration): Tell tokenizer to recognize get/set
+
+       * Remove old targets.
+
+       * Re-add the parser target.
+
+2001-07-13  Simon Cozens <simon@simon-cozens.org>
+
+       * cs-parser.jay: Add precendence rules for a number of operators
+       ot reduce the number of shift/reduce conflicts in the grammar.
+       
+2001-07-17  Miguel de Icaza  <miguel@ximian.com>
+
+       * tree.cs: moved IGenerator interface and renamed it to ITreeDump
+       and put it here.
+
+       Get rid of old crufty code.
+
+       * rootcontext.cs: Use this to keep track of the parsed
+       representation and the defined types available to the program. 
+
+       * gen-treedump.cs: adjust for new convention.
+
+       * type.cs: Split out the type manager, and the assembly builder
+       from here. 
+
+       * typemanager.cs: the type manager will live here now.
+
+       * cil-codegen.cs: And the code generator here. 
+
+2001-07-14  Sean MacIsaac  <macisaac@ximian.com>
+
+       * makefile: Fixed up for easy making.
+
+2001-07-13  Simon Cozens <simon@simon-cozens.org>
+
+       * cs-parser.jay (rank_specifier): Remove a conflict by reordering
+       the 
+
+       (unary_expression): Expand pre_increment_expression and
+       post_decrement_expression to reduce a shift/reduce.
+
+2001-07-11  Simon Cozens
+
+       * cs-tokenizer.cs: Hex numbers should begin with a 0.
+
+       Improve allow_keyword_as_indent name.
+
+2001-06-19  Miguel de Icaza  <miguel@ximian.com>
+
+       * Adjustments for Beta2. 
+
+2001-06-13  Miguel de Icaza  <miguel@ximian.com>
+
+       * decl.cs: Added `Define' abstract method.
+       (InTransit): new property, used to catch recursive definitions. 
+
+       * interface.cs: Implement `Define'. 
+
+       * modifiers.cs: Map Modifiers.constants to
+       System.Reflection.TypeAttribute flags.
+
+       * class.cs: Keep track of types and user-defined types.
+       (BuilderInit): New method for creating an assembly
+       (ResolveType): New function to launch the resolution process, only
+       used by interfaces for now.
+
+       * cs-parser.jay: Keep track of Classes, Structs and Interfaces
+       that are inserted into the name space. 
+
+2001-06-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * ARGH.  I have screwed up my tree so many times due to the use of
+       rsync rather than using CVS.  Going to fix this at once. 
+
+       * driver.cs: Objetify driver.  Load assemblies, use assemblies to
+       load types.
+
+2001-06-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * Experiment successful: Use System.Type rather that our own
+       version of Type.  
+
+2001-05-25  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Removed nsAliases from here.
+
+       Use new namespaces, handle `using XXX;' 
+
+       * namespace.cs: Reimplemented namespace handling, use a recursive
+       definition of the class.  Now we can keep track of using clauses
+       and catch invalid using clauses.
+
+2001-05-24  Miguel de Icaza  <miguel@ximian.com>
+
+       * gen-treedump.cs: Adapted for all the renaming.
+
+       * expression.cs (Expression): this class now has a Type property
+       which returns an expression Type.
+
+       (Probe::, New::, TypeOf::, SizeOf::, Constant::): renamed from
+       `Type', as this has a different meaning now in the base
+
+2001-05-22  Miguel de Icaza  <miguel@ximian.com>
+
+       * interface.cs, class.cs: Removed from all the sources the
+       references to signature computation, as we can not do method
+       signature computation during the parsing time, as we are not
+       trying to solve at that point distinguishing:
+
+       class X {
+               void a (Blah x) {}
+               void a (NS.Blah x) {}
+       }
+
+       Which depending on the context might be valid or not, as we do not
+       know if Blah is the same thing as NS.Blah at that point.
+
+       * Redid everything so the code uses TypeRefs now instead of
+       Types.  TypeRefs are just temporary type placeholders, that need
+       to be resolved.  They initially have a pointer to a string and the
+       current scope in which they are used.  This is used later by the
+       compiler to resolve the reference to an actual Type. 
+
+       * DeclSpace is no longer a CIR.Type, and neither are
+       TypeContainers (Class and Struct) nor Interfaces nor Enums.  They
+       are all DeclSpaces, but no Types. 
+
+       * type.cs (TypeRefManager): This implements the TypeRef manager,
+       which keeps track of all the types that need to be resolved after
+       the parsing has finished. 
+
+2001-05-13  Miguel de Icaza  <miguel@ximian.com>
+
+       * ARGH.  We are going to have to store `foreach' as a class rather
+       than resolving it, as we need to verify error 1579 after name
+       resolution.   *OR* we could keep a flag that says `This request to
+       IEnumerator comes from a foreach statement' which we can then use
+       to generate the error.
+
+2001-05-10  Miguel de Icaza  <miguel@ximian.com>
+
+       * class.cs (TypeContainer.AddMethod): we now add methods to the
+       MethodGroup instead of the method hashtable.  
+
+       * expression.cs: Add MethodGroup abstraction, which gets us one
+       step closer to the specification in the way we handle method
+       declarations.  
+
+       * cs-parser.jay (primary_expression): qualified_identifier now
+       tried to match up an identifier to a local variable reference or
+       to a parameter reference.
+
+       current_local_parameters is now a parser global variable that
+       points to the current parameters for the block, used during name
+       lookup.
+
+       (property_declaration): Now creates an implicit `value' argument to
+       the set accessor.
+
+2001-05-09  Miguel de Icaza  <miguel@ximian.com>
+
+       * parameter.cs: Do not use `param' arguments as part of the
+       signature, per the spec.
+
+2001-05-08  Miguel de Icaza  <miguel@ximian.com>
+
+       * decl.cs: Base class for classes, structs and interfaces.  This
+       is the "Declaration Space" 
+
+       * cs-parser.jay: Use CheckDef for checking declaration errors
+       instead of having one on each function.
+
+       * class.cs: Factor out some code for handling error handling in
+       accordance to the "Declarations" section in the "Basic Concepts"
+       chapter in the ECMA C# spec.
+
+       * interface.cs: Make all interface member classes derive from
+       InterfaceMemberBase.
+
+2001-05-07  Miguel de Icaza  <miguel@ximian.com>
+
+       * Many things: all interfaces are parsed and generated in
+       gen-treedump.  Support for member variables, constructors,
+       destructors, properties, constants is there.
+
+       Beginning of the IL backend, but very little done, just there for
+       testing purposes. 
+
+2001-04-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * cs-parser.jay: Fix labeled statement.
+
+       * cs-tokenizer.cs (escape): Escape " and ' always.
+       ref_line, ref_name: keep track of the line/filename as instructed
+       by #line by the compiler.
+       Parse #line.
+
+2001-04-27  Miguel de Icaza  <miguel@ximian.com>
+
+       * System.CodeDOM/CodeBinaryOperatorExpression.cs: Rearrange enum
+       to match the values in System.CodeDOM.
+
+       Divid renamed to Divide.
+
+       * System.CodeDOM/CodeForLoopStatement.cs: Always have valid
+       statements. 
+       (Statements.set): remove.
+
+       * System.CodeDOM/CodeCatchClause.cs: always have a valid
+       statements. 
+
+       * System.CodeDOM/CodeIfStatement.cs: trueStatements and
+       falseStatements always have valid values. 
+
+       * cs-parser.jay: Use System.CodeDOM now.
+
diff --git a/mcs/gmcs/Makefile b/mcs/gmcs/Makefile
new file mode 100644 (file)
index 0000000..e922174
--- /dev/null
@@ -0,0 +1,86 @@
+thisdir := mcs
+SUBDIRS := 
+include ../build/rules.make
+
+COMPILER_SOURCES = \
+       AssemblyInfo.cs                 \
+       anonymous.cs                    \
+       assign.cs                       \
+       attribute.cs                    \
+       driver.cs                       \
+       cs-tokenizer.cs                 \
+       cfold.cs                        \
+       class.cs                        \
+       codegen.cs                      \
+       const.cs                        \
+       constant.cs                     \
+       convert.cs                      \
+       decl.cs                         \
+       delegate.cs                     \
+       enum.cs                         \
+       ecore.cs                        \
+       expression.cs                   \
+       genericparser.cs                \
+       interface.cs                    \
+       iterators.cs                    \
+       literal.cs                      \
+       location.cs                     \
+       modifiers.cs                    \
+       namespace.cs                    \
+       parameter.cs                    \
+       pending.cs                      \
+       report.cs                       \
+       rootcontext.cs                  \
+       statement.cs                    \
+       support.cs                      \
+       typemanager.cs                  \
+       symbolwriter.cs                 \
+       tree.cs
+
+all_sources = $(COMPILER_SOURCES) cs-parser.cs
+
+DISTFILES = \
+       $(COMPILER_SOURCES)     \
+       compiler.csproj         \
+       compiler.csproj.user    \
+       compiler.doc            \
+       compiler.sln            \
+       cs-parser.jay           \
+       mcs.exe.config          \
+       NOTES                   \
+       TODO
+
+all-local: mcs.exe
+
+install-local: mcs.exe
+       $(MKINSTALLDIRS) $(DESTDIR)$(prefix)/bin
+       $(INSTALL_BIN) mcs.exe $(DESTDIR)$(prefix)/bin
+
+test-local run-test-local:
+
+clean-local:
+       rm -f *.exe *.pdb cs-parser.cs y.output
+
+dist-local: dist-default
+
+mcs.exe: $(all_sources)
+       $(BOOT_COMPILE) /target:exe /out:$@ $^
+
+cs-parser.cs: cs-parser.jay $(topdir)/jay/skeleton.cs
+       $(topdir)/jay/jay -ctv < $(topdir)/jay/skeleton.cs $< >$@
+
+# Testing targets
+
+TIME = time
+
+# This used to be called test, but that conflicts with the global
+# recursive target.
+
+btest: mcs2.exe mcs3.exe
+       ls -l mcs2.exe mcs3.exe
+
+mcs2.exe: mcs.exe
+       $(TIME) $(RUNTIME) ./mcs.exe $(USE_MCS_FLAGS) /target:exe /out:$@ $(all_sources)
+
+mcs3.exe: mcs2.exe
+       $(TIME) $(RUNTIME) ./mcs2.exe $(USE_MCS_FLAGS) /target:exe /out:$@ $(all_sources)
diff --git a/mcs/gmcs/anonymous.cs b/mcs/gmcs/anonymous.cs
new file mode 100644 (file)
index 0000000..e32d9f7
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// anonymous.cs: Support for anonymous methods
+//
+// Author:
+//   Miguel de Icaza (miguel@ximain.com)
+//
+// (C) 2003 Ximian, Inc.
+//
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Mono.CSharp {
+
+       public class AnonymousMethod : Expression {
+               // An array list of AnonymousMethodParameter or null
+               Parameters parameters;
+               Block block;
+               
+               public AnonymousMethod (Parameters parameters, Block block, Location l)
+               {
+                       this.parameters = parameters;
+                       this.block = block;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // Set class type, set type
+                       //
+
+                       eclass = ExprClass.Value;
+
+                       //
+                       // This hack means `The type is not accessible
+                       // anywhere', we depend on special conversion
+                       // rules.
+                       // 
+                       type = typeof (AnonymousMethod);
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       // nothing, as we only exist to not do anything.
+               }
+       }
+}
+       
diff --git a/mcs/gmcs/assign.cs b/mcs/gmcs/assign.cs
new file mode 100755 (executable)
index 0000000..e837640
--- /dev/null
@@ -0,0 +1,527 @@
+//
+// assign.cs: Assignments.
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//   Martin Baulig (martin@gnome.org)
+//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+//
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///   This interface is implemented by expressions that can be assigned to.
+       /// </summary>
+       /// <remarks>
+       ///   This interface is implemented by Expressions whose values can not
+       ///   store the result on the top of the stack.
+       ///
+       ///   Expressions implementing this (Properties, Indexers and Arrays) would
+       ///   perform an assignment of the Expression "source" into its final
+       ///   location.
+       ///
+       ///   No values on the top of the stack are expected to be left by
+       ///   invoking this method.
+       /// </remarks>
+       public interface IAssignMethod {
+               //
+               // This method will emit the code for the actual assignment
+               //
+               void EmitAssign (EmitContext ec, Expression source);
+
+               //
+               // This method is invoked before any code generation takes
+               // place, and it is a mechanism to inform that the expression
+               // will be invoked more than once, and that the method should
+               // use temporary values to avoid having side effects
+               //
+               // Example: a [ g () ] ++
+               //
+               void CacheTemporaries (EmitContext ec);
+       }
+
+       /// <summary>
+       ///   An Expression to hold a temporary value.
+       /// </summary>
+       /// <remarks>
+       ///   The LocalTemporary class is used to hold temporary values of a given
+       ///   type to "simulate" the expression semantics on property and indexer
+       ///   access whose return values are void.
+       ///
+       ///   The local temporary is used to alter the normal flow of code generation
+       ///   basically it creates a local variable, and its emit instruction generates
+       ///   code to access this value, return its address or save its value.
+       /// </remarks>
+       public class LocalTemporary : Expression, IMemoryLocation {
+               LocalBuilder builder;
+               
+               public LocalTemporary (EmitContext ec, Type t)
+               {
+                       type = t;
+                       eclass = ExprClass.Value;
+                       loc = Location.Null;
+                       builder = ec.GetTemporaryStorage (t);
+               }
+
+               public void Release (EmitContext ec)
+               {
+                       ec.FreeTemporaryStorage (builder);
+                       builder = null;
+               }
+               
+               public LocalTemporary (LocalBuilder b, Type t)
+               {
+                       type = t;
+                       eclass = ExprClass.Value;
+                       loc = Location.Null;
+                       builder = b;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldloc, builder); 
+               }
+
+               public void Store (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Stloc, builder);
+               }
+
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       ec.ig.Emit (OpCodes.Ldloca, builder);
+               }
+       }
+
+       /// <summary>
+       ///   The Assign node takes care of assigning the value of source into
+       ///   the expression represented by target. 
+       /// </summary>
+       public class Assign : ExpressionStatement {
+               protected Expression target, source, real_source;
+               protected LocalTemporary temp = null, real_temp = null;
+               protected Assign embedded = null;
+               protected bool is_embedded = false;
+               protected bool must_free_temp = false;
+
+               public Assign (Expression target, Expression source, Location l)
+               {
+                       this.target = target;
+                       this.source = this.real_source = source;
+                       this.loc = l;
+               }
+
+               protected Assign (Assign embedded, Location l)
+                       : this (embedded.target, embedded.source, l)
+               {
+                       this.is_embedded = true;
+               }
+
+               protected virtual Assign GetEmbeddedAssign (Location loc)
+               {
+                       return new Assign (this, loc);
+               }
+
+               public Expression Target {
+                       get {
+                               return target;
+                       }
+
+                       set {
+                               target = value;
+                       }
+               }
+
+               public Expression Source {
+                       get {
+                               return source;
+                       }
+
+                       set {
+                               source = value;
+                       }
+               }
+
+               public static void error70 (EventInfo ei, Location l)
+               {
+                       Report.Error (70, l, "The event '" + ei.Name +
+                                     "' can only appear on the left-side of a += or -= (except when" +
+                                     " used from within the type '" + ei.DeclaringType + "')");
+               }
+
+               //
+               // Will return either `this' or an instance of `New'.
+               //
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // Create an embedded assignment if our source is an assignment.
+                       if (source is Assign)
+                               source = embedded = ((Assign) source).GetEmbeddedAssign (loc);
+
+                       real_source = source = source.Resolve (ec);
+                       if (source == null)
+                               return null;
+
+                       //
+                       // This is used in an embedded assignment.
+                       // As an example, consider the statement "A = X = Y = Z".
+                       //
+                       if (is_embedded && !(source is Constant)) {
+                               // If this is the innermost assignment (the "Y = Z" in our example),
+                               // create a new temporary local, otherwise inherit that variable
+                               // from our child (the "X = (Y = Z)" inherits the local from the
+                               // "Y = Z" assignment).
+
+                               if (embedded == null) {
+                                       if (this is CompoundAssign)
+                                               real_temp = temp = new LocalTemporary (ec, target.Type);
+                                       else
+                                               real_temp = temp = new LocalTemporary (ec, source.Type);
+                               } else
+                                       temp = embedded.temp;
+
+                               // Set the source to the new temporary variable.
+                               // This means that the following target.ResolveLValue () will tell
+                               // the target to read it's source value from that variable.
+                               source = temp;
+                       }
+
+                       // If we have an embedded assignment, use the embedded assignment's temporary
+                       // local variable as source.
+                       if (embedded != null)
+                               source = (embedded.temp != null) ? embedded.temp : embedded.source;
+
+                       target = target.ResolveLValue (ec, source);
+
+                       if (target == null)
+                               return null;
+
+                       Type target_type = target.Type;
+                       Type source_type = real_source.Type;
+
+                       // If we're an embedded assignment, our parent will reuse our source as its
+                       // source, it won't read from our target.
+                       if (is_embedded)
+                               type = source_type;
+                       else
+                               type = target_type;
+                       eclass = ExprClass.Value;
+
+                       //
+                       // If we are doing a property assignment, then
+                       // set the `value' field on the property, and Resolve
+                       // it.
+                       //
+                       if (target is PropertyExpr){
+                               PropertyExpr property_assign = (PropertyExpr) target;
+
+                               if (source_type != target_type){
+                                       source = Convert.ImplicitConversionRequired (ec, source, target_type, loc);
+                                       if (source == null)
+                                               return null;
+                               }
+
+                               //
+                               // FIXME: Maybe handle this in the LValueResolve
+                               //
+                               if (!property_assign.VerifyAssignable ())
+                                       return null;
+
+                               return this;
+                       }
+
+                       if (target is IndexerAccess) {
+                               return this;
+                       }
+
+                       if (target is EventExpr) {
+                               EventInfo ei = ((EventExpr) target).EventInfo;
+
+                               Expression ml = MemberLookup (
+                                       ec, ec.ContainerType, ei.Name,
+                                       MemberTypes.Event, AllBindingFlags | BindingFlags.DeclaredOnly, loc);
+
+                               if (ml == null) {
+                                       //
+                                       // If this is the case, then the Event does not belong 
+                                       // to this Type and so, according to the spec
+                                       // is allowed to only appear on the left hand of
+                                       // the += and -= operators
+                                       //
+                                       // Note that target will not appear as an EventExpr
+                                       // in the case it is being referenced within the same type container;
+                                       // it will appear as a FieldExpr in that case.
+                                       //
+                                       
+                                       if (!(source is Binary)) {
+                                               error70 (ei, loc);
+                                               return null;
+                                       } else {
+                                               Binary tmp = ((Binary) source);
+                                               if (tmp.Oper != Binary.Operator.Addition &&
+                                                   tmp.Oper != Binary.Operator.Subtraction) {
+                                                       error70 (ei, loc);
+                                                       return null;
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       if (source is New && target_type.IsValueType){
+                               New n = (New) source;
+
+                               if (n.SetValueTypeVariable (target))
+                                       return n;
+                               else
+                                       return null;
+                       }
+
+                       if (target.eclass != ExprClass.Variable && target.eclass != ExprClass.EventAccess){
+                               Report.Error (131, loc,
+                                             "Left hand of an assignment must be a variable, " +
+                                             "a property or an indexer");
+                               return null;
+                       }
+
+                       if ((source.eclass == ExprClass.Type) && (source is TypeExpr)) {
+                               source.Error_UnexpectedKind ("variable or value");
+                               return null;
+                       } else if (source is MethodGroupExpr){
+                               ((MethodGroupExpr) source).ReportUsageError ();
+                               return null;
+                       }
+
+                       if (target_type == source_type)
+                               return this;
+                       
+                       //
+                       // If this assignemnt/operator was part of a compound binary
+                       // operator, then we allow an explicit conversion, as detailed
+                       // in the spec. 
+                       //
+
+                       if (this is CompoundAssign){
+                               CompoundAssign a = (CompoundAssign) this;
+                               
+                               Binary b = source as Binary;
+                               if (b != null && b.IsBuiltinOperator){
+                                       //
+                                       // 1. if the source is explicitly convertible to the
+                                       //    target_type
+                                       //
+                                       
+                                       source = Convert.ExplicitConversion (ec, source, target_type, loc);
+                                       if (source == null){
+                                               Convert.Error_CannotImplicitConversion (loc, source_type, target_type);
+                                               return null;
+                                       }
+                               
+                                       //
+                                       // 2. and the original right side is implicitly convertible to
+                                       // the type of target_type.
+                                       //
+                                       if (Convert.ImplicitStandardConversionExists (a.original_source, target_type))
+                                               return this;
+
+                                       Convert.Error_CannotImplicitConversion (loc, a.original_source.Type, target_type);
+                                       return null;
+                               }
+                       }
+                       
+                       source = Convert.ImplicitConversionRequired (ec, source, target_type, loc);
+                       if (source == null)
+                               return null;
+
+                       // If we're an embedded assignment, we need to create a new temporary variable
+                       // for the converted value.  Our parent will use this new variable as its source.
+                       // The same applies when we have an embedded assignment - in this case, we need
+                       // to convert our embedded assignment's temporary local variable to the correct
+                       // type and store it in a new temporary local.
+                       if (is_embedded || embedded != null) {
+                               type = target_type;
+                               temp = new LocalTemporary (ec, type);
+                               must_free_temp = true;
+                       }
+                       
+                       return this;
+               }
+
+               Expression EmitEmbedded (EmitContext ec)
+               {
+                       // Emit an embedded assignment.
+
+                       if (real_temp != null) {
+                               // If we're the innermost assignment, `real_source' is the right-hand
+                               // expression which gets assigned to all the variables left of it.
+                               // Emit this expression and store its result in real_temp.
+                               real_source.Emit (ec);
+                               real_temp.Store (ec);
+                       }
+
+                       if (embedded != null)
+                               embedded.EmitEmbedded (ec);
+
+                       // This happens when we've done a type conversion, in this case source will be
+                       // the expression which does the type conversion from real_temp.
+                       // So emit it and store the result in temp; this is the var which will be read
+                       // by our parent.
+                       if (temp != real_temp) {
+                               source.Emit (ec);
+                               temp.Store (ec);
+                       }
+
+                       Expression temp_source = (temp != null) ? temp : source;
+                       ((IAssignMethod) target).EmitAssign (ec, temp_source);
+                       return temp_source;
+               }
+
+               void ReleaseEmbedded (EmitContext ec)
+               {
+                       if (embedded != null)
+                               embedded.ReleaseEmbedded (ec);
+
+                       if (real_temp != null)
+                               real_temp.Release (ec);
+
+                       if (must_free_temp)
+                               temp.Release (ec);
+               }
+
+               void Emit (EmitContext ec, bool is_statement)
+               {
+                       if (target is EventExpr) {
+                               ((EventExpr) target).EmitAddOrRemove (ec, source);
+                               return;
+                       }
+
+                       bool use_temporaries = false;
+                       
+                       //
+                       // FIXME! We need a way to "probe" if the process can
+                       // just use `dup' to propagate the result
+                       // 
+                       IAssignMethod am = (IAssignMethod) target;
+                       
+                       if (this is CompoundAssign){
+                               am.CacheTemporaries (ec);
+                               use_temporaries = true;
+                       }
+
+                       if (!is_statement)
+                               use_temporaries = true;
+
+                       Expression temp_source;
+                       if (embedded != null) {
+                               temp_source = embedded.EmitEmbedded (ec);
+
+                               if (temp != null) {
+                                       source.Emit (ec);
+                                       temp.Store (ec);
+                                       temp_source = temp;
+                               }
+                       } else
+                               temp_source = source;
+
+                       if (use_temporaries){
+                               //
+                               // Doing this for every path is too expensive
+                               // I wonder if we can work around this and have a less
+                               // expensive path
+                               //
+                               LocalTemporary tempo;
+                               
+                               tempo = new LocalTemporary (ec, source.Type);
+                               
+                               temp_source.Emit (ec);
+                               tempo.Store (ec);
+                               am.EmitAssign (ec, tempo);
+                               if (!is_statement)
+                                       tempo.Emit (ec);
+                               
+                               tempo.Release (ec);
+                       } else {
+                               am.EmitAssign (ec, temp_source);
+                       }
+                               
+                       if (embedded != null) {
+                               if (temp != null)
+                                       temp.Release (ec);
+                               embedded.ReleaseEmbedded (ec);
+                       }
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       Emit (ec, false);
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       Emit (ec, true);
+               }
+       }
+
+       
+       //
+       // This class is used for compound assignments.  
+       //
+       class CompoundAssign : Assign {
+               Binary.Operator op;
+               public Expression original_source;
+               
+               public CompoundAssign (Binary.Operator op, Expression target, Expression source, Location l)
+                       : base (target, source, l)
+               {
+                       original_source = source;
+                       this.op = op;
+               }
+
+               protected CompoundAssign (CompoundAssign embedded, Location l)
+                       : this (embedded.op, embedded.target, embedded.source, l)
+               {
+                       this.is_embedded = true;
+               }
+
+               protected override Assign GetEmbeddedAssign (Location loc)
+               {
+                       return new CompoundAssign (this, loc);
+               }
+
+               public Expression ResolveSource (EmitContext ec)
+               {
+                       return original_source.Resolve (ec);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       original_source = original_source.Resolve (ec);
+                       if (original_source == null)
+                               return null;
+
+                       target = target.Resolve (ec);
+                       if (target == null)
+                               return null;
+                       
+                       //
+                       // Only now we can decouple the original source/target
+                       // into a tree, to guarantee that we do not have side
+                       // effects.
+                       //
+                       source = new Binary (op, target, original_source, loc);
+                       return base.DoResolve (ec);
+               }
+       }
+}
+
+
+
+
diff --git a/mcs/gmcs/attribute.cs b/mcs/gmcs/attribute.cs
new file mode 100644 (file)
index 0000000..8400748
--- /dev/null
@@ -0,0 +1,1121 @@
+//\r
+// attribute.cs: Attribute Handler\r
+//\r
+// Author: Ravi Pratap (ravi@ximian.com)\r
+//\r
+// Licensed under the terms of the GNU GPL\r
+//\r
+// (C) 2001 Ximian, Inc (http://www.ximian.com)\r
+//\r
+//\r
+\r
+using System;\r
+using System.Diagnostics;\r
+using System.Collections;\r
+using System.Reflection;\r
+using System.Reflection.Emit;\r
+using System.Runtime.InteropServices;\r
+using System.Runtime.CompilerServices;\r
+using System.Text;\r
+\r
+namespace Mono.CSharp {\r
+\r
+       public class Attribute {\r
+               public readonly string    Name;\r
+               public readonly ArrayList Arguments;\r
+\r
+               Location Location;\r
+\r
+               public Type Type;\r
+               \r
+               //\r
+               // The following are only meaningful when the attribute\r
+               // being emitted is one of the builtin ones\r
+               //\r
+               AttributeTargets Targets;\r
+               bool AllowMultiple;\r
+               bool Inherited;\r
+\r
+               bool UsageAttr = false;\r
+               \r
+               MethodImplOptions ImplOptions;\r
+               UnmanagedType     UnmanagedType;\r
+               CustomAttributeBuilder cb;\r
+       \r
+               /* non-null if named args present after Resolve () is called */\r
+               PropertyInfo [] prop_info_arr;\r
+               FieldInfo [] field_info_arr;\r
+               object [] field_values_arr;\r
+               object [] prop_values_arr;\r
+               \r
+               public Attribute (string name, ArrayList args, Location loc)\r
+               {\r
+                       Name = name;\r
+                       Arguments = args;\r
+                       Location = loc;\r
+               }\r
+\r
+               void Error_InvalidNamedArgument (string name)\r
+               {\r
+                       Report.Error (617, Location, "'" + name + "' is not a valid named attribute " +\r
+                                     "argument. Named attribute arguments must be fields which are not " +\r
+                                     "readonly, static or const, or properties with a set accessor which "+\r
+                                     "are not static.");\r
+               }\r
+\r
+               static void Error_AttributeArgumentNotValid (Location loc)\r
+               {\r
+                       Report.Error (182, loc,\r
+                                     "An attribute argument must be a constant expression, typeof " +\r
+                                     "expression or array creation expression");\r
+               }\r
+\r
+               static void Error_AttributeConstructorMismatch (Location loc)\r
+               {\r
+                       Report.Error (-6, loc,\r
+                                      "Could not find a constructor for this argument list.");\r
+               }\r
+               \r
+               private Type CheckAttributeType (EmitContext ec) {\r
+                       Type t;\r
+                       bool isattributeclass = true;\r
+                       \r
+                       t = RootContext.LookupType (ec.DeclSpace, Name, true, Location);\r
+                       if (t != null) {\r
+                               isattributeclass = t.IsSubclassOf (TypeManager.attribute_type);\r
+                               if (isattributeclass)\r
+                                       return t;\r
+                       }\r
+                       t = RootContext.LookupType (ec.DeclSpace, Name + "Attribute", true, Location);\r
+                       if (t != null) {\r
+                               if (t.IsSubclassOf (TypeManager.attribute_type))\r
+                                       return t;\r
+                       }\r
+                       if (!isattributeclass) {\r
+                               Report.Error (616, Location, "'" + Name + "': is not an attribute class");\r
+                               return null;\r
+                       }\r
+                       if (t != null) {\r
+                               Report.Error (616, Location, "'" + Name + "Attribute': is not an attribute class");\r
+                               return null;\r
+                       }\r
+                       Report.Error (\r
+                               246, Location, "Could not find attribute '" + Name + "' (are you" +\r
+                               " missing a using directive or an assembly reference ?)");\r
+                       return null;\r
+               }\r
+\r
+               public Type ResolveType (EmitContext ec)\r
+               {\r
+                       Type = CheckAttributeType (ec);\r
+                       return Type;\r
+               }\r
+\r
+               /// <summary>\r
+               ///   Validates the guid string\r
+               /// </summary>\r
+               bool ValidateGuid (string guid)\r
+               {\r
+                       try {\r
+                               new Guid (guid);\r
+                               return true;\r
+                       } catch {\r
+                               Report.Error (647, Location, "Format of GUID is invalid: " + guid);\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               //\r
+               // Given an expression, if the expression is a valid attribute-argument-expression\r
+               // returns an object that can be used to encode it, or null on failure.\r
+               //\r
+               public static bool GetAttributeArgumentExpression (Expression e, Location loc, out object result)\r
+               {\r
+                       if (e is Constant) {\r
+                               result = ((Constant) e).GetValue ();\r
+                               return true;\r
+                       } else if (e is TypeOf) {\r
+                               result = ((TypeOf) e).TypeArg;\r
+                               return true;\r
+                       } else if (e is ArrayCreation){\r
+                               result =  ((ArrayCreation) e).EncodeAsAttribute ();\r
+                               if (result != null)\r
+                                       return true;\r
+                       }\r
+\r
+                       result = null;\r
+                       Error_AttributeArgumentNotValid (loc);\r
+                       return false;\r
+               }\r
+               \r
+               public CustomAttributeBuilder Resolve (EmitContext ec)\r
+               {\r
+                       if (Type == null)\r
+                               Type = CheckAttributeType (ec);\r
+                       if (Type == null)\r
+                               return null;\r
+\r
+                       bool MethodImplAttr = false;\r
+                       bool MarshalAsAttr = false;\r
+                       bool GuidAttr = false;\r
+                       UsageAttr = false;\r
+\r
+                       bool DoCompares = true;\r
+                       if (Type == TypeManager.attribute_usage_type)\r
+                               UsageAttr = true;\r
+                       else if (Type == TypeManager.methodimpl_attr_type)\r
+                               MethodImplAttr = true;\r
+                       else if (Type == TypeManager.marshal_as_attr_type)\r
+                               MarshalAsAttr = true;\r
+                       else if (Type == TypeManager.guid_attr_type)\r
+                               GuidAttr = true;\r
+                       else\r
+                               DoCompares = false;\r
+\r
+                       // Now we extract the positional and named arguments\r
+                       \r
+                       ArrayList pos_args = new ArrayList ();\r
+                       ArrayList named_args = new ArrayList ();\r
+                       int pos_arg_count = 0;\r
+                       \r
+                       if (Arguments != null) {\r
+                               pos_args = (ArrayList) Arguments [0];\r
+                               if (pos_args != null)\r
+                                       pos_arg_count = pos_args.Count;\r
+                               if (Arguments.Count > 1)\r
+                                       named_args = (ArrayList) Arguments [1];\r
+                       }\r
+\r
+                       object [] pos_values = new object [pos_arg_count];\r
+\r
+                       //\r
+                       // First process positional arguments \r
+                       //\r
+\r
+                       int i;\r
+                       for (i = 0; i < pos_arg_count; i++) {\r
+                               Argument a = (Argument) pos_args [i];\r
+                               Expression e;\r
+\r
+                               if (!a.Resolve (ec, Location))\r
+                                       return null;\r
+\r
+                               e = a.Expr;\r
+\r
+                               object val;\r
+                               if (!GetAttributeArgumentExpression (e, Location, out val))\r
+                                       return null;\r
+                               \r
+                               pos_values [i] = val;\r
+                               if (DoCompares){\r
+                                       if (UsageAttr)\r
+                                               this.Targets = (AttributeTargets) pos_values [0];\r
+                                       else if (MethodImplAttr)\r
+                                               this.ImplOptions = (MethodImplOptions) pos_values [0];\r
+                                       else if (GuidAttr){\r
+                                               //\r
+                                               // we will later check the validity of the type\r
+                                               //\r
+                                               if (pos_values [0] is string){\r
+                                                       if (!ValidateGuid ((string) pos_values [0]))\r
+                                                               return null;\r
+                                               }\r
+                                               \r
+                                       } else if (MarshalAsAttr)\r
+                                               this.UnmanagedType =\r
+                                               (System.Runtime.InteropServices.UnmanagedType) pos_values [0];\r
+                               }\r
+                       }\r
+\r
+                       //\r
+                       // Now process named arguments\r
+                       //\r
+\r
+                       ArrayList field_infos = null;\r
+                       ArrayList prop_infos  = null;\r
+                       ArrayList field_values = null;\r
+                       ArrayList prop_values = null;\r
+\r
+                       if (named_args.Count > 0) {\r
+                               field_infos = new ArrayList ();\r
+                               prop_infos  = new ArrayList ();\r
+                               field_values = new ArrayList ();\r
+                               prop_values = new ArrayList ();\r
+                       }\r
+                       \r
+                       for (i = 0; i < named_args.Count; i++) {\r
+                               DictionaryEntry de = (DictionaryEntry) named_args [i];\r
+                               string member_name = (string) de.Key;\r
+                               Argument a  = (Argument) de.Value;\r
+                               Expression e;\r
+                               \r
+                               if (!a.Resolve (ec, Location))\r
+                                       return null;\r
+\r
+                               Expression member = Expression.MemberLookup (\r
+                                       ec, Type, member_name,\r
+                                       MemberTypes.Field | MemberTypes.Property,\r
+                                       BindingFlags.Public | BindingFlags.Instance,\r
+                                       Location);\r
+\r
+                               if (member == null || !(member is PropertyExpr || member is FieldExpr)) {\r
+                                       Error_InvalidNamedArgument (member_name);\r
+                                       return null;\r
+                               }\r
+\r
+                               e = a.Expr;\r
+                               if (member is PropertyExpr) {\r
+                                       PropertyExpr pe = (PropertyExpr) member;\r
+                                       PropertyInfo pi = pe.PropertyInfo;\r
+\r
+                                       if (!pi.CanWrite) {\r
+                                               Error_InvalidNamedArgument (member_name);\r
+                                               return null;\r
+                                       }\r
+\r
+                                       if (e is Constant) {\r
+                                               object o = ((Constant) e).GetValue ();\r
+                                               prop_values.Add (o);\r
+                                               \r
+                                               if (UsageAttr) {\r
+                                                       if (member_name == "AllowMultiple")\r
+                                                               this.AllowMultiple = (bool) o;\r
+                                                       if (member_name == "Inherited")\r
+                                                               this.Inherited = (bool) o;\r
+                                               }\r
+                                               \r
+                                       } else if (e is TypeOf) {\r
+                                               prop_values.Add (((TypeOf) e).TypeArg);\r
+                                       } else {\r
+                                               Error_AttributeArgumentNotValid (Location);\r
+                                               return null;\r
+                                       }\r
+                                       \r
+                                       prop_infos.Add (pi);\r
+                                       \r
+                               } else if (member is FieldExpr) {\r
+                                       FieldExpr fe = (FieldExpr) member;\r
+                                       FieldInfo fi = fe.FieldInfo;\r
+\r
+                                       if (fi.IsInitOnly) {\r
+                                               Error_InvalidNamedArgument (member_name);\r
+                                               return null;\r
+                                       }\r
+\r
+                                       //\r
+                                       // Handle charset here, and set the TypeAttributes\r
+                                       \r
+                                       if (e is Constant){\r
+                                               object value = ((Constant) e).GetValue ();\r
+                                               \r
+                                               field_values.Add (value);\r
+                                       } else if (e is TypeOf) {\r
+                                               field_values.Add (((TypeOf) e).TypeArg);\r
+                                       } else {\r
+                                               Error_AttributeArgumentNotValid (Location);\r
+                                               return null;\r
+                                       }\r
+                                       \r
+                                       field_infos.Add (fi);\r
+                               }\r
+                       }\r
+\r
+                       Expression mg = Expression.MemberLookup (\r
+                               ec, Type, ".ctor", MemberTypes.Constructor,\r
+                               BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,\r
+                                Location);\r
+\r
+                       if (mg == null) {\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       MethodBase constructor = Invocation.OverloadResolve (\r
+                               ec, (MethodGroupExpr) mg, pos_args, Location);\r
+\r
+                       if (constructor == null) {\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       //\r
+                       // Now we perform some checks on the positional args as they\r
+                       // cannot be null for a constructor which expects a parameter\r
+                       // of type object\r
+                       //\r
+\r
+                       ParameterData pd = Invocation.GetParameterData (constructor);\r
+\r
+                       int group_in_params_array = Int32.MaxValue;\r
+                       int pc = pd.Count;\r
+                       if (pc > 0 && pd.ParameterModifier (pc-1) == Parameter.Modifier.PARAMS)\r
+                               group_in_params_array = pc-1;\r
+                       \r
+                       for (int j = 0; j < pos_arg_count; ++j) {\r
+                               Argument a = (Argument) pos_args [j];\r
+                               \r
+                               if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) {\r
+                                       Error_AttributeArgumentNotValid (Location);\r
+                                       return null;\r
+                               }\r
+\r
+                               if (j < group_in_params_array)\r
+                                       continue;\r
+                               \r
+                               if (j == group_in_params_array){\r
+                                       object v = pos_values [j];\r
+                                       int count = pos_arg_count - j;\r
+\r
+                                       object [] array = new object [count];\r
+                                       pos_values [j] = array;\r
+                                       array [0] = v;\r
+                               } else {\r
+                                       object [] array = (object []) pos_values [group_in_params_array];\r
+\r
+                                       array [j - group_in_params_array] = pos_values [j];\r
+                               }\r
+                       }\r
+\r
+                       //\r
+                       // Adjust the size of the pos_values if it had params\r
+                       //\r
+                       if (group_in_params_array != Int32.MaxValue){\r
+                               int argc = group_in_params_array+1;\r
+                               object [] new_pos_values = new object [argc];\r
+\r
+                               for (int p = 0; p < argc; p++)\r
+                                       new_pos_values [p] = pos_values [p];\r
+                               pos_values = new_pos_values;\r
+                       }\r
+\r
+                       try {\r
+                               if (named_args.Count > 0) {\r
+                                       prop_info_arr = new PropertyInfo [prop_infos.Count];\r
+                                       field_info_arr = new FieldInfo [field_infos.Count];\r
+                                       field_values_arr = new object [field_values.Count];\r
+                                       prop_values_arr = new object [prop_values.Count];\r
+\r
+                                       field_infos.CopyTo  (field_info_arr, 0);\r
+                                       field_values.CopyTo (field_values_arr, 0);\r
+\r
+                                       prop_values.CopyTo  (prop_values_arr, 0);\r
+                                       prop_infos.CopyTo   (prop_info_arr, 0);\r
+\r
+                                       cb = new CustomAttributeBuilder (\r
+                                               (ConstructorInfo) constructor, pos_values,\r
+                                               prop_info_arr, prop_values_arr,\r
+                                               field_info_arr, field_values_arr);\r
+                               }\r
+                               else\r
+                                       cb = new CustomAttributeBuilder (\r
+                                               (ConstructorInfo) constructor, pos_values);\r
+                       } catch (NullReferenceException) {\r
+                               // \r
+                               // Don't know what to do here\r
+                               //\r
+                               Report.Warning (\r
+                                       -100, Location, "NullReferenceException while trying to create attribute. Something's wrong!");\r
+                       } catch (Exception e) {\r
+                               //\r
+                               // Sample:\r
+                               // using System.ComponentModel;\r
+                               // [DefaultValue (CollectionChangeAction.Add)]\r
+                               // class X { static void Main () {} }\r
+                               //\r
+                               Report.Warning (\r
+                                       -23, Location,\r
+                                       "The compiler can not encode this attribute in .NET due to\n" +\r
+                                       "\ta bug in the .NET runtime.  Try the Mono runtime.\nThe error was: " + e.Message);\r
+                       }\r
+                       \r
+                       return cb;\r
+               }\r
+\r
+               static string GetValidPlaces (Attribute attr)\r
+               {\r
+                       StringBuilder sb = new StringBuilder ();\r
+                       AttributeTargets targets = 0;\r
+                       \r
+                       TypeContainer a = TypeManager.LookupAttr (attr.Type);\r
+\r
+                       if (a == null) {\r
+                               \r
+                               System.Attribute [] attrs = null;\r
+                               \r
+                               try {\r
+                                       attrs = System.Attribute.GetCustomAttributes (attr.Type);\r
+                                       \r
+                               } catch {\r
+                                       Report.Error (-20, attr.Location, "Cannot find attribute type " + attr.Name +\r
+                                                     " (maybe you forgot to set the usage using the" +\r
+                                                     " AttributeUsage attribute ?).");\r
+                                       return null;\r
+                               }\r
+                                       \r
+                               foreach (System.Attribute tmp in attrs)\r
+                                       if (tmp is AttributeUsageAttribute) {\r
+                                               targets = ((AttributeUsageAttribute) tmp).ValidOn;\r
+                                               break;\r
+                                       }\r
+                       } else\r
+                               targets = a.Targets;\r
+\r
+                       \r
+                       if ((targets & AttributeTargets.Assembly) != 0)\r
+                               sb.Append ("'assembly' ");\r
+\r
+                       if ((targets & AttributeTargets.Class) != 0)\r
+                               sb.Append ("'class' ");\r
+\r
+                       if ((targets & AttributeTargets.Constructor) != 0)\r
+                               sb.Append ("'constructor' ");\r
+\r
+                       if ((targets & AttributeTargets.Delegate) != 0)\r
+                               sb.Append ("'delegate' ");\r
+\r
+                       if ((targets & AttributeTargets.Enum) != 0)\r
+                               sb.Append ("'enum' ");\r
+\r
+                       if ((targets & AttributeTargets.Event) != 0)\r
+                               sb.Append ("'event' ");\r
+\r
+                       if ((targets & AttributeTargets.Field) != 0)\r
+                               sb.Append ("'field' ");\r
+\r
+                       if ((targets & AttributeTargets.Interface) != 0)\r
+                               sb.Append ("'interface' ");\r
+\r
+                       if ((targets & AttributeTargets.Method) != 0)\r
+                               sb.Append ("'method' ");\r
+\r
+                       if ((targets & AttributeTargets.Module) != 0)\r
+                               sb.Append ("'module' ");\r
+\r
+                       if ((targets & AttributeTargets.Parameter) != 0)\r
+                               sb.Append ("'parameter' ");\r
+\r
+                       if ((targets & AttributeTargets.Property) != 0)\r
+                               sb.Append ("'property' ");\r
+\r
+                       if ((targets & AttributeTargets.ReturnValue) != 0)\r
+                               sb.Append ("'return value' ");\r
+\r
+                       if ((targets & AttributeTargets.Struct) != 0)\r
+                               sb.Append ("'struct' ");\r
+\r
+                       return sb.ToString ();\r
+\r
+               }\r
+\r
+               public static void Error_AttributeNotValidForElement (Attribute a, Location loc)\r
+               {\r
+                       Report.Error (\r
+                               592, loc, "Attribute '" + a.Name +\r
+                               "' is not valid on this declaration type. " +\r
+                               "It is valid on " + GetValidPlaces (a) + "declarations only.");\r
+               }\r
+\r
+               public static bool CheckAttribute (Attribute a, object element)\r
+               {\r
+                       TypeContainer attr = TypeManager.LookupAttr (a.Type);\r
+                       AttributeTargets targets = 0;\r
+\r
+                       \r
+                       if (attr == null) {\r
+                               System.Attribute [] attrs = null;\r
+                               \r
+                               try {\r
+                                       attrs = System.Attribute.GetCustomAttributes (a.Type);\r
+\r
+                               } catch {\r
+                                       Report.Error (-20, a.Location, "Cannot find attribute type " + a.Name +\r
+                                                     " (maybe you forgot to set the usage using the" +\r
+                                                     " AttributeUsage attribute ?).");\r
+                                       return false;\r
+                               }\r
+                                       \r
+                               foreach (System.Attribute tmp in attrs)\r
+                                       if (tmp is AttributeUsageAttribute) \r
+                                               targets = ((AttributeUsageAttribute) tmp).ValidOn;\r
+                       } else\r
+                               targets = attr.Targets;\r
+\r
+                       if (element is Class) {\r
+                               if ((targets & AttributeTargets.Class) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                               \r
+                       } else if (element is Struct) {\r
+                               if ((targets & AttributeTargets.Struct) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                       } else if (element is Constructor) {\r
+                               if ((targets & AttributeTargets.Constructor) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                       } else if (element is Delegate) {\r
+                               if ((targets & AttributeTargets.Delegate) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                       } else if (element is Enum) {\r
+                               if ((targets & AttributeTargets.Enum) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                       } else if (element is Event || element is InterfaceEvent) {\r
+                               if ((targets & AttributeTargets.Event) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                       } else if (element is Field || element is FieldBuilder) {\r
+                               if ((targets & AttributeTargets.Field) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                       } else if (element is Interface) {\r
+                               if ((targets & AttributeTargets.Interface) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                       } else if (element is Method || element is Operator || element is InterfaceMethod || element is Accessor) {\r
+                               if ((targets & AttributeTargets.Method) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                       } else if (element is ParameterBuilder) {\r
+                               if ((targets & AttributeTargets.Parameter) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                       } else if (element is Property || element is Indexer ||\r
+                                  element is InterfaceProperty || element is InterfaceIndexer) {\r
+                               if ((targets & AttributeTargets.Property) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                       } else if (element is AssemblyBuilder){\r
+                               if ((targets & AttributeTargets.Assembly) != 0)\r
+                                       return true;\r
+                               else\r
+                                       return false;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+               //\r
+               // This method should be invoked to pull the IndexerName attribute from an\r
+               // Indexer if it exists.\r
+               //\r
+               public static string ScanForIndexerName (EmitContext ec, Attributes opt_attrs)\r
+               {\r
+                       if (opt_attrs == null)\r
+                               return null;\r
+                       if (opt_attrs.AttributeSections == null)\r
+                               return null;\r
+\r
+                       foreach (AttributeSection asec in opt_attrs.AttributeSections) {\r
+                               if (asec.Attributes == null)\r
+                                       continue;\r
+\r
+                               foreach (Attribute a in asec.Attributes){\r
+                                       if (a.ResolveType (ec) == null)\r
+                                               return null;\r
+                                       \r
+                                       if (a.Type != TypeManager.indexer_name_type)\r
+                                               continue;\r
+\r
+                                       //\r
+                                       // So we have found an IndexerName, pull the data out.\r
+                                       //\r
+                                       if (a.Arguments == null || a.Arguments [0] == null){\r
+                                               Error_AttributeConstructorMismatch (a.Location);\r
+                                               return null;\r
+                                       }\r
+                                       ArrayList pos_args = (ArrayList) a.Arguments [0];\r
+                                       if (pos_args.Count == 0){\r
+                                               Error_AttributeConstructorMismatch (a.Location);\r
+                                               return null;\r
+                                       }\r
+                                       \r
+                                       Argument arg = (Argument) pos_args [0];\r
+                                       if (!arg.Resolve (ec, a.Location))\r
+                                               return null;\r
+                                       \r
+                                       Expression e = arg.Expr;\r
+                                       if (!(e is StringConstant)){\r
+                                               Error_AttributeConstructorMismatch (a.Location);\r
+                                               return null;\r
+                                       }\r
+\r
+                                       //\r
+                                       // Remove the attribute from the list\r
+                                       //\r
+                                       asec.Attributes.Remove (a);\r
+\r
+                                       return (((StringConstant) e).Value);\r
+                               }\r
+                       }\r
+                       return null;\r
+               }\r
+\r
+               //\r
+               // This pulls the condition name out of a Conditional attribute\r
+               //\r
+               public string Conditional_GetConditionName ()\r
+               {\r
+                       //\r
+                       // So we have a Conditional, pull the data out.\r
+                       //\r
+                       if (Arguments == null || Arguments [0] == null){\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       ArrayList pos_args = (ArrayList) Arguments [0];\r
+                       if (pos_args.Count != 1){\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       Argument arg = (Argument) pos_args [0]; \r
+                       if (!(arg.Expr is StringConstant)){\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       return ((StringConstant) arg.Expr).Value;\r
+               }\r
+\r
+               //\r
+               // This pulls the obsolete message and error flag out of an Obsolete attribute\r
+               //\r
+               public string Obsolete_GetObsoleteMessage (out bool is_error)\r
+               {\r
+                       is_error = false;\r
+                       //\r
+                       // So we have an Obsolete, pull the data out.\r
+                       //\r
+                       if (Arguments == null || Arguments [0] == null)\r
+                               return "";\r
+\r
+                       ArrayList pos_args = (ArrayList) Arguments [0];\r
+                       if (pos_args.Count == 0)\r
+                               return "";\r
+                       else if (pos_args.Count > 2){\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       Argument arg = (Argument) pos_args [0]; \r
+                       if (!(arg.Expr is StringConstant)){\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       if (pos_args.Count == 2){\r
+                               Argument arg2 = (Argument) pos_args [1];\r
+                               if (!(arg2.Expr is BoolConstant)){\r
+                                       Error_AttributeConstructorMismatch (Location);\r
+                                       return null;\r
+                               }\r
+                               is_error = ((BoolConstant) arg2.Expr).Value;\r
+                       }\r
+\r
+                       return ((StringConstant) arg.Expr).Value;\r
+               }\r
+\r
+               static object GetFieldValue (Attribute a, string name) {\r
+                       int i;\r
+                       if (a.field_info_arr == null)\r
+                               return null;\r
+                       i = 0;\r
+                       foreach (FieldInfo fi in a.field_info_arr) {\r
+                               if (fi.Name == name)\r
+                                       return a.field_values_arr [i];\r
+                               i++;\r
+                       }\r
+                       return null;\r
+               }\r
+\r
+               static UnmanagedMarshal GetMarshal (Attribute a) {\r
+                       UnmanagedMarshal marshal;\r
+\r
+                       if (a.UnmanagedType == UnmanagedType.CustomMarshaler) {\r
+                               MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom", BindingFlags.Static | BindingFlags.Public);\r
+                               if (define_custom == null) {\r
+                                       return null;\r
+                               }\r
+                               object[] args = new object [4];\r
+                               args [0] = GetFieldValue (a, "MarshalTypeRef");\r
+                               args [1] = GetFieldValue (a, "MarshalCookie");\r
+                               args [2] = GetFieldValue (a, "MarshalType");\r
+                               args [3] = Guid.Empty;\r
+                               marshal = (UnmanagedMarshal) define_custom.Invoke (null, args);\r
+                       /*\r
+                        * need to special case other special marshal types\r
+                        */\r
+                       } else {\r
+                               marshal = UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType);\r
+                       }\r
+                       return marshal;\r
+               }\r
+\r
+               //\r
+               // Applies the attributes to the `builder'.\r
+               //\r
+               public static void ApplyAttributes (EmitContext ec, object builder, object kind,\r
+                                                   Attributes opt_attrs)\r
+               {\r
+                       Type attr_type = null;\r
+                       \r
+                       if (opt_attrs == null)\r
+                               return;\r
+                       if (opt_attrs.AttributeSections == null)\r
+                               return;\r
+\r
+                       ArrayList emitted_attrs = new ArrayList ();\r
+                       ArrayList emitted_targets = new ArrayList ();\r
+\r
+                       foreach (AttributeSection asec in opt_attrs.AttributeSections) {\r
+                               string attr_target = asec.Target;\r
+                               \r
+                               if (asec.Attributes == null)\r
+                                       continue;\r
+\r
+                               if (attr_target == "assembly" && !(builder is AssemblyBuilder))\r
+                                       continue;\r
+\r
+                               if (attr_target == "return" && !(builder is ParameterBuilder))\r
+                                       continue;\r
+                               \r
+                               foreach (Attribute a in asec.Attributes) {\r
+                                       Location loc = a.Location;\r
+                                       CustomAttributeBuilder cb = a.Resolve (ec);\r
+                                       attr_type = a.Type;\r
+\r
+                                       if (cb == null) \r
+                                               continue;\r
+                                       \r
+                                       if (!(kind is TypeContainer))\r
+                                               if (!CheckAttribute (a, kind)) {\r
+                                                       Error_AttributeNotValidForElement (a, loc);\r
+                                                       return;\r
+                                               }\r
+\r
+                                       //\r
+                                       // Perform the check for duplicate attributes\r
+                                       //\r
+                                       if (emitted_attrs.Contains (attr_type) &&\r
+                                           emitted_targets.Contains (attr_target) &&\r
+                                           !TypeManager.AreMultipleAllowed (attr_type)) {\r
+                                               Report.Error (579, loc, "Duplicate '" + a.Name + "' attribute");\r
+                                               return;\r
+                                       }\r
+\r
+                                       if (kind is Method || kind is Operator || kind is InterfaceMethod ||\r
+                                           kind is Accessor) {\r
+                                               if (attr_type == TypeManager.methodimpl_attr_type) {\r
+                                                       if (a.ImplOptions == MethodImplOptions.InternalCall)\r
+                                                               ((MethodBuilder) builder).\r
+                                                               SetImplementationFlags (\r
+                                                                       MethodImplAttributes.InternalCall |\r
+                                                                       MethodImplAttributes.Runtime);\r
+                                                       else\r
+                                                               ((MethodBuilder) builder).SetCustomAttribute (cb);\r
+                                               } else if (attr_type != TypeManager.dllimport_type){\r
+                                                       ((MethodBuilder) builder).SetCustomAttribute (cb);\r
+                                               }\r
+                                       } else if (kind is Constructor) {\r
+                                               ((ConstructorBuilder) builder).SetCustomAttribute (cb);\r
+                                       } else if (kind is Field) {\r
+                                               ((FieldBuilder) builder).SetCustomAttribute (cb);\r
+                                       } else if (kind is Property || kind is Indexer ||\r
+                                                  kind is InterfaceProperty || kind is InterfaceIndexer) {\r
+                                               ((PropertyBuilder) builder).SetCustomAttribute (cb);\r
+                                       } else if (kind is Event || kind is InterfaceEvent) {\r
+                                               ((MyEventBuilder) builder).SetCustomAttribute (cb);\r
+                                       } else if (kind is ParameterBuilder) {\r
+\r
+                                               if (attr_type == TypeManager.marshal_as_attr_type) {\r
+                                                       UnmanagedMarshal marshal = GetMarshal (a);\r
+                                                       if (marshal == null) {\r
+                                                               Report.Warning (-24, loc,\r
+                                                                       "The Microsoft Runtime cannot set this marshal info. " +\r
+                                                                       "Please use the Mono runtime instead.");\r
+                                                       } else {\r
+                                                               ((ParameterBuilder) builder).SetMarshal (marshal);\r
+                                                       }\r
+                                               } else { \r
+\r
+                                                       try {\r
+                                                               ((ParameterBuilder) builder).SetCustomAttribute (cb);\r
+                                                       } catch (System.ArgumentException) {\r
+                                                               Report.Warning (-24, loc,\r
+                                                                               "The Microsoft Runtime cannot set attributes \n" +\r
+                                                                               "on the return type of a method. Please use the \n" +\r
+                                                                               "Mono runtime instead.");\r
+                                                       }\r
+\r
+                                               }\r
+                                       } else if (kind is Enum) {\r
+                                               ((TypeBuilder) builder).SetCustomAttribute (cb); \r
+\r
+                                       } else if (kind is TypeContainer) {\r
+                                               TypeContainer tc = (TypeContainer) kind;\r
+                                               \r
+                                               if (a.UsageAttr) {\r
+                                                       tc.Targets = a.Targets;\r
+                                                       tc.AllowMultiple = a.AllowMultiple;\r
+                                                       tc.Inherited = a.Inherited;\r
+\r
+                                                       TypeManager.RegisterAttributeAllowMultiple (tc.TypeBuilder,\r
+                                                                                                   tc.AllowMultiple);\r
+                                                       \r
+                                               } else if (attr_type == TypeManager.default_member_type) {\r
+                                                       if (tc.Indexers != null) {\r
+                                                               Report.Error (646, loc,\r
+                                                                     "Cannot specify the DefaultMember attribute on" +\r
+                                                                     " a type containing an indexer");\r
+                                                               return;\r
+                                                       }\r
+\r
+                                               } else {\r
+                                                       if (!CheckAttribute (a, kind)) {\r
+                                                               Error_AttributeNotValidForElement (a, loc);\r
+                                                               return;\r
+                                                       }\r
+                                               }\r
+\r
+                                               try {\r
+                                                       ((TypeBuilder) builder).SetCustomAttribute (cb);\r
+                                               } catch (System.ArgumentException) {\r
+                                                       Report.Warning (\r
+                                                               -21, loc,\r
+                                               "The CharSet named property on StructLayout\n"+\r
+                                               "\tdoes not work correctly on Microsoft.NET\n"+\r
+                                               "\tYou might want to remove the CharSet declaration\n"+\r
+                                               "\tor compile using the Mono runtime instead of the\n"+\r
+                                               "\tMicrosoft .NET runtime");\r
+                                               }\r
+                                               \r
+                                       } else if (kind is Interface) {\r
+                                               Interface iface = (Interface) kind;\r
+\r
+                                               if ((attr_type == TypeManager.default_member_type) &&\r
+                                                   (iface.InterfaceIndexers != null)) {\r
+                                                       Report.Error (\r
+                                                               646, loc,\r
+                                                               "Cannot specify the DefaultMember attribute on" +\r
+                                                               " a type containing an indexer");\r
+                                                       return;\r
+                                               }\r
+\r
+                                               if (!CheckAttribute (a, kind)) {\r
+                                                       Error_AttributeNotValidForElement (a, loc);\r
+                                                       return;\r
+                                               }\r
+\r
+                                               ((TypeBuilder) builder).SetCustomAttribute (cb);\r
+                                       } else if (kind is AssemblyBuilder){\r
+                                               ((AssemblyBuilder) builder).SetCustomAttribute (cb);\r
+                                       } else if (kind is ModuleBuilder) {\r
+                                               ((ModuleBuilder) builder).SetCustomAttribute (cb);\r
+                                       } else if (kind is FieldBuilder) {\r
+                                               if (attr_type == TypeManager.marshal_as_attr_type) {\r
+                                                       UnmanagedMarshal marshal = GetMarshal (a);\r
+                                                       if (marshal == null) {\r
+                                                               Report.Warning (-24, loc,\r
+                                                                       "The Microsoft Runtime cannot set this marshal info. " +\r
+                                                                       "Please use the Mono runtime instead.");\r
+                                                       } else {\r
+                                                               ((ParameterBuilder) builder).SetMarshal (marshal);\r
+                                                       }\r
+                                               } else { \r
+                                                       ((FieldBuilder) builder).SetCustomAttribute (cb);\r
+                                               }\r
+                                       } else\r
+                                               throw new Exception ("Unknown kind: " + kind);\r
+\r
+                                       //\r
+                                       // Once an attribute type has been emitted once we\r
+                                       // keep track of the info to prevent multiple occurences\r
+                                       // for attributes which do not explicitly allow it\r
+                                       //\r
+                                       if (!emitted_attrs.Contains (attr_type))\r
+                                               emitted_attrs.Add (attr_type);\r
+\r
+                                       //\r
+                                       // We keep of this target-wise and so emitted targets\r
+                                       // are tracked too\r
+                                       //\r
+                                       if (!emitted_targets.Contains (attr_target))\r
+                                               emitted_targets.Add (attr_target);\r
+                               }\r
+                               \r
+                               \r
+                       }\r
+               }\r
+\r
+               public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,\r
+                                                         MethodAttributes flags, Type ret_type, Type [] param_types)\r
+               {\r
+                       //\r
+                       // We extract from the attribute the information we need \r
+                       //\r
+\r
+                       if (Arguments == null) {\r
+                               Console.WriteLine ("Internal error : this is not supposed to happen !");\r
+                               return null;\r
+                       }\r
+\r
+                       Type = CheckAttributeType (ec);\r
+                       if (Type == null)\r
+                               return null;\r
+                       \r
+                       ArrayList named_args = new ArrayList ();\r
+                       \r
+                       ArrayList pos_args = (ArrayList) Arguments [0];\r
+                       if (Arguments.Count > 1)\r
+                               named_args = (ArrayList) Arguments [1];\r
+                       \r
+\r
+                       string dll_name = null;\r
+                       \r
+                       Argument tmp = (Argument) pos_args [0];\r
+\r
+                       if (!tmp.Resolve (ec, Location))\r
+                               return null;\r
+                       \r
+                       if (tmp.Expr is Constant)\r
+                               dll_name = (string) ((Constant) tmp.Expr).GetValue ();\r
+                       else { \r
+                               Error_AttributeArgumentNotValid (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       // Now we process the named arguments\r
+                       CallingConvention cc = CallingConvention.Winapi;\r
+                       CharSet charset = CharSet.Ansi;\r
+                       bool preserve_sig = true;\r
+                       bool exact_spelling = false;\r
+                       bool set_last_err = false;\r
+                       string entry_point = null;\r
+\r
+                       for (int i = 0; i < named_args.Count; i++) {\r
+\r
+                               DictionaryEntry de = (DictionaryEntry) named_args [i];\r
+\r
+                               string member_name = (string) de.Key;\r
+                               Argument a  = (Argument) de.Value;\r
+\r
+                               if (!a.Resolve (ec, Location))\r
+                                       return null;\r
+\r
+                               Expression member = Expression.MemberLookup (\r
+                                       ec, Type, member_name, \r
+                                       MemberTypes.Field | MemberTypes.Property,\r
+                                       BindingFlags.Public | BindingFlags.Instance,\r
+                                       Location);\r
+\r
+                               if (member == null || !(member is FieldExpr)) {\r
+                                       Error_InvalidNamedArgument (member_name);\r
+                                       return null;\r
+                               }\r
+\r
+                               if (member is FieldExpr) {\r
+                                       FieldExpr fe = (FieldExpr) member;\r
+                                       FieldInfo fi = fe.FieldInfo;\r
+\r
+                                       if (fi.IsInitOnly) {\r
+                                               Error_InvalidNamedArgument (member_name);\r
+                                               return null;\r
+                                       }\r
+\r
+                                       if (a.Expr is Constant) {\r
+                                               Constant c = (Constant) a.Expr;\r
+                                               \r
+                                               if (member_name == "CallingConvention")\r
+                                                       cc = (CallingConvention) c.GetValue ();\r
+                                               else if (member_name == "CharSet")\r
+                                                       charset = (CharSet) c.GetValue ();\r
+                                               else if (member_name == "EntryPoint")\r
+                                                       entry_point = (string) c.GetValue ();\r
+                                               else if (member_name == "SetLastError")\r
+                                                       set_last_err = (bool) c.GetValue ();\r
+                                               else if (member_name == "ExactSpelling")\r
+                                                       exact_spelling = (bool) c.GetValue ();\r
+                                               else if (member_name == "PreserveSig")\r
+                                                       preserve_sig = (bool) c.GetValue ();\r
+                                       } else { \r
+                                               Error_AttributeArgumentNotValid (Location);\r
+                                               return null;\r
+                                       }\r
+                                       \r
+                               }\r
+                       }\r
+\r
+                       if (entry_point == null)\r
+                               entry_point = name;\r
+                       \r
+                       MethodBuilder mb = builder.DefinePInvokeMethod (\r
+                               name, dll_name, entry_point, flags | MethodAttributes.HideBySig,\r
+                               CallingConventions.Standard,\r
+                               ret_type,\r
+                               param_types,\r
+                               cc,\r
+                               charset);\r
+\r
+                       if (preserve_sig)\r
+                               mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);\r
+                       \r
+                       return mb;\r
+               }\r
+               \r
+       }\r
+       \r
+       public class AttributeSection {\r
+               public readonly string    Target;\r
+               public readonly ArrayList Attributes;\r
+               \r
+               public AttributeSection (string target, ArrayList attrs)\r
+               {\r
+                       Target = target;\r
+                       Attributes = attrs;\r
+               }\r
+               \r
+       }\r
+\r
+       public class Attributes {\r
+               public ArrayList AttributeSections;\r
+\r
+               public Attributes (AttributeSection a)\r
+               {\r
+                       AttributeSections = new ArrayList ();\r
+                       AttributeSections.Add (a);\r
+\r
+               }\r
+\r
+               public void AddAttributeSection (AttributeSection a)\r
+               {\r
+                       if (a != null && !AttributeSections.Contains (a))\r
+                               AttributeSections.Add (a);\r
+               }\r
+\r
+               public bool Contains (Type t)\r
+               {\r
+                       foreach (AttributeSection attr_section in AttributeSections){\r
+                               foreach (Attribute a in attr_section.Attributes){\r
+                                       if (a.Type == t)\r
+                                               return true;\r
+                               }\r
+                       }\r
+                        \r
+                       return false;\r
+               }\r
+       }\r
+}\r
diff --git a/mcs/gmcs/cfold.cs b/mcs/gmcs/cfold.cs
new file mode 100755 (executable)
index 0000000..7d08602
--- /dev/null
@@ -0,0 +1,1152 @@
+//
+// cfold.cs: Constant Folding
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2002, 2003 Ximian, Inc.
+//
+
+using System;
+
+namespace Mono.CSharp {
+
+       public class ConstantFold {
+
+               //
+               // Performs the numeric promotions on the left and right expresions
+               // and desposits the results on `lc' and `rc'.
+               //
+               // On success, the types of `lc' and `rc' on output will always match,
+               // and the pair will be one of:
+               //
+               //   (double, double)
+               //   (float, float)
+               //   (ulong, ulong)
+               //   (long, long)
+               //   (uint, uint)
+               //   (int, int)
+               //   (short, short)   (Happens with enumerations with underlying short type)
+               //   (ushort, ushort) (Happens with enumerations with underlying short type)
+               //
+               static void DoConstantNumericPromotions (EmitContext ec, Binary.Operator oper,
+                                                        ref Constant left, ref Constant right,
+                                                        Location loc)
+               {
+                       if (left is DoubleConstant || right is DoubleConstant){
+                               //
+                               // If either side is a double, convert the other to a double
+                               //
+                               if (!(left is DoubleConstant))
+                                       left = left.ToDouble (loc);
+
+                               if (!(right is DoubleConstant))
+                                       right = right.ToDouble (loc);
+                               return;
+                       } else if (left is FloatConstant || right is FloatConstant) {
+                               //
+                               // If either side is a float, convert the other to a float
+                               //
+                               if (!(left is FloatConstant))
+                                       left = left.ToFloat (loc);
+
+                               if (!(right is FloatConstant))
+                                       right = right.ToFloat (loc);
+;                              return;
+                       } else if (left is ULongConstant || right is ULongConstant){
+                               //
+                               // If either operand is of type ulong, the other operand is
+                               // converted to type ulong.  or an error ocurrs if the other
+                               // operand is of type sbyte, short, int or long
+                               //
+                               Constant match, other;
+                                       
+                               if (left is ULongConstant){
+                                       other = right;
+                                       match = left;
+                                       if (!(right is ULongConstant))
+                                               right = right.ToULong (loc);
+                               } else {
+                                       other = left;
+                                       match = right;
+                                       left = left.ToULong (loc);
+                               }
+
+#if WRONG
+                               if (other is SByteConstant || other is ShortConstant ||
+                                   other is IntConstant || other is LongConstant){
+                                       Binary.Error_OperatorAmbiguous
+                                               (loc, oper, other.Type, match.Type);
+                                       left = null;
+                                       right = null;
+                               }
+#endif
+                               return;
+                       } else if (left is LongConstant || right is LongConstant){
+                               //
+                               // If either operand is of type long, the other operand is converted
+                               // to type long.
+                               //
+                               if (!(left is LongConstant))
+                                       left = left.ToLong (loc);
+                               else if (!(right is LongConstant))
+                                       right = right.ToLong (loc);
+                               return;
+                       } else if (left is UIntConstant || right is UIntConstant){
+                               //
+                               // If either operand is of type uint, and the other
+                               // operand is of type sbyte, short or int, the operands are
+                               // converted to type long.
+                               //
+                               Constant match, other;
+                               if (left is UIntConstant){
+                                       other = right;
+                                       match = left;
+                               } else {
+                                       other = left;
+                                       match = right;
+                               }
+
+                               // Nothing to do.
+                               if (other is UIntConstant)
+                                       return;
+
+                               if (other is SByteConstant || other is ShortConstant ||
+                                   other is IntConstant){
+                                       left = left.ToLong (loc);
+                                       right = right.ToLong (loc);
+                               }
+
+                               return;
+                       } else if (left is EnumConstant || right is EnumConstant){
+                               //
+                               // If either operand is an enum constant, the other one must
+                               // be implicitly convertable to that enum's underlying type.
+                               //
+                               EnumConstant match;
+                               Constant other;
+                               if (left is EnumConstant){
+                                       other = right;
+                                       match = (EnumConstant) left;
+                               } else {
+                                       other = left;
+                                       match = (EnumConstant) right;
+                               }
+
+                               bool need_check = (other is EnumConstant) ||
+                                       ((oper != Binary.Operator.Addition) &&
+                                        (oper != Binary.Operator.Subtraction));
+
+                               if (need_check &&
+                                   !Convert.ImplicitConversionExists (ec, match, other.Type)) {
+                                       Convert.Error_CannotImplicitConversion (loc, match.Type, other.Type);
+                                       left = null;
+                                       right = null;
+                                       return;
+                               }
+
+                               if (left is EnumConstant)
+                                       left = ((EnumConstant) left).Child;
+                               if (right is EnumConstant)
+                                       right = ((EnumConstant) right).Child;
+                               return;
+
+                       } else {
+                               //
+                               // Force conversions to int32
+                               //
+                               if (!(left is IntConstant))
+                                       left = left.ToInt (loc);
+                               if (!(right is IntConstant))
+                                       right = right.ToInt (loc);
+                       }
+                       return;
+               }
+
+               static void Error_CompileTimeOverflow (Location loc)
+               {
+                       Report.Error (220, loc, "The operation overflows at compile time in checked mode");
+               }
+               
+               /// <summary>
+               ///   Constant expression folder for binary operations.
+               ///
+               ///   Returns null if the expression can not be folded.
+               /// </summary>
+               static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,
+                                                    Constant left, Constant right, Location loc)
+               {
+                       Type lt = left.Type;
+                       Type rt = right.Type;
+                       Type result_type = null;
+                       bool bool_res;
+                       
+                       //
+                       // Enumerator folding
+                       //
+                       if (rt == lt && left is EnumConstant)
+                               result_type = lt;
+
+                       //
+                       // During an enum evaluation, we need to unwrap enumerations
+                       //
+                       if (ec.InEnumContext){
+                               if (left is EnumConstant)
+                                       left = ((EnumConstant) left).Child;
+                               
+                               if (right is EnumConstant)
+                                       right = ((EnumConstant) right).Child;
+                       }
+
+                       Type wrap_as;
+                       Constant result = null;
+                       switch (oper){
+                       case Binary.Operator.BitwiseOr:
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+                               
+                               if (left is IntConstant){
+                                       IntConstant v;
+                                       int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
+                                       
+                                       v = new IntConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is UIntConstant){
+                                       UIntConstant v;
+                                       uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
+                                       
+                                       v = new UIntConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is LongConstant){
+                                       LongConstant v;
+                                       long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
+                                       
+                                       v = new LongConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is ULongConstant){
+                                       ULongConstant v;
+                                       ulong res = ((ULongConstant)left).Value |
+                                               ((ULongConstant)right).Value;
+                                       
+                                       v = new ULongConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is UShortConstant){
+                                       UShortConstant v;
+                                       ushort res = (ushort) (((UShortConstant)left).Value |
+                                                              ((UShortConstant)right).Value);
+                                       
+                                       v = new UShortConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is ShortConstant){
+                                       ShortConstant v;
+                                       short res = (short) (((ShortConstant)left).Value |
+                                                            ((ShortConstant)right).Value);
+                                       
+                                       v = new ShortConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               }
+                               break;
+                               
+                       case Binary.Operator.BitwiseAnd:
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+                               
+                               if (left is IntConstant){
+                                       IntConstant v;
+                                       int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
+                                       
+                                       v = new IntConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is UIntConstant){
+                                       UIntConstant v;
+                                       uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
+                                       
+                                       v = new UIntConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is LongConstant){
+                                       LongConstant v;
+                                       long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
+                                       
+                                       v = new LongConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is ULongConstant){
+                                       ULongConstant v;
+                                       ulong res = ((ULongConstant)left).Value &
+                                               ((ULongConstant)right).Value;
+                                       
+                                       v = new ULongConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is UShortConstant){
+                                       UShortConstant v;
+                                       ushort res = (ushort) (((UShortConstant)left).Value &
+                                                              ((UShortConstant)right).Value);
+                                       
+                                       v = new UShortConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is ShortConstant){
+                                       ShortConstant v;
+                                       short res = (short) (((ShortConstant)left).Value &
+                                                            ((ShortConstant)right).Value);
+                                       
+                                       v = new ShortConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               }
+                               break;
+
+                       case Binary.Operator.ExclusiveOr:
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+                               
+                               if (left is IntConstant){
+                                       IntConstant v;
+                                       int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
+                                       
+                                       v = new IntConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is UIntConstant){
+                                       UIntConstant v;
+                                       uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
+                                       
+                                       v = new UIntConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is LongConstant){
+                                       LongConstant v;
+                                       long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
+                                       
+                                       v = new LongConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is ULongConstant){
+                                       ULongConstant v;
+                                       ulong res = ((ULongConstant)left).Value ^
+                                               ((ULongConstant)right).Value;
+                                       
+                                       v = new ULongConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is UShortConstant){
+                                       UShortConstant v;
+                                       ushort res = (ushort) (((UShortConstant)left).Value ^
+                                                              ((UShortConstant)right).Value);
+                                       
+                                       v = new UShortConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               } else if (left is ShortConstant){
+                                       ShortConstant v;
+                                       short res = (short)(((ShortConstant)left).Value ^
+                                                           ((ShortConstant)right).Value);
+                                       
+                                       v = new ShortConstant (res);
+                                       if (result_type == null)
+                                               return v;
+                                       else
+                                               return new EnumConstant (v, result_type);
+                               }
+                               break;
+
+                       case Binary.Operator.Addition:
+                               bool left_is_string = left is StringConstant;
+                               bool right_is_string = right is StringConstant;
+
+                               //
+                               // If both sides are strings, then concatenate, if
+                               // one is a string, and the other is not, then defer
+                               // to runtime concatenation
+                               //
+                               wrap_as = null;
+                               if (left_is_string || right_is_string){
+                                       if (left_is_string && right_is_string)
+                                               return new StringConstant (
+                                                       ((StringConstant) left).Value +
+                                                       ((StringConstant) right).Value);
+                                       
+                                       return null;
+                               }
+
+                               //
+                               // handle "E operator + (E x, U y)"
+                               // handle "E operator + (Y y, E x)"
+                               //
+                               // note that E operator + (E x, E y) is invalid
+                               //
+                               if (left is EnumConstant){
+                                       if (right is EnumConstant){
+                                               return null;
+                                       }
+                                       if (((EnumConstant) left).Child.Type != right.Type)
+                                               return null;
+
+                                       wrap_as = left.Type;
+                               } else if (right is EnumConstant){
+                                       if (((EnumConstant) right).Child.Type != left.Type)
+                                               return null;
+                                       wrap_as = right.Type;
+                               }
+
+                               result = null;
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+
+                               try {
+                                       if (left is DoubleConstant){
+                                               double res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((DoubleConstant) left).Value +
+                                                                      ((DoubleConstant) right).Value);
+                                               else
+                                                       res = unchecked (((DoubleConstant) left).Value +
+                                                                        ((DoubleConstant) right).Value);
+                                               
+                                               result = new DoubleConstant (res);
+                                       } else if (left is FloatConstant){
+                                               float res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((FloatConstant) left).Value +
+                                                                      ((FloatConstant) right).Value);
+                                               else
+                                                       res = unchecked (((FloatConstant) left).Value +
+                                                                        ((FloatConstant) right).Value);
+                                               
+                                               result = new FloatConstant (res);
+                                       } else if (left is ULongConstant){
+                                               ulong res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((ULongConstant) left).Value +
+                                                                      ((ULongConstant) right).Value);
+                                               else
+                                                       res = unchecked (((ULongConstant) left).Value +
+                                                                        ((ULongConstant) right).Value);
+
+                                               result = new ULongConstant (res);
+                                       } else if (left is LongConstant){
+                                               long res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((LongConstant) left).Value +
+                                                                      ((LongConstant) right).Value);
+                                               else
+                                                       res = unchecked (((LongConstant) left).Value +
+                                                                        ((LongConstant) right).Value);
+                                               
+                                               result = new LongConstant (res);
+                                       } else if (left is UIntConstant){
+                                               uint res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((UIntConstant) left).Value +
+                                                                      ((UIntConstant) right).Value);
+                                               else
+                                                       res = unchecked (((UIntConstant) left).Value +
+                                                                        ((UIntConstant) right).Value);
+                                               
+                                               result = new UIntConstant (res);
+                                       } else if (left is IntConstant){
+                                               int res;
+
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((IntConstant) left).Value +
+                                                                      ((IntConstant) right).Value);
+                                               else
+                                                       res = unchecked (((IntConstant) left).Value +
+                                                                        ((IntConstant) right).Value);
+
+                                               result = new IntConstant (res);
+                                       } else {
+                                               throw new Exception ( "Unexepected input: " + left);
+                                       }
+                               } catch (OverflowException){
+                                       Error_CompileTimeOverflow (loc);
+                               }
+
+                               if (wrap_as != null)
+                                       return new EnumConstant (result, wrap_as);
+                               else
+                                       return result;
+
+                       case Binary.Operator.Subtraction:
+                               //
+                               // handle "E operator - (E x, U y)"
+                               // handle "E operator - (Y y, E x)"
+                               // handle "U operator - (E x, E y)"
+                               //
+                               wrap_as = null;
+                               if (left is EnumConstant){
+                                       if (right is EnumConstant){
+                                               if (left.Type == right.Type)
+                                                       wrap_as = TypeManager.EnumToUnderlying (left.Type);
+                                               else
+                                                       return null;
+                                       }
+                                       if (((EnumConstant) left).Child.Type != right.Type)
+                                               return null;
+
+                                       wrap_as = left.Type;
+                               } else if (right is EnumConstant){
+                                       if (((EnumConstant) right).Child.Type != left.Type)
+                                               return null;
+                                       wrap_as = right.Type;
+                               }
+
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+
+                               try {
+                                       if (left is DoubleConstant){
+                                               double res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((DoubleConstant) left).Value -
+                                                                      ((DoubleConstant) right).Value);
+                                               else
+                                                       res = unchecked (((DoubleConstant) left).Value -
+                                                                        ((DoubleConstant) right).Value);
+                                               
+                                               result = new DoubleConstant (res);
+                                       } else if (left is FloatConstant){
+                                               float res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((FloatConstant) left).Value -
+                                                                      ((FloatConstant) right).Value);
+                                               else
+                                                       res = unchecked (((FloatConstant) left).Value -
+                                                                        ((FloatConstant) right).Value);
+                                               
+                                               result = new FloatConstant (res);
+                                       } else if (left is ULongConstant){
+                                               ulong res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((ULongConstant) left).Value -
+                                                                      ((ULongConstant) right).Value);
+                                               else
+                                                       res = unchecked (((ULongConstant) left).Value -
+                                                                        ((ULongConstant) right).Value);
+                                               
+                                               result = new ULongConstant (res);
+                                       } else if (left is LongConstant){
+                                               long res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((LongConstant) left).Value -
+                                                                      ((LongConstant) right).Value);
+                                               else
+                                                       res = unchecked (((LongConstant) left).Value -
+                                                                        ((LongConstant) right).Value);
+                                               
+                                               result = new LongConstant (res);
+                                       } else if (left is UIntConstant){
+                                               uint res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((UIntConstant) left).Value -
+                                                                      ((UIntConstant) right).Value);
+                                               else
+                                                       res = unchecked (((UIntConstant) left).Value -
+                                                                        ((UIntConstant) right).Value);
+                                               
+                                               result = new UIntConstant (res);
+                                       } else if (left is IntConstant){
+                                               int res;
+
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((IntConstant) left).Value -
+                                                                      ((IntConstant) right).Value);
+                                               else
+                                                       res = unchecked (((IntConstant) left).Value -
+                                                                        ((IntConstant) right).Value);
+
+                                               result = new IntConstant (res);
+                                       } else {
+                                               throw new Exception ( "Unexepected input: " + left);
+                                       }
+                               } catch (OverflowException){
+                                       Error_CompileTimeOverflow (loc);
+                               }
+                               if (wrap_as != null)
+                                       return new EnumConstant (result, wrap_as);
+                               else
+                                       return result;
+                               
+                       case Binary.Operator.Multiply:
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+
+                               try {
+                                       if (left is DoubleConstant){
+                                               double res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((DoubleConstant) left).Value *
+                                                                      ((DoubleConstant) right).Value);
+                                               else
+                                                       res = unchecked (((DoubleConstant) left).Value *
+                                                                        ((DoubleConstant) right).Value);
+                                               
+                                               return new DoubleConstant (res);
+                                       } else if (left is FloatConstant){
+                                               float res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((FloatConstant) left).Value *
+                                                                      ((FloatConstant) right).Value);
+                                               else
+                                                       res = unchecked (((FloatConstant) left).Value *
+                                                                        ((FloatConstant) right).Value);
+                                               
+                                               return new FloatConstant (res);
+                                       } else if (left is ULongConstant){
+                                               ulong res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((ULongConstant) left).Value *
+                                                                      ((ULongConstant) right).Value);
+                                               else
+                                                       res = unchecked (((ULongConstant) left).Value *
+                                                                        ((ULongConstant) right).Value);
+                                               
+                                               return new ULongConstant (res);
+                                       } else if (left is LongConstant){
+                                               long res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((LongConstant) left).Value *
+                                                                      ((LongConstant) right).Value);
+                                               else
+                                                       res = unchecked (((LongConstant) left).Value *
+                                                                        ((LongConstant) right).Value);
+                                               
+                                               return new LongConstant (res);
+                                       } else if (left is UIntConstant){
+                                               uint res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((UIntConstant) left).Value *
+                                                                      ((UIntConstant) right).Value);
+                                               else
+                                                       res = unchecked (((UIntConstant) left).Value *
+                                                                        ((UIntConstant) right).Value);
+                                               
+                                               return new UIntConstant (res);
+                                       } else if (left is IntConstant){
+                                               int res;
+
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((IntConstant) left).Value *
+                                                                      ((IntConstant) right).Value);
+                                               else
+                                                       res = unchecked (((IntConstant) left).Value *
+                                                                        ((IntConstant) right).Value);
+
+                                               return new IntConstant (res);
+                                       } else {
+                                               throw new Exception ( "Unexepected input: " + left);
+                                       }
+                               } catch (OverflowException){
+                                       Error_CompileTimeOverflow (loc);
+                               }
+                               break;
+
+                       case Binary.Operator.Division:
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+
+                               try {
+                                       if (left is DoubleConstant){
+                                               double res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((DoubleConstant) left).Value /
+                                                                      ((DoubleConstant) right).Value);
+                                               else
+                                                       res = unchecked (((DoubleConstant) left).Value /
+                                                                        ((DoubleConstant) right).Value);
+                                               
+                                               return new DoubleConstant (res);
+                                       } else if (left is FloatConstant){
+                                               float res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((FloatConstant) left).Value /
+                                                                      ((FloatConstant) right).Value);
+                                               else
+                                                       res = unchecked (((FloatConstant) left).Value /
+                                                                        ((FloatConstant) right).Value);
+                                               
+                                               return new FloatConstant (res);
+                                       } else if (left is ULongConstant){
+                                               ulong res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((ULongConstant) left).Value /
+                                                                      ((ULongConstant) right).Value);
+                                               else
+                                                       res = unchecked (((ULongConstant) left).Value /
+                                                                        ((ULongConstant) right).Value);
+                                               
+                                               return new ULongConstant (res);
+                                       } else if (left is LongConstant){
+                                               long res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((LongConstant) left).Value /
+                                                                      ((LongConstant) right).Value);
+                                               else
+                                                       res = unchecked (((LongConstant) left).Value /
+                                                                        ((LongConstant) right).Value);
+                                               
+                                               return new LongConstant (res);
+                                       } else if (left is UIntConstant){
+                                               uint res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((UIntConstant) left).Value /
+                                                                      ((UIntConstant) right).Value);
+                                               else
+                                                       res = unchecked (((UIntConstant) left).Value /
+                                                                        ((UIntConstant) right).Value);
+                                               
+                                               return new UIntConstant (res);
+                                       } else if (left is IntConstant){
+                                               int res;
+
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((IntConstant) left).Value /
+                                                                      ((IntConstant) right).Value);
+                                               else
+                                                       res = unchecked (((IntConstant) left).Value /
+                                                                        ((IntConstant) right).Value);
+
+                                               return new IntConstant (res);
+                                       } else {
+                                               throw new Exception ( "Unexepected input: " + left);
+                                       }
+                               } catch (OverflowException){
+                                       Error_CompileTimeOverflow (loc);
+
+                               } catch (DivideByZeroException) {
+                                       Report.Error (020, loc, "Division by constant zero");
+                               }
+                               
+                               break;
+                               
+                       case Binary.Operator.Modulus:
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+
+                               try {
+                                       if (left is DoubleConstant){
+                                               double res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((DoubleConstant) left).Value %
+                                                                      ((DoubleConstant) right).Value);
+                                               else
+                                                       res = unchecked (((DoubleConstant) left).Value %
+                                                                        ((DoubleConstant) right).Value);
+                                               
+                                               return new DoubleConstant (res);
+                                       } else if (left is FloatConstant){
+                                               float res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((FloatConstant) left).Value %
+                                                                      ((FloatConstant) right).Value);
+                                               else
+                                                       res = unchecked (((FloatConstant) left).Value %
+                                                                        ((FloatConstant) right).Value);
+                                               
+                                               return new FloatConstant (res);
+                                       } else if (left is ULongConstant){
+                                               ulong res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((ULongConstant) left).Value %
+                                                                      ((ULongConstant) right).Value);
+                                               else
+                                                       res = unchecked (((ULongConstant) left).Value %
+                                                                        ((ULongConstant) right).Value);
+                                               
+                                               return new ULongConstant (res);
+                                       } else if (left is LongConstant){
+                                               long res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((LongConstant) left).Value %
+                                                                      ((LongConstant) right).Value);
+                                               else
+                                                       res = unchecked (((LongConstant) left).Value %
+                                                                        ((LongConstant) right).Value);
+                                               
+                                               return new LongConstant (res);
+                                       } else if (left is UIntConstant){
+                                               uint res;
+                                               
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((UIntConstant) left).Value %
+                                                                      ((UIntConstant) right).Value);
+                                               else
+                                                       res = unchecked (((UIntConstant) left).Value %
+                                                                        ((UIntConstant) right).Value);
+                                               
+                                               return new UIntConstant (res);
+                                       } else if (left is IntConstant){
+                                               int res;
+
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((IntConstant) left).Value %
+                                                                      ((IntConstant) right).Value);
+                                               else
+                                                       res = unchecked (((IntConstant) left).Value %
+                                                                        ((IntConstant) right).Value);
+
+                                               return new IntConstant (res);
+                                       } else {
+                                               throw new Exception ( "Unexepected input: " + left);
+                                       }
+                               } catch (DivideByZeroException){
+                                       Report.Error (020, loc, "Division by constant zero");
+                               } catch (OverflowException){
+                                       Error_CompileTimeOverflow (loc);
+                               }
+                               break;
+
+                               //
+                               // There is no overflow checking on left shift
+                               //
+                       case Binary.Operator.LeftShift:
+                               IntConstant ic = right.ToInt (loc);
+                               if (ic == null){
+                                       Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
+                                       return null;
+                               }
+                               int lshift_val = ic.Value;
+
+                               IntConstant lic;
+                               if ((lic = left.ConvertToInt ()) != null)
+                                       return new IntConstant (lic.Value << lshift_val);
+
+                               UIntConstant luic;
+                               if ((luic = left.ConvertToUInt ()) != null)
+                                       return new UIntConstant (luic.Value << lshift_val);
+
+                               LongConstant llc;
+                               if ((llc = left.ConvertToLong ()) != null)
+                                       return new LongConstant (llc.Value << lshift_val);
+
+                               ULongConstant lulc;
+                               if ((lulc = left.ConvertToULong ()) != null)
+                                       return new ULongConstant (lulc.Value << lshift_val);
+
+                               Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
+                               break;
+
+                               //
+                               // There is no overflow checking on right shift
+                               //
+                       case Binary.Operator.RightShift:
+                               IntConstant sic = right.ToInt (loc);
+                               if (sic == null){
+                                       Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
+                                       return null;
+                               }
+                               int rshift_val = sic.Value;
+
+                               IntConstant ric;
+                               if ((ric = left.ConvertToInt ()) != null)
+                                       return new IntConstant (ric.Value >> rshift_val);
+
+                               UIntConstant ruic;
+                               if ((ruic = left.ConvertToUInt ()) != null)
+                                       return new UIntConstant (ruic.Value >> rshift_val);
+
+                               LongConstant rlc;
+                               if ((rlc = left.ConvertToLong ()) != null)
+                                       return new LongConstant (rlc.Value >> rshift_val);
+
+                               ULongConstant rulc;
+                               if ((rulc = left.ConvertToULong ()) != null)
+                                       return new ULongConstant (rulc.Value >> rshift_val);
+
+                               Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
+                               break;
+
+                       case Binary.Operator.LogicalAnd:
+                               if (left is BoolConstant && right is BoolConstant){
+                                       return new BoolConstant (
+                                               ((BoolConstant) left).Value &&
+                                               ((BoolConstant) right).Value);
+                               }
+                               break;
+
+                       case Binary.Operator.LogicalOr:
+                               if (left is BoolConstant && right is BoolConstant){
+                                       return new BoolConstant (
+                                               ((BoolConstant) left).Value ||
+                                               ((BoolConstant) right).Value);
+                               }
+                               break;
+                               
+                       case Binary.Operator.Equality:
+                               if (left is BoolConstant && right is BoolConstant){
+                                       return new BoolConstant (
+                                               ((BoolConstant) left).Value ==
+                                               ((BoolConstant) right).Value);
+                               
+                               }
+                               if (left is StringConstant && right is StringConstant){
+                                       return new BoolConstant (
+                                               ((StringConstant) left).Value ==
+                                               ((StringConstant) right).Value);
+                                       
+                               }
+                               
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+
+                               bool_res = false;
+                               if (left is DoubleConstant)
+                                       bool_res = ((DoubleConstant) left).Value ==
+                                               ((DoubleConstant) right).Value;
+                               else if (left is FloatConstant)
+                                       bool_res = ((FloatConstant) left).Value ==
+                                               ((FloatConstant) right).Value;
+                               else if (left is ULongConstant)
+                                       bool_res = ((ULongConstant) left).Value ==
+                                               ((ULongConstant) right).Value;
+                               else if (left is LongConstant)
+                                       bool_res = ((LongConstant) left).Value ==
+                                               ((LongConstant) right).Value;
+                               else if (left is UIntConstant)
+                                       bool_res = ((UIntConstant) left).Value ==
+                                               ((UIntConstant) right).Value;
+                               else if (left is IntConstant)
+                                       bool_res = ((IntConstant) left).Value ==
+                                               ((IntConstant) right).Value;
+                               else
+                                       return null;
+
+                               return new BoolConstant (bool_res);
+
+                       case Binary.Operator.Inequality:
+                               if (left is BoolConstant && right is BoolConstant){
+                                       return new BoolConstant (
+                                               ((BoolConstant) left).Value !=
+                                               ((BoolConstant) right).Value);
+                               }
+                               if (left is StringConstant && right is StringConstant){
+                                       return new BoolConstant (
+                                               ((StringConstant) left).Value !=
+                                               ((StringConstant) right).Value);
+                                       
+                               }
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+
+                               bool_res = false;
+                               if (left is DoubleConstant)
+                                       bool_res = ((DoubleConstant) left).Value !=
+                                               ((DoubleConstant) right).Value;
+                               else if (left is FloatConstant)
+                                       bool_res = ((FloatConstant) left).Value !=
+                                               ((FloatConstant) right).Value;
+                               else if (left is ULongConstant)
+                                       bool_res = ((ULongConstant) left).Value !=
+                                               ((ULongConstant) right).Value;
+                               else if (left is LongConstant)
+                                       bool_res = ((LongConstant) left).Value !=
+                                               ((LongConstant) right).Value;
+                               else if (left is UIntConstant)
+                                       bool_res = ((UIntConstant) left).Value !=
+                                               ((UIntConstant) right).Value;
+                               else if (left is IntConstant)
+                                       bool_res = ((IntConstant) left).Value !=
+                                               ((IntConstant) right).Value;
+                               else
+                                       return null;
+
+                               return new BoolConstant (bool_res);
+
+                       case Binary.Operator.LessThan:
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+
+                               bool_res = false;
+                               if (left is DoubleConstant)
+                                       bool_res = ((DoubleConstant) left).Value <
+                                               ((DoubleConstant) right).Value;
+                               else if (left is FloatConstant)
+                                       bool_res = ((FloatConstant) left).Value <
+                                               ((FloatConstant) right).Value;
+                               else if (left is ULongConstant)
+                                       bool_res = ((ULongConstant) left).Value <
+                                               ((ULongConstant) right).Value;
+                               else if (left is LongConstant)
+                                       bool_res = ((LongConstant) left).Value <
+                                               ((LongConstant) right).Value;
+                               else if (left is UIntConstant)
+                                       bool_res = ((UIntConstant) left).Value <
+                                               ((UIntConstant) right).Value;
+                               else if (left is IntConstant)
+                                       bool_res = ((IntConstant) left).Value <
+                                               ((IntConstant) right).Value;
+                               else
+                                       return null;
+
+                               return new BoolConstant (bool_res);
+                               
+                       case Binary.Operator.GreaterThan:
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+
+                               bool_res = false;
+                               if (left is DoubleConstant)
+                                       bool_res = ((DoubleConstant) left).Value >
+                                               ((DoubleConstant) right).Value;
+                               else if (left is FloatConstant)
+                                       bool_res = ((FloatConstant) left).Value >
+                                               ((FloatConstant) right).Value;
+                               else if (left is ULongConstant)
+                                       bool_res = ((ULongConstant) left).Value >
+                                               ((ULongConstant) right).Value;
+                               else if (left is LongConstant)
+                                       bool_res = ((LongConstant) left).Value >
+                                               ((LongConstant) right).Value;
+                               else if (left is UIntConstant)
+                                       bool_res = ((UIntConstant) left).Value >
+                                               ((UIntConstant) right).Value;
+                               else if (left is IntConstant)
+                                       bool_res = ((IntConstant) left).Value >
+                                               ((IntConstant) right).Value;
+                               else
+                                       return null;
+
+                               return new BoolConstant (bool_res);
+
+                       case Binary.Operator.GreaterThanOrEqual:
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+
+                               bool_res = false;
+                               if (left is DoubleConstant)
+                                       bool_res = ((DoubleConstant) left).Value >=
+                                               ((DoubleConstant) right).Value;
+                               else if (left is FloatConstant)
+                                       bool_res = ((FloatConstant) left).Value >=
+                                               ((FloatConstant) right).Value;
+                               else if (left is ULongConstant)
+                                       bool_res = ((ULongConstant) left).Value >=
+                                               ((ULongConstant) right).Value;
+                               else if (left is LongConstant)
+                                       bool_res = ((LongConstant) left).Value >=
+                                               ((LongConstant) right).Value;
+                               else if (left is UIntConstant)
+                                       bool_res = ((UIntConstant) left).Value >=
+                                               ((UIntConstant) right).Value;
+                               else if (left is IntConstant)
+                                       bool_res = ((IntConstant) left).Value >=
+                                               ((IntConstant) right).Value;
+                               else
+                                       return null;
+
+                               return new BoolConstant (bool_res);
+
+                       case Binary.Operator.LessThanOrEqual:
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               if (left == null || right == null)
+                                       return null;
+
+                               bool_res = false;
+                               if (left is DoubleConstant)
+                                       bool_res = ((DoubleConstant) left).Value <=
+                                               ((DoubleConstant) right).Value;
+                               else if (left is FloatConstant)
+                                       bool_res = ((FloatConstant) left).Value <=
+                                               ((FloatConstant) right).Value;
+                               else if (left is ULongConstant)
+                                       bool_res = ((ULongConstant) left).Value <=
+                                               ((ULongConstant) right).Value;
+                               else if (left is LongConstant)
+                                       bool_res = ((LongConstant) left).Value <=
+                                               ((LongConstant) right).Value;
+                               else if (left is UIntConstant)
+                                       bool_res = ((UIntConstant) left).Value <=
+                                               ((UIntConstant) right).Value;
+                               else if (left is IntConstant)
+                                       bool_res = ((IntConstant) left).Value <=
+                                               ((IntConstant) right).Value;
+                               else
+                                       return null;
+
+                               return new BoolConstant (bool_res);
+                       }
+                                       
+                       return null;
+               }
+       }
+}
diff --git a/mcs/gmcs/class.cs b/mcs/gmcs/class.cs
new file mode 100755 (executable)
index 0000000..11e5b30
--- /dev/null
@@ -0,0 +1,5057 @@
+//
+// class.cs: Class and Struct handlers
+//
+// Authors: Miguel de Icaza (miguel@gnu.org)
+//          Martin Baulig (martin@gnome.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
+//
+//
+//  2002-10-11  Miguel de Icaza  <miguel@ximian.com>
+//
+//     * class.cs: Following the comment from 2002-09-26 to AddMethod, I
+//     have fixed a remaining problem: not every AddXXXX was adding a
+//     fully qualified name.  
+//
+//     Now everyone registers a fully qualified name in the DeclSpace as
+//     being defined instead of the partial name.  
+//
+//     Downsides: we are slower than we need to be due to the excess
+//     copies and the names being registered this way.  
+//
+//     The reason for this is that we currently depend (on the corlib
+//     bootstrap for instance) that types are fully qualified, because
+//     we dump all the types in the namespace, and we should really have
+//     types inserted into the proper namespace, so we can only store the
+//     basenames in the defined_names array.
+//
+//
+#define CACHE
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///   This is the base class for structs and classes.  
+       /// </summary>
+       public class TypeContainer : DeclSpace, IMemberContainer {
+               // Holds a list of classes and structures
+               ArrayList types;
+
+               // Holds the list of properties
+               ArrayList properties;
+
+               // Holds the list of enumerations
+               ArrayList enums;
+
+               // Holds the list of delegates
+               ArrayList delegates;
+               
+               // Holds the list of constructors
+               ArrayList instance_constructors;
+
+               // Holds the list of fields
+               ArrayList fields;
+
+               // Holds a list of fields that have initializers
+               ArrayList initialized_fields;
+
+               // Holds a list of static fields that have initializers
+               ArrayList initialized_static_fields;
+
+               // Holds the list of constants
+               ArrayList constants;
+
+               // Holds the list of
+               ArrayList interfaces;
+
+               // Holds order in which interfaces must be closed
+               ArrayList interface_order;
+               
+               // Holds the methods.
+               ArrayList methods;
+
+               // Holds the events
+               ArrayList events;
+
+               // Holds the indexers
+               ArrayList indexers;
+
+               // Holds the operators
+               ArrayList operators;
+
+               // The emit context for toplevel objects.
+               EmitContext ec;
+               
+               //
+               // Pointers to the default constructor and the default static constructor
+               //
+               Constructor default_constructor;
+               Constructor default_static_constructor;
+
+               //
+               // Whether we have seen a static constructor for this class or not
+               //
+               bool have_static_constructor = false;
+
+               //
+               // Whether we have at least one non-static field
+               //
+               bool have_nonstatic_fields = false;
+               
+               //
+               // This one is computed after we can distinguish interfaces
+               // from classes from the arraylist `type_bases' 
+               //
+               string     base_class_name;
+
+               ArrayList type_bases;
+
+               // Attributes for this type
+               protected Attributes attributes;
+
+               // Information in the case we are an attribute type
+
+               public AttributeTargets Targets = AttributeTargets.All;
+               public bool AllowMultiple = false;
+               public bool Inherited;
+
+               // The interfaces we implement.
+               Type [] ifaces;
+
+               // The parent member container and our member cache
+               IMemberContainer parent_container;
+               MemberCache member_cache;
+               
+               //
+               // The indexer name for this class
+               //
+               public string IndexerName;
+
+               public TypeContainer (TypeContainer parent, string name, Location l)
+                       : base (parent, name, l)
+               {
+                       string n;
+                       types = new ArrayList ();
+
+                       if (parent == null)
+                               n = "";
+                       else
+                               n = parent.Name;
+
+                       base_class_name = null;
+                       
+                       //Console.WriteLine ("New class " + name + " inside " + n);
+               }
+
+               public AdditionResult AddConstant (Const constant)
+               {
+                       AdditionResult res;
+                       string basename = constant.Name;
+                       string fullname = Name + "." + basename;
+
+                       if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
+                               return res;
+                       
+                       if (constants == null)
+                               constants = new ArrayList ();
+
+                       constants.Add (constant);
+                       DefineName (fullname, constant);
+
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddEnum (Mono.CSharp.Enum e)
+               {
+                       AdditionResult res;
+
+                       if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
+                               return res;
+
+                       if (enums == null)
+                               enums = new ArrayList ();
+
+                       enums.Add (e);
+                       DefineName (e.Name, e);
+
+                       return AdditionResult.Success;
+               }
+               
+               public AdditionResult AddClass (Class c)
+               {
+                       AdditionResult res;
+                       string name = c.Basename;
+                       
+                       if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
+                               return res;
+
+                       DefineName (c.Name, c);
+                       types.Add (c);
+
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddStruct (Struct s)
+               {
+                       AdditionResult res;
+                       string name = s.Basename;
+                       
+                       if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
+                               return res;
+
+                       DefineName (s.Name, s);
+                       types.Add (s);
+
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddDelegate (Delegate d)
+               {
+                       AdditionResult res;
+                       string name = d.Basename;
+                       
+                       if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
+                               return res;
+
+                       if (delegates == null)
+                               delegates = new ArrayList ();
+                       
+                       DefineName (d.Name, d);
+                       delegates.Add (d);
+
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddMethod (Method method)
+               {
+                       string basename = method.Name;
+                       string fullname = Name + "." + basename;
+
+                       Object value = defined_names [fullname];
+
+                       if (value != null && (!(value is Method)))
+                               return AdditionResult.NameExists;
+
+                       if (basename == Basename)
+                               return AdditionResult.EnclosingClash;
+
+                       if (methods == null)
+                               methods = new ArrayList ();
+
+                       if (method.Name.IndexOf (".") != -1)
+                               methods.Insert (0, method);
+                       else 
+                               methods.Add (method);
+                       
+                       if (value == null)
+                               DefineName (fullname, method);
+
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddConstructor (Constructor c)
+               {
+                       if (c.Name != Basename) 
+                               return AdditionResult.NotAConstructor;
+
+                       bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
+                       
+                       if (is_static){
+                               have_static_constructor = true;
+                               if (default_static_constructor != null){
+                                       Console.WriteLine ("I have a static constructor already");
+                                       Console.WriteLine ("   " + default_static_constructor);
+                                       return AdditionResult.MethodExists;
+                               }
+
+                               default_static_constructor = c;
+                       } else {
+                               if (c.IsDefault ()){
+                                       if (default_constructor != null)
+                                               return AdditionResult.MethodExists;
+                                       default_constructor = c;
+                               }
+                               
+                               if (instance_constructors == null)
+                                       instance_constructors = new ArrayList ();
+                               
+                               instance_constructors.Add (c);
+                       }
+                       
+                       return AdditionResult.Success;
+               }
+               
+               public AdditionResult AddInterface (Interface iface)
+               {
+                       AdditionResult res;
+                       string name = iface.Basename;
+                       
+                       if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
+                               return res;
+                       
+                       if (interfaces == null)
+                               interfaces = new ArrayList ();
+                       interfaces.Add (iface);
+                       DefineName (iface.Name, iface);
+                       
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddField (Field field)
+               {
+                       AdditionResult res;
+                       string basename = field.Name;
+                       string fullname = Name + "." + basename;
+
+                       if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
+                               return res;
+                       
+                       if (fields == null)
+                               fields = new ArrayList ();
+                       
+                       fields.Add (field);
+                       
+                       if (field.HasInitializer){
+                               if ((field.ModFlags & Modifiers.STATIC) != 0){
+                                       if (initialized_static_fields == null)
+                                               initialized_static_fields = new ArrayList ();
+
+                                       initialized_static_fields.Add (field);
+
+                                       //
+                                       // We have not seen a static constructor,
+                                       // but we will provide static initialization of fields
+                                       //
+                                       have_static_constructor = true;
+                               } else {
+                                       if (initialized_fields == null)
+                                               initialized_fields = new ArrayList ();
+                               
+                                       initialized_fields.Add (field);
+                               }
+                       }
+
+                       if ((field.ModFlags & Modifiers.STATIC) == 0)
+                               have_nonstatic_fields = true;
+
+                       DefineName (fullname, field);
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddProperty (Property prop)
+               {
+                       AdditionResult res;
+                       string basename = prop.Name;
+                       string fullname = Name + "." + basename;
+
+                       if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
+                               return res;
+
+                       if (properties == null)
+                               properties = new ArrayList ();
+
+                       if (prop.Name.IndexOf (".") != -1)
+                               properties.Insert (0, prop);
+                       else
+                               properties.Add (prop);
+                       DefineName (fullname, prop);
+
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddEvent (Event e)
+               {
+                       AdditionResult res;
+                       string basename = e.Name;
+                       string fullname = Name + "." + basename;
+
+                       if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
+                               return res;
+
+                       if (events == null)
+                               events = new ArrayList ();
+                       
+                       events.Add (e);
+                       DefineName (fullname, e);
+
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddIndexer (Indexer i)
+               {
+                       if (indexers == null)
+                               indexers = new ArrayList ();
+
+                       if (i.InterfaceType != null)
+                               indexers.Insert (0, i);
+                       else
+                               indexers.Add (i);
+
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddOperator (Operator op)
+               {
+                       if (operators == null)
+                               operators = new ArrayList ();
+
+                       operators.Add (op);
+
+                       return AdditionResult.Success;
+               }
+
+               public void RegisterOrder (Interface iface)
+               {
+                       if (interface_order == null)
+                               interface_order = new ArrayList ();
+
+                       interface_order.Add (iface);
+               }
+               
+               public ArrayList Types {
+                       get {
+                               return types;
+                       }
+               }
+
+               public ArrayList Methods {
+                       get {
+                               return methods;
+                       }
+               }
+
+               public ArrayList Constants {
+                       get {
+                               return constants;
+                       }
+               }
+
+               public ArrayList Interfaces {
+                       get {
+                               return interfaces;
+                       }
+               }
+               
+               public string Base {
+                       get {
+                               return base_class_name;
+                       }
+               }
+               
+               public ArrayList Bases {
+                       get {
+                               return type_bases;
+                       }
+
+                       set {
+                               type_bases = value;
+                       }
+               }
+
+               public ArrayList Fields {
+                       get {
+                               return fields;
+                       }
+
+                       set {
+                               fields = value;
+                       }
+               }
+
+               public ArrayList InstanceConstructors {
+                       get {
+                               return instance_constructors;
+                       }
+               }
+
+               public ArrayList Properties {
+                       get {
+                               return properties;
+                       }
+               }
+
+               public ArrayList Events {
+                       get {
+                               return events;
+                       }
+               }
+               
+               public ArrayList Enums {
+                       get {
+                               return enums;
+                       }
+               }
+
+               public ArrayList Indexers {
+                       get {
+                               return indexers;
+                       }
+               }
+
+               public ArrayList Operators {
+                       get {
+                               return operators;
+                       }
+               }
+
+               public ArrayList Delegates {
+                       get {
+                               return delegates;
+                       }
+               }
+               
+               public Attributes OptAttributes {
+                       get {
+                               return attributes;
+                       }
+               }
+               
+               public bool HaveStaticConstructor {
+                       get {
+                               return have_static_constructor;
+                       }
+               }
+               
+               public virtual TypeAttributes TypeAttr {
+                       get {
+                               return Modifiers.TypeAttr (ModFlags, this);
+                       }
+               }
+
+               //
+               // Emits the instance field initializers
+               //
+               public bool EmitFieldInitializers (EmitContext ec)
+               {
+                       ArrayList fields;
+                       ILGenerator ig = ec.ig;
+                       Expression instance_expr;
+                       
+                       if (ec.IsStatic){
+                               fields = initialized_static_fields;
+                               instance_expr = null;
+                       } else {
+                               fields = initialized_fields;
+                               instance_expr = new This (Location.Null).Resolve (ec);
+                       }
+
+                       if (fields == null)
+                               return true;
+
+                       foreach (Field f in fields){
+                               Expression e = f.GetInitializerExpression (ec);
+                               if (e == null)
+                                       return false;
+
+                               Location l = f.Location;
+                               FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
+                               fe.InstanceExpression = instance_expr;
+                               ExpressionStatement a = new Assign (fe, e, l);
+
+                               a = a.ResolveStatement (ec);
+                               if (a == null)
+                                       return false;
+
+                               a.EmitStatement (ec);
+                       }
+
+                       return true;
+               }
+               
+               //
+               // Defines the default constructors
+               //
+               void DefineDefaultConstructor (bool is_static)
+               {
+                       Constructor c;
+                       int mods = 0;
+
+                       c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
+                                            new ConstructorBaseInitializer (
+                                                    null, Parameters.EmptyReadOnlyParameters,
+                                                    Location),
+                                            Location);
+                       
+                       if (is_static)
+                               mods = Modifiers.STATIC;
+
+                       c.ModFlags = mods;
+
+                       AddConstructor (c);
+                       
+                       c.Block = new Block (null);
+                       
+               }
+
+               public void ReportStructInitializedInstanceError ()
+               {
+                       string n = TypeBuilder.FullName;
+                       
+                       foreach (Field f in initialized_fields){
+                               Report.Error (
+                                       573, Location,
+                                       "`" + n + "." + f.Name + "': can not have " +
+                                       "instance field initializers in structs");
+                       }
+               }
+
+               /// <remarks>
+               ///  The pending methods that need to be implemented (interfaces or abstract methods)
+               /// </remarks>
+               public PendingImplementation Pending;
+
+               /// <summary>
+               ///   This function computes the Base class and also the
+               ///   list of interfaces that the class or struct @c implements.
+               ///   
+               ///   The return value is an array (might be null) of
+               ///   interfaces implemented (as Types).
+               ///   
+               ///   The @parent argument is set to the parent object or null
+               ///   if this is `System.Object'. 
+               /// </summary>
+               Type [] GetClassBases (bool is_class, out Type parent, out bool error)
+               {
+                       ArrayList bases = Bases;
+                       int count;
+                       int start, j, i;
+
+                       error = false;
+
+                       if (is_class)
+                               parent = null;
+                       else
+                               parent = TypeManager.value_type;
+
+                       if (bases == null){
+                               if (is_class){
+                                       if (RootContext.StdLib)
+                                               parent = TypeManager.object_type;
+                                       else if (Name != "System.Object")
+                                               parent = TypeManager.object_type;
+                               } else {
+                                       //
+                                       // If we are compiling our runtime,
+                                       // and we are defining ValueType, then our
+                                       // parent is `System.Object'.
+                                       //
+                                       if (!RootContext.StdLib && Name == "System.ValueType")
+                                               parent = TypeManager.object_type;
+                               }
+
+                               return null;
+                       }
+
+                       //
+                       // Bases should be null if there are no bases at all
+                       //
+                       count = bases.Count;
+
+                       if (is_class){
+                               Expression name = (Expression) bases [0];
+                               name = ResolveTypeExpr (name, false, Location);
+
+                               if (name == null){
+                                       error = true;
+                                       return null;
+                               }
+
+                               Type first = name.Type;
+
+                               if (first.IsClass){
+                                       parent = first;
+                                       start = 1;
+                               } else {
+                                       parent = TypeManager.object_type;
+                                       start = 0;
+                               }
+                               if (first.IsSealed){
+                                       string detail = "";
+                                       
+                                       if (first.IsValueType)
+                                               detail = " (a class can not inherit from a struct/enum)";
+                                       
+                                       Report.Error (509, "class `"+ Name +
+                                                     "': Cannot inherit from sealed class `"+
+                                                     first + "'" + detail);
+                                       error = true;
+                                       return null;
+                               }
+
+                               if (!AsAccessible (parent, ModFlags))
+                                       Report.Error (60, Location,
+                                                     "Inconsistent accessibility: base class `" +
+                                                     TypeManager.CSharpName (parent) + "' is less " +
+                                                     "accessible than class `" +
+                                                     Name + "'");
+
+                       } else {
+                               start = 0;
+                       }
+
+                       if (parent != null)
+                               base_class_name = parent.Name;
+
+                       Type [] ifaces = new Type [count-start];
+                       
+                       for (i = start, j = 0; i < count; i++, j++){
+                               Expression name = (Expression) bases [i];
+                               Expression resolved = ResolveTypeExpr (name, false, Location);
+                               if (resolved == null)
+                                       return null;
+                               
+                               bases [i] = resolved;
+                               Type t = resolved.Type;
+
+                               if (t == null){
+                                       error = true;
+                                       return null;
+                               }
+
+                               if (is_class == false && !t.IsInterface){
+                                       Report.Error (527, "In Struct `" + Name + "', type `"+
+                                                     name +"' is not an interface");
+                                       error = true;
+                                       return null;
+                               }
+                               
+                               if (t.IsClass) {
+                                       if (parent != null){
+                                               Report.Error (527, "In Class `" + Name + "', type `"+
+                                                             name+"' is not an interface");
+                                               error = true;
+                                               return null;
+                                       }
+                               }
+
+                               for (int x = 0; x < j; x++) {
+                                       if (t == ifaces [x]) {
+                                               Report.Error (528, "`" + name + "' is already listed in interface list");
+                                               error = true;
+                                               return null;
+                                       }
+                               }
+
+                               ifaces [j] = t;
+                       }
+
+                       return TypeManager.ExpandInterfaces (ifaces);
+               }
+               
+               //
+               // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
+               //
+               public override TypeBuilder DefineType ()
+               {
+                       Type parent;
+                       bool error;
+                       bool is_class;
+
+                       if (TypeBuilder != null)
+                               return TypeBuilder;
+                       
+                       if (InTransit)
+                               return null;
+                       
+                       InTransit = true;
+
+                       if (this is Class)
+                               is_class = true;
+                       else
+                               is_class = false;
+
+                       ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
+
+                       ifaces = GetClassBases (is_class, out parent, out error); 
+
+                       if (error)
+                               return null;
+
+                       if (is_class && parent != null){
+                               if (parent == TypeManager.enum_type ||
+                                   (parent == TypeManager.value_type && RootContext.StdLib) ||
+                                   parent == TypeManager.delegate_type ||
+                                   parent == TypeManager.array_type){
+                                       Report.Error (
+                                               644, Location, "`" + Name + "' cannot inherit from " +
+                                               "special class `" + TypeManager.CSharpName (parent) + "'");
+                                       return null;
+                               }
+                       }
+
+                       if (!is_class && TypeManager.value_type == null)
+                               throw new Exception ();
+
+                       TypeAttributes type_attributes = TypeAttr;
+
+                       // if (parent_builder is ModuleBuilder) {
+                       if (IsTopLevel){
+                               if (TypeManager.NamespaceClash (Name, Location))
+                                       return null;
+                               
+                               ModuleBuilder builder = CodeGen.ModuleBuilder;
+                               TypeBuilder = builder.DefineType (
+                                       Name, type_attributes, parent, ifaces);
+                               
+                       } else {
+                               TypeBuilder builder = Parent.TypeBuilder;
+                               TypeBuilder = builder.DefineNestedType (
+                                       Basename, type_attributes, parent, ifaces);
+                       }
+                               
+                       //
+                       // Structs with no fields need to have at least one byte.
+                       // The right thing would be to set the PackingSize in a DefineType
+                       // but there are no functions that allow interfaces *and* the size to
+                       // be specified.
+                       //
+
+                       if (!is_class && !have_nonstatic_fields){
+                               TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
+                                                        FieldAttributes.Private);
+                               // add interfaces that were not added at type creation
+                               if (ifaces != null) {
+                                       foreach (Type i in ifaces)
+                                               TypeBuilder.AddInterfaceImplementation (i);
+                               }
+                       }
+
+                       //
+                       // Finish the setup for the EmitContext
+                       //
+                       ec.ContainerType = TypeBuilder;
+
+                       TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
+
+                       if ((parent != null) &&
+                           (parent == TypeManager.attribute_type ||
+                            parent.IsSubclassOf (TypeManager.attribute_type))) {
+                               RootContext.RegisterAttribute (this);
+                               TypeManager.RegisterAttrType (TypeBuilder, this);
+                       } else
+                               RootContext.RegisterOrder (this); 
+                               
+                       if (Interfaces != null) {
+                               foreach (Interface iface in Interfaces)
+                                       iface.DefineType ();
+                       }
+                       
+                       if (Types != null) {
+                               foreach (TypeContainer tc in Types)
+                                       tc.DefineType ();
+                       }
+
+                       if (Delegates != null) {
+                               foreach (Delegate d in Delegates)
+                                       d.DefineType ();
+                       }
+
+                       if (Enums != null) {
+                               foreach (Enum en in Enums)
+                                       en.DefineType ();
+                       }
+
+                       InTransit = false;
+                       return TypeBuilder;
+               }
+
+
+               /// <summary>
+               ///   Defines the MemberCore objects that are in the `list' Arraylist
+               ///
+               ///   The `defined_names' array contains a list of members defined in
+               ///   a base class
+               /// </summary>
+               static ArrayList remove_list = new ArrayList ();
+               void DefineMembers (ArrayList list, MemberInfo [] defined_names)
+               {
+                       int idx;
+                       
+                       remove_list.Clear ();
+
+                       foreach (MemberCore mc in list){
+                               if (!mc.Define (this)){
+                                       remove_list.Add (mc);
+                                       continue;
+                               }
+                                               
+                               if (defined_names == null)
+                                       continue;
+
+                               idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
+                               if (idx < 0){
+                                       if (RootContext.WarningLevel >= 4){
+                                               if ((mc.ModFlags & Modifiers.NEW) != 0)
+                                                       Warning_KewywordNewNotRequired (mc.Location, mc);
+                                       }
+                                       continue;
+                               }
+
+                               MemberInfo match = defined_names [idx];
+
+                               if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
+                                       continue;
+
+                               //
+                               // If we are both methods, let the method resolution emit warnings
+                               //
+                               if (match is MethodBase && mc is MethodCore)
+                                       continue; 
+
+                               if ((mc.ModFlags & Modifiers.NEW) == 0) {
+                                       if (mc is Event) {
+                                               if (!(match is EventInfo)) {
+                                                       Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
+                                                       return;
+                                               }
+
+                                               if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
+                                                       continue;
+                                       }
+
+                                       Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
+                               }
+                       }
+                       
+                       foreach (object o in remove_list)
+                               list.Remove (o);
+                       
+                       remove_list.Clear ();
+               }
+
+               //
+               // Defines the indexers, and also verifies that the IndexerNameAttribute in the
+               // class is consisten.  Either it is `Item' or it is the name defined by all the
+               // indexers with the `IndexerName' attribute.
+               //
+               // Turns out that the IndexerNameAttribute is applied to each indexer,
+               // but it is never emitted, instead a DefaultName attribute is attached
+               // to the class.
+               //
+               void DefineIndexers ()
+               {
+                       string class_indexer_name = null;
+
+                       //
+                       // If there's both an explicit and an implicit interface implementation, the
+                       // explicit one actually implements the interface while the other one is just
+                       // a normal indexer.  See bug #37714.
+                       //
+                       ArrayList list = new ArrayList ();
+                       foreach (Indexer i in Indexers){
+                               if (i.ExplicitInterfaceName != null)
+                                       list.Add (i);
+                       }
+                       foreach (Indexer i in Indexers){
+                               if (i.ExplicitInterfaceName == null)
+                                       list.Add (i);
+                       }
+
+                       foreach (Indexer i in list){
+                               string name;
+
+                               i.Define (this);
+
+                               name = i.IndexerName;
+
+                               if (i.InterfaceType != null)
+                                       continue;
+
+                               if (class_indexer_name == null){
+                                       class_indexer_name = name;
+                                       continue;
+                               }
+                               
+                               if (name == class_indexer_name)
+                                       continue;
+                               
+                               Report.Error (
+                                       668, "Two indexers have different names, " +
+                                       " you should use the same name for all your indexers");
+                       }
+                       if (class_indexer_name == null)
+                               class_indexer_name = "Item";
+                       IndexerName = class_indexer_name;
+               }
+
+               static void Error_KeywordNotAllowed (Location loc)
+               {
+                       Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
+               }
+
+               /// <summary>
+               ///   Populates our TypeBuilder with fields and methods
+               /// </summary>
+               public override bool DefineMembers (TypeContainer container)
+               {
+                       MemberInfo [] defined_names = null;
+
+                       if (interface_order != null){
+                               foreach (Interface iface in interface_order)
+                                       if ((iface.ModFlags & Modifiers.NEW) == 0)
+                                               iface.DefineMembers (this);
+                                       else
+                                               Error_KeywordNotAllowed (iface.Location);
+                       }
+
+                       if (RootContext.WarningLevel > 1){
+                               Type ptype;
+
+                               //
+                               // This code throws an exception in the comparer
+                               // I guess the string is not an object?
+                               //
+                               ptype = TypeBuilder.BaseType;
+                               if (ptype != null){
+                                       defined_names = (MemberInfo []) FindMembers (
+                                               ptype, MemberTypes.All & ~MemberTypes.Constructor,
+                                               BindingFlags.Public | BindingFlags.Instance |
+                                               BindingFlags.Static, null, null);
+
+                                       Array.Sort (defined_names, mif_compare);
+                               }
+                       }
+
+                       Class pclass = Parent as Class;
+                       if (pclass != null) {
+                               string pname = null;
+                               Type ptype = null;
+                               Type t = pclass.TypeBuilder.BaseType;
+                               while ((t != null) && (ptype == null)) {
+                                       pname = MakeFQN (t.Name, Basename);
+                                       ptype = RootContext.LookupType (this, pname, true, Location.Null);
+                                       t = t.BaseType;
+                               }
+
+                               if ((ModFlags & Modifiers.NEW) != 0) {
+                                       if (ptype == null)
+                                               Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
+                                                               "inherited member. The keyword new is not required.");
+                               } else if (ptype != null) {
+                                       Report.Warning (108, Location, "The keyword new is required on `" +
+                                                       Name + "' because it hides inherited member '" +
+                                                       pname + "'.");
+                               }
+                       } else if ((ModFlags & Modifiers.NEW) != 0)
+                               Error_KeywordNotAllowed (Location);
+
+                       if (constants != null)
+                               DefineMembers (constants, defined_names);
+
+                       if (fields != null)
+                               DefineMembers (fields, defined_names);
+
+                       if (this is Class){
+                               if (instance_constructors == null){
+                                       if (default_constructor == null)
+                                               DefineDefaultConstructor (false);
+                               }
+
+                               if (initialized_static_fields != null &&
+                                   default_static_constructor == null)
+                                       DefineDefaultConstructor (true);
+                       }
+
+                       if (this is Struct){
+                               //
+                               // Structs can not have initialized instance
+                               // fields
+                               //
+                               if (initialized_static_fields != null &&
+                                   default_static_constructor == null)
+                                       DefineDefaultConstructor (true);
+
+                               if (initialized_fields != null)
+                                       ReportStructInitializedInstanceError ();
+                       }
+
+                       Pending = PendingImplementation.GetPendingImplementations (this);
+                       
+                       //
+                       // Constructors are not in the defined_names array
+                       //
+                       if (instance_constructors != null)
+                               DefineMembers (instance_constructors, null);
+               
+                       if (default_static_constructor != null)
+                               default_static_constructor.Define (this);
+                       
+                       if (methods != null)
+                               DefineMembers (methods, defined_names);
+
+                       if (properties != null)
+                               DefineMembers (properties, defined_names);
+
+                       if (events != null)
+                               DefineMembers (events, defined_names);
+
+                       if (indexers != null) {
+                               DefineIndexers ();
+                       } else
+                               IndexerName = "Item";
+
+                       if (operators != null){
+                               DefineMembers (operators, null);
+
+                               CheckPairedOperators ();
+                       }
+
+                       if (enums != null)
+                               DefineMembers (enums, defined_names);
+                       
+                       if (delegates != null)
+                               DefineMembers (delegates, defined_names);
+
+#if CACHE
+                       if (TypeBuilder.BaseType != null)
+                               parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
+
+                       member_cache = new MemberCache (this);
+#endif
+
+                       
+                       return true;
+               }
+
+               public override bool Define (TypeContainer container)
+               {
+                       if (interface_order != null){
+                               foreach (Interface iface in interface_order)
+                                       if ((iface.ModFlags & Modifiers.NEW) == 0)
+                                               iface.Define (this);
+                       }
+
+                       return true;
+               }
+
+               /// <summary>
+               ///   This function is based by a delegate to the FindMembers routine
+               /// </summary>
+               static bool AlwaysAccept (MemberInfo m, object filterCriteria)
+               {
+                       return true;
+               }
+
+               /// <summary>
+               ///   This filter is used by FindMembers, and we just keep
+               ///   a global for the filter to `AlwaysAccept'
+               /// </summary>
+               static MemberFilter accepting_filter;
+
+               
+               /// <summary>
+               ///   A member comparission method based on name only
+               /// </summary>
+               static IComparer mif_compare;
+
+               static TypeContainer ()
+               {
+                       accepting_filter = new MemberFilter (AlwaysAccept);
+                       mif_compare = new MemberInfoCompare ();
+               }
+               
+               /// <summary>
+               ///   This method returns the members of this type just like Type.FindMembers would
+               ///   Only, we need to use this for types which are _being_ defined because MS' 
+               ///   implementation can't take care of that.
+               /// </summary>
+               //
+               // FIXME: return an empty static array instead of null, that cleans up
+               // some code and is consistent with some coding conventions I just found
+               // out existed ;-)
+               //
+               //
+               // Notice that in various cases we check if our field is non-null,
+               // something that would normally mean that there was a bug elsewhere.
+               //
+               // The problem happens while we are defining p-invoke methods, as those
+               // will trigger a FindMembers, but this happens before things are defined
+               //
+               // Since the whole process is a no-op, it is fine to check for null here.
+               //
+               public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                                       MemberFilter filter, object criteria)
+               {
+                       ArrayList members = new ArrayList ();
+
+                       int modflags = 0;
+                       if ((bf & BindingFlags.Public) != 0)
+                               modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
+                                       Modifiers.INTERNAL;
+                       if ((bf & BindingFlags.NonPublic) != 0)
+                               modflags |= Modifiers.PRIVATE;
+
+                       int static_mask = 0, static_flags = 0;
+                       switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
+                       case BindingFlags.Static:
+                               static_mask = static_flags = Modifiers.STATIC;
+                               break;
+
+                       case BindingFlags.Instance:
+                               static_mask = Modifiers.STATIC;
+                               static_flags = 0;
+                               break;
+
+                       default:
+                               static_mask = static_flags = 0;
+                               break;
+                       }
+
+                       Timer.StartTimer (TimerType.TcFindMembers);
+
+                       if (filter == null)
+                               filter = accepting_filter; 
+
+                       if ((mt & MemberTypes.Field) != 0) {
+                               if (fields != null) {
+                                       foreach (Field f in fields) {
+                                               if ((f.ModFlags & modflags) == 0)
+                                                       continue;
+                                               if ((f.ModFlags & static_mask) != static_flags)
+                                                       continue;
+
+                                               FieldBuilder fb = f.FieldBuilder;
+                                               if (fb != null && filter (fb, criteria) == true)
+                                                       members.Add (fb);
+                                       }
+                               }
+
+                               if (constants != null) {
+                                       foreach (Const con in constants) {
+                                               if ((con.ModFlags & modflags) == 0)
+                                                       continue;
+                                               if ((con.ModFlags & static_mask) != static_flags)
+                                                       continue;
+
+                                               FieldBuilder fb = con.FieldBuilder;
+                                               if (fb != null && filter (fb, criteria) == true)
+                                                       members.Add (fb);
+                                       }
+                               }
+                       }
+
+                       if ((mt & MemberTypes.Method) != 0) {
+                               if (methods != null) {
+                                       foreach (Method m in methods) {
+                                               if ((m.ModFlags & modflags) == 0)
+                                                       continue;
+                                               if ((m.ModFlags & static_mask) != static_flags)
+                                                       continue;
+                                               
+                                               MethodBuilder mb = m.MethodBuilder;
+
+                                               if (mb != null && filter (mb, criteria) == true)
+                                                       members.Add (mb);
+                                       }
+                               }
+
+                               if (operators != null){
+                                       foreach (Operator o in operators) {
+                                               if ((o.ModFlags & modflags) == 0)
+                                                       continue;
+                                               if ((o.ModFlags & static_mask) != static_flags)
+                                                       continue;
+                                               
+                                               MethodBuilder ob = o.OperatorMethodBuilder;
+                                               if (ob != null && filter (ob, criteria) == true)
+                                                       members.Add (ob);
+                                       }
+                               }
+
+                               if (properties != null){
+                                       foreach (Property p in properties){
+                                               if ((p.ModFlags & modflags) == 0)
+                                                       continue;
+                                               if ((p.ModFlags & static_mask) != static_flags)
+                                                       continue;
+                                               
+                                               MethodBuilder b;
+
+                                               b = p.GetBuilder;
+                                               if (b != null && filter (b, criteria) == true)
+                                                       members.Add (b);
+
+                                               b = p.SetBuilder;
+                                               if (b != null && filter (b, criteria) == true)
+                                                       members.Add (b);
+                                       }
+                               }
+                               
+                               if (indexers != null){
+                                       foreach (Indexer ix in indexers){
+                                               if ((ix.ModFlags & modflags) == 0)
+                                                       continue;
+                                               if ((ix.ModFlags & static_mask) != static_flags)
+                                                       continue;
+                                               
+                                               MethodBuilder b;
+
+                                               b = ix.GetBuilder;
+                                               if (b != null && filter (b, criteria) == true)
+                                                       members.Add (b);
+
+                                               b = ix.SetBuilder;
+                                               if (b != null && filter (b, criteria) == true)
+                                                       members.Add (b);
+                                       }
+                               }
+                       }
+
+                       if ((mt & MemberTypes.Event) != 0) {
+                               if (events != null)
+                                       foreach (Event e in events) {
+                                               if ((e.ModFlags & modflags) == 0)
+                                                       continue;
+                                               if ((e.ModFlags & static_mask) != static_flags)
+                                                       continue;
+
+                                               MemberInfo eb = e.EventBuilder;
+                                               if (eb != null && filter (eb, criteria) == true)
+                                                       members.Add (e.EventBuilder);
+                                       }
+                       }
+                       
+                       if ((mt & MemberTypes.Property) != 0){
+                               if (properties != null)
+                                       foreach (Property p in properties) {
+                                               if ((p.ModFlags & modflags) == 0)
+                                                       continue;
+                                               if ((p.ModFlags & static_mask) != static_flags)
+                                                       continue;
+
+                                               MemberInfo pb = p.PropertyBuilder;
+                                               if (pb != null && filter (pb, criteria) == true) {
+                                                       members.Add (p.PropertyBuilder);
+                                               }
+                                       }
+
+                               if (indexers != null)
+                                       foreach (Indexer ix in indexers) {
+                                               if ((ix.ModFlags & modflags) == 0)
+                                                       continue;
+                                               if ((ix.ModFlags & static_mask) != static_flags)
+                                                       continue;
+
+                                               MemberInfo ib = ix.PropertyBuilder;
+                                               if (ib != null && filter (ib, criteria) == true) {
+                                                       members.Add (ix.PropertyBuilder);
+                                               }
+                                       }
+                       }
+                       
+                       if ((mt & MemberTypes.NestedType) != 0) {
+                               if (types != null){
+                                       foreach (TypeContainer t in types) {
+                                               if ((t.ModFlags & modflags) == 0)
+                                                       continue;
+
+                                               TypeBuilder tb = t.TypeBuilder;
+                                               if (tb != null && (filter (tb, criteria) == true))
+                                                               members.Add (tb);
+                                       }
+                               }
+
+                               if (enums != null){
+                                       foreach (Enum en in enums){
+                                               if ((en.ModFlags & modflags) == 0)
+                                                       continue;
+
+                                               TypeBuilder tb = en.TypeBuilder;
+                                               if (tb != null && (filter (tb, criteria) == true))
+                                                       members.Add (tb);
+                                       }
+                               }
+                               
+                               if (delegates != null){
+                                       foreach (Delegate d in delegates){
+                                               if ((d.ModFlags & modflags) == 0)
+                                                       continue;
+
+                                               TypeBuilder tb = d.TypeBuilder;
+                                               if (tb != null && (filter (tb, criteria) == true))
+                                                       members.Add (tb);
+                                       }
+                               }
+
+                               if (interfaces != null){
+                                       foreach (Interface iface in interfaces){
+                                               if ((iface.ModFlags & modflags) == 0)
+                                                       continue;
+
+                                               TypeBuilder tb = iface.TypeBuilder;
+                                               if (tb != null && (filter (tb, criteria) == true))
+                                                       members.Add (tb);
+                                       }
+                               }
+                       }
+
+                       if ((mt & MemberTypes.Constructor) != 0){
+                               if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
+                                       foreach (Constructor c in instance_constructors){
+                                               ConstructorBuilder cb = c.ConstructorBuilder;
+                                               if (cb != null)
+                                                       if (filter (cb, criteria) == true)
+                                                               members.Add (cb);
+                                       }
+                               }
+
+                               if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
+                                       ConstructorBuilder cb =
+                                               default_static_constructor.ConstructorBuilder;
+                                       
+                                       if (cb != null)
+                                       if (filter (cb, criteria) == true)
+                                               members.Add (cb);
+                               }
+                       }
+
+                       //
+                       // Lookup members in parent if requested.
+                       //
+                       if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
+                               MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
+                               members.AddRange (list);
+                       }
+
+                       Timer.StopTimer (TimerType.TcFindMembers);
+
+                       return new MemberList (members);
+               }
+
+               public override MemberCache MemberCache {
+                       get {
+                               return member_cache;
+                       }
+               }
+
+               public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+                                                     MemberFilter filter, object criteria)
+               {
+                       DeclSpace ds = TypeManager.LookupDeclSpace (t);
+
+                       if (ds != null)
+                               return ds.FindMembers (mt, bf, filter, criteria);
+                       else
+                               return new MemberList (t.FindMembers (mt, bf, filter, criteria));
+               }
+
+               //
+               // FindMethods will look for methods not only in the type `t', but in
+               // any interfaces implemented by the type.
+               //
+               public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
+                                                        MemberFilter filter, object criteria)
+               {
+                       return null;
+               }
+
+               /// <summary>
+               ///   Emits the values for the constants
+               /// </summary>
+               public void EmitConstants ()
+               {
+                       if (constants != null)
+                               foreach (Const con in constants)
+                                       con.EmitConstant (this);
+                       return;
+               }
+
+               /// <summary>
+               ///   Emits the code, this step is performed after all
+               ///   the types, enumerations, constructors
+               /// </summary>
+               public void Emit ()
+               {
+                       if (instance_constructors != null)
+                               foreach (Constructor c in instance_constructors)
+                                       c.Emit (this);
+
+                       if (default_static_constructor != null)
+                               default_static_constructor.Emit (this);
+                       
+                       if (methods != null)
+                               foreach (Method m in methods)
+                                       m.Emit (this);
+
+                       if (operators != null)
+                               foreach (Operator o in operators)
+                                       o.Emit (this);
+
+                       if (properties != null)
+                               foreach (Property p in properties)
+                                       p.Emit (this);
+
+                       if (indexers != null){
+                               foreach (Indexer ix in indexers)
+                                       ix.Emit (this);
+                               
+                               CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
+                                       this, IndexerName, ModFlags, Location);
+                               TypeBuilder.SetCustomAttribute (cb);
+                       }
+                       
+                       if (fields != null)
+                               foreach (Field f in fields)
+                                       f.Emit (this);
+
+                       if (events != null){
+                               foreach (Event e in Events)
+                                       e.Emit (this);
+                       }
+
+                       if (Pending != null)
+                               if (Pending.VerifyPendingMethods ())
+                                       return;
+                       
+                       Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
+
+                       //
+                       // Check for internal or private fields that were never assigned
+                       //
+                       if (RootContext.WarningLevel >= 3) {
+                               if (fields != null){
+                                       foreach (Field f in fields) {
+                                               if ((f.ModFlags & Modifiers.PUBLIC) != 0)
+                                                       continue;
+                                               
+                                               if (f.status == 0){
+                                                       Report.Warning (
+                                                               169, f.Location, "Private field " +
+                                                               MakeName (f.Name) + " is never used");
+                                                       continue;
+                                               }
+                                               
+                                               //
+                                               // Only report 649 on level 4
+                                               //
+                                               if (RootContext.WarningLevel < 4)
+                                                       continue;
+                                               
+                                               if ((f.status & Field.Status.ASSIGNED) != 0)
+                                                       continue;
+                                               
+                                               Report.Warning (
+                                                       649, f.Location,
+                                                       "Field " + MakeName (f.Name) + " is never assigned " +
+                                                       " to and will always have its default value");
+                                       }
+                               }
+
+                               if (events != null){
+                                       foreach (Event e in events){
+                                               if (e.status == 0)
+                                                       Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
+                                       }
+                               }
+                       }
+                       
+//                     if (types != null)
+//                             foreach (TypeContainer tc in types)
+//                                     tc.Emit ();
+               }
+               
+               public override void CloseType ()
+               {
+                       try {
+                               if (!Created){
+                                       Created = true;
+                                       TypeBuilder.CreateType ();
+                               }
+                       } catch (TypeLoadException){
+                               //
+                               // This is fine, the code still created the type
+                               //
+//                             Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
+//                             Console.WriteLine (e.Message);
+                       } catch {
+                               Console.WriteLine ("In type: " + Name);
+                               throw;
+                       }
+                       
+                       if (Enums != null)
+                               foreach (Enum en in Enums)
+                                       en.CloseType ();
+
+                       if (interface_order != null){
+                               foreach (Interface iface in interface_order)
+                                       iface.CloseType ();
+                       }
+                       
+                       if (Types != null){
+                               foreach (TypeContainer tc in Types)
+                                       if (tc is Struct)
+                                               tc.CloseType ();
+
+                               foreach (TypeContainer tc in Types)
+                                       if (!(tc is Struct))
+                                               tc.CloseType ();
+                       }
+
+                       if (Delegates != null)
+                               foreach (Delegate d in Delegates)
+                                       d.CloseType ();
+               }
+
+               public string MakeName (string n)
+               {
+                       return "`" + Name + "." + n + "'";
+               }
+
+               public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
+               {
+                       Report.Warning (
+                               108, l, "The keyword new is required on " + 
+                               MakeName (mi.Name) + " because it hides `" +
+                               mi.ReflectedType.Name + "." + mi.Name + "'");
+               }
+
+               public void Warning_KewywordNewNotRequired (Location l, MemberCore mc)
+               {
+                       Report.Warning (
+                               109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
+                               "inherited member, the keyword new is not required");
+               }
+
+               public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
+               {
+                       Report.Error (
+                               72, l, MakeName (mi.Name) + " : cannot override; `" +
+                               mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
+               }
+               
+               public static int CheckMember (string name, MemberInfo mi, int ModFlags)
+               {
+                       return 0;
+               }
+
+               //
+               // Performs the validation on a Method's modifiers (properties have
+               // the same properties).
+               //
+               public bool MethodModifiersValid (int flags, string n, Location loc)
+               {
+                       const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
+                       const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
+                       const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
+                       bool ok = true;
+                       
+                       //
+                       // At most one of static, virtual or override
+                       //
+                       if ((flags & Modifiers.STATIC) != 0){
+                               if ((flags & vao) != 0){
+                                       Report.Error (
+                                               112, loc, "static method " + MakeName (n) + "can not be marked " +
+                                               "as virtual, abstract or override");
+                                       ok = false;
+                               }
+                       }
+
+                       if (this is Struct){
+                               if ((flags & va) != 0){
+                                       Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
+                                       ok = false;
+                               }
+                       }
+
+                       if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
+                               Report.Error (
+                                       113, loc, MakeName (n) +
+                                       " marked as override cannot be marked as new or virtual");
+                               ok = false;
+                       }
+
+                       //
+                       // If the declaration includes the abstract modifier, then the
+                       // declaration does not include static, virtual or extern
+                       //
+                       if ((flags & Modifiers.ABSTRACT) != 0){
+                               if ((flags & Modifiers.EXTERN) != 0){
+                                       Report.Error (
+                                               180, loc, MakeName (n) + " can not be both abstract and extern");
+                                       ok = false;
+                               }
+
+                               if ((flags & Modifiers.VIRTUAL) != 0){
+                                       Report.Error (
+                                               503, loc, MakeName (n) + " can not be both abstract and virtual");
+                                       ok = false;
+                               }
+
+                               if ((ModFlags & Modifiers.ABSTRACT) == 0){
+                                       Report.Error (
+                                               513, loc, MakeName (n) +
+                                               " is abstract but its container class is not");
+                                       ok = false;
+
+                               }
+                       }
+
+                       if ((flags & Modifiers.PRIVATE) != 0){
+                               if ((flags & vao) != 0){
+                                       Report.Error (
+                                               621, loc, MakeName (n) +
+                                               " virtual or abstract members can not be private");
+                                       ok = false;
+                               }
+                       }
+
+                       if ((flags & Modifiers.SEALED) != 0){
+                               if ((flags & Modifiers.OVERRIDE) == 0){
+                                       Report.Error (
+                                               238, loc, MakeName (n) +
+                                               " cannot be sealed because it is not an override");
+                                       ok = false;
+                               }
+                       }
+
+                       return ok;
+               }
+
+               // Access level of a type.
+               enum AccessLevel {
+                       Public                  = 0,
+                       ProtectedInternal       = 1,
+                       Internal                = 2,
+                       Protected               = 3,
+                       Private                 = 4
+               }
+
+               // Check whether `flags' denotes a more restricted access than `level'
+               // and return the new level.
+               static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
+               {
+                       AccessLevel old_level = level;
+
+                       if ((flags & Modifiers.INTERNAL) != 0) {
+                               if ((flags & Modifiers.PROTECTED) != 0) {
+                                       if ((int) level < (int) AccessLevel.ProtectedInternal)
+                                               level = AccessLevel.ProtectedInternal;
+                               } else {
+                                       if ((int) level < (int) AccessLevel.Internal)
+                                               level = AccessLevel.Internal;
+                               }
+                       } else if ((flags & Modifiers.PROTECTED) != 0) {
+                               if ((int) level < (int) AccessLevel.Protected)
+                                       level = AccessLevel.Protected;
+                       } else if ((flags & Modifiers.PRIVATE) != 0)
+                               level = AccessLevel.Private;
+
+                       return level;
+               }
+
+               // Return the access level for a new member which is defined in the current
+               // TypeContainer with access modifiers `flags'.
+               AccessLevel GetAccessLevel (int flags)
+               {
+                       if ((flags & Modifiers.PRIVATE) != 0)
+                               return AccessLevel.Private;
+
+                       AccessLevel level;
+                       if (!IsTopLevel && (Parent != null))
+                               level = Parent.GetAccessLevel (flags);
+                       else
+                               level = AccessLevel.Public;
+
+                       return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
+               }
+
+               // Return the access level for type `t', but don't give more access than `flags'.
+               static AccessLevel GetAccessLevel (Type t, int flags)
+               {
+                       if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
+                               return AccessLevel.Private;
+
+                       AccessLevel level;
+                       if (TypeManager.IsBuiltinType (t))
+                               return AccessLevel.Public;
+                       else if ((t.DeclaringType != null) && (t != t.DeclaringType))
+                               level = GetAccessLevel (t.DeclaringType, flags);
+                       else {
+                               level = CheckAccessLevel (AccessLevel.Public, flags);
+                       }
+
+                       if (t.IsNestedPublic)
+                               return level;
+
+                       if (t.IsNestedAssembly || t.IsNotPublic) {
+                               if ((int) level < (int) AccessLevel.Internal)
+                                       level = AccessLevel.Internal;
+                       }
+
+                       if (t.IsNestedFamily) {
+                               if ((int) level < (int) AccessLevel.Protected)
+                                       level = AccessLevel.Protected;
+                       }
+
+                       if (t.IsNestedFamORAssem) {
+                               if ((int) level < (int) AccessLevel.ProtectedInternal)
+                                       level = AccessLevel.ProtectedInternal;
+                       }
+
+                       return level;
+               }
+
+               //
+               // Returns true if `parent' is as accessible as the flags `flags'
+               // given for this member.
+               //
+               public bool AsAccessible (Type parent, int flags)
+               {
+                       while (parent.IsArray || parent.IsPointer || parent.IsByRef)
+                               parent = TypeManager.GetElementType (parent);
+
+                       AccessLevel level = GetAccessLevel (flags);
+                       AccessLevel level2 = GetAccessLevel (parent, flags);
+
+                       return (int) level >= (int) level2;
+               }
+
+               Hashtable builder_and_args;
+               
+               public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
+               {
+                       if (builder_and_args == null)
+                               builder_and_args = new Hashtable ();
+                       return true;
+               }
+
+               /// <summary>
+               ///   Performs checks for an explicit interface implementation.  First it
+               ///   checks whether the `interface_type' is a base inteface implementation.
+               ///   Then it checks whether `name' exists in the interface type.
+               /// </summary>
+               public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
+               {
+                       bool found = false;
+
+                       if (ifaces != null){
+                               foreach (Type t in ifaces){
+                                       if (t == interface_type){
+                                               found = true;
+                                               break;
+                                       }
+                               }
+                       }
+                       
+                       if (!found){
+                               Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
+               {
+                       Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
+               }
+
+               //
+               // IMemberContainer
+               //
+
+               string IMemberContainer.Name {
+                       get {
+                               return Name;
+                       }
+               }
+
+               Type IMemberContainer.Type {
+                       get {
+                               return TypeBuilder;
+                       }
+               }
+
+               IMemberContainer IMemberContainer.Parent {
+                       get {
+                               return parent_container;
+                       }
+               }
+
+               MemberCache IMemberContainer.MemberCache {
+                       get {
+                               return member_cache;
+                       }
+               }
+
+               bool IMemberContainer.IsInterface {
+                       get {
+                               return false;
+                       }
+               }
+
+               MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
+               {
+                       return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
+               }
+
+               //
+               // Operator pair checking
+               //
+
+               class OperatorEntry {
+                       public int flags;
+                       public Type ret_type;
+                       public Type type1, type2;
+                       public Operator op;
+                       public Operator.OpType ot;
+                       
+                       public OperatorEntry (int f, Operator o)
+                       {
+                               flags = f;
+
+                               ret_type = o.OperatorMethod.GetReturnType ();
+                               Type [] pt = o.OperatorMethod.ParameterTypes;
+                               type1 = pt [0];
+                               type2 = pt [1];
+                               op = o;
+                               ot = o.OperatorType;
+                       }
+
+                       public override int GetHashCode ()
+                       {       
+                               return ret_type.GetHashCode ();
+                       }
+
+                       public override bool Equals (object o)
+                       {
+                               OperatorEntry other = (OperatorEntry) o;
+
+                               if (other.ret_type != ret_type)
+                                       return false;
+                               if (other.type1 != type1)
+                                       return false;
+                               if (other.type2 != type2)
+                                       return false;
+                               return true;
+                       }
+               }
+                               
+               //
+               // Checks that some operators come in pairs:
+               //  == and !=
+               // > and <
+               // >= and <=
+               // true and false
+               //
+               // They are matched based on the return type and the argument types
+               //
+               void CheckPairedOperators ()
+               {
+                       Hashtable pairs = new Hashtable (null, null);
+                       Operator true_op = null;
+                       Operator false_op = null;
+                       bool has_equality_or_inequality = false;
+                       
+                       // Register all the operators we care about.
+                       foreach (Operator op in operators){
+                               int reg = 0;
+                               
+                               switch (op.OperatorType){
+                               case Operator.OpType.Equality:
+                                       reg = 1;
+                                       has_equality_or_inequality = true;
+                                       break;
+                               case Operator.OpType.Inequality:
+                                       reg = 2;
+                                       has_equality_or_inequality = true;
+                                       break;
+
+                               case Operator.OpType.True:
+                                       true_op = op;
+                                       break;
+                               case Operator.OpType.False:
+                                       false_op = op;
+                                       break;
+                                       
+                               case Operator.OpType.GreaterThan:
+                                       reg = 1; break;
+                               case Operator.OpType.LessThan:
+                                       reg = 2; break;
+                                       
+                               case Operator.OpType.GreaterThanOrEqual:
+                                       reg = 1; break;
+                               case Operator.OpType.LessThanOrEqual:
+                                       reg = 2; break;
+                               }
+                               if (reg == 0)
+                                       continue;
+
+                               OperatorEntry oe = new OperatorEntry (reg, op);
+
+                               object o = pairs [oe];
+                               if (o == null)
+                                       pairs [oe] = oe;
+                               else {
+                                       oe = (OperatorEntry) o;
+                                       oe.flags |= reg;
+                               }
+                       }
+
+                       if (true_op != null){
+                               if (false_op == null)
+                                       Report.Error (216, true_op.Location, "operator true requires a matching operator false");
+                       } else if (false_op != null)
+                               Report.Error (216, false_op.Location, "operator false requires a matching operator true");
+                       
+                       //
+                       // Look for the mistakes.
+                       //
+                       foreach (DictionaryEntry de in pairs){
+                               OperatorEntry oe = (OperatorEntry) de.Key;
+
+                               if (oe.flags == 3)
+                                       continue;
+
+                               string s = "";
+                               switch (oe.ot){
+                               case Operator.OpType.Equality:
+                                       s = "!=";
+                                       break;
+                               case Operator.OpType.Inequality: 
+                                       s = "==";
+                                       break;
+                               case Operator.OpType.GreaterThan: 
+                                       s = "<";
+                                       break;
+                               case Operator.OpType.LessThan:
+                                       s = ">";
+                                       break;
+                               case Operator.OpType.GreaterThanOrEqual:
+                                       s = "<=";
+                                       break;
+                               case Operator.OpType.LessThanOrEqual:
+                                       s = ">=";
+                                       break;
+                               }
+                               Report.Error (216, oe.op.Location,
+                                             "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
+                       }
+
+                       if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
+                               MethodSignature equals_ms = new MethodSignature (
+                                       "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
+                               MethodSignature hash_ms = new MethodSignature (
+                                       "GetHashCode", TypeManager.int32_type, new Type [0]);
+
+                               MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
+                                                                   BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
+                                                                   equals_ms);
+                               MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
+                                                                 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
+                                                                 hash_ms);
+
+                               bool equals_ok = false;
+                               if ((equals_ml != null) && (equals_ml.Count == 1))
+                                       equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
+                               bool hash_ok = false;
+                               if ((hash_ml != null) && (hash_ml.Count == 1))
+                                       hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
+
+                               if (!equals_ok)
+                                       Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
+                                                       "not override Object.Equals (object o)");
+                               if (!hash_ok)
+                                       Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
+                                                       "not override Object.GetHashCode ()");
+                       }
+               }
+               
+               
+       }
+
+       public class Class : TypeContainer {
+               // <summary>
+               //   Modifiers allowed in a class declaration
+               // </summary>
+               public const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.ABSTRACT |
+                       Modifiers.SEALED |
+                       Modifiers.UNSAFE;
+
+               public Class (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
+                       : base (parent, name, l)
+               {
+                       int accmods;
+
+                       if (parent.Parent == null)
+                               accmods = Modifiers.INTERNAL;
+                       else
+                               accmods = Modifiers.PRIVATE;
+
+                       this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
+                       this.attributes = attrs;
+               }
+
+               //
+               // FIXME: How do we deal with the user specifying a different
+               // layout?
+               //
+               public override TypeAttributes TypeAttr {
+                       get {
+                               return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
+                       }
+               }
+       }
+
+       public class Struct : TypeContainer {
+               // <summary>
+               //   Modifiers allowed in a struct declaration
+               // </summary>
+               public const int AllowedModifiers =
+                       Modifiers.NEW       |
+                       Modifiers.PUBLIC    |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL  |
+                       Modifiers.UNSAFE    |
+                       Modifiers.PRIVATE;
+
+               public Struct (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
+                       : base (parent, name, l)
+               {
+                       int accmods;
+                       
+                       if (parent.Parent == null)
+                               accmods = Modifiers.INTERNAL;
+                       else
+                               accmods = Modifiers.PRIVATE;
+                       
+                       this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
+
+                       this.ModFlags |= Modifiers.SEALED;
+                       this.attributes = attrs;
+                       
+               }
+
+               //
+               // FIXME: Allow the user to specify a different set of attributes
+               // in some cases (Sealed for example is mandatory for a class,
+               // but what SequentialLayout can be changed
+               //
+               public override TypeAttributes TypeAttr {
+                       get {
+                               return base.TypeAttr |
+                                       TypeAttributes.SequentialLayout |
+                                       TypeAttributes.Sealed |
+                                       TypeAttributes.BeforeFieldInit;
+                       }
+               }
+       }
+
+       public abstract class MethodCore : MemberBase {
+               public readonly Parameters Parameters;
+               protected Block block;
+               
+               //
+               // Parameters, cached for semantic analysis.
+               //
+               protected InternalParameters parameter_info;
+               protected Type [] parameter_types;
+
+               public MethodCore (Expression type, int mod, int allowed_mod, string name,
+                                  Attributes attrs, Parameters parameters, Location loc)
+                       : base (type, mod, allowed_mod, name, attrs, loc)
+               {
+                       Parameters = parameters;
+               }
+               
+               //
+               //  Returns the System.Type array for the parameters of this method
+               //
+               public Type [] ParameterTypes {
+                       get {
+                               return parameter_types;
+                       }
+               }
+
+               public InternalParameters ParameterInfo
+               {
+                       get {
+                               return parameter_info;
+                       }
+               }
+               
+               public Block Block {
+                       get {
+                               return block;
+                       }
+
+                       set {
+                               block = value;
+                       }
+               }
+
+               protected virtual bool DoDefineParameters (TypeContainer container)
+               {
+                       // Check if arguments were correct
+                       parameter_types = Parameters.GetParameterInfo (container);
+                       if ((parameter_types == null) || !CheckParameters (container, parameter_types))
+                               return false;
+
+                       parameter_info = new InternalParameters (container, Parameters);
+
+                       Parameter array_param = Parameters.ArrayParameter;
+                       if ((array_param != null) &&
+                           (!array_param.ParameterType.IsArray ||
+                            (array_param.ParameterType.GetArrayRank () != 1))) {
+                               Report.Error (225, Location, "params parameter has to be a single dimensional array");
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               public CallingConventions GetCallingConvention (bool is_class)
+               {
+                       CallingConventions cc = 0;
+                       
+                       cc = Parameters.GetCallingConvention ();
+
+                       if (is_class)
+                               if ((ModFlags & Modifiers.STATIC) == 0)
+                                       cc |= CallingConventions.HasThis;
+
+                       // FIXME: How is `ExplicitThis' used in C#?
+                       
+                       return cc;
+               }
+
+               //
+               // The method's attributes are passed in because we need to extract
+               // the "return:" attribute from there to apply on the return type
+               //
+               public void LabelParameters (EmitContext ec, MethodBase builder, Attributes method_attrs)
+               {
+                       //
+                       // Define each type attribute (in/out/ref) and
+                       // the argument names.
+                       //
+                       Parameter [] p = Parameters.FixedParameters;
+                       int i = 0;
+                       
+                       MethodBuilder mb = null;
+                       ConstructorBuilder cb = null;
+
+                       if (builder is MethodBuilder)
+                               mb = (MethodBuilder) builder;
+                       else
+                               cb = (ConstructorBuilder) builder;
+
+                       if (p != null){
+                               for (i = 0; i < p.Length; i++) {
+                                       ParameterBuilder pb;
+                                       ParameterAttributes par_attr = p [i].Attributes;
+                                       
+                                       if (mb == null)
+                                               pb = cb.DefineParameter (
+                                                       i + 1, par_attr, p [i].Name);
+                                       else 
+                                               pb = mb.DefineParameter (
+                                                       i + 1, par_attr, p [i].Name);
+                                       
+                                       Attributes attr = p [i].OptAttributes;
+                                       if (attr != null){
+                                               Attribute.ApplyAttributes (ec, pb, pb, attr);
+
+                                               if (par_attr == ParameterAttributes.Out){
+                                                       if (attr.Contains (TypeManager.in_attribute_type))
+                                                               Report.Error (36, Location, "Can not use [In] attribute on out parameter");
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (Parameters.ArrayParameter != null){
+                               ParameterBuilder pb;
+                               Parameter array_param = Parameters.ArrayParameter;
+
+                               if (mb == null)
+                                       pb = cb.DefineParameter (
+                                               i + 1, array_param.Attributes,
+                                               array_param.Name);
+                               else
+                                       pb = mb.DefineParameter (
+                                               i + 1, array_param.Attributes,
+                                               array_param.Name);
+                                       
+                               CustomAttributeBuilder a = new CustomAttributeBuilder (
+                                       TypeManager.cons_param_array_attribute, new object [0]);
+                               
+                               pb.SetCustomAttribute (a);
+                       }
+
+                       //
+                       // And now for the return type attribute decoration
+                       //
+                       ParameterBuilder ret_pb;
+                       Attributes ret_attrs = null;
+                               
+                       if (mb == null || method_attrs == null)
+                               return;
+
+                       foreach (AttributeSection asec in method_attrs.AttributeSections) {
+
+                               if (asec.Target != "return")
+                                       continue;
+
+                               if (ret_attrs == null)
+                                       ret_attrs = new Attributes (asec);
+                               else
+                                       ret_attrs.AddAttributeSection (asec);
+                       }
+
+                       if (ret_attrs != null) {
+                               try {
+                                       ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
+                                       Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
+                               } catch (ArgumentOutOfRangeException) {
+                                       Report.Warning (
+                                               -24, Location,
+                                               ".NET SDK 1.0 does not permit to set custom attributes to the return type of a method");
+                               }
+                       }
+               }
+       }
+
+       public class Method : MethodCore, IIteratorContainer {
+               public MethodBuilder MethodBuilder;
+               public MethodData MethodData;
+
+               /// <summary>
+               ///   Modifiers allowed in a class declaration
+               /// </summary>
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.STATIC |
+                       Modifiers.VIRTUAL |
+                       Modifiers.SEALED |
+                       Modifiers.OVERRIDE |
+                       Modifiers.ABSTRACT |
+                       Modifiers.UNSAFE |
+                       Modifiers.EXTERN;
+
+               //
+               // return_type can be "null" for VOID values.
+               //
+               public Method (Expression return_type, int mod, string name, Parameters parameters,
+                              Attributes attrs, Location l)
+                       : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
+               { }
+
+               //
+               // Returns the `System.Type' for the ReturnType of this
+               // function.  Provides a nice cache.  (used between semantic analysis
+               // and actual code generation
+               //
+               public Type GetReturnType ()
+               {
+                       return MemberType;
+               }
+
+               // Whether this is an operator method.
+               public bool IsOperator;
+
+                void DuplicateEntryPoint (MethodInfo b, Location location)
+                {
+                        Report.Error (
+                                17, location,
+                                "Program `" + CodeGen.FileName +
+                                "'  has more than one entry point defined: `" +
+                                TypeManager.CSharpSignature(b) + "'");
+                }
+
+                void Report28 (MethodInfo b)
+                {
+                        Report.Warning (
+                                28, Location,
+                                "`" + TypeManager.CSharpSignature(b) +
+                                "' has the wrong signature to be an entry point");
+                }
+
+                public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
+                {
+                        if (b.ReturnType != TypeManager.void_type &&
+                            b.ReturnType != TypeManager.int32_type)
+                                return false;
+
+                        if (pinfo.Count == 0)
+                                return true;
+
+                        if (pinfo.Count > 1)
+                                return false;
+
+                        Type t = pinfo.ParameterType(0);
+                        if (t.IsArray &&
+                            (t.GetArrayRank() == 1) &&
+                            (TypeManager.GetElementType(t) == TypeManager.string_type) &&
+                            (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
+                                return true;
+                        else
+                                return false;
+                }
+
+               //
+               // Checks our base implementation if any
+               //
+               protected override bool CheckBase (TypeContainer container)
+               {
+                       base.CheckBase (container);
+                       
+                       // Check whether arguments were correct.
+                       if (!DoDefineParameters (container))
+                               return false;
+
+                       MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
+                       if (IsOperator) {
+                               flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
+                       } else {
+                               MemberList mi_this;
+
+                               mi_this = TypeContainer.FindMembers (
+                                       container.TypeBuilder, MemberTypes.Method,
+                                       BindingFlags.NonPublic | BindingFlags.Public |
+                                       BindingFlags.Static | BindingFlags.Instance |
+                                       BindingFlags.DeclaredOnly,
+                                       MethodSignature.method_signature_filter, ms);
+
+                               if (mi_this.Count > 0) {
+                                       Report.Error (111, Location, "Class `" + container.Name + "' " +
+                                                     "already defines a member called `" + Name + "' " +
+                                                     "with the same parameter types");
+                                       return false;
+                               }
+                       } 
+
+                       //
+                       // Verify if the parent has a type with the same name, and then
+                       // check whether we have to create a new slot for it or not.
+                       //
+                       Type ptype = container.TypeBuilder.BaseType;
+
+                       // ptype is only null for System.Object while compiling corlib.
+                       if (ptype != null){
+                               MemberList mi, mi_static, mi_instance;
+
+                               mi_instance = TypeContainer.FindMembers (
+                                       ptype, MemberTypes.Method,
+                                       BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
+                                       MethodSignature.inheritable_method_signature_filter,
+                                       ms);
+
+                               if (mi_instance.Count > 0){
+                                       mi = mi_instance;
+                               } else {
+                                       mi_static = TypeContainer.FindMembers (
+                                               ptype, MemberTypes.Method,
+                                               BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
+                                               MethodSignature.inheritable_method_signature_filter, ms);
+
+                                       if (mi_static.Count > 0)
+                                               mi = mi_static;
+                                       else
+                                               mi = null;
+                               }
+
+                               if (mi != null && mi.Count > 0){
+                                       parent_method = (MethodInfo) mi [0];
+                                       string name = parent_method.DeclaringType.Name + "." +
+                                               parent_method.Name;
+
+                                       if (!CheckMethodAgainstBase (container, flags, parent_method, name))
+                                               return false;
+
+                                       if ((ModFlags & Modifiers.NEW) == 0) {
+                                               Type parent_ret = TypeManager.TypeToCoreType (
+                                                       parent_method.ReturnType);
+
+                                               if (parent_ret != MemberType) {
+                                                       Report.Error (
+                                                               508, Location, container.MakeName (Name) + ": cannot " +
+                                                               "change return type when overriding " +
+                                                               "inherited member " + name);
+                                                       return false;
+                                               }
+                                       }
+                               } else {
+                                       if ((ModFlags & Modifiers.NEW) != 0)
+                                               WarningNotHiding (container);
+
+                                       if ((ModFlags & Modifiers.OVERRIDE) != 0){
+                                               Report.Error (115, Location,
+                                                             container.MakeName (Name) +
+                                                             " no suitable methods found to override");
+                                       }
+                               }
+                       } else if ((ModFlags & Modifiers.NEW) != 0)
+                               WarningNotHiding (container);
+
+                       return true;
+               }
+
+               //
+               // Creates the type
+               //
+               public override bool Define (TypeContainer container)
+               {
+                       if (!DoDefine (container))
+                               return false;
+
+                       if (!CheckBase (container))
+                               return false;
+
+                       CallingConventions cc = GetCallingConvention (container is Class);
+
+                       MethodData = new MethodData (this, null, MemberType, ParameterTypes,
+                                                    ParameterInfo, cc, OptAttributes,
+                                                    ModFlags, flags, true);
+
+                       if (!MethodData.Define (container))
+                               return false;
+
+                       //
+                       // Setup iterator if we are one
+                       //
+                       if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
+                               IteratorHandler ih = new  IteratorHandler (
+                                           Name, container, MemberType,
+                                           ParameterTypes, ParameterInfo,
+                                           ModFlags, Location);
+
+                               Block new_block = ih.Setup (block);
+                               if (new_block == null)
+                                       return false;
+                               block = new_block;
+                       }
+
+                       MethodBuilder = MethodData.MethodBuilder;
+                       
+                       //
+                       // This is used to track the Entry Point,
+                       //
+                       if (Name == "Main" &&
+                           ((ModFlags & Modifiers.STATIC) != 0) && 
+                           (RootContext.MainClass == null ||
+                            RootContext.MainClass == container.TypeBuilder.FullName)){
+                                if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
+                                        if (RootContext.EntryPoint == null) {
+                                                RootContext.EntryPoint = MethodBuilder;
+                                                RootContext.EntryPointLocation = Location;
+                                        } else {
+                                                DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
+                                                DuplicateEntryPoint (MethodBuilder, Location);
+                                        }
+                                } else                                         
+                                               Report28(MethodBuilder);
+                       }
+
+                       return true;
+               }
+
+               //
+               // Emits the code
+               // 
+               public void Emit (TypeContainer container)
+               {
+                       MethodData.Emit (container, Block, this);
+                       Block = null;
+               }
+
+               void IIteratorContainer.SetYields ()
+               {
+                       ModFlags |= Modifiers.METHOD_YIELDS;
+               }
+       }
+
+       public abstract class ConstructorInitializer {
+               ArrayList argument_list;
+               ConstructorInfo parent_constructor;
+               Parameters parameters;
+               Location loc;
+               
+               public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
+                                              Location loc)
+               {
+                       this.argument_list = argument_list;
+                       this.parameters = parameters;
+                       this.loc = loc;
+               }
+
+               public ArrayList Arguments {
+                       get {
+                               return argument_list;
+                       }
+               }
+
+               public bool Resolve (EmitContext ec)
+               {
+                       Expression parent_constructor_group;
+                       Type t;
+
+                       ec.CurrentBlock = new Block (null, Block.Flags.Implicit, parameters);
+
+                       if (argument_list != null){
+                               foreach (Argument a in argument_list){
+                                       if (!a.Resolve (ec, loc))
+                                               return false;
+                               }
+                       }
+                       ec.CurrentBlock = null;
+
+                       if (this is ConstructorBaseInitializer) {
+                               if (ec.ContainerType.BaseType == null)
+                                       return true;
+
+                               t = ec.ContainerType.BaseType;
+                               if (ec.ContainerType.IsValueType) {
+                                       Report.Error (522, loc,
+                                               "structs cannot call base class constructors");
+                                       return false;
+                               }
+                       } else
+                               t = ec.ContainerType;
+
+                       parent_constructor_group = Expression.MemberLookup (
+                               ec, t, null, t, ".ctor", 
+                               MemberTypes.Constructor,
+                               BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
+                               loc);
+                       
+                       if (parent_constructor_group == null){
+                               Report.Error (1501, loc,
+                                      "Can not find a constructor for this argument list");
+                               return false;
+                       }
+                       
+                       parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec, 
+                               (MethodGroupExpr) parent_constructor_group, argument_list, loc);
+                       
+                       if (parent_constructor == null){
+                               Report.Error (1501, loc,
+                                      "Can not find a constructor for this argument list");
+                               return false;
+                       }
+                       
+                       return true;
+               }
+
+               public void Emit (EmitContext ec)
+               {
+                       if (parent_constructor != null){
+                               ec.Mark (loc, false);
+                               if (ec.IsStatic)
+                                       Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
+                               else
+                                       Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
+                       }
+               }
+       }
+
+       public class ConstructorBaseInitializer : ConstructorInitializer {
+               public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
+                       base (argument_list, pars, l)
+               {
+               }
+       }
+
+       public class ConstructorThisInitializer : ConstructorInitializer {
+               public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
+                       base (argument_list, pars, l)
+               {
+               }
+       }
+       
+       public class Constructor : MethodCore {
+               public ConstructorBuilder ConstructorBuilder;
+               public ConstructorInitializer Initializer;
+               new public Attributes OptAttributes;
+
+               // <summary>
+               //   Modifiers allowed for a constructor.
+               // </summary>
+               public const int AllowedModifiers =
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.STATIC |
+                       Modifiers.UNSAFE |
+                       Modifiers.EXTERN |              
+                       Modifiers.PRIVATE;
+
+               //
+               // The spec claims that static is not permitted, but
+               // my very own code has static constructors.
+               //
+               public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
+                       : base (null, 0, AllowedModifiers, name, null, args, l)
+               {
+                       Initializer = init;
+               }
+
+               //
+               // Returns true if this is a default constructor
+               //
+               public bool IsDefault ()
+               {
+                       if ((ModFlags & Modifiers.STATIC) != 0)
+                               return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
+                                       (Parameters.ArrayParameter == null ? true : Parameters.Empty);
+                       
+                       else
+                               return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
+                                       (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
+                                       (Initializer is ConstructorBaseInitializer) &&
+                                       (Initializer.Arguments == null);
+               }
+
+               //
+               // Creates the ConstructorBuilder
+               //
+               public override bool Define (TypeContainer container)
+               {
+                       MethodAttributes ca = (MethodAttributes.RTSpecialName |
+                                              MethodAttributes.SpecialName);
+
+                       // Check if arguments were correct.
+                       if (!DoDefineParameters (container))
+                               return false;
+
+                       if ((ModFlags & Modifiers.STATIC) != 0){
+                               ca |= MethodAttributes.Static | MethodAttributes.Private;
+                       } else {
+                               if (container is Struct && ParameterTypes.Length == 0){
+                                       Report.Error (
+                                               568, Location, 
+                                               "Structs can not contain explicit parameterless " +
+                                               "constructors");
+                                       return false;
+                               }
+                               ca |= MethodAttributes.HideBySig;
+
+                               if ((ModFlags & Modifiers.PUBLIC) != 0)
+                                       ca |= MethodAttributes.Public;
+                               else if ((ModFlags & Modifiers.PROTECTED) != 0){
+                                       if ((ModFlags & Modifiers.INTERNAL) != 0)
+                                               ca |= MethodAttributes.FamORAssem;
+                                       else 
+                                               ca |= MethodAttributes.Family;
+                               } else if ((ModFlags & Modifiers.INTERNAL) != 0)
+                                       ca |= MethodAttributes.Assembly;
+                               else if (IsDefault ())
+                                       ca |= MethodAttributes.Public;
+                               else
+                                       ca |= MethodAttributes.Private;
+                       }
+
+                       ConstructorBuilder = container.TypeBuilder.DefineConstructor (
+                               ca, GetCallingConvention (container is Class), ParameterTypes);
+
+                       if ((ModFlags & Modifiers.UNSAFE) != 0)
+                               ConstructorBuilder.InitLocals = false;
+                       
+                       //
+                       // HACK because System.Reflection.Emit is lame
+                       //
+                       if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
+                               Report.Error (
+                                       111, Location,
+                                       "Class `" +container.Name+ "' already contains a definition with the " +
+                                       "same return value and parameter types for constructor `" + Name
+                                       + "'");
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               //
+               // Emits the code
+               //
+               public void Emit (TypeContainer container)
+               {
+                       ILGenerator ig = ConstructorBuilder.GetILGenerator ();
+                       EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
+
+                       //
+                       // extern methods have no bodies
+                       //
+                       if ((ModFlags & Modifiers.EXTERN) != 0) {
+                               if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
+                                       Report.Error (
+                                               179, Location, "External constructor `" +
+                                               TypeManager.CSharpSignature (ConstructorBuilder) +
+                                               "' can not have a body");
+                                       return;
+                               }
+                       } else if (block == null) {
+                               Report.Error (
+                                       501, Location, "Constructor `" +
+                                       TypeManager.CSharpSignature (ConstructorBuilder) +
+                                       "' must declare a body since it is not marked extern");
+                               return;
+                       }
+
+                       if ((ModFlags & Modifiers.STATIC) == 0){
+                               if (container is Class && Initializer == null)
+                                       Initializer = new ConstructorBaseInitializer (
+                                               null, Parameters.EmptyReadOnlyParameters, Location);
+
+
+                               //
+                               // Spec mandates that Initializers will not have
+                               // `this' access
+                               //
+                               ec.IsStatic = true;
+                               if (Initializer != null && !Initializer.Resolve (ec))
+                                       return;
+                               ec.IsStatic = false;
+                       }
+
+                       LabelParameters (ec, ConstructorBuilder, OptAttributes);
+                       
+                       SymbolWriter sw = CodeGen.SymbolWriter;
+                       bool generate_debugging = false;
+
+                       if ((sw != null) && (block != null) &&
+                               !Location.IsNull (Location) &&
+                               !Location.IsNull (block.EndLocation)) {
+
+                               sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
+
+                               generate_debugging = true;
+                       }
+
+                       //
+                       // Classes can have base initializers and instance field initializers.
+                       //
+                       if (container is Class){
+                               if ((ModFlags & Modifiers.STATIC) == 0){
+
+                                       //
+                                       // If we use a "this (...)" constructor initializer, then
+                                       // do not emit field initializers, they are initialized in the other constructor
+                                       //
+                                       if (!(Initializer != null && Initializer is ConstructorThisInitializer))
+                                               container.EmitFieldInitializers (ec);
+                               }
+                       }
+                       if (Initializer != null)
+                               Initializer.Emit (ec);
+                       
+                       if ((ModFlags & Modifiers.STATIC) != 0)
+                               container.EmitFieldInitializers (ec);
+
+                       Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
+
+                       // If this is a non-static `struct' constructor and doesn't have any
+                       // initializer, it must initialize all of the struct's fields.
+                       if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
+                               Block.AddThisVariable (container, Location);
+
+                       ec.EmitTopBlock (block, ParameterInfo, Location);
+
+                       if (generate_debugging)
+                               sw.CloseMethod ();
+
+                       block = null;
+               }
+       }
+
+       //
+       // Encapsulates most of the Method's state
+       //
+       public class MethodData {
+               //
+               // The return type of this method
+               //
+               public readonly Type ReturnType;
+               public readonly Type[] ParameterTypes;
+               public readonly InternalParameters ParameterInfo;
+               public readonly CallingConventions CallingConventions;
+               public readonly Attributes OptAttributes;
+               public readonly Location Location;
+
+               //
+               // Are we implementing an interface ?
+               //
+               public bool IsImplementing = false;
+
+               //
+               // Protected data.
+               //
+               protected MemberBase member;
+               protected int modifiers;
+               protected MethodAttributes flags;
+               protected bool is_method;
+               protected string accessor_name;
+
+               //
+               // It can either hold a string with the condition, or an arraylist of conditions.
+               object conditionals;
+
+               MethodBuilder builder = null;
+               public MethodBuilder MethodBuilder {
+                       get {
+                               return builder;
+                       }
+               }
+
+               public MethodData (MemberBase member, string name, Type return_type,
+                                  Type [] parameter_types, InternalParameters parameters,
+                                  CallingConventions cc, Attributes opt_attrs,
+                                  int modifiers, MethodAttributes flags, bool is_method)
+               {
+                       this.member = member;
+                       this.accessor_name = name;
+                       this.ReturnType = return_type;
+                       this.ParameterTypes = parameter_types;
+                       this.ParameterInfo = parameters;
+                       this.CallingConventions = cc;
+                       this.OptAttributes = opt_attrs;
+                       this.modifiers = modifiers;
+                       this.flags = flags;
+                       this.is_method = is_method;
+                       this.Location = member.Location;
+                       this.conditionals = null;
+               }
+
+               //
+               // Attributes.
+               //
+               Attribute dllimport_attribute = null;
+               string obsolete = null;
+               bool obsolete_error = false;
+
+               public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
+               {
+                       if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
+                               return true;
+
+                       foreach (AttributeSection asec in opt_attrs.AttributeSections) {
+                               if (asec.Attributes == null)
+                                       continue;
+                                       
+                               foreach (Attribute a in asec.Attributes) {
+                                       if (a.Name == "Conditional") {
+                                               if (!ApplyConditionalAttribute (a))
+                                                       return false;
+                                       } else if (a.Name == "Obsolete") {
+                                               if (!ApplyObsoleteAttribute (a))
+                                                       return false;
+                                       } else if (a.Name.IndexOf ("DllImport") != -1) {
+                                               if (!is_method) {
+                                                       a.Type = TypeManager.dllimport_type;
+                                                       Attribute.Error_AttributeNotValidForElement (a, Location);
+                                                       return false;
+                                               }
+                                               if (!ApplyDllImportAttribute (a))
+                                                       return false;
+                                       }
+                               }
+                       }
+
+                       return true;
+               }
+
+               //
+               // Applies the `DllImport' attribute to the method.
+               //
+               protected virtual bool ApplyDllImportAttribute (Attribute a)
+               {
+                       const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
+                       if ((modifiers & extern_static) != extern_static) {
+                               Report.Error (601, Location,
+                                             "The DllImport attribute must be specified on a method " +
+                                             "marked `static' and `extern'.");
+                               return false;
+                       }
+
+                       flags |= MethodAttributes.PinvokeImpl;
+                       dllimport_attribute = a;
+                       return true;
+               }
+
+               //
+               // Applies the `Obsolete' attribute to the method.
+               //
+               protected virtual bool ApplyObsoleteAttribute (Attribute a)
+               {
+                       if (obsolete != null) {
+                               Report.Error (579, Location, "Duplicate `Obsolete' attribute");
+                               return false;
+                       }
+
+                       obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
+                       return obsolete != null;
+               }
+
+               //
+               // Applies the `Conditional' attribute to the method.
+               //
+               protected virtual bool ApplyConditionalAttribute (Attribute a)
+               {
+                       // The Conditional attribute is only valid on methods.
+                       if (!is_method) {
+                               Attribute.Error_AttributeNotValidForElement (a, Location);
+                               return false;
+                       }
+
+                       string condition = a.Conditional_GetConditionName ();
+
+                       if (condition == null)
+                               return false;
+
+                       if (ReturnType != TypeManager.void_type) {
+                               Report.Error (578, Location,
+                                             "Conditional not valid on `" + member.Name + "' " +
+                                             "because its return type is not void");
+                               return false;
+                       }
+
+                       if ((modifiers & Modifiers.OVERRIDE) != 0) {
+                               Report.Error (243, Location,
+                                             "Conditional not valid on `" + member.Name + "' " +
+                                             "because it is an override method");
+                               return false;
+                       }
+
+                       if (member.IsExplicitImpl) {
+                               Report.Error (577, Location,
+                                             "Conditional not valid on `" + member.Name + "' " +
+                                             "because it is an explicit interface implementation");
+                               return false;
+                       }
+
+                       if (IsImplementing) {
+                               Report.Error (623, Location,
+                                             "Conditional not valid on `" + member.Name + "' " +
+                                             "because it is an interface method");
+                               return false;
+                       }
+
+                       //
+                       // The likelyhood that the conditional will be more than 1 is very slim
+                       //
+                       if (conditionals == null)
+                               conditionals = condition;
+                       else if (conditionals is string){
+                               string s = (string) conditionals;
+                               conditionals = new ArrayList ();
+                               ((ArrayList)conditionals).Add (s);
+                       } else
+                               ((ArrayList)conditionals).Add (condition);
+
+                       return true;
+               }
+
+               //
+               // Checks whether this method should be ignored due to its Conditional attributes.
+               //
+               bool ShouldIgnore (Location loc)
+               {
+                       // When we're overriding a virtual method, we implicitly inherit the
+                       // Conditional attributes from our parent.
+                       if (member.ParentMethod != null) {
+                               TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
+                                       member.ParentMethod, loc);
+
+                               if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
+                                       return true;
+                       }
+
+                       if (conditionals != null){
+                               if (conditionals is string){
+                                       if (RootContext.AllDefines [conditionals] == null)
+                                               return true;
+                               } else {
+                                       foreach (string condition in (ArrayList) conditionals)
+                                       if (RootContext.AllDefines [condition] == null)
+                                               return true;
+                               }
+                       }
+                       return false;
+               }
+
+               //
+               // Returns the TypeManager.MethodFlags for this method.
+               // This emits an error 619 / warning 618 if the method is obsolete.
+               // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
+               //
+               public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
+               {
+                       TypeManager.MethodFlags flags = 0;
+
+                       if (obsolete != null) {
+                               if (obsolete_error) {
+                                       Report.Error (619, loc, "Method `" + member.Name +
+                                                     "' is obsolete: `" + obsolete + "'");
+                                       return TypeManager.MethodFlags.IsObsoleteError;
+                               } else
+                                       Report.Warning (618, loc, "Method `" + member.Name +
+                                                       "' is obsolete: `" + obsolete + "'");
+
+                               flags |= TypeManager.MethodFlags.IsObsolete;
+                       }
+
+                       if (ShouldIgnore (loc))
+                               flags |= TypeManager.MethodFlags.ShouldIgnore;
+
+                       return flags;
+               }
+
+               public virtual bool Define (TypeContainer container)
+               {
+                       MethodInfo implementing = null;
+                       string method_name, name, prefix;
+
+                       if (OptAttributes != null)
+                               if (!ApplyAttributes (OptAttributes, is_method))
+                                       return false;
+
+                       if (member.IsExplicitImpl)
+                               prefix = member.InterfaceType.FullName + ".";
+                       else
+                               prefix = "";
+
+                       if (accessor_name != null)
+                               name = accessor_name + "_" + member.ShortName;
+                       else
+                               name = member.ShortName;
+                       method_name = prefix + name;
+
+                       if (container.Pending != null){
+                               if (member is Indexer)
+                                       implementing = container.Pending.IsInterfaceIndexer (
+                                               member.InterfaceType, ReturnType, ParameterTypes);
+                               else
+                                       implementing = container.Pending.IsInterfaceMethod (
+                                               member.InterfaceType, name, ReturnType, ParameterTypes);
+
+                               if (member.InterfaceType != null && implementing == null){
+                                       TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
+                                               Location, name);
+                                       return false;
+                               }
+                       }
+
+                       //
+                       // For implicit implementations, make sure we are public, for
+                       // explicit implementations, make sure we are private.
+                       //
+                       if (implementing != null){
+                               //
+                               // Setting null inside this block will trigger a more
+                               // verbose error reporting for missing interface implementations
+                               //
+                               // The "candidate" function has been flagged already
+                               // but it wont get cleared
+                               //
+                               if (member.IsExplicitImpl){
+                                       if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
+                                               Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
+                                               implementing = null;
+                                       }
+                               } else {
+                                       //
+                                       // If this is an interface method implementation,
+                                       // check for public accessibility
+                                       //
+                                       if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
+                                               if (TypeManager.IsInterfaceType (implementing.DeclaringType))
+                                                       implementing = null;
+                                       }
+                               } 
+                                       
+                               //
+                               // Static is not allowed
+                               //
+                               if ((modifiers & Modifiers.STATIC) != 0){
+                                       implementing = null;
+                                       Modifiers.Error_InvalidModifier (Location, "static");
+                               }
+                       }
+                       
+                       //
+                       // If implementing is still valid, set flags
+                       //
+                       if (implementing != null){
+                               //
+                               // When implementing interface methods, set NewSlot
+                               // unless, we are overwriting a method.
+                               //
+                               if (implementing.DeclaringType.IsInterface){
+                                       if ((modifiers & Modifiers.OVERRIDE) == 0)
+                                               flags |= MethodAttributes.NewSlot;
+                               }
+                               flags |=
+                                       MethodAttributes.Virtual |
+                                       MethodAttributes.HideBySig;
+
+                               // Set Final unless we're virtual, abstract or already overriding a method.
+                               if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
+                                       flags |= MethodAttributes.Final;
+
+                               // Get the method name from the explicit interface.
+                               if (member.InterfaceType != null) {
+                                       name = implementing.Name;
+                                       method_name = prefix + name;
+                               }
+
+                               IsImplementing = true;
+                       }
+
+                       //
+                       // Create the MethodBuilder for the method
+                       //
+                       if ((flags & MethodAttributes.PinvokeImpl) != 0) {
+                               if ((modifiers & Modifiers.STATIC) == 0) {
+                                       Report.Error (601, Location,
+                                                     "The DllImport attribute must be specified on " +
+                                                     "a method marked 'static' and 'extern'.");
+                                       return false;
+                               }
+                               
+                               EmitContext ec = new EmitContext (
+                                       container, Location, null, ReturnType, modifiers);
+                               
+                               builder = dllimport_attribute.DefinePInvokeMethod (
+                                       ec, container.TypeBuilder, method_name, flags,
+                                       ReturnType, ParameterTypes);
+                       } else
+                               builder = container.TypeBuilder.DefineMethod (
+                                       method_name, flags, CallingConventions,
+                                       ReturnType, ParameterTypes);
+
+                       if (builder == null)
+                               return false;
+
+                       if ((modifiers & Modifiers.UNSAFE) != 0)
+                               builder.InitLocals = false;
+
+                       if (IsImplementing){
+                               //
+                               // clear the pending implemntation flag
+                               //
+                               if (member is Indexer) {
+                                       container.Pending.ImplementIndexer (
+                                               member.InterfaceType, builder, ReturnType,
+                                               ParameterTypes, true);
+                               } else
+                                       container.Pending.ImplementMethod (
+                                               member.InterfaceType, name, ReturnType,
+                                               ParameterTypes, member.IsExplicitImpl);
+
+                               if (member.IsExplicitImpl)
+                                       container.TypeBuilder.DefineMethodOverride (
+                                               builder, implementing);
+
+                       }
+
+                       if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
+                               Report.Error (111, Location,
+                                             "Class `" + container.Name +
+                                             "' already contains a definition with the " +
+                                             "same return value and parameter types as the " +
+                                             "'get' method of property `" + member.Name + "'");
+                               return false;
+                       }
+
+                       TypeManager.AddMethod (builder, this);
+
+                       return true;
+               }
+
+               //
+               // Emits the code
+               // 
+               public virtual void Emit (TypeContainer container, Block block, object kind)
+               {
+                       ILGenerator ig;
+                       EmitContext ec;
+
+                       if ((flags & MethodAttributes.PinvokeImpl) == 0)
+                               ig = builder.GetILGenerator ();
+                       else
+                               ig = null;
+
+                       ec = new EmitContext (container, Location, ig, ReturnType, modifiers);
+
+                       if (OptAttributes != null)
+                               Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
+
+                       if (member is MethodCore)
+                               ((MethodCore) member).LabelParameters (ec, MethodBuilder, OptAttributes);
+
+                       //
+                       // abstract or extern methods have no bodies
+                       //
+                       if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
+                               if (block == null) {
+                                       SymbolWriter sw = CodeGen.SymbolWriter;
+
+                                       if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
+                                               sw.OpenMethod (container, MethodBuilder, Location, Location);
+                                               sw.CloseMethod ();
+                                       }
+
+                                       return;
+                               }
+
+                               //
+                               // abstract or extern methods have no bodies.
+                               //
+                               if ((modifiers & Modifiers.ABSTRACT) != 0)
+                                       Report.Error (
+                                               500, Location, "Abstract method `" +
+                                               TypeManager.CSharpSignature (builder) +
+                                               "' can not have a body");
+
+                               if ((modifiers & Modifiers.EXTERN) != 0)
+                                       Report.Error (
+                                               179, Location, "External method `" +
+                                               TypeManager.CSharpSignature (builder) +
+                                               "' can not have a body");
+
+                               return;
+                       }
+
+                       //
+                       // Methods must have a body unless they're extern or abstract
+                       //
+                       if (block == null) {
+                               Report.Error (
+                                       501, Location, "Method `" +
+                                       TypeManager.CSharpSignature (builder) +
+                                       "' must declare a body since it is not marked " +
+                                       "abstract or extern");
+                               return;
+                       }
+
+                       //
+                       // Handle destructors specially
+                       //
+                       // FIXME: This code generates buggy code
+                       //
+                       if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
+                               EmitDestructor (ec, block);
+                       else {
+                               SymbolWriter sw = CodeGen.SymbolWriter;
+
+                               if ((sw != null) && !Location.IsNull (Location) &&
+                                   !Location.IsNull (block.EndLocation)) {
+                                       sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
+
+                                       ec.EmitTopBlock (block, ParameterInfo, Location);
+
+                                       sw.CloseMethod ();
+                               } else
+                                       ec.EmitTopBlock (block, ParameterInfo, Location);
+                       }
+               }
+
+               void EmitDestructor (EmitContext ec, Block block)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       Label finish = ig.DefineLabel ();
+                       bool old_in_try = ec.InTry;
+                       
+                       ig.BeginExceptionBlock ();
+                       ec.InTry = true;
+                       ec.ReturnLabel = finish;
+                       ec.HasReturnLabel = true;
+                       ec.EmitTopBlock (block, null, Location);
+                       ec.InTry = old_in_try;
+                       
+                       // ig.MarkLabel (finish);
+                       bool old_in_finally = ec.InFinally;
+                       ec.InFinally = true;
+                       ig.BeginFinallyBlock ();
+                       
+                       if (ec.ContainerType.BaseType != null) {
+                               Expression member_lookup = Expression.MemberLookup (
+                                       ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
+                                       "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
+
+                               if (member_lookup != null){
+                                       MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
+                               
+                                       ig.Emit (OpCodes.Ldarg_0);
+                                       ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
+                               }
+                       }
+                       ec.InFinally = old_in_finally;
+                       
+                       ig.EndExceptionBlock ();
+                       //ig.MarkLabel (ec.ReturnLabel);
+                       ig.Emit (OpCodes.Ret);
+               }
+       }
+
+       abstract public class MemberBase : MemberCore {
+               public Expression Type;
+               public readonly Attributes OptAttributes;
+
+               protected MethodAttributes flags;
+
+               //
+               // The "short" name of this property / indexer / event.  This is the
+               // name without the explicit interface.
+               //
+               public string ShortName;
+
+               //
+               // The type of this property / indexer / event
+               //
+               public Type MemberType;
+
+               //
+               // If true, this is an explicit interface implementation
+               //
+               public bool IsExplicitImpl = false;
+
+               //
+               // The name of the interface we are explicitly implementing
+               //
+               public string ExplicitInterfaceName = null;
+
+               //
+               // If true, the interface type we are explicitly implementing
+               //
+               public Type InterfaceType = null;
+
+               //
+               // The method we're overriding if this is an override method.
+               //
+               protected MethodInfo parent_method = null;
+               public MethodInfo ParentMethod {
+                       get {
+                               return parent_method;
+                       }
+               }
+
+               //
+               // The constructor is only exposed to our children
+               //
+               protected MemberBase (Expression type, int mod, int allowed_mod, string name,
+                                     Attributes attrs, Location loc)
+                       : base (name, loc)
+               {
+                       Type = type;
+                       ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
+                       OptAttributes = attrs;
+               }
+
+               protected virtual bool CheckBase (TypeContainer container)
+               {
+                       if ((container is Struct) || (RootContext.WarningLevel > 3)){
+                               if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
+                                       if (container is Struct){
+                                               Report.Error (666, Location, "Protected member in struct declaration");
+                                               return false;
+                                       } else
+                                               Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
+                               }
+                       }
+                       return true;
+               }
+
+               protected virtual bool CheckParameters (TypeContainer container, Type [] parameters)
+               {
+                       bool error = false;
+
+                       foreach (Type partype in parameters){
+                               if (partype.IsPointer){
+                                       if (!UnsafeOK (container))
+                                               error = true;
+                                       if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
+                                               error = true;
+                               }
+
+                               if (container.AsAccessible (partype, ModFlags))
+                                       continue;
+
+                               if (this is Indexer)
+                                       Report.Error (55, Location,
+                                                     "Inconsistent accessibility: parameter type `" +
+                                                     TypeManager.CSharpName (partype) + "' is less " +
+                                                     "accessible than indexer `" + Name + "'");
+                               else if ((this is Method) && ((Method) this).IsOperator)
+                                       Report.Error (57, Location,
+                                                     "Inconsistent accessibility: parameter type `" +
+                                                     TypeManager.CSharpName (partype) + "' is less " +
+                                                     "accessible than operator `" + Name + "'");
+                               else
+                                       Report.Error (51, Location,
+                                                     "Inconsistent accessibility: parameter type `" +
+                                                     TypeManager.CSharpName (partype) + "' is less " +
+                                                     "accessible than method `" + Name + "'");
+                               error = true;
+                       }
+
+                       return !error;
+               }
+
+               protected virtual bool DoDefine (TypeContainer container)
+               {
+                       if (Name == null)
+                               Name = "this";
+
+                       if (!container.MethodModifiersValid (ModFlags, Name, Location))
+                               return false;
+
+                       flags = Modifiers.MethodAttr (ModFlags);
+
+                       // Lookup Type, verify validity
+                       MemberType = container.ResolveType (Type, false, Location);
+                       if (MemberType == null)
+                               return false;
+
+                       if ((container.ModFlags & Modifiers.SEALED) != 0){
+                               if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
+                                       Report.Error (549, Location, "Virtual method can not be contained in sealed class");
+                                       return false;
+                               }
+                       }
+                       
+                       // verify accessibility
+                       if (!container.AsAccessible (MemberType, ModFlags)) {
+                               if (this is Property)
+                                       Report.Error (53, Location,
+                                                     "Inconsistent accessibility: property type `" +
+                                                     TypeManager.CSharpName (MemberType) + "' is less " +
+                                                     "accessible than property `" + Name + "'");
+                               else if (this is Indexer)
+                                       Report.Error (54, Location,
+                                                     "Inconsistent accessibility: indexer return type `" +
+                                                     TypeManager.CSharpName (MemberType) + "' is less " +
+                                                     "accessible than indexer `" + Name + "'");
+                               else if (this is Method) {
+                                       if (((Method) this).IsOperator)
+                                               Report.Error (56, Location,
+                                                             "Inconsistent accessibility: return type `" +
+                                                             TypeManager.CSharpName (MemberType) + "' is less " +
+                                                             "accessible than operator `" + Name + "'");
+                                       else
+                                               Report.Error (50, Location,
+                                                             "Inconsistent accessibility: return type `" +
+                                                             TypeManager.CSharpName (MemberType) + "' is less " +
+                                                             "accessible than method `" + Name + "'");
+                               } else
+                                       Report.Error (52, Location,
+                                                     "Inconsistent accessibility: field type `" +
+                                                     TypeManager.CSharpName (MemberType) + "' is less " +
+                                                     "accessible than field `" + Name + "'");
+                               return false;
+                       }
+
+                       if (MemberType.IsPointer && !UnsafeOK (container))
+                               return false;
+                       
+                       //
+                       // Check for explicit interface implementation
+                       //
+                       if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
+                               int pos = Name.LastIndexOf (".");
+
+                               ExplicitInterfaceName = Name.Substring (0, pos);
+                               ShortName = Name.Substring (pos + 1);
+                       } else
+                               ShortName = Name;
+
+                       if (ExplicitInterfaceName != null) {
+                               InterfaceType  = RootContext.LookupType (
+                                       container, ExplicitInterfaceName, false, Location);
+                               if (InterfaceType == null)
+                                       return false;
+
+                               // Compute the full name that we need to export.
+                               Name = InterfaceType.FullName + "." + ShortName;
+                               
+                               if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
+                                       return false;
+                               
+                               IsExplicitImpl = true;
+                       } else
+                               IsExplicitImpl = false;
+
+                       return true;
+               }
+       }
+
+       //
+       // Fields and Events both generate FieldBuilders, we use this to share 
+       // their common bits.  This is also used to flag usage of the field
+       //
+       abstract public class FieldBase : MemberBase {
+               public FieldBuilder  FieldBuilder;
+               public Status status;
+
+               [Flags]
+               public enum Status : byte { ASSIGNED = 1, USED = 2 }
+
+               //
+               // The constructor is only exposed to our children
+               //
+               protected FieldBase (Expression type, int mod, int allowed_mod, string name,
+                                    object init, Attributes attrs, Location loc)
+                       : base (type, mod, allowed_mod, name, attrs, loc)
+               {
+                       this.init = init;
+               }
+
+               //
+               // Whether this field has an initializer.
+               //
+               public bool HasInitializer {
+                       get {
+                               return init != null;
+                       }
+               }
+
+               protected readonly Object init;
+               // Private.
+               Expression init_expr;
+               bool init_expr_initialized = false;
+
+               //
+               // Resolves and returns the field initializer.
+               //
+               public Expression GetInitializerExpression (EmitContext ec)
+               {
+                       if (init_expr_initialized)
+                               return init_expr;
+
+                       Expression e;
+                       if (init is Expression)
+                               e = (Expression) init;
+                       else
+                               e = new ArrayCreation (Type, "", (ArrayList)init, Location);
+
+                       ec.IsFieldInitializer = true;
+                       e = e.DoResolve (ec);
+                       ec.IsFieldInitializer = false;
+
+                       init_expr = e;
+                       init_expr_initialized = true;
+
+                       return init_expr;
+               }
+       }
+
+       //
+       // The Field class is used to represents class/struct fields during parsing.
+       //
+       public class Field : FieldBase {
+               // <summary>
+               //   Modifiers allowed in a class declaration
+               // </summary>
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.STATIC |
+                       Modifiers.VOLATILE |
+                       Modifiers.UNSAFE |
+                       Modifiers.READONLY;
+
+               public Field (Expression type, int mod, string name, Object expr_or_array_init,
+                             Attributes attrs, Location loc)
+                       : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
+               {
+               }
+
+               public override bool Define (TypeContainer container)
+               {
+                       Type t = container.ResolveType (Type, false, Location);
+                       
+                       if (t == null)
+                               return false;
+
+                       CheckBase (container);
+                       
+                       if (!container.AsAccessible (t, ModFlags)) {
+                               Report.Error (52, Location,
+                                             "Inconsistent accessibility: field type `" +
+                                             TypeManager.CSharpName (t) + "' is less " +
+                                             "accessible than field `" + Name + "'");
+                               return false;
+                       }
+
+                       if (t.IsPointer && !UnsafeOK (container))
+                               return false;
+                       
+                       if (RootContext.WarningLevel > 1){
+                               Type ptype = container.TypeBuilder.BaseType;
+
+                               // ptype is only null for System.Object while compiling corlib.
+                               if (ptype != null){
+                                       TypeContainer.FindMembers (
+                                               ptype, MemberTypes.Method,
+                                               BindingFlags.Public |
+                                               BindingFlags.Static | BindingFlags.Instance,
+                                               System.Type.FilterName, Name);
+                               }
+                       }
+
+                       if ((ModFlags & Modifiers.VOLATILE) != 0){
+                               if (!t.IsClass){
+                                       Type vt = t;
+                                       
+                                       if (TypeManager.IsEnumType (vt))
+                                               vt = TypeManager.EnumToUnderlying (t);
+
+                                       if (!((vt == TypeManager.bool_type) ||
+                                             (vt == TypeManager.sbyte_type) ||
+                                             (vt == TypeManager.byte_type) ||
+                                             (vt == TypeManager.short_type) ||    
+                                             (vt == TypeManager.ushort_type) ||
+                                             (vt == TypeManager.int32_type) ||    
+                                             (vt == TypeManager.uint32_type) ||    
+                                             (vt == TypeManager.char_type) ||    
+                                             (vt == TypeManager.float_type))){
+                                               Report.Error (
+                                                       677, Location, container.MakeName (Name) +
+                                                       " A volatile field can not be of type `" +
+                                                       TypeManager.CSharpName (vt) + "'");
+                                               return false;
+                                       }
+                               }
+
+                               if ((ModFlags & Modifiers.READONLY) != 0){
+                                       Report.Error (
+                                                     678, Location,
+                                                     "A field can not be both volatile and readonly");
+                                       return false;
+                               }
+                       }
+
+                       FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
+
+                       if (container is Struct && 
+                           ((fa & FieldAttributes.Static) == 0) &&
+                           t == container.TypeBuilder &&
+                           !TypeManager.IsBuiltinType (t)){
+                               Report.Error (523, Location, "Struct member `" + container.Name + "." + Name + 
+                                             "' causes a cycle in the structure layout");
+                               return false;
+                       }
+
+                       FieldBuilder = container.TypeBuilder.DefineField (
+                               Name, t, Modifiers.FieldAttr (ModFlags));
+
+                       TypeManager.RegisterFieldBase (FieldBuilder, this);
+                       return true;
+               }
+
+               public void Emit (TypeContainer tc)
+               {
+                       EmitContext ec = new EmitContext (tc, Location, null,
+                                                         FieldBuilder.FieldType, ModFlags);
+
+                       Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
+               }
+       }
+
+       //
+       // `set' and `get' accessors are represented with an Accessor.
+       // 
+       public class Accessor {
+               //
+               // Null if the accessor is empty, or a Block if not
+               //
+               public Block Block;
+               public Attributes OptAttributes;
+               
+               public Accessor (Block b, Attributes attrs)
+               {
+                       Block = b;
+                       OptAttributes = attrs;
+               }
+       }
+
+       //
+       // Properties and Indexers both generate PropertyBuilders, we use this to share 
+       // their common bits.
+       //
+       abstract public class PropertyBase : MethodCore {
+               public Accessor Get, Set;
+               public PropertyBuilder PropertyBuilder;
+               public MethodBuilder GetBuilder, SetBuilder;
+               public MethodData GetData, SetData;
+
+               protected EmitContext ec;
+
+               public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
+                                    Parameters parameters, Accessor get_block, Accessor set_block,
+                                    Attributes attrs, Location loc)
+                       : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
+               {
+                       Get = get_block;
+                       Set = set_block;
+               }
+
+               protected override bool DoDefine (TypeContainer container)
+               {
+                       if (!base.DoDefine (container))
+                               return false;
+
+                       ec = new EmitContext (container, Location, null, MemberType, ModFlags);
+
+                       return true;
+               }
+
+               //
+               // Checks our base implementation if any
+               //
+               protected override bool CheckBase (TypeContainer container)
+               {
+                       base.CheckBase (container);
+                       
+                       // Check whether arguments were correct.
+                       if (!DoDefineParameters (container))
+                               return false;
+
+                       if (IsExplicitImpl)
+                               return true;
+
+                       string report_name;
+                       MethodSignature ms, base_ms;
+                       if (this is Indexer) {
+                               string name, base_name;
+
+                               report_name = "this";
+                               name = TypeManager.IndexerPropertyName (container.TypeBuilder);
+                               ms = new MethodSignature (name, null, ParameterTypes);
+                               base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
+                               base_ms = new MethodSignature (base_name, null, ParameterTypes);
+                       } else {
+                               report_name = Name;
+                               ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
+                       }
+
+                       //
+                       // Verify if the parent has a type with the same name, and then
+                       // check whether we have to create a new slot for it or not.
+                       //
+                       Type ptype = container.TypeBuilder.BaseType;
+
+                       // ptype is only null for System.Object while compiling corlib.
+                       if (ptype == null) {
+                               if ((ModFlags & Modifiers.NEW) != 0)
+                                       WarningNotHiding (container);
+
+                               return true;
+                       }
+
+                       MemberList props_this;
+
+                       props_this = TypeContainer.FindMembers (
+                               container.TypeBuilder, MemberTypes.Property,
+                               BindingFlags.NonPublic | BindingFlags.Public |
+                               BindingFlags.Static | BindingFlags.Instance |
+                               BindingFlags.DeclaredOnly,
+                               MethodSignature.method_signature_filter, ms);
+
+                       if (props_this.Count > 0) {
+                               Report.Error (111, Location, "Class `" + container.Name + "' " +
+                                             "already defines a member called `" + report_name + "' " +
+                                             "with the same parameter types");
+                               return false;
+                       }
+
+                       MemberList mi_props;
+
+                       mi_props = TypeContainer.FindMembers (
+                               ptype, MemberTypes.Property,
+                               BindingFlags.NonPublic | BindingFlags.Public |
+                               BindingFlags.Instance | BindingFlags.Static,
+                               MethodSignature.inheritable_method_signature_filter, base_ms);
+
+                       if (mi_props.Count > 0){
+                               PropertyInfo parent_property = (PropertyInfo) mi_props [0];
+                               string name = parent_property.DeclaringType.Name + "." +
+                                       parent_property.Name;
+
+                               MethodInfo get, set, parent_method;
+                               get = parent_property.GetGetMethod (true);
+                               set = parent_property.GetSetMethod (true);
+
+                               if (get != null)
+                                       parent_method = get;
+                               else if (set != null)
+                                       parent_method = set;
+                               else
+                                       throw new Exception ("Internal error!");
+
+                               if (!CheckMethodAgainstBase (container, flags, parent_method, name))
+                                       return false;
+
+                               if ((ModFlags & Modifiers.NEW) == 0) {
+                                       Type parent_type = TypeManager.TypeToCoreType (
+                                               parent_property.PropertyType);
+
+                                       if (parent_type != MemberType) {
+                                               Report.Error (
+                                                       508, Location, container.MakeName (Name) + ": cannot " +
+                                                       "change return type when overriding " +
+                                                       "inherited member " + name);
+                                               return false;
+                                       }
+                               }
+                       } else {
+                               if ((ModFlags & Modifiers.NEW) != 0)
+                                       WarningNotHiding (container);
+
+                               if ((ModFlags & Modifiers.OVERRIDE) != 0){
+                                       if (this is Indexer)
+                                               Report.Error (115, Location,
+                                                             container.MakeName (Name) +
+                                                             " no suitable indexers found to override");
+                                       else
+                                               Report.Error (115, Location,
+                                                             container.MakeName (Name) +
+                                                             " no suitable properties found to override");
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+
+               public void Emit (TypeContainer tc)
+               {
+                       //
+                       // The PropertyBuilder can be null for explicit implementations, in that
+                       // case, we do not actually emit the ".property", so there is nowhere to
+                       // put the attribute
+                       //
+                       if (PropertyBuilder != null)
+                               Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
+
+                       if (GetData != null) {
+                               GetData.Emit (tc, Get.Block, Get);
+                               Get.Block = null;
+                       }
+
+                       if (SetData != null) {
+                               SetData.Emit (tc, Set.Block, Set);
+                               Set.Block = null;
+                       }
+               }
+       }
+                       
+       public class Property : PropertyBase {
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.STATIC |
+                       Modifiers.SEALED |
+                       Modifiers.OVERRIDE |
+                       Modifiers.ABSTRACT |
+                       Modifiers.UNSAFE |
+                       Modifiers.EXTERN |
+                       Modifiers.VIRTUAL;
+
+               public Property (Expression type, string name, int mod_flags,
+                                Accessor get_block, Accessor set_block,
+                                Attributes attrs, Location loc)
+                       : base (type, name, mod_flags, AllowedModifiers,
+                               Parameters.EmptyReadOnlyParameters,
+                               get_block, set_block, attrs, loc)
+               {
+               }
+
+               public override bool Define (TypeContainer container)
+               {
+                       if (!DoDefine (container))
+                               return false;
+
+                       if (!CheckBase (container))
+                               return false;
+
+                       flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
+
+                       if (Get != null) {
+                               Type [] parameters = TypeManager.NoTypes;
+
+                               InternalParameters ip = new InternalParameters (
+                                       container, Parameters.EmptyReadOnlyParameters);
+
+                               GetData = new MethodData (this, "get", MemberType,
+                                                         parameters, ip, CallingConventions.Standard,
+                                                         Get.OptAttributes, ModFlags, flags, false);
+
+                               if (!GetData.Define (container))
+                                       return false;
+
+                               GetBuilder = GetData.MethodBuilder;
+                       }
+
+                       if (Set != null) {
+                               Type [] parameters = new Type [1];
+                               parameters [0] = MemberType;
+
+                               Parameter [] parms = new Parameter [1];
+                               parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
+                               InternalParameters ip = new InternalParameters (
+                                       container, new Parameters (parms, null, Location));
+
+                               SetData = new MethodData (this, "set", TypeManager.void_type,
+                                                         parameters, ip, CallingConventions.Standard,
+                                                         Set.OptAttributes, ModFlags, flags, false);
+
+                               if (!SetData.Define (container))
+                                       return false;
+
+                               SetBuilder = SetData.MethodBuilder;
+                               SetBuilder.DefineParameter (1, ParameterAttributes.None, "value"); 
+                       }
+
+                       // FIXME - PropertyAttributes.HasDefault ?
+                       
+                       PropertyAttributes prop_attr =
+                       PropertyAttributes.RTSpecialName |
+                       PropertyAttributes.SpecialName;
+
+                       if (!IsExplicitImpl){
+                               PropertyBuilder = container.TypeBuilder.DefineProperty (
+                                       Name, prop_attr, MemberType, null);
+                               
+                               if (Get != null)
+                                       PropertyBuilder.SetGetMethod (GetBuilder);
+                               
+                               if (Set != null)
+                                       PropertyBuilder.SetSetMethod (SetBuilder);
+
+                               //
+                               // HACK for the reasons exposed above
+                               //
+                               if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
+                                       Report.Error (
+                                               111, Location,
+                                               "Class `" + container.Name +
+                                               "' already contains a definition for the property `" +
+                                               Name + "'");
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+       }
+
+       /// </summary>
+       ///  Gigantic workaround  for lameness in SRE follows :
+       ///  This class derives from EventInfo and attempts to basically
+       ///  wrap around the EventBuilder so that FindMembers can quickly
+       ///  return this in it search for members
+       /// </summary>
+       public class MyEventBuilder : EventInfo {
+               
+               //
+               // We use this to "point" to our Builder which is
+               // not really a MemberInfo
+               //
+               EventBuilder MyBuilder;
+               
+               //
+               // We "catch" and wrap these methods
+               //
+               MethodInfo raise, remove, add;
+
+               EventAttributes attributes;
+               Type declaring_type, reflected_type, event_type;
+               string name;
+
+               Event my_event;
+
+               public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
+               {
+                       MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
+
+                       // And now store the values in our own fields.
+                       
+                       declaring_type = type_builder;
+
+                       reflected_type = type_builder;
+                       
+                       attributes = event_attr;
+                       this.name = name;
+                       my_event = ev;
+                       this.event_type = event_type;
+               }
+               
+               //
+               // Methods that you have to override.  Note that you only need 
+               // to "implement" the variants that take the argument (those are
+               // the "abstract" methods, the others (GetAddMethod()) are 
+               // regular.
+               //
+               public override MethodInfo GetAddMethod (bool nonPublic)
+               {
+                       return add;
+               }
+               
+               public override MethodInfo GetRemoveMethod (bool nonPublic)
+               {
+                       return remove;
+               }
+               
+               public override MethodInfo GetRaiseMethod (bool nonPublic)
+               {
+                       return raise;
+               }
+               
+               //
+               // These methods make "MyEventInfo" look like a Builder
+               //
+               public void SetRaiseMethod (MethodBuilder raiseMethod)
+               {
+                       raise = raiseMethod;
+                       MyBuilder.SetRaiseMethod (raiseMethod);
+               }
+
+               public void SetRemoveOnMethod (MethodBuilder removeMethod)
+               {
+                       remove = removeMethod;
+                       MyBuilder.SetRemoveOnMethod (removeMethod);
+               }
+
+               public void SetAddOnMethod (MethodBuilder addMethod)
+               {
+                       add = addMethod;
+                       MyBuilder.SetAddOnMethod (addMethod);
+               }
+
+               public void SetCustomAttribute (CustomAttributeBuilder cb)
+               {
+                       MyBuilder.SetCustomAttribute (cb);
+               }
+               
+               public override object [] GetCustomAttributes (bool inherit)
+               {
+                       // FIXME : There's nothing which can be seemingly done here because
+                       // we have no way of getting at the custom attribute objects of the
+                       // EventBuilder !
+                       return null;
+               }
+
+               public override object [] GetCustomAttributes (Type t, bool inherit)
+               {
+                       // FIXME : Same here !
+                       return null;
+               }
+
+               public override bool IsDefined (Type t, bool b)
+               {
+                       return true;
+               }
+
+               public override EventAttributes Attributes {
+                       get {
+                               return attributes;
+                       }
+               }
+
+               public override string Name {
+                       get {
+                               return name;
+                       }
+               }
+
+               public override Type DeclaringType {
+                       get {
+                               return declaring_type;
+                       }
+               }
+
+               public override Type ReflectedType {
+                       get {
+                               return reflected_type;
+                       }
+               }
+
+               public Type EventType {
+                       get {
+                               return event_type;
+                       }
+               }
+               
+               public void SetUsed ()
+               {
+                       if (my_event != null)
+                               my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
+               }
+       }
+       
+       public class Event : FieldBase {
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.STATIC |
+                       Modifiers.VIRTUAL |
+                       Modifiers.SEALED |
+                       Modifiers.OVERRIDE |
+                       Modifiers.UNSAFE |
+                       Modifiers.ABSTRACT;
+
+               public readonly Accessor  Add;
+               public readonly Accessor  Remove;
+               public MyEventBuilder     EventBuilder;
+
+               MethodBuilder AddBuilder, RemoveBuilder;
+               MethodData AddData, RemoveData;
+               
+               public Event (Expression type, string name, Object init, int mod, Accessor add,
+                             Accessor remove, Attributes attrs, Location loc)
+                       : base (type, mod, AllowedModifiers, name, init, attrs, loc)
+               {
+                       Add = add;
+                       Remove = remove;
+               }
+
+               public override bool Define (TypeContainer container)
+               {
+                       EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
+                       MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
+;
+                       if (!DoDefine (container))
+                               return false;
+
+                       if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
+                               Report.Error (74, Location, "'" + container.Name + "." + Name +
+                                             "': abstract event can not have an initializer");
+                               return false;
+                       }
+                       
+                       if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
+                               Report.Error (66, Location, "'" + container.Name + "." + Name +
+                                             "' : event must be of a delegate type");
+                               return false;
+                       }
+
+                       Type [] parameter_types = new Type [1];
+                       parameter_types [0] = MemberType;
+
+                       Parameter [] parms = new Parameter [1];
+                       parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
+                       InternalParameters ip = new InternalParameters (
+                               container, new Parameters (parms, null, Location)); 
+
+                       if (!CheckBase (container))
+                               return false;
+
+                       //
+                       // Now define the accessors
+                       //
+                       AddData = new MethodData (this, "add", TypeManager.void_type,
+                                                 parameter_types, ip, CallingConventions.Standard,
+                                                 (Add != null) ? Add.OptAttributes : null,
+                                                 ModFlags, flags | m_attr, false);
+
+                       if (!AddData.Define (container))
+                               return false;
+
+                       AddBuilder = AddData.MethodBuilder;
+                       AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
+
+                       RemoveData = new MethodData (this, "remove", TypeManager.void_type,
+                                                    parameter_types, ip, CallingConventions.Standard,
+                                                    (Remove != null) ? Remove.OptAttributes : null,
+                                                    ModFlags, flags | m_attr, false);
+
+                       if (!RemoveData.Define (container))
+                               return false;
+
+                       RemoveBuilder = RemoveData.MethodBuilder;
+                       RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
+
+                       if (!IsExplicitImpl){
+                               EventBuilder = new MyEventBuilder (this,
+                                       container.TypeBuilder, Name, e_attr, MemberType);
+                                       
+                               if (Add == null && Remove == null) {
+                                       FieldBuilder = container.TypeBuilder.DefineField (
+                                               Name, MemberType,
+                                               FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
+                                       TypeManager.RegisterPrivateFieldOfEvent (
+                                               (EventInfo) EventBuilder, FieldBuilder);
+                                       TypeManager.RegisterFieldBase (FieldBuilder, this);
+                               }
+                       
+                               EventBuilder.SetAddOnMethod (AddBuilder);
+                               EventBuilder.SetRemoveOnMethod (RemoveBuilder);
+
+                               if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
+                                       Report.Error (111, Location,
+                                                     "Class `" + container.Name +
+                                                     "' already contains a definition for the event `" +
+                                                     Name + "'");
+                                       return false;
+                               }
+                       }
+                       
+                       return true;
+               }
+
+               void EmitDefaultMethod (EmitContext ec, bool is_add)
+               {
+                       ILGenerator ig = ec.ig;
+                       MethodInfo method = null;
+                       
+                       if (is_add)
+                               method = TypeManager.delegate_combine_delegate_delegate;
+                       else
+                               method = TypeManager.delegate_remove_delegate_delegate;
+
+                       if ((ModFlags & Modifiers.STATIC) != 0) {
+                               ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ig.Emit (OpCodes.Call, method);
+                               ig.Emit (OpCodes.Castclass, MemberType);
+                               ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
+                       } else {
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
+                               ig.Emit (OpCodes.Ldarg_1);
+                               ig.Emit (OpCodes.Call, method);
+                               ig.Emit (OpCodes.Castclass, MemberType);
+                               ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
+                       }
+                       ig.Emit (OpCodes.Ret);
+               }
+
+               public void Emit (TypeContainer tc)
+               {
+                       EmitContext ec;
+
+                       ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
+                       Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
+
+                       if (Add != null) {
+                               AddData.Emit (tc, Add.Block, Add);
+                               Add.Block = null;
+                       } else {
+                               ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
+                               ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
+                               EmitDefaultMethod (ec, true);
+                       }
+
+                       if (Remove != null) {
+                               RemoveData.Emit (tc, Remove.Block, Remove);
+                               Remove.Block = null;
+                       } else {
+                               ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
+                               ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
+                               EmitDefaultMethod (ec, false);
+                       }
+               }
+               
+       }
+
+       //
+       // FIXME: This does not handle:
+       //
+       //   int INTERFACENAME [ args ]
+       //   Does not 
+       //
+       // Only:
+       // 
+       // int this [ args ]
+       public class Indexer : PropertyBase {
+
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.VIRTUAL |
+                       Modifiers.SEALED |
+                       Modifiers.OVERRIDE |
+                       Modifiers.UNSAFE |
+                       Modifiers.EXTERN |
+                       Modifiers.ABSTRACT;
+
+               public string IndexerName;
+               public string InterfaceIndexerName;
+
+               //
+               // Are we implementing an interface ?
+               //
+               bool IsImplementing = false;
+               
+               public Indexer (Expression type, string int_type, int flags, Parameters parameters,
+                               Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
+                       : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
+                               attrs, loc)
+               {
+                       ExplicitInterfaceName = int_type;
+               }
+
+               public override bool Define (TypeContainer container)
+               {
+                       PropertyAttributes prop_attr =
+                               PropertyAttributes.RTSpecialName |
+                               PropertyAttributes.SpecialName;
+                       
+                       if (!DoDefine (container))
+                               return false;
+
+                       IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
+                       if (IndexerName == null)
+                               IndexerName = "Item";
+                       else if (IsExplicitImpl)
+                               Report.Error (592, Location,
+                                             "Attribute 'IndexerName' is not valid on this declaration " +
+                                             "type. It is valid on `property' declarations only.");
+
+                       ShortName = IndexerName;
+                       if (IsExplicitImpl) {
+                               InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
+                               Name = InterfaceType.FullName + "." + IndexerName;
+                       } else {
+                               InterfaceIndexerName = IndexerName;
+                               Name = ShortName;
+                       }
+
+                       if (!CheckBase (container))
+                               return false;
+
+                       flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
+                       if (Get != null){
+                                InternalParameters ip = new InternalParameters (container, Parameters);
+
+                               GetData = new MethodData (this, "get", MemberType,
+                                                         ParameterTypes, ip, CallingConventions.Standard,
+                                                         Get.OptAttributes, ModFlags, flags, false);
+
+                               if (!GetData.Define (container))
+                                       return false;
+
+                               GetBuilder = GetData.MethodBuilder;
+                       }
+                       
+                       if (Set != null){
+                               int top = ParameterTypes.Length;
+                               Type [] set_pars = new Type [top + 1];
+                               ParameterTypes.CopyTo (set_pars, 0);
+                               set_pars [top] = MemberType;
+
+                               Parameter [] fixed_parms = Parameters.FixedParameters;
+
+                               if (fixed_parms == null){
+                                       throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
+                                       // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
+                                       // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
+                                       //
+                                       // Here is the problem: the `value' parameter has
+                                       // to come *after* the array parameter in the declaration
+                                       // like this:
+                                       // X (object [] x, Type value)
+                                       // .param [0]
+                                       //
+                                       // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
+                                       // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
+                                       
+                               }
+                               
+                               Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
+
+
+                               fixed_parms.CopyTo (tmp, 0);
+                               tmp [fixed_parms.Length] = new Parameter (
+                                       Type, "value", Parameter.Modifier.NONE, null);
+
+                               Parameters set_formal_params = new Parameters (tmp, null, Location);
+                               
+                               InternalParameters ip = new InternalParameters (container, set_formal_params);
+
+                               SetData = new MethodData (this, "set", TypeManager.void_type,
+                                                         set_pars, ip, CallingConventions.Standard,
+                                                         Set.OptAttributes, ModFlags, flags, false);
+
+                               if (!SetData.Define (container))
+                                       return false;
+
+                               SetBuilder = SetData.MethodBuilder;
+                       }
+
+                       //
+                       // Now name the parameters
+                       //
+                       Parameter [] p = Parameters.FixedParameters;
+                       if (p != null) {
+                               int i;
+                               
+                               for (i = 0; i < p.Length; ++i) {
+                                       if (Get != null)
+                                               GetBuilder.DefineParameter (
+                                                       i + 1, p [i].Attributes, p [i].Name);
+
+                                       if (Set != null)
+                                               SetBuilder.DefineParameter (
+                                                       i + 1, p [i].Attributes, p [i].Name);
+                               }
+
+                               if (Set != null)
+                                       SetBuilder.DefineParameter (
+                                               i + 1, ParameterAttributes.None, "value");
+                                       
+                               if (i != ParameterTypes.Length) {
+                                       Parameter array_param = Parameters.ArrayParameter;
+
+                                       SetBuilder.DefineParameter (
+                                               i + 1, array_param.Attributes, array_param.Name);
+                               }
+                       }
+
+                       if (GetData != null)
+                               IsImplementing = GetData.IsImplementing;
+                       else if (SetData != null)
+                               IsImplementing = SetData.IsImplementing;
+
+                       //
+                       // Define the PropertyBuilder if one of the following conditions are met:
+                       // a) we're not implementing an interface indexer.
+                       // b) the indexer has a different IndexerName and this is no
+                       //    explicit interface implementation.
+                       //
+                       if (!IsExplicitImpl) {
+                               PropertyBuilder = container.TypeBuilder.DefineProperty (
+                                       IndexerName, prop_attr, MemberType, ParameterTypes);
+
+                               if (GetData != null)
+                                       PropertyBuilder.SetGetMethod (GetBuilder);
+
+                               if (SetData != null)
+                                       PropertyBuilder.SetSetMethod (SetBuilder);
+                               
+                               TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
+                                                            ParameterTypes);
+                       }
+
+                       return true;
+               }
+       }
+
+       public class Operator : MemberCore {
+
+               const int AllowedModifiers =
+                       Modifiers.PUBLIC |
+                       Modifiers.UNSAFE |
+                       Modifiers.EXTERN |
+                       Modifiers.STATIC;
+
+               const int RequiredModifiers =
+                       Modifiers.PUBLIC |
+                       Modifiers.STATIC;
+
+               public enum OpType : byte {
+
+                       // Unary operators
+                       LogicalNot,
+                       OnesComplement,
+                       Increment,
+                       Decrement,
+                       True,
+                       False,
+
+                       // Unary and Binary operators
+                       Addition,
+                       Subtraction,
+
+                       UnaryPlus,
+                       UnaryNegation,
+                       
+                       // Binary operators
+                       Multiply,
+                       Division,
+                       Modulus,
+                       BitwiseAnd,
+                       BitwiseOr,
+                       ExclusiveOr,
+                       LeftShift,
+                       RightShift,
+                       Equality,
+                       Inequality,
+                       GreaterThan,
+                       LessThan,
+                       GreaterThanOrEqual,
+                       LessThanOrEqual,
+
+                       // Implicit and Explicit
+                       Implicit,
+                       Explicit
+               };
+
+               public readonly OpType OperatorType;
+               public readonly Expression ReturnType;
+               public readonly Expression FirstArgType, SecondArgType;
+               public readonly string FirstArgName, SecondArgName;
+               public Block           Block;
+               public Attributes      OptAttributes;
+               public MethodBuilder   OperatorMethodBuilder;
+               
+               public string MethodName;
+               public Method OperatorMethod;
+
+               public Operator (OpType type, Expression ret_type, int flags,
+                                Expression arg1type, string arg1name,
+                                Expression arg2type, string arg2name,
+                                Block block, Attributes attrs, Location loc)
+                       : base ("", loc)
+               {
+                       OperatorType = type;
+                       ReturnType = ret_type;
+                       ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PUBLIC, loc);
+                       FirstArgType = arg1type;
+                       FirstArgName = arg1name;
+                       SecondArgType = arg2type;
+                       SecondArgName = arg2name;
+                       Block = block;
+                       OptAttributes = attrs;
+               }
+
+               string Prototype (TypeContainer container)
+               {
+                       return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
+                               SecondArgType + ")";
+               }
+               
+               public override bool Define (TypeContainer container)
+               {
+                       int length = 1;
+                       MethodName = "op_" + OperatorType;
+                       
+                       if (SecondArgType != null)
+                               length = 2;
+                       
+                       Parameter [] param_list = new Parameter [length];
+
+                       if ((ModFlags & RequiredModifiers) != RequiredModifiers){
+                               Report.Error (
+                                       558, Location, 
+                                       "User defined operators `" +
+                                       Prototype (container) +
+                                       "' must be declared static and public");
+                               return false;
+                       }
+
+                       param_list[0] = new Parameter (FirstArgType, FirstArgName,
+                                                      Parameter.Modifier.NONE, null);
+                       if (SecondArgType != null)
+                               param_list[1] = new Parameter (SecondArgType, SecondArgName,
+                                                              Parameter.Modifier.NONE, null);
+                       
+                       OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
+                                                    new Parameters (param_list, null, Location),
+                                                    OptAttributes, Location);
+
+                       OperatorMethod.IsOperator = true;                       
+                       OperatorMethod.Define (container);
+
+                       if (OperatorMethod.MethodBuilder == null)
+                               return false;
+                       
+                       OperatorMethodBuilder = OperatorMethod.MethodBuilder;
+
+                       Type [] param_types = OperatorMethod.ParameterTypes;
+                       Type declaring_type = OperatorMethodBuilder.DeclaringType;
+                       Type return_type = OperatorMethod.GetReturnType ();
+                       Type first_arg_type = param_types [0];
+
+                       // Rules for conversion operators
+                       
+                       if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
+                               if (first_arg_type == return_type && first_arg_type == declaring_type){
+                                       Report.Error (
+                                               555, Location,
+                                               "User-defined conversion cannot take an object of the " +
+                                               "enclosing type and convert to an object of the enclosing" +
+                                               " type");
+                                       return false;
+                               }
+                               
+                               if (first_arg_type != declaring_type && return_type != declaring_type){
+                                       Report.Error (
+                                               556, Location, 
+                                               "User-defined conversion must convert to or from the " +
+                                               "enclosing type");
+                                       return false;
+                               }
+                               
+                               if (first_arg_type == TypeManager.object_type ||
+                                   return_type == TypeManager.object_type){
+                                       Report.Error (
+                                               -8, Location,
+                                               "User-defined conversion cannot convert to or from " +
+                                               "object type");
+                                       return false;
+                               }
+
+                               if (first_arg_type.IsInterface || return_type.IsInterface){
+                                       Report.Error (
+                                               552, Location,
+                                               "User-defined conversion cannot convert to or from an " +
+                                               "interface type");
+                                       return false;
+                               }
+                               
+                               if (first_arg_type.IsSubclassOf (return_type) ||
+                                   return_type.IsSubclassOf (first_arg_type)){
+                                       Report.Error (
+                                               -10, Location,
+                                               "User-defined conversion cannot convert between types " +
+                                               "that derive from each other");
+                                       return false;
+                               }
+                       } else if (SecondArgType == null) {
+                               // Checks for Unary operators
+                               
+                               if (first_arg_type != declaring_type){
+                                       Report.Error (
+                                               562, Location,
+                                               "The parameter of a unary operator must be the " +
+                                               "containing type");
+                                       return false;
+                               }
+                               
+                               if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
+                                       if (return_type != declaring_type){
+                                               Report.Error (
+                                                       559, Location,
+                                                       "The parameter and return type for ++ and -- " +
+                                                       "must be the containing type");
+                                               return false;
+                                       }
+                                       
+                               }
+                               
+                               if (OperatorType == OpType.True || OperatorType == OpType.False) {
+                                       if (return_type != TypeManager.bool_type){
+                                               Report.Error (
+                                                       215, Location,
+                                                       "The return type of operator True or False " +
+                                                       "must be bool");
+                                               return false;
+                                       }
+                               }
+                               
+                       } else {
+                               // Checks for Binary operators
+                               
+                               if (first_arg_type != declaring_type &&
+                                   param_types [1] != declaring_type){
+                                       Report.Error (
+                                               563, Location,
+                                               "One of the parameters of a binary operator must " +
+                                               "be the containing type");
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+               
+               public void Emit (TypeContainer container)
+               {
+                       //
+                       // abstract or extern methods have no bodies
+                       //
+                       if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
+                               return;
+                       
+                       OperatorMethod.Block = Block;
+                       OperatorMethod.Emit (container);
+                       Block = null;
+               }
+
+               public static string GetName (OpType ot)
+               {
+                       switch (ot){
+                       case OpType.LogicalNot:
+                               return "!";
+                       case OpType.OnesComplement:
+                               return "~";
+                       case OpType.Increment:
+                               return "++";
+                       case OpType.Decrement:
+                               return "--";
+                       case OpType.True:
+                               return "true";
+                       case OpType.False:
+                               return "false";
+                       case OpType.Addition:
+                               return "+";
+                       case OpType.Subtraction:
+                               return "-";
+                       case OpType.UnaryPlus:
+                               return "+";
+                       case OpType.UnaryNegation:
+                               return "-";
+                       case OpType.Multiply:
+                               return "*";
+                       case OpType.Division:
+                               return "/";
+                       case OpType.Modulus:
+                               return "%";
+                       case OpType.BitwiseAnd:
+                               return "&";
+                       case OpType.BitwiseOr:
+                               return "|";
+                       case OpType.ExclusiveOr:
+                               return "^";
+                       case OpType.LeftShift:
+                               return "<<";
+                       case OpType.RightShift:
+                               return ">>";
+                       case OpType.Equality:
+                               return "==";
+                       case OpType.Inequality:
+                               return "!=";
+                       case OpType.GreaterThan:
+                               return ">";
+                       case OpType.LessThan:
+                               return "<";
+                       case OpType.GreaterThanOrEqual:
+                               return ">=";
+                       case OpType.LessThanOrEqual:
+                               return "<=";
+                       case OpType.Implicit:
+                               return "implicit";
+                       case OpType.Explicit:
+                               return "explicit";
+                       default: return "";
+                       }
+               }
+               
+               public override string ToString ()
+               {
+                       Type return_type = OperatorMethod.GetReturnType();
+                       Type [] param_types = OperatorMethod.ParameterTypes;
+                       
+                       if (SecondArgType == null)
+                               return String.Format (
+                                       "{0} operator {1}({2})",
+                                       TypeManager.CSharpName (return_type),
+                                       GetName (OperatorType),
+                                       param_types [0]);
+                       else
+                               return String.Format (
+                                       "{0} operator {1}({2}, {3})",
+                                       TypeManager.CSharpName (return_type),
+                                       GetName (OperatorType),
+                                       param_types [0], param_types [1]);
+               }
+       }
+
+       //
+       // This is used to compare method signatures
+       //
+       struct MethodSignature {
+               public string Name;
+               public Type RetType;
+               public Type [] Parameters;
+               
+               /// <summary>
+               ///    This delegate is used to extract methods which have the
+               ///    same signature as the argument
+               /// </summary>
+               public static MemberFilter method_signature_filter;
+
+               /// <summary>
+               ///   This delegate is used to extract inheritable methods which
+               ///   have the same signature as the argument.  By inheritable,
+               ///   this means that we have permissions to override the method
+               ///   from the current assembly and class
+               /// </summary>
+               public static MemberFilter inheritable_method_signature_filter;
+
+               static MethodSignature ()
+               {
+                       method_signature_filter = new MemberFilter (MemberSignatureCompare);
+                       inheritable_method_signature_filter = new MemberFilter (
+                               InheritableMemberSignatureCompare);
+               }
+               
+               public MethodSignature (string name, Type ret_type, Type [] parameters)
+               {
+                       Name = name;
+                       RetType = ret_type;
+
+                       if (parameters == null)
+                               Parameters = TypeManager.NoTypes;
+                       else
+                               Parameters = parameters;
+               }
+
+               public override string ToString ()
+               {
+                       string pars = "";
+                       if (Parameters.Length != 0){
+                               System.Text.StringBuilder sb = new System.Text.StringBuilder ();
+                               for (int i = 0; i < Parameters.Length; i++){
+                                       sb.Append (Parameters [i]);
+                                       if (i+1 < Parameters.Length)
+                                               sb.Append (", ");
+                               }
+                               pars = sb.ToString ();
+                       }
+
+                       return String.Format ("{0} {1} ({2})", RetType, Name, pars);
+               }
+               
+               public override int GetHashCode ()
+               {
+                       return Name.GetHashCode ();
+               }
+
+               public override bool Equals (Object o)
+               {
+                       MethodSignature other = (MethodSignature) o;
+
+                       if (other.Name != Name)
+                               return false;
+
+                       if (other.RetType != RetType)
+                               return false;
+                       
+                       if (Parameters == null){
+                               if (other.Parameters == null)
+                                       return true;
+                               return false;
+                       }
+
+                       if (other.Parameters == null)
+                               return false;
+                       
+                       int c = Parameters.Length;
+                       if (other.Parameters.Length != c)
+                               return false;
+
+                       for (int i = 0; i < c; i++)
+                               if (other.Parameters [i] != Parameters [i])
+                                       return false;
+
+                       return true;
+               }
+
+               static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
+               {
+                       MethodSignature sig = (MethodSignature) filter_criteria;
+
+                       if (m.Name != sig.Name)
+                               return false;
+
+                       Type ReturnType;
+                       MethodInfo mi = m as MethodInfo;
+                       PropertyInfo pi = m as PropertyInfo;
+
+                       if (mi != null)
+                               ReturnType = mi.ReturnType;
+                       else if (pi != null)
+                               ReturnType = pi.PropertyType;
+                       else
+                               return false;
+                       
+                       //
+                       // we use sig.RetType == null to mean `do not check the
+                       // method return value.  
+                       //
+                       if (sig.RetType != null)
+                               if (ReturnType != sig.RetType)
+                                       return false;
+
+                       Type [] args;
+                       if (mi != null)
+                               args = TypeManager.GetArgumentTypes (mi);
+                       else
+                               args = TypeManager.GetArgumentTypes (pi);
+                       Type [] sigp = sig.Parameters;
+
+                       if (args.Length != sigp.Length)
+                               return false;
+
+                       for (int i = args.Length; i > 0; ){
+                               i--;
+                               if (args [i] != sigp [i])
+                                       return false;
+                       }
+                       return true;
+               }
+
+               //
+               // This filter should be used when we are requesting methods that
+               // we want to override.
+               //
+               // This makes a number of assumptions, for example
+               // that the methods being extracted are of a parent
+               // class (this means we know implicitly that we are
+               // being called to find out about members by a derived
+               // class).
+               // 
+               static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
+               {
+                       MethodInfo mi;
+                       PropertyInfo pi = m as PropertyInfo;
+
+                       if (pi != null) {
+                               mi = pi.GetGetMethod (true);
+                               if (mi == null)
+                                       mi = pi.GetSetMethod (true);
+                       } else
+                               mi = m as MethodInfo;
+
+                       if (mi == null){
+                               Console.WriteLine ("Nothing found");
+                       }
+                       
+                       MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
+
+                       // If only accessible to the current class.
+                       if (prot == MethodAttributes.Private)
+                               return false;
+
+                       if (!MemberSignatureCompare (m, filter_criteria))
+                               return false;
+
+                       // If only accessible to the defining assembly or 
+                       if (prot == MethodAttributes.FamANDAssem ||
+                           prot == MethodAttributes.Assembly){
+                               if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
+                                       return true;
+                               else
+                                       return false;
+                       }
+
+                       // Anything else (FamOrAssembly and Public) is fine
+                       return true;
+               }
+       }
+}
diff --git a/mcs/gmcs/codegen.cs b/mcs/gmcs/codegen.cs
new file mode 100755 (executable)
index 0000000..43ac7de
--- /dev/null
@@ -0,0 +1,627 @@
+//
+// codegen.cs: The code generator
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc.
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///    Code generator class.
+       /// </summary>
+       public class CodeGen {
+               static AppDomain current_domain;
+               public static AssemblyBuilder AssemblyBuilder;
+               public static ModuleBuilder   ModuleBuilder;
+
+               static public SymbolWriter SymbolWriter;
+
+               public static string Basename (string name)
+               {
+                       int pos = name.LastIndexOf ("/");
+
+                       if (pos != -1)
+                               return name.Substring (pos + 1);
+
+                       pos = name.LastIndexOf ("\\");
+                       if (pos != -1)
+                               return name.Substring (pos + 1);
+
+                       return name;
+               }
+
+               public static string Dirname (string name)
+               {
+                       int pos = name.LastIndexOf ("/");
+
+                       if (pos != -1)
+                               return name.Substring (0, pos);
+
+                       pos = name.LastIndexOf ("\\");
+                       if (pos != -1)
+                               return name.Substring (0, pos);
+
+                       return ".";
+               }
+
+               static string TrimExt (string name)
+               {
+                       int pos = name.LastIndexOf (".");
+
+                       return name.Substring (0, pos);
+               }
+
+               static public string FileName;
+
+               //
+               // Initializes the symbol writer
+               //
+               static void InitializeSymbolWriter ()
+               {
+                       SymbolWriter = SymbolWriter.GetSymbolWriter (ModuleBuilder);
+
+                       //
+                       // If we got an ISymbolWriter instance, initialize it.
+                       //
+                       if (SymbolWriter == null) {
+                               Report.Warning (
+                                       -18, "Could not find the symbol writer assembly (Mono.CSharp.Debugger.dll). This is normally an installation problem. Please make sure to compile and install the mcs/class/Mono.CSharp.Debugger directory.");
+                               return;
+                       }
+               }
+
+               //
+               // Initializes the code generator variables
+               //
+               static public void Init (string name, string output, bool want_debugging_support)
+               {
+                       AssemblyName an;
+
+                       FileName = output;
+                       an = new AssemblyName ();
+                       an.Name = Path.GetFileNameWithoutExtension (name);
+                       
+                       current_domain = AppDomain.CurrentDomain;
+                       AssemblyBuilder = current_domain.DefineDynamicAssembly (
+                               an, AssemblyBuilderAccess.RunAndSave, Dirname (name));
+
+                       //
+                       // Pass a path-less name to DefineDynamicModule.  Wonder how
+                       // this copes with output in different directories then.
+                       // FIXME: figure out how this copes with --output /tmp/blah
+                       //
+                       // If the third argument is true, the ModuleBuilder will dynamically
+                       // load the default symbol writer.
+                       //
+                       ModuleBuilder = AssemblyBuilder.DefineDynamicModule (
+                               Basename (name), Basename (output), want_debugging_support);
+
+                       if (want_debugging_support)
+                               InitializeSymbolWriter ();
+               }
+
+               static public void Save (string name)
+               {
+                       try {
+                               AssemblyBuilder.Save (Basename (name));
+                       } catch (System.IO.IOException io){
+                               Report.Error (16, "Could not write to file `"+name+"', cause: " + io.Message);
+                       }
+               }
+       }
+
+       /// <summary>
+       ///   An Emit Context is created for each body of code (from methods,
+       ///   properties bodies, indexer bodies or constructor bodies)
+       /// </summary>
+       public class EmitContext {
+               public DeclSpace DeclSpace;
+               public DeclSpace TypeContainer;
+               public ILGenerator   ig;
+
+               /// <summary>
+               ///   This variable tracks the `checked' state of the compilation,
+               ///   it controls whether we should generate code that does overflow
+               ///   checking, or if we generate code that ignores overflows.
+               ///
+               ///   The default setting comes from the command line option to generate
+               ///   checked or unchecked code plus any source code changes using the
+               ///   checked/unchecked statements or expressions.   Contrast this with
+               ///   the ConstantCheckState flag.
+               /// </summary>
+               
+               public bool CheckState;
+
+               /// <summary>
+               ///   The constant check state is always set to `true' and cant be changed
+               ///   from the command line.  The source code can change this setting with
+               ///   the `checked' and `unchecked' statements and expressions. 
+               /// </summary>
+               public bool ConstantCheckState;
+
+               /// <summary>
+               ///   Whether we are emitting code inside a static or instance method
+               /// </summary>
+               public bool IsStatic;
+
+               /// <summary>
+               ///   Whether we are emitting a field initializer
+               /// </summary>
+               public bool IsFieldInitializer;
+
+               /// <summary>
+               ///   The value that is allowed to be returned or NULL if there is no
+               ///   return type.
+               /// </summary>
+               public Type ReturnType;
+
+               /// <summary>
+               ///   Points to the Type (extracted from the TypeContainer) that
+               ///   declares this body of code
+               /// </summary>
+               public Type ContainerType;
+               
+               /// <summary>
+               ///   Whether this is generating code for a constructor
+               /// </summary>
+               public bool IsConstructor;
+
+               /// <summary>
+               ///   Whether we're control flow analysis enabled
+               /// </summary>
+               public bool DoFlowAnalysis;
+               
+               /// <summary>
+               ///   Keeps track of the Type to LocalBuilder temporary storage created
+               ///   to store structures (used to compute the address of the structure
+               ///   value on structure method invocations)
+               /// </summary>
+               public Hashtable temporary_storage;
+
+               public Block CurrentBlock;
+
+               public int CurrentFile;
+
+               /// <summary>
+               ///   The location where we store the return value.
+               /// </summary>
+               LocalBuilder return_value;
+
+               /// <summary>
+               ///   The location where return has to jump to return the
+               ///   value
+               /// </summary>
+               public Label ReturnLabel;
+
+               /// <summary>
+               ///   If we already defined the ReturnLabel
+               /// </summary>
+               public bool HasReturnLabel;
+
+               /// <summary>
+               ///   Whether we are in a Finally block
+               /// </summary>
+               public bool InFinally;
+
+               /// <summary>
+               ///   Whether we are in a Try block
+               /// </summary>
+               public bool InTry;
+
+               /// <summary>
+               ///   Whether we are inside an iterator block.
+               /// </summary>
+               public bool InIterator;
+
+               /// <summary>
+               ///   Whether we need an explicit return statement at the end of the method.
+               /// </summary>
+               public bool NeedExplicitReturn;
+               
+               /// <summary>
+               ///   Whether remapping of locals, parameters and fields is turned on.
+               ///   Used by iterators and anonymous methods.
+               /// </summary>
+               public bool RemapToProxy;
+
+               /// <summary>
+               ///   Whether we are in a Catch block
+               /// </summary>
+               public bool InCatch;
+
+               /// <summary>
+               ///  Whether we are inside an unsafe block
+               /// </summary>
+               public bool InUnsafe;
+
+               /// <summary>
+               ///  Whether we are in a `fixed' initialization
+               /// </summary>
+               public bool InFixedInitializer;
+
+               /// <summary>
+               ///  Whether we are inside an anonymous method.
+               /// </summary>
+               public bool InAnonymousMethod;
+               
+               /// <summary>
+               ///   Location for this EmitContext
+               /// </summary>
+               public Location loc;
+
+               /// <summary>
+               ///   Used to flag that it is ok to define types recursively, as the
+               ///   expressions are being evaluated as part of the type lookup
+               ///   during the type resolution process
+               /// </summary>
+               public bool ResolvingTypeTree;
+               
+               /// <summary>
+               ///   Inside an enum definition, we do not resolve enumeration values
+               ///   to their enumerations, but rather to the underlying type/value
+               ///   This is so EnumVal + EnumValB can be evaluated.
+               ///
+               ///   There is no "E operator + (E x, E y)", so during an enum evaluation
+               ///   we relax the rules
+               /// </summary>
+               public bool InEnumContext;
+
+               protected Stack FlowStack;
+               
+               public EmitContext (DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
+                                   Type return_type, int code_flags, bool is_constructor)
+               {
+                       this.ig = ig;
+
+                       TypeContainer = parent;
+                       DeclSpace = ds;
+                       CheckState = RootContext.Checked;
+                       ConstantCheckState = true;
+                       
+                       IsStatic = (code_flags & Modifiers.STATIC) != 0;
+                       InIterator = (code_flags & Modifiers.METHOD_YIELDS) != 0;
+                       RemapToProxy = InIterator;
+                       ReturnType = return_type;
+                       IsConstructor = is_constructor;
+                       CurrentBlock = null;
+                       CurrentFile = 0;
+                       
+                       if (parent != null){
+                               // Can only be null for the ResolveType contexts.
+                               ContainerType = parent.TypeBuilder;
+                               if (parent.UnsafeContext)
+                                       InUnsafe = true;
+                               else
+                                       InUnsafe = (code_flags & Modifiers.UNSAFE) != 0;
+                       }
+                       loc = l;
+
+                       FlowStack = new Stack ();
+                       
+                       if (ReturnType == TypeManager.void_type)
+                               ReturnType = null;
+               }
+
+               public EmitContext (TypeContainer tc, Location l, ILGenerator ig,
+                                   Type return_type, int code_flags, bool is_constructor)
+                       : this (tc, tc, l, ig, return_type, code_flags, is_constructor)
+               {
+               }
+
+               public EmitContext (TypeContainer tc, Location l, ILGenerator ig,
+                                   Type return_type, int code_flags)
+                       : this (tc, tc, l, ig, return_type, code_flags, false)
+               {
+               }
+
+               public FlowBranching CurrentBranching {
+                       get {
+                               return (FlowBranching) FlowStack.Peek ();
+                       }
+               }
+
+               // <summary>
+               //   Starts a new code branching.  This inherits the state of all local
+               //   variables and parameters from the current branching.
+               // </summary>
+               public FlowBranching StartFlowBranching (FlowBranchingType type, Location loc)
+               {
+                       FlowBranching cfb = new FlowBranching (CurrentBranching, type, null, loc);
+
+                       FlowStack.Push (cfb);
+
+                       return cfb;
+               }
+
+               // <summary>
+               //   Starts a new code branching for block `block'.
+               // </summary>
+               public FlowBranching StartFlowBranching (Block block)
+               {
+                       FlowBranching cfb;
+                       FlowBranchingType type;
+
+                       if (CurrentBranching.Type == FlowBranchingType.SWITCH)
+                               type = FlowBranchingType.SWITCH_SECTION;
+                       else
+                               type = FlowBranchingType.BLOCK;
+
+                       cfb = new FlowBranching (CurrentBranching, type, block, block.StartLocation);
+
+                       FlowStack.Push (cfb);
+
+                       return cfb;
+               }
+
+               // <summary>
+               //   Ends a code branching.  Merges the state of locals and parameters
+               //   from all the children of the ending branching.
+               // </summary>
+               public FlowReturns EndFlowBranching ()
+               {
+                       FlowBranching cfb = (FlowBranching) FlowStack.Pop ();
+
+                       return CurrentBranching.MergeChild (cfb);
+               }
+
+               // <summary>
+               //   Kills the current code branching.  This throws away any changed state
+               //   information and should only be used in case of an error.
+               // </summary>
+               public void KillFlowBranching ()
+               {
+                       FlowBranching cfb = (FlowBranching) FlowStack.Pop ();
+               }
+
+               public void EmitTopBlock (Block block, InternalParameters ip, Location loc)
+               {
+                       bool has_ret = false;
+
+                       if (!Location.IsNull (loc))
+                               CurrentFile = loc.File;
+
+                       if (block != null){
+                           try {
+                               int errors = Report.Errors;
+
+                               block.EmitMeta (this, ip, block);
+
+                               if (Report.Errors == errors){
+                                       bool old_do_flow_analysis = DoFlowAnalysis;
+                                       DoFlowAnalysis = true;
+
+                                       FlowBranching cfb = new FlowBranching (block, loc);
+                                       FlowStack.Push (cfb);
+
+                                       if (!block.Resolve (this)) {
+                                               FlowStack.Pop ();
+                                               DoFlowAnalysis = old_do_flow_analysis;
+                                               return;
+                                       }
+
+                                       cfb = (FlowBranching) FlowStack.Pop ();
+                                       FlowReturns returns = cfb.MergeTopBlock ();
+
+                                       DoFlowAnalysis = old_do_flow_analysis;
+
+                                       has_ret = block.Emit (this);
+
+                                       if ((returns == FlowReturns.ALWAYS) ||
+                                           (returns == FlowReturns.EXCEPTION) ||
+                                           (returns == FlowReturns.UNREACHABLE))
+                                               has_ret = true;
+
+                                       if (Report.Errors == errors){
+                                               if (RootContext.WarningLevel >= 3)
+                                                       block.UsageWarning ();
+                                       }
+                               }
+                           } catch {
+                                       Console.WriteLine ("Exception caught by the compiler while compiling:");
+                                       Console.WriteLine ("   Block that caused the problem begin at: " + loc);
+                                       
+                                       if (CurrentBlock != null){
+                                               Console.WriteLine ("                     Block being compiled: [{0},{1}]",
+                                                                  CurrentBlock.StartLocation, CurrentBlock.EndLocation);
+                                       }
+                                       throw;
+                           }
+                       }
+
+                       if (ReturnType != null && !has_ret){
+                               //
+                               // FIXME: we need full flow analysis to implement this
+                               // correctly and emit an error instead of a warning.
+                               //
+                               //
+                               if (!InIterator){
+                                       Report.Error (161, loc, "Not all code paths return a value");
+                                       return;
+                               }
+                       }
+
+                       if (HasReturnLabel)
+                               ig.MarkLabel (ReturnLabel);
+                       if (return_value != null){
+                               ig.Emit (OpCodes.Ldloc, return_value);
+                               ig.Emit (OpCodes.Ret);
+                       } else {
+                               if (!InTry){
+                                       if (InIterator)
+                                               has_ret = true;
+                                       
+                                       if (!has_ret || HasReturnLabel) {
+                                               ig.Emit (OpCodes.Ret);
+                                               NeedExplicitReturn = false;
+                                       }
+                               }
+
+                               // Unfortunately, System.Reflection.Emit automatically emits a leave
+                               // to the end of a finally block.  This is a problem if no code is
+                               // following the try/finally block since we may jump to a point after
+                               // the end of the method. As a workaround, emit an explicit ret here.
+
+                               if (NeedExplicitReturn) {
+                                       if (ReturnType != null)
+                                               ig.Emit (OpCodes.Ldloc, TemporaryReturn ());
+                                       ig.Emit (OpCodes.Ret);
+                               }
+                       }
+               }
+
+               /// <summary>
+               ///   This is called immediately before emitting an IL opcode to tell the symbol
+               ///   writer to which source line this opcode belongs.
+               /// </summary>
+               public void Mark (Location loc, bool check_file)
+               {
+                       if ((CodeGen.SymbolWriter == null) || Location.IsNull (loc))
+                               return;
+
+                       if (check_file && (CurrentFile != loc.File))
+                               return;
+
+                       ig.MarkSequencePoint (null, loc.Row, 0, 0, 0);
+               }
+
+               /// <summary>
+               ///   Returns a temporary storage for a variable of type t as 
+               ///   a local variable in the current body.
+               /// </summary>
+               public LocalBuilder GetTemporaryStorage (Type t)
+               {
+                       LocalBuilder location;
+                       
+                       if (temporary_storage != null){
+                               location = (LocalBuilder) temporary_storage [t];
+                               if (location != null)
+                                       return location;
+                       }
+                       
+                       location = ig.DeclareLocal (t);
+                       
+                       return location;
+               }
+
+               public void FreeTemporaryStorage (LocalBuilder b)
+               {
+                       // Empty for now.
+               }
+
+               /// <summary>
+               ///   Current loop begin and end labels.
+               /// </summary>
+               public Label LoopBegin, LoopEnd;
+
+               /// <summary>
+               ///   Whether we are inside a loop and break/continue are possible.
+               /// </summary>
+               public bool  InLoop;
+
+               /// <summary>
+               ///   This is incremented each time we enter a try/catch block and
+               ///   decremented if we leave it.
+               /// </summary>
+               public int   TryCatchLevel;
+
+               /// <summary>
+               ///   The TryCatchLevel at the begin of the current loop.
+               /// </summary>
+               public int   LoopBeginTryCatchLevel;
+
+               /// <summary>
+               ///   Default target in a switch statement.   Only valid if
+               ///   InSwitch is true
+               /// </summary>
+               public Label DefaultTarget;
+
+               /// <summary>
+               ///   If this is non-null, points to the current switch statement
+               /// </summary>
+               public Switch Switch;
+
+               /// <summary>
+               ///   ReturnValue creates on demand the LocalBuilder for the
+               ///   return value from the function.  By default this is not
+               ///   used.  This is only required when returns are found inside
+               ///   Try or Catch statements.
+               /// </summary>
+               public LocalBuilder TemporaryReturn ()
+               {
+                       if (return_value == null){
+                               return_value = ig.DeclareLocal (ReturnType);
+                               ReturnLabel = ig.DefineLabel ();
+                               HasReturnLabel = true;
+                       }
+
+                       return return_value;
+               }
+
+               //
+               // Creates a field `name' with the type `t' on the proxy class
+               //
+               public FieldBuilder MapVariable (string name, Type t)
+               {
+                       if (InIterator){
+                               return IteratorHandler.Current.MapVariable (name, t);
+                       }
+
+                       throw new Exception ("MapVariable for an unknown state");
+               }
+
+               //
+               // Emits the proper object to address fields on a remapped
+               // variable/parameter to field in anonymous-method/iterator proxy classes.
+               //
+               public void EmitThis ()
+               {
+                       ig.Emit (OpCodes.Ldarg_0);
+
+                       if (!IsStatic){
+                               if (InIterator)
+                                       ig.Emit (OpCodes.Ldfld, IteratorHandler.Current.this_field);
+                               else
+                                       throw new Exception ("EmitThis for an unknown state");
+                       }
+               }
+
+               public void EmitArgument (int idx)
+               {
+                       if (InIterator)
+                               ig.Emit (OpCodes.Ldfld, IteratorHandler.Current.parameter_fields [idx]);
+                       else
+                               throw new Exception ("EmitStoreArgument for an unknown state");
+               }
+               
+               public void EmitStoreArgument (int idx)
+               {
+                       if (InIterator)
+                               ig.Emit (OpCodes.Stfld, IteratorHandler.Current.parameter_fields [idx]);
+                       else
+                               throw new Exception ("EmitStoreArgument for an unknown state");
+               }
+               
+               public Expression GetThis (Location loc)
+               {
+                       This my_this;
+                       if (CurrentBlock != null)
+                               my_this = new This (CurrentBlock, loc);
+                       else
+                               my_this = new This (loc);
+
+                       if (!my_this.ResolveBase (this))
+                               my_this = null;
+
+                       return my_this;
+               }
+       }
+}
diff --git a/mcs/gmcs/const.cs b/mcs/gmcs/const.cs
new file mode 100755 (executable)
index 0000000..4f54d70
--- /dev/null
@@ -0,0 +1,242 @@
+//
+// const.cs: Constant declarations.
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc.
+//
+//
+
+//
+// This is needed because the following situation arises:
+//
+//     The FieldBuilder is declared with the real type for an enumeration
+//
+//     When we attempt to set the value for the constant, the FieldBuilder.SetConstant
+//     function aborts because it requires its argument to be of the same type
+//
+
+namespace Mono.CSharp {
+
+       using System;
+       using System.Reflection;
+       using System.Reflection.Emit;
+       using System.Collections;
+
+       public class Const : MemberCore {
+               public Expression ConstantType;
+               public Expression Expr;
+               public Attributes  OptAttributes;
+               public FieldBuilder FieldBuilder;
+               EmitContext const_ec;
+
+               object ConstantValue = null;
+               Type type;
+
+               bool in_transit = false;
+
+               public const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE;
+
+               public Const (Expression constant_type, string name, Expression expr, int mod_flags,
+                             Attributes attrs, Location loc)
+                       : base (name, loc)
+               {
+                       ConstantType = constant_type;
+                       Name = name;
+                       Expr = expr;
+                       ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
+                       OptAttributes = attrs;
+               }
+
+               public FieldAttributes FieldAttr {
+                       get {
+                               return FieldAttributes.Literal | FieldAttributes.Static |
+                                       Modifiers.FieldAttr (ModFlags) ;
+                       }
+               }
+
+#if DEBUG
+               void dump_tree (Type t)
+               {
+                       Console.WriteLine ("Dumping hierarchy");
+                       while (t != null){
+                               Console.WriteLine ("   " + t.FullName + " " +
+                                       (t.GetType ().IsEnum ? "yes" : "no"));
+                               t = t.BaseType;
+                       }
+               }
+#endif
+
+               /// <summary>
+               ///   Defines the constant in the @parent
+               /// </summary>
+               public override bool Define (TypeContainer parent)
+               {
+                       type = parent.ResolveType (ConstantType, false, Location);
+
+                       if (type == null)
+                               return false;
+
+                       const_ec = new EmitContext (parent, Location, null, type, ModFlags);
+                       
+                       if (!TypeManager.IsBuiltinType (type) &&
+                           (!type.IsSubclassOf (TypeManager.enum_type))) {
+                               Report.Error (
+                                       -3, Location,
+                                       "Constant type is not valid (only system types are allowed)");
+                               return false;
+                       }
+
+                       Type ptype = parent.TypeBuilder.BaseType;
+
+                       if (ptype != null) {
+                               MemberList list = TypeContainer.FindMembers (
+                                       ptype, MemberTypes.Field, BindingFlags.Public,
+                                       Type.FilterName, Name);
+                               
+                               if (list.Count == 0)
+                                       if ((ModFlags & Modifiers.NEW) != 0)
+                                               WarningNotHiding (parent);
+
+                       } else if ((ModFlags & Modifiers.NEW) != 0)
+                               WarningNotHiding (parent);
+
+                       FieldBuilder = parent.TypeBuilder.DefineField (Name, type, FieldAttr);
+
+                       TypeManager.RegisterConstant (FieldBuilder, this);
+
+                       return true;
+               }
+
+               /// <summary>
+               ///  Looks up the value of a constant field. Defines it if it hasn't
+               ///  already been. Similar to LookupEnumValue in spirit.
+               /// </summary>
+               public object LookupConstantValue ()
+               {
+                       if (ConstantValue != null)
+                               return ConstantValue;
+
+                       if (in_transit) {
+                               Report.Error (110, Location,
+                                             "The evaluation of the constant value for `" +
+                                             Name + "' involves a circular definition.");
+                               return null;
+                       }
+
+                       in_transit = true;
+                       int errors = Report.Errors;
+
+                       Expr = Expr.Resolve (const_ec);
+
+                       in_transit = false;
+
+                       if (Expr == null) {
+                               if (errors == Report.Errors)
+                                       Report.Error (150, Location, "A constant value is expected");
+                               return null;
+                       }
+
+                       if (!(Expr is Constant)) {
+                               UnCheckedExpr un_expr = Expr as UnCheckedExpr;
+                               CheckedExpr ch_expr = Expr as CheckedExpr;
+
+                               if ((un_expr != null) && (un_expr.Expr is Constant))
+                                       Expr = un_expr.Expr;
+                               else if ((ch_expr != null) && (ch_expr.Expr is Constant))
+                                       Expr = ch_expr.Expr;
+                               else {
+                                       if (errors == Report.Errors)
+                                               Report.Error (150, Location, "A constant value is expected");
+                                       return null;
+                               }
+                       }
+
+                       ConstantValue = ((Constant) Expr).GetValue ();
+
+                       if (type != Expr.Type) {
+                               bool fail;
+
+                               // from the null type to any reference-type.
+                               if (Expr is NullLiteral && !type.IsValueType &&
+                                   !TypeManager.IsEnumType (type)){
+                                       return NullLiteral.Null;
+                               }
+                               
+                               ConstantValue = TypeManager.ChangeType (ConstantValue, type, out fail);
+                               if (fail){
+                                       Convert.Error_CannotImplicitConversion (Location, Expr.Type, type);
+                                       return null;
+                               }
+
+                               if (type == TypeManager.int32_type)
+                                       Expr = new IntConstant ((int) ConstantValue);
+                               else if (type == TypeManager.uint32_type)
+                                       Expr = new UIntConstant ((uint) ConstantValue);
+                               else if (type == TypeManager.int64_type)
+                                       Expr = new LongConstant ((long) ConstantValue);
+                               else if (type == TypeManager.uint64_type)
+                                       Expr = new ULongConstant ((ulong) ConstantValue);
+                               else if (type == TypeManager.float_type)
+                                       Expr = new FloatConstant ((float) ConstantValue);
+                               else if (type == TypeManager.double_type)
+                                       Expr = new DoubleConstant ((double) ConstantValue);
+                               else if (type == TypeManager.string_type)
+                                       Expr = new StringConstant ((string) ConstantValue);
+                               else if (type == TypeManager.short_type)
+                                       Expr = new ShortConstant ((short) ConstantValue);
+                               else if (type == TypeManager.ushort_type)
+                                       Expr = new UShortConstant ((ushort) ConstantValue);
+                               else if (type == TypeManager.sbyte_type)
+                                       Expr = new SByteConstant ((sbyte) ConstantValue);
+                               else if (type == TypeManager.byte_type)
+                                       Expr = new ByteConstant ((byte) ConstantValue);
+                               else if (type == TypeManager.char_type)
+                                       Expr = new CharConstant ((char) ConstantValue);
+                               else if (type == TypeManager.bool_type)
+                                       Expr = new BoolConstant ((bool) ConstantValue);
+                       }
+
+                       if (type.IsEnum){
+                               //
+                               // This sadly does not work for our user-defined enumerations types ;-(
+                               //
+                               try {
+                                       ConstantValue = System.Enum.ToObject (
+                                               type, ConstantValue);
+                               } catch (ArgumentException){
+                                       Report.Error (
+                                               -16, Location,
+                                               ".NET SDK 1.0 does not permit to create the constant "+
+                                               " field from a user-defined enumeration");
+                               }
+                       }
+
+                       FieldBuilder.SetConstant (ConstantValue);
+
+                       if (!TypeManager.RegisterFieldValue (FieldBuilder, ConstantValue))
+                               return null;
+
+                       return ConstantValue;
+               }
+               
+               
+               /// <summary>
+               ///  Emits the field value by evaluating the expression
+               /// </summary>
+               public void EmitConstant (TypeContainer parent)
+               {
+                       LookupConstantValue ();
+                       
+                       return;
+               }
+       }
+}
+
+
diff --git a/mcs/gmcs/constant.cs b/mcs/gmcs/constant.cs
new file mode 100755 (executable)
index 0000000..2e79afb
--- /dev/null
@@ -0,0 +1,974 @@
+//
+// constant.cs: Constants.
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc.
+//
+//
+
+namespace Mono.CSharp {
+
+       using System;
+       using System.Reflection.Emit;
+
+       /// <summary>
+       ///   Base class for constants and literals.
+       /// </summary>
+       public abstract class Constant : Expression {
+               /// <remarks>
+               ///   This is different from ToString in that ToString
+               ///   is supposed to be there for debugging purposes,
+               ///   and is not guaranteed to be useful for anything else,
+               ///   AsString() will provide something that can be used
+               ///   for round-tripping C# code.  Maybe it can be used
+               ///   for IL assembly as well.
+               /// </remarks>
+               public abstract string AsString ();
+
+               override public string ToString ()
+               {
+                       return this.GetType ().Name + " (" + AsString () + ")";
+               }
+
+               /// <summary>
+               ///  This is used to obtain the actual value of the literal
+               ///  cast into an object.
+               /// </summary>
+               public abstract object GetValue ();
+
+               /// <summary>
+               ///   Constants are always born in a fully resolved state
+               /// </summary>
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               //
+               // The various ToXXXX conversion functions are used by the constant
+               // folding evaluator.   A null value is returned if the conversion is
+               // not possible.   
+               //
+               // Note: not all the patterns for catching `implicit_conv' are the same.
+               // some implicit conversions can never be performed between two types
+               // even if the conversion would be lossless (for example short to uint),
+               // but some conversions are explicitly permitted by the standard provided
+               // that there will be no loss of information (for example, int to uint).
+               //
+               public DoubleConstant ToDouble (Location loc)
+               {
+                       DoubleConstant c = ConvertToDouble ();
+
+                       if (c == null)
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.double_type);
+
+                       return c;
+               }
+
+               public FloatConstant ToFloat (Location loc)
+               {
+                       FloatConstant c = ConvertToFloat ();
+
+                       if (c == null)
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.float_type);
+
+                       return c;
+               }
+
+               public ULongConstant ToULong (Location loc)
+               {
+                       ULongConstant c = ConvertToULong ();
+
+                       if (c == null)
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint64_type);
+
+                       return c;
+               }
+
+               public LongConstant ToLong (Location loc)
+               {
+                       LongConstant c = ConvertToLong ();
+
+                       if (c == null)
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int64_type);
+
+                       return c;
+               }
+               
+               public UIntConstant ToUInt (Location loc)
+               {
+                       UIntConstant c = ConvertToUInt ();
+
+                       if (c == null)
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint32_type);
+
+                       return c;
+               }
+
+               public IntConstant ToInt (Location loc)
+               {
+                       IntConstant c = ConvertToInt ();
+
+                       if (c == null)
+                               Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int32_type);
+
+                       return c;
+               }
+               
+               public virtual DoubleConstant ConvertToDouble ()
+               {
+                       return null;
+               }
+
+               public virtual FloatConstant ConvertToFloat ()
+               {
+                       return null;
+               }
+
+               public virtual ULongConstant ConvertToULong ()
+               {
+                       return null;
+               }
+
+               public virtual LongConstant ConvertToLong ()
+               {
+                       return null;
+               }
+
+               public virtual UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public virtual IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
+       }
+       
+       public class BoolConstant : Constant {
+               public readonly bool Value;
+               
+               public BoolConstant (bool val)
+               {
+                       type = TypeManager.bool_type;
+                       eclass = ExprClass.Value;
+
+                       Value = val;
+               }
+
+               override public string AsString ()
+               {
+                       return Value ? "true" : "false";
+               }
+
+               public override object GetValue ()
+               {
+                       return (object) Value;
+               }
+                               
+               
+               public override void Emit (EmitContext ec)
+               {
+                       if (Value)
+                               ec.ig.Emit (OpCodes.Ldc_I4_1);
+                       else
+                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+               }
+       }
+
+       public class ByteConstant : Constant {
+               public readonly byte Value;
+
+               public ByteConstant (byte v)
+               {
+                       type = TypeManager.byte_type;
+                       eclass = ExprClass.Value;
+                       Value = v;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       IntLiteral.EmitInt (ec.ig, Value);
+               }
+
+               public override string AsString ()
+               {
+                       return Value.ToString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return new ULongConstant (Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return new UIntConstant (Value);
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return new IntConstant (Value);
+               }
+       }
+
+       public class CharConstant : Constant {
+               public readonly char Value;
+
+               public CharConstant (char v)
+               {
+                       type = TypeManager.char_type;
+                       eclass = ExprClass.Value;
+                       Value = v;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       IntLiteral.EmitInt (ec.ig, Value);
+               }
+
+               static public string descape (char c)
+               {
+                       switch (c){
+                       case '\a':
+                               return "\\a"; 
+                       case '\b':
+                               return "\\b"; 
+                       case '\n':
+                               return "\\n"; 
+                       case '\t':
+                               return "\\t"; 
+                       case '\v':
+                               return "\\v"; 
+                       case '\r':
+                               return "\\r"; 
+                       case '\\':
+                               return "\\\\";
+                       case '\f':
+                               return "\\f"; 
+                       case '\0':
+                               return "\\0"; 
+                       case '"':
+                               return "\\\""; 
+                       case '\'':
+                               return "\\\'"; 
+                       }
+                       return c.ToString ();
+               }
+
+               public override string AsString ()
+               {
+                       return "\"" + descape (Value) + "\"";
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return new ULongConstant (Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return new UIntConstant (Value);
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return new IntConstant (Value);
+               }
+       }
+
+       public class SByteConstant : Constant {
+               public readonly sbyte Value;
+
+               public SByteConstant (sbyte v)
+               {
+                       type = TypeManager.sbyte_type;
+                       eclass = ExprClass.Value;
+                       Value = v;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       IntLiteral.EmitInt (ec.ig, Value);
+               }
+
+               public override string AsString ()
+               {
+                       return Value.ToString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       if (Value >= 0)
+                               return new ULongConstant ((ulong) Value);
+                       
+                       return null;
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return new IntConstant (Value);
+               }
+       }
+
+       public class ShortConstant : Constant {
+               public readonly short Value;
+
+               public ShortConstant (short v)
+               {
+                       type = TypeManager.short_type;
+                       eclass = ExprClass.Value;
+                       Value = v;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       IntLiteral.EmitInt (ec.ig, Value);
+               }
+
+               public override string AsString ()
+               {
+                       return Value.ToString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return null;
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return new IntConstant (Value);
+               }
+       }
+
+       public class UShortConstant : Constant {
+               public readonly ushort Value;
+
+               public UShortConstant (ushort v)
+               {
+                       type = TypeManager.ushort_type;
+                       eclass = ExprClass.Value;
+                       Value = v;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       IntLiteral.EmitInt (ec.ig, Value);
+               }
+
+               public override string AsString ()
+               {
+                       return Value.ToString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return new ULongConstant (Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return new UIntConstant (Value);
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return new IntConstant (Value);
+               }
+       }
+
+       public class IntConstant : Constant {
+               public readonly int Value;
+
+               public IntConstant (int v)
+               {
+                       type = TypeManager.int32_type;
+                       eclass = ExprClass.Value;
+                       Value = v;
+               }
+
+               static public void EmitInt (ILGenerator ig, int i)
+               {
+                       switch (i){
+                       case -1:
+                               ig.Emit (OpCodes.Ldc_I4_M1);
+                               break;
+                               
+                       case 0:
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               break;
+                               
+                       case 1:
+                               ig.Emit (OpCodes.Ldc_I4_1);
+                               break;
+                               
+                       case 2:
+                               ig.Emit (OpCodes.Ldc_I4_2);
+                               break;
+                               
+                       case 3:
+                               ig.Emit (OpCodes.Ldc_I4_3);
+                               break;
+                               
+                       case 4:
+                               ig.Emit (OpCodes.Ldc_I4_4);
+                               break;
+                               
+                       case 5:
+                               ig.Emit (OpCodes.Ldc_I4_5);
+                               break;
+                               
+                       case 6:
+                               ig.Emit (OpCodes.Ldc_I4_6);
+                               break;
+                               
+                       case 7:
+                               ig.Emit (OpCodes.Ldc_I4_7);
+                               break;
+                               
+                       case 8:
+                               ig.Emit (OpCodes.Ldc_I4_8);
+                               break;
+
+                       default:
+                               if (i >= -128 && i <= 127){
+                                       ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
+                               } else
+                                       ig.Emit (OpCodes.Ldc_I4, i);
+                               break;
+                       }
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       EmitInt (ec.ig, Value);
+               }
+
+               public override string AsString ()
+               {
+                       return Value.ToString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       if (Value < 0)
+                               return null;
+
+                       return new ULongConstant ((ulong) Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       if (Value < 0)
+                               return null;
+
+                       return new UIntConstant ((uint) Value);
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return this;
+               }
+       }
+
+       public class UIntConstant : Constant {
+               public readonly uint Value;
+
+               public UIntConstant (uint v)
+               {
+                       type = TypeManager.uint32_type;
+                       eclass = ExprClass.Value;
+                       Value = v;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
+               }
+
+               public override string AsString ()
+               {
+                       return Value.ToString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return new ULongConstant (Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return new LongConstant (Value);
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return this;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
+       }
+
+       public class LongConstant : Constant {
+               public readonly long Value;
+
+               public LongConstant (long v)
+               {
+                       type = TypeManager.int64_type;
+                       eclass = ExprClass.Value;
+                       Value = v;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       EmitLong (ig, Value);
+               }
+
+               static public void EmitLong (ILGenerator ig, long l)
+               {
+                       if ((l >> 32) == 0){
+                               IntLiteral.EmitInt (ig, unchecked ((int) l));
+                               ig.Emit (OpCodes.Conv_U8);
+                       } else {
+                               ig.Emit (OpCodes.Ldc_I8, l);
+                       }
+               }
+
+               public override string AsString ()
+               {
+                       return Value.ToString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       if (Value < 0)
+                               return null;
+                       
+                       return new ULongConstant ((ulong) Value);
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return this;
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
+       }
+
+       public class ULongConstant : Constant {
+               public readonly ulong Value;
+
+               public ULongConstant (ulong v)
+               {
+                       type = TypeManager.uint64_type;
+                       eclass = ExprClass.Value;
+                       Value = v;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       LongLiteral.EmitLong (ig, unchecked ((long) Value));
+               }
+
+               public override string AsString ()
+               {
+                       return Value.ToString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return new FloatConstant (Value);
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return this;
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return null;
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
+       }
+
+       public class FloatConstant : Constant {
+               public readonly float Value;
+
+               public FloatConstant (float v)
+               {
+                       type = TypeManager.float_type;
+                       eclass = ExprClass.Value;
+                       Value = v;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldc_R4, Value);
+               }
+
+               public override string AsString ()
+               {
+                       return Value.ToString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return new DoubleConstant (Value);
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return this;
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return null;
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
+       }
+
+       public class DoubleConstant : Constant {
+               public readonly double Value;
+
+               public DoubleConstant (double v)
+               {
+                       type = TypeManager.double_type;
+                       eclass = ExprClass.Value;
+                       Value = v;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldc_R8, Value);
+               }
+
+               public override string AsString ()
+               {
+                       return Value.ToString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return this;
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return null;
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return null;
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return null;
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return null;
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return null;
+               }
+       }
+
+       public class DecimalConstant : Constant {
+               public readonly decimal Value;
+
+               public DecimalConstant (decimal d)
+               {
+                       type = TypeManager.decimal_type;
+                       eclass = ExprClass.Value;
+                       Value = d;
+               }
+
+               override public string AsString ()
+               {
+                       return Value.ToString ();
+               }
+
+               public override object GetValue ()
+               {
+                       return (object) Value;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       int [] words = Decimal.GetBits (Value);
+                       
+                       //
+                       // FIXME: we could optimize this, and call a better 
+                       // constructor
+                       //
+
+                       ILGenerator ig = ec.ig;
+                       
+                       IntConstant.EmitInt (ig, words [0]);
+                       IntConstant.EmitInt (ig, words [1]);
+                       IntConstant.EmitInt (ig, words [2]);
+
+                       // sign
+                       IntConstant.EmitInt (ig, words [3] >> 31);
+
+                       // power
+                       IntConstant.EmitInt (ig, (words [3] >> 16) & 0xff);
+
+                       ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
+               }
+       }
+
+       public class StringConstant : Constant {
+               public readonly string Value;
+
+               public StringConstant (string s)
+               {
+                       type = TypeManager.string_type;
+                       eclass = ExprClass.Value;
+                       Value = s;
+               }
+
+               // FIXME: Escape the string.
+               override public string AsString ()
+               {
+                       return "\"" + Value + "\"";
+               }
+
+               public override object GetValue ()
+               {
+                       return Value;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldstr, Value);
+               }
+       }
+
+}
+
+
diff --git a/mcs/gmcs/convert.cs b/mcs/gmcs/convert.cs
new file mode 100644 (file)
index 0000000..ad577ca
--- /dev/null
@@ -0,0 +1,1722 @@
+//
+// conversion.cs: various routines for implementing conversions.
+//
+// Authors:
+//   Miguel de Icaza (miguel@ximian.com)
+//   Ravi Pratap (ravi@ximian.com)
+//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+//
+
+namespace Mono.CSharp {
+       using System;
+       using System.Collections;
+       using System.Diagnostics;
+       using System.Reflection;
+       using System.Reflection.Emit;
+
+       //
+       // A container class for all the conversion operations
+       //
+       public class Convert {
+               static public void Error_CannotConvertType (Location loc, Type source, Type target)
+               {
+                       Report.Error (30, loc, "Cannot convert type '" +
+                                     TypeManager.CSharpName (source) + "' to '" +
+                                     TypeManager.CSharpName (target) + "'");
+               }
+
+               static EmptyExpression MyEmptyExpr;
+               static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
+               {
+                       Type expr_type = expr.Type;
+
+                       if (expr_type == null && expr.eclass == ExprClass.MethodGroup){
+                               // if we are a method group, emit a warning
+
+                               expr.Emit (null);
+                       }
+
+                       //
+                       // notice that it is possible to write "ValueType v = 1", the ValueType here
+                       // is an abstract class, and not really a value type, so we apply the same rules.
+                       //
+                       if (target_type == TypeManager.object_type) {
+                               //
+                               // A pointer type cannot be converted to object
+                               // 
+                               if (expr_type.IsPointer)
+                                       return null;
+
+                               if (expr_type.IsValueType)
+                                       return new BoxedCast (expr);
+                               if (expr_type.IsClass || expr_type.IsInterface || expr_type == TypeManager.enum_type)
+                                       return new EmptyCast (expr, target_type);
+                       } else if (target_type == TypeManager.value_type) {
+                               if (expr_type.IsValueType)
+                                       return new BoxedCast (expr);
+                               if (expr is NullLiteral)
+                                       return new BoxedCast (expr);
+                       } else if (expr_type.IsSubclassOf (target_type)) {
+                               //
+                               // Special case: enumeration to System.Enum.
+                               // System.Enum is not a value type, it is a class, so we need
+                               // a boxing conversion
+                               //
+                               if (expr_type.IsEnum)
+                                       return new BoxedCast (expr);
+
+                               return new EmptyCast (expr, target_type);
+                       } else {
+
+                               // This code is kind of mirrored inside ImplicitStandardConversionExists
+                               // with the small distinction that we only probe there
+                               //
+                               // Always ensure that the code here and there is in sync
+
+                               // from the null type to any reference-type.
+                               if (expr is NullLiteral){
+                                       if (target_type.IsPointer)
+                                               return NullPointer.Null;
+                                       
+                                       if (!target_type.IsValueType)
+                                               return new NullCast (expr, target_type);
+                               }
+
+                               // from any class-type S to any interface-type T.
+                               if (target_type.IsInterface) {
+                                       if (TypeManager.ImplementsInterface (expr_type, target_type)){
+                                               if (expr_type.IsClass)
+                                                       return new EmptyCast (expr, target_type);
+                                               else if (expr_type.IsValueType)
+                                                       return new BoxedCast (expr, target_type);
+                                       }
+                               }
+
+                               // from any interface type S to interface-type T.
+                               if (expr_type.IsInterface && target_type.IsInterface) {
+                                       if (TypeManager.ImplementsInterface (expr_type, target_type))
+                                               return new EmptyCast (expr, target_type);
+                                       else
+                                               return null;
+                               }
+                               
+                               // from an array-type S to an array-type of type T
+                               if (expr_type.IsArray && target_type.IsArray) {
+                                       if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
+
+                                               Type expr_element_type = TypeManager.GetElementType (expr_type);
+
+                                               if (MyEmptyExpr == null)
+                                                       MyEmptyExpr = new EmptyExpression ();
+                                               
+                                               MyEmptyExpr.SetType (expr_element_type);
+                                               Type target_element_type = TypeManager.GetElementType (target_type);
+
+                                               if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
+                                                       if (ImplicitStandardConversionExists (MyEmptyExpr,
+                                                                                     target_element_type))
+                                                               return new EmptyCast (expr, target_type);
+                                       }
+                               }
+                               
+                               
+                               // from an array-type to System.Array
+                               if (expr_type.IsArray && target_type == TypeManager.array_type)
+                                       return new EmptyCast (expr, target_type);
+                               
+                               // from any delegate type to System.Delegate
+                               if ((expr_type == TypeManager.delegate_type || 
+                                    expr_type.IsSubclassOf (TypeManager.delegate_type)) &&
+                                   target_type == TypeManager.delegate_type)
+                                       return new EmptyCast (expr, target_type);
+                                       
+                               // from any array-type or delegate type into System.ICloneable.
+                               if (expr_type.IsArray ||
+                                   expr_type == TypeManager.delegate_type ||
+                                   expr_type.IsSubclassOf (TypeManager.delegate_type))
+                                       if (target_type == TypeManager.icloneable_type)
+                                               return new EmptyCast (expr, target_type);
+                               
+                               return null;
+
+                       }
+                       
+                       return null;
+               }
+
+               //
+               // Tests whether an implicit reference conversion exists between expr_type
+               // and target_type
+               //
+               public static bool ImplicitReferenceConversionExists (Expression expr, Type target_type)
+               {
+                       Type expr_type = expr.Type;
+
+                       //
+                       // This is the boxed case.
+                       //
+                       if (target_type == TypeManager.object_type) {
+                               if (expr_type.IsClass || expr_type.IsValueType ||
+                                   expr_type.IsInterface || expr_type == TypeManager.enum_type)
+                                       return true;
+                       } else if (expr_type.IsSubclassOf (target_type)) {
+                               return true;
+                       } else {
+                               // Please remember that all code below actually comes
+                               // from ImplicitReferenceConversion so make sure code remains in sync
+                               
+                               // from any class-type S to any interface-type T.
+                               if (target_type.IsInterface) {
+                                       if (TypeManager.ImplementsInterface (expr_type, target_type))
+                                               return true;
+                               }
+                               
+                               // from any interface type S to interface-type T.
+                               if (expr_type.IsInterface && target_type.IsInterface)
+                                       if (TypeManager.ImplementsInterface (expr_type, target_type))
+                                               return true;
+                               
+                               // from an array-type S to an array-type of type T
+                               if (expr_type.IsArray && target_type.IsArray) {
+                                       if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
+                                               
+                                               Type expr_element_type = expr_type.GetElementType ();
+
+                                               if (MyEmptyExpr == null)
+                                                       MyEmptyExpr = new EmptyExpression ();
+                                               
+                                               MyEmptyExpr.SetType (expr_element_type);
+                                               Type target_element_type = TypeManager.GetElementType (target_type);
+                                               
+                                               if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
+                                                       if (ImplicitStandardConversionExists (MyEmptyExpr,
+                                                                                     target_element_type))
+                                                               return true;
+                                       }
+                               }
+                               
+                               // from an array-type to System.Array
+                               if (expr_type.IsArray && (target_type == TypeManager.array_type))
+                                       return true;
+                               
+                               // from any delegate type to System.Delegate
+                               if ((expr_type == TypeManager.delegate_type ||
+                                    expr_type.IsSubclassOf (TypeManager.delegate_type)) &&
+                                   target_type == TypeManager.delegate_type)
+                                       if (target_type.IsAssignableFrom (expr_type))
+                                               return true;
+                                       
+                               // from any array-type or delegate type into System.ICloneable.
+                               if (expr_type.IsArray ||
+                                   expr_type == TypeManager.delegate_type ||
+                                   expr_type.IsSubclassOf (TypeManager.delegate_type))
+                                       if (target_type == TypeManager.icloneable_type)
+                                               return true;
+                               
+                               // from the null type to any reference-type.
+                               if (expr is NullLiteral && !target_type.IsValueType &&
+                                   !TypeManager.IsEnumType (target_type))
+                                       return true;
+                               
+                       }
+                       return false;
+               }
+
+               /// <summary>
+               ///   Implicit Numeric Conversions.
+               ///
+               ///   expr is the expression to convert, returns a new expression of type
+               ///   target_type or null if an implicit conversion is not possible.
+               /// </summary>
+               static public Expression ImplicitNumericConversion (EmitContext ec, Expression expr,
+                                                                   Type target_type, Location loc)
+               {
+                       Type expr_type = expr.Type;
+                       
+                       //
+                       // Attempt to do the implicit constant expression conversions
+
+                       if (expr is Constant){
+                               
+                               if (expr is IntConstant){
+                                       Expression e;
+                                       
+                                       e = TryImplicitIntConversion (target_type, (IntConstant) expr);
+                                       
+                                       if (e != null)
+                                               return e;
+                               } else if (expr is LongConstant && target_type == TypeManager.uint64_type){
+                                       //
+                                       // Try the implicit constant expression conversion
+                                       // from long to ulong, instead of a nice routine,
+                                       // we just inline it
+                                       //
+                                       long v = ((LongConstant) expr).Value;
+                                       if (v > 0)
+                                               return new ULongConstant ((ulong) v);
+                               } 
+                       }
+                       
+                       Type real_target_type = target_type;
+
+                       if (expr_type == TypeManager.sbyte_type){
+                               //
+                               // From sbyte to short, int, long, float, double.
+                               //
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
+                       } else if (expr_type == TypeManager.byte_type){
+                               //
+                               // From byte to short, ushort, int, uint, long, ulong, float, double
+                               // 
+                               if ((real_target_type == TypeManager.short_type) ||
+                                   (real_target_type == TypeManager.ushort_type) ||
+                                   (real_target_type == TypeManager.int32_type) ||
+                                   (real_target_type == TypeManager.uint32_type))
+                                       return new EmptyCast (expr, target_type);
+
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                       } else if (expr_type == TypeManager.short_type){
+                               //
+                               // From short to int, long, float, double
+                               // 
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new EmptyCast (expr, target_type);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                       } else if (expr_type == TypeManager.ushort_type){
+                               //
+                               // From ushort to int, uint, long, ulong, float, double
+                               //
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new EmptyCast (expr, target_type);
+
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                       } else if (expr_type == TypeManager.int32_type){
+                               //
+                               // From int to long, float, double
+                               //
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                       } else if (expr_type == TypeManager.uint32_type){
+                               //
+                               // From uint to long, ulong, float, double
+                               //
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R4);
+                       } else if (expr_type == TypeManager.int64_type){
+                               //
+                               // From long/ulong to float, double
+                               //
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);     
+                       } else if (expr_type == TypeManager.uint64_type){
+                               //
+                               // From ulong to float, double
+                               //
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
+                                                              OpCodes.Conv_R4);        
+                       } else if (expr_type == TypeManager.char_type){
+                               //
+                               // From char to ushort, int, uint, long, ulong, float, double
+                               // 
+                               if ((real_target_type == TypeManager.ushort_type) ||
+                                   (real_target_type == TypeManager.int32_type) ||
+                                   (real_target_type == TypeManager.uint32_type))
+                                       return new EmptyCast (expr, target_type);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                       } else if (expr_type == TypeManager.float_type){
+                               //
+                               // float to double
+                               //
+                               if (real_target_type == TypeManager.double_type)
+                                       return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+                       }
+
+                       return null;
+               }
+
+
+               /// <summary>
+               ///  Same as ImplicitStandardConversionExists except that it also looks at
+               ///  implicit user defined conversions - needed for overload resolution
+               /// </summary>
+               public static bool ImplicitConversionExists (EmitContext ec, Expression expr, Type target_type)
+               {
+                       if (ImplicitStandardConversionExists (expr, target_type))
+                               return true;
+
+                       Expression dummy = ImplicitUserConversion (ec, expr, target_type, Location.Null);
+
+                       if (dummy != null)
+                               return true;
+
+                       return false;
+               }
+
+               public static bool ImplicitUserConversionExists (EmitContext ec, Type source, Type target)
+               {
+                       Expression dummy = ImplicitUserConversion (
+                               ec, new EmptyExpression (source), target, Location.Null);
+                       return dummy != null;
+               }
+
+               /// <summary>
+               ///  Determines if a standard implicit conversion exists from
+               ///  expr_type to target_type
+               /// </summary>
+               public static bool ImplicitStandardConversionExists (Expression expr, Type target_type)
+               {
+                       Type expr_type = expr.Type;
+
+                       if (expr_type == TypeManager.void_type)
+                               return false;
+
+                        //Console.WriteLine ("Expr is {0}", expr);
+                        //Console.WriteLine ("{0} -> {1} ?", expr_type, target_type);
+                       if (expr_type == target_type)
+                               return true;
+
+                        //Console.WriteLine ("No !!");
+
+                       // First numeric conversions 
+
+                       if (expr_type == TypeManager.sbyte_type){
+                               //
+                               // From sbyte to short, int, long, float, double.
+                               //
+                               if ((target_type == TypeManager.int32_type) || 
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type)  ||
+                                   (target_type == TypeManager.short_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                               
+                       } else if (expr_type == TypeManager.byte_type){
+                               //
+                               // From byte to short, ushort, int, uint, long, ulong, float, double
+                               // 
+                               if ((target_type == TypeManager.short_type) ||
+                                   (target_type == TypeManager.ushort_type) ||
+                                   (target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.uint32_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+       
+                       } else if (expr_type == TypeManager.short_type){
+                               //
+                               // From short to int, long, float, double
+                               // 
+                               if ((target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                                       
+                       } else if (expr_type == TypeManager.ushort_type){
+                               //
+                               // From ushort to int, uint, long, ulong, float, double
+                               //
+                               if ((target_type == TypeManager.uint32_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                                   
+                       } else if (expr_type == TypeManager.int32_type){
+                               //
+                               // From int to long, float, double
+                               //
+                               if ((target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                                       
+                       } else if (expr_type == TypeManager.uint32_type){
+                               //
+                               // From uint to long, ulong, float, double
+                               //
+                               if ((target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                                       
+                       } else if ((expr_type == TypeManager.uint64_type) ||
+                                  (expr_type == TypeManager.int64_type)) {
+                               //
+                               // From long/ulong to float, double
+                               //
+                               if ((target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                                   
+                       } else if (expr_type == TypeManager.char_type){
+                               //
+                               // From char to ushort, int, uint, long, ulong, float, double
+                               // 
+                               if ((target_type == TypeManager.ushort_type) ||
+                                   (target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.uint32_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+
+                       } else if (expr_type == TypeManager.float_type){
+                               //
+                               // float to double
+                               //
+                               if (target_type == TypeManager.double_type)
+                                       return true;
+                       }       
+                       
+                       if (ImplicitReferenceConversionExists (expr, target_type))
+                               return true;
+                       
+                       if (expr is IntConstant){
+                               int value = ((IntConstant) expr).Value;
+
+                               if (target_type == TypeManager.sbyte_type){
+                                       if (value >= SByte.MinValue && value <= SByte.MaxValue)
+                                               return true;
+                               } else if (target_type == TypeManager.byte_type){
+                                       if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
+                                               return true;
+                               } else if (target_type == TypeManager.short_type){
+                                       if (value >= Int16.MinValue && value <= Int16.MaxValue)
+                                               return true;
+                               } else if (target_type == TypeManager.ushort_type){
+                                       if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
+                                               return true;
+                               } else if (target_type == TypeManager.uint32_type){
+                                       if (value >= 0)
+                                               return true;
+                               } else if (target_type == TypeManager.uint64_type){
+                                        //
+                                        // we can optimize this case: a positive int32
+                                        // always fits on a uint64.  But we need an opcode
+                                        // to do it.
+                                        //
+                                       if (value >= 0)
+                                               return true;
+                               }
+                               
+                               if (value == 0 && expr is IntLiteral && TypeManager.IsEnumType (target_type))
+                                       return true;
+                       }
+
+                       if (expr is LongConstant && target_type == TypeManager.uint64_type){
+                               //
+                               // Try the implicit constant expression conversion
+                               // from long to ulong, instead of a nice routine,
+                               // we just inline it
+                               //
+                               long v = ((LongConstant) expr).Value;
+                               if (v > 0)
+                                       return true;
+                       }
+                       
+                       if ((target_type == TypeManager.enum_type ||
+                            target_type.IsSubclassOf (TypeManager.enum_type)) &&
+                            expr is IntLiteral){
+                               IntLiteral i = (IntLiteral) expr;
+
+                               if (i.Value == 0)
+                                       return true;
+                       }
+
+                       if (target_type == TypeManager.void_ptr_type && expr_type.IsPointer)
+                               return true;
+
+                       return false;
+               }
+
+               //
+               // Used internally by FindMostEncompassedType, this is used
+               // to avoid creating lots of objects in the tight loop inside
+               // FindMostEncompassedType
+               //
+               static EmptyExpression priv_fmet_param;
+               
+               /// <summary>
+               ///  Finds "most encompassed type" according to the spec (13.4.2)
+               ///  amongst the methods in the MethodGroupExpr
+               /// </summary>
+               static Type FindMostEncompassedType (ArrayList types)
+               {
+                       Type best = null;
+
+                       if (priv_fmet_param == null)
+                               priv_fmet_param = new EmptyExpression ();
+
+                       foreach (Type t in types){
+                               priv_fmet_param.SetType (t);
+                               
+                               if (best == null) {
+                                       best = t;
+                                       continue;
+                               }
+                               
+                               if (ImplicitStandardConversionExists (priv_fmet_param, best))
+                                       best = t;
+                       }
+
+                       return best;
+               }
+
+               //
+               // Used internally by FindMostEncompassingType, this is used
+               // to avoid creating lots of objects in the tight loop inside
+               // FindMostEncompassingType
+               //
+               static EmptyExpression priv_fmee_ret;
+               
+               /// <summary>
+               ///  Finds "most encompassing type" according to the spec (13.4.2)
+               ///  amongst the types in the given set
+               /// </summary>
+               static Type FindMostEncompassingType (ArrayList types)
+               {
+                       Type best = null;
+
+                       if (priv_fmee_ret == null)
+                               priv_fmee_ret = new EmptyExpression ();
+
+                       foreach (Type t in types){
+                               priv_fmee_ret.SetType (best);
+
+                               if (best == null) {
+                                       best = t;
+                                       continue;
+                               }
+
+                               if (ImplicitStandardConversionExists (priv_fmee_ret, t))
+                                       best = t;
+                       }
+                       
+                       return best;
+               }
+
+               //
+               // Used to avoid creating too many objects
+               //
+               static EmptyExpression priv_fms_expr;
+               
+               /// <summary>
+               ///   Finds the most specific source Sx according to the rules of the spec (13.4.4)
+               ///   by making use of FindMostEncomp* methods. Applies the correct rules separately
+               ///   for explicit and implicit conversion operators.
+               /// </summary>
+               static public Type FindMostSpecificSource (MethodGroupExpr me, Expression source,
+                                                          bool apply_explicit_conv_rules,
+                                                          Location loc)
+               {
+                       ArrayList src_types_set = new ArrayList ();
+                       
+                       if (priv_fms_expr == null)
+                               priv_fms_expr = new EmptyExpression ();
+
+                       //
+                       // If any operator converts from S then Sx = S
+                       //
+                       Type source_type = source.Type;
+                       foreach (MethodBase mb in me.Methods){
+                               ParameterData pd = Invocation.GetParameterData (mb);
+                               Type param_type = pd.ParameterType (0);
+
+                               if (param_type == source_type)
+                                       return param_type;
+
+                               if (apply_explicit_conv_rules) {
+                                       //
+                                       // From the spec :
+                                       // Find the set of applicable user-defined conversion operators, U.  This set
+                                       // consists of the
+                                       // user-defined implicit or explicit conversion operators declared by
+                                       // the classes or structs in D that convert from a type encompassing
+                                       // or encompassed by S to a type encompassing or encompassed by T
+                                       //
+                                       priv_fms_expr.SetType (param_type);
+                                       if (ImplicitStandardConversionExists (priv_fms_expr, source_type))
+                                               src_types_set.Add (param_type);
+                                       else {
+                                               if (ImplicitStandardConversionExists (source, param_type))
+                                                       src_types_set.Add (param_type);
+                                       }
+                               } else {
+                                       //
+                                       // Only if S is encompassed by param_type
+                                       //
+                                       if (ImplicitStandardConversionExists (source, param_type))
+                                               src_types_set.Add (param_type);
+                               }
+                       }
+                       
+                       //
+                       // Explicit Conv rules
+                       //
+                       if (apply_explicit_conv_rules) {
+                               ArrayList candidate_set = new ArrayList ();
+
+                               foreach (Type param_type in src_types_set){
+                                       if (ImplicitStandardConversionExists (source, param_type))
+                                               candidate_set.Add (param_type);
+                               }
+
+                               if (candidate_set.Count != 0)
+                                       return FindMostEncompassedType (candidate_set);
+                       }
+
+                       //
+                       // Final case
+                       //
+                       if (apply_explicit_conv_rules)
+                               return FindMostEncompassingType (src_types_set);
+                       else
+                               return FindMostEncompassedType (src_types_set);
+               }
+
+               //
+               // Useful in avoiding proliferation of objects
+               //
+               static EmptyExpression priv_fmt_expr;
+               
+               /// <summary>
+               ///  Finds the most specific target Tx according to section 13.4.4
+               /// </summary>
+               static public Type FindMostSpecificTarget (MethodGroupExpr me, Type target,
+                                                          bool apply_explicit_conv_rules,
+                                                          Location loc)
+               {
+                       ArrayList tgt_types_set = new ArrayList ();
+                       
+                       if (priv_fmt_expr == null)
+                               priv_fmt_expr = new EmptyExpression ();
+                       
+                       //
+                       // If any operator converts to T then Tx = T
+                       //
+                       foreach (MethodInfo mi in me.Methods){
+                               Type ret_type = mi.ReturnType;
+
+                               if (ret_type == target)
+                                       return ret_type;
+
+                               if (apply_explicit_conv_rules) {
+                                       //
+                                       // From the spec :
+                                       // Find the set of applicable user-defined conversion operators, U.
+                                       //
+                                       // This set consists of the
+                                       // user-defined implicit or explicit conversion operators declared by
+                                       // the classes or structs in D that convert from a type encompassing
+                                       // or encompassed by S to a type encompassing or encompassed by T
+                                       //
+                                       priv_fms_expr.SetType (ret_type);
+                                       if (ImplicitStandardConversionExists (priv_fms_expr, target))
+                                               tgt_types_set.Add (ret_type);
+                                       else {
+                                               priv_fms_expr.SetType (target);
+                                               if (ImplicitStandardConversionExists (priv_fms_expr, ret_type))
+                                                       tgt_types_set.Add (ret_type);
+                                       }
+                               } else {
+                                       //
+                                       // Only if T is encompassed by param_type
+                                       //
+                                       priv_fms_expr.SetType (ret_type);
+                                       if (ImplicitStandardConversionExists (priv_fms_expr, target))
+                                               tgt_types_set.Add (ret_type);
+                               }
+                       }
+
+                       //
+                       // Explicit conv rules
+                       //
+                       if (apply_explicit_conv_rules) {
+                               ArrayList candidate_set = new ArrayList ();
+
+                               foreach (Type ret_type in tgt_types_set){
+                                       priv_fmt_expr.SetType (ret_type);
+                                       
+                                       if (ImplicitStandardConversionExists (priv_fmt_expr, target))
+                                               candidate_set.Add (ret_type);
+                               }
+
+                               if (candidate_set.Count != 0)
+                                       return FindMostEncompassingType (candidate_set);
+                       }
+                       
+                       //
+                       // Okay, final case !
+                       //
+                       if (apply_explicit_conv_rules)
+                               return FindMostEncompassedType (tgt_types_set);
+                       else 
+                               return FindMostEncompassingType (tgt_types_set);
+               }
+               
+               /// <summary>
+               ///  User-defined Implicit conversions
+               /// </summary>
+               static public Expression ImplicitUserConversion (EmitContext ec, Expression source,
+                                                                Type target, Location loc)
+               {
+                       return UserDefinedConversion (ec, source, target, loc, false);
+               }
+
+               /// <summary>
+               ///  User-defined Explicit conversions
+               /// </summary>
+               static public Expression ExplicitUserConversion (EmitContext ec, Expression source,
+                                                                Type target, Location loc)
+               {
+                       return UserDefinedConversion (ec, source, target, loc, true);
+               }
+
+               /// <summary>
+               ///   Computes the MethodGroup for the user-defined conversion
+               ///   operators from source_type to target_type.  `look_for_explicit'
+               ///   controls whether we should also include the list of explicit
+               ///   operators
+               /// </summary>
+               static MethodGroupExpr GetConversionOperators (EmitContext ec,
+                                                              Type source_type, Type target_type,
+                                                              Location loc, bool look_for_explicit)
+               {
+                       Expression mg1 = null, mg2 = null;
+                       Expression mg5 = null, mg6 = null, mg7 = null, mg8 = null;
+                       string op_name;
+
+                       op_name = "op_Implicit";
+
+                       MethodGroupExpr union3;
+
+                       mg1 = Expression.MethodLookup (ec, source_type, op_name, loc);
+                       if (source_type.BaseType != null)
+                               mg2 = Expression.MethodLookup (ec, source_type.BaseType, op_name, loc);
+
+                       if (mg1 == null)
+                               union3 = (MethodGroupExpr) mg2;
+                       else if (mg2 == null)
+                               union3 = (MethodGroupExpr) mg1;
+                       else
+                               union3 = Invocation.MakeUnionSet (mg1, mg2, loc);
+
+                       mg1 = Expression.MethodLookup (ec, target_type, op_name, loc);
+                       if (mg1 != null){
+                               if (union3 != null)
+                                       union3 = Invocation.MakeUnionSet (union3, mg1, loc);
+                               else
+                                       union3 = (MethodGroupExpr) mg1;
+                       }
+
+                       if (target_type.BaseType != null)
+                               mg1 = Expression.MethodLookup (ec, target_type.BaseType, op_name, loc);
+                       
+                       if (mg1 != null){
+                               if (union3 != null)
+                                       union3 = Invocation.MakeUnionSet (union3, mg1, loc);
+                               else
+                                       union3 = (MethodGroupExpr) mg1;
+                       }
+
+                       MethodGroupExpr union4 = null;
+
+                       if (look_for_explicit) {
+                               op_name = "op_Explicit";
+
+                               mg5 = Expression.MemberLookup (ec, source_type, op_name, loc);
+                               if (source_type.BaseType != null)
+                                       mg6 = Expression.MethodLookup (ec, source_type.BaseType, op_name, loc);
+                               
+                               mg7 = Expression.MemberLookup (ec, target_type, op_name, loc);
+                               if (target_type.BaseType != null)
+                                       mg8 = Expression.MethodLookup (ec, target_type.BaseType, op_name, loc);
+                               
+                               MethodGroupExpr union5 = Invocation.MakeUnionSet (mg5, mg6, loc);
+                               MethodGroupExpr union6 = Invocation.MakeUnionSet (mg7, mg8, loc);
+
+                               union4 = Invocation.MakeUnionSet (union5, union6, loc);
+                       }
+                       
+                       return Invocation.MakeUnionSet (union3, union4, loc);
+               }
+               
+               /// <summary>
+               ///   User-defined conversions
+               /// </summary>
+               static public Expression UserDefinedConversion (EmitContext ec, Expression source,
+                                                               Type target, Location loc,
+                                                               bool look_for_explicit)
+               {
+                       MethodGroupExpr union;
+                       Type source_type = source.Type;
+                       MethodBase method = null;
+
+                       union = GetConversionOperators (ec, source_type, target, loc, look_for_explicit);
+                       if (union == null)
+                               return null;
+                       
+                       Type most_specific_source, most_specific_target;
+#if BLAH
+                       foreach (MethodBase m in union.Methods){
+                               Console.WriteLine ("Name: " + m.Name);
+                               Console.WriteLine ("    : " + ((MethodInfo)m).ReturnType);
+                       }
+#endif
+                       
+                       most_specific_source = FindMostSpecificSource (union, source, look_for_explicit, loc);
+                       if (most_specific_source == null)
+                               return null;
+
+                       most_specific_target = FindMostSpecificTarget (union, target, look_for_explicit, loc);
+                       if (most_specific_target == null) 
+                               return null;
+
+                       int count = 0;
+
+                       
+                       foreach (MethodBase mb in union.Methods){
+                               ParameterData pd = Invocation.GetParameterData (mb);
+                               MethodInfo mi = (MethodInfo) mb;
+                               
+                               if (pd.ParameterType (0) == most_specific_source &&
+                                   mi.ReturnType == most_specific_target) {
+                                       method = mb;
+                                       count++;
+                               }
+                       }
+                       
+                       if (method == null || count > 1)
+                               return null;
+                       
+                       
+                       //
+                       // This will do the conversion to the best match that we
+                       // found.  Now we need to perform an implict standard conversion
+                       // if the best match was not the type that we were requested
+                       // by target.
+                       //
+                       if (look_for_explicit)
+                               source = ExplicitConversionStandard (ec, source, most_specific_source, loc);
+                       else
+                               source = ImplicitConversionStandard (ec, source, most_specific_source, loc);
+
+                       if (source == null)
+                               return null;
+
+                       Expression e;
+                       e =  new UserCast ((MethodInfo) method, source, loc);
+                       if (e.Type != target){
+                               if (!look_for_explicit)
+                                       e = ImplicitConversionStandard (ec, e, target, loc);
+                               else
+                                       e = ExplicitConversionStandard (ec, e, target, loc);
+                       }
+
+                       return e;
+               }
+               
+               /// <summary>
+               ///   Converts implicitly the resolved expression `expr' into the
+               ///   `target_type'.  It returns a new expression that can be used
+               ///   in a context that expects a `target_type'. 
+               /// </summary>
+               static public Expression ImplicitConversion (EmitContext ec, Expression expr,
+                                                         Type target_type, Location loc)
+               {
+                       Type expr_type = expr.Type;
+                       Expression e;
+
+                       if (target_type == null)
+                               throw new Exception ("Target type is null");
+
+                       e = ImplicitConversionStandard (ec, expr, target_type, loc);
+                       if (e != null)
+                               return e;
+
+                       e = ImplicitUserConversion (ec, expr, target_type, loc);
+                       if (e != null)
+                               return e;
+
+                       return null;
+               }
+
+               
+               /// <summary>
+               ///   Attempts to apply the `Standard Implicit
+               ///   Conversion' rules to the expression `expr' into
+               ///   the `target_type'.  It returns a new expression
+               ///   that can be used in a context that expects a
+               ///   `target_type'.
+               ///
+               ///   This is different from `ImplicitConversion' in that the
+               ///   user defined implicit conversions are excluded. 
+               /// </summary>
+               static public Expression ImplicitConversionStandard (EmitContext ec, Expression expr,
+                                                                    Type target_type, Location loc)
+               {
+                       Type expr_type = expr.Type;
+                       Expression e;
+
+                       if (expr_type == target_type && !(expr is NullLiteral))
+                               return expr;
+
+                       e = ImplicitNumericConversion (ec, expr, target_type, loc);
+                       if (e != null)
+                               return e;
+
+                       e = ImplicitReferenceConversion (expr, target_type);
+                       if (e != null)
+                               return e;
+                       
+                       if ((target_type == TypeManager.enum_type ||
+                            target_type.IsSubclassOf (TypeManager.enum_type)) &&
+                           expr is IntLiteral){
+                               IntLiteral i = (IntLiteral) expr;
+
+                               if (i.Value == 0)
+                                       return new EnumConstant ((Constant) expr, target_type);
+                       }
+
+                       if (ec.InUnsafe) {
+                               if (expr_type.IsPointer){
+                                       if (target_type == TypeManager.void_ptr_type)
+                                               return new EmptyCast (expr, target_type);
+
+                                       //
+                                       // yep, comparing pointer types cant be done with
+                                       // t1 == t2, we have to compare their element types.
+                                       //
+                                       if (target_type.IsPointer){
+                                               if (TypeManager.GetElementType(target_type) == TypeManager.GetElementType(expr_type))
+                                                       return expr;
+                                       }
+                               }
+                               
+                               if (target_type.IsPointer) {
+                                       if (expr is NullLiteral)
+                                               return new EmptyCast (expr, target_type);
+
+                                       if (expr_type == TypeManager.void_ptr_type)
+                                               return new EmptyCast (expr, target_type);
+                               }
+                       }
+
+                       return null;
+               }
+
+               /// <summary>
+               ///   Attemps to perform an implict constant conversion of the IntConstant
+               ///   into a different data type using casts (See Implicit Constant
+               ///   Expression Conversions)
+               /// </summary>
+               static public Expression TryImplicitIntConversion (Type target_type, IntConstant ic)
+               {
+                       int value = ic.Value;
+
+                       if (target_type == TypeManager.sbyte_type){
+                               if (value >= SByte.MinValue && value <= SByte.MaxValue)
+                                       return new SByteConstant ((sbyte) value);
+                       } else if (target_type == TypeManager.byte_type){
+                               if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
+                                       return new ByteConstant ((byte) value);
+                       } else if (target_type == TypeManager.short_type){
+                               if (value >= Int16.MinValue && value <= Int16.MaxValue)
+                                       return new ShortConstant ((short) value);
+                       } else if (target_type == TypeManager.ushort_type){
+                               if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
+                                       return new UShortConstant ((ushort) value);
+                       } else if (target_type == TypeManager.uint32_type){
+                               if (value >= 0)
+                                       return new UIntConstant ((uint) value);
+                       } else if (target_type == TypeManager.uint64_type){
+                               //
+                               // we can optimize this case: a positive int32
+                               // always fits on a uint64.  But we need an opcode
+                               // to do it.
+                               //
+                               if (value >= 0)
+                                       return new ULongConstant ((ulong) value);
+                       } else if (target_type == TypeManager.double_type)
+                               return new DoubleConstant ((double) value);
+                       else if (target_type == TypeManager.float_type)
+                               return new FloatConstant ((float) value);
+                       
+                       if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)){
+                               Type underlying = TypeManager.EnumToUnderlying (target_type);
+                               Constant e = (Constant) ic;
+                               
+                               //
+                               // Possibly, we need to create a different 0 literal before passing
+                               // to EnumConstant
+                               //n
+                               if (underlying == TypeManager.int64_type)
+                                       e = new LongLiteral (0);
+                               else if (underlying == TypeManager.uint64_type)
+                                       e = new ULongLiteral (0);
+
+                               return new EnumConstant (e, target_type);
+                       }
+                       return null;
+               }
+
+               static public void Error_CannotImplicitConversion (Location loc, Type source, Type target)
+               {
+                       string msg = "Cannot convert implicitly from `"+
+                               TypeManager.CSharpName (source) + "' to `" +
+                               TypeManager.CSharpName (target) + "'";
+
+                       Report.Error (29, loc, msg);
+               }
+
+               /// <summary>
+               ///   Attemptes to implicityly convert `target' into `type', using
+               ///   ImplicitConversion.  If there is no implicit conversion, then
+               ///   an error is signaled
+               /// </summary>
+               static public Expression ImplicitConversionRequired (EmitContext ec, Expression source,
+                                                                    Type target_type, Location loc)
+               {
+                       Expression e;
+                       
+                       e = ImplicitConversion (ec, source, target_type, loc);
+                       if (e != null)
+                               return e;
+
+                       if (source is DoubleLiteral && target_type == TypeManager.float_type){
+                               Report.Error (664, loc,
+                                             "Double literal cannot be implicitly converted to " +
+                                             "float type, use F suffix to create a float literal");
+                       }
+
+                       Error_CannotImplicitConversion (loc, source.Type, target_type);
+
+                       return null;
+               }
+
+               /// <summary>
+               ///   Performs the explicit numeric conversions
+               /// </summary>
+               static Expression ExplicitNumericConversion (EmitContext ec, Expression expr, Type target_type, Location loc)
+               {
+                       Type expr_type = expr.Type;
+
+                       //
+                       // If we have an enumeration, extract the underlying type,
+                       // use this during the comparison, but wrap around the original
+                       // target_type
+                       //
+                       Type real_target_type = target_type;
+
+                       if (TypeManager.IsEnumType (real_target_type))
+                               real_target_type = TypeManager.EnumToUnderlying (real_target_type);
+
+                       if (ImplicitStandardConversionExists (expr, real_target_type)){
+                               Expression ce = ImplicitConversionStandard (ec, expr, real_target_type, loc);
+
+                               if (real_target_type != target_type)
+                                       return new EmptyCast (ce, target_type);
+                               return ce;
+                       }
+                       
+                       if (expr_type == TypeManager.sbyte_type){
+                               //
+                               // From sbyte to byte, ushort, uint, ulong, char
+                               //
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U1);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U2);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U4);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_CH);
+                       } else if (expr_type == TypeManager.byte_type){
+                               //
+                               // From byte to sbyte and char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_I1);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_CH);
+                       } else if (expr_type == TypeManager.short_type){
+                               //
+                               // From short to sbyte, byte, ushort, uint, ulong, char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U1);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U2);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U4);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_CH);
+                       } else if (expr_type == TypeManager.ushort_type){
+                               //
+                               // From ushort to sbyte, byte, short, char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I2);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_CH);
+                       } else if (expr_type == TypeManager.int32_type){
+                               //
+                               // From int to sbyte, byte, short, ushort, uint, ulong, char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U2);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U4);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_CH);
+                       } else if (expr_type == TypeManager.uint32_type){
+                               //
+                               // From uint to sbyte, byte, short, ushort, int, char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U2);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I4);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_CH);
+                       } else if (expr_type == TypeManager.int64_type){
+                               //
+                               // From long to sbyte, byte, short, ushort, int, uint, ulong, char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U2);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I4);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U4);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_CH);
+                       } else if (expr_type == TypeManager.uint64_type){
+                               //
+                               // From ulong to sbyte, byte, short, ushort, int, uint, long, char
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U2);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I4);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U4);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_CH);
+                       } else if (expr_type == TypeManager.char_type){
+                               //
+                               // From char to sbyte, byte, short
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_I2);
+                       } else if (expr_type == TypeManager.float_type){
+                               //
+                               // From float to sbyte, byte, short,
+                               // ushort, int, uint, long, ulong, char
+                               // or decimal
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U2);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I4);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U4);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I8);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_CH);
+                       } else if (expr_type == TypeManager.double_type){
+                               //
+                               // From double to byte, byte, short,
+                               // ushort, int, uint, long, ulong,
+                               // char, float or decimal
+                               //
+                               if (real_target_type == TypeManager.sbyte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I1);
+                               if (real_target_type == TypeManager.byte_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U1);
+                               if (real_target_type == TypeManager.short_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I2);
+                               if (real_target_type == TypeManager.ushort_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U2);
+                               if (real_target_type == TypeManager.int32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I4);
+                               if (real_target_type == TypeManager.uint32_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U4);
+                               if (real_target_type == TypeManager.int64_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I8);
+                               if (real_target_type == TypeManager.uint64_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U8);
+                               if (real_target_type == TypeManager.char_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_CH);
+                               if (real_target_type == TypeManager.float_type)
+                                       return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4);
+                       } 
+
+                       // decimal is taken care of by the op_Explicit methods.
+
+                       return null;
+               }
+
+               /// <summary>
+               ///  Returns whether an explicit reference conversion can be performed
+               ///  from source_type to target_type
+               /// </summary>
+               public static bool ExplicitReferenceConversionExists (Type source_type, Type target_type)
+               {
+                       bool target_is_value_type = target_type.IsValueType;
+                       
+                       if (source_type == target_type)
+                               return true;
+                       
+                       //
+                       // From object to any reference type
+                       //
+                       if (source_type == TypeManager.object_type && !target_is_value_type)
+                               return true;
+                                       
+                       //
+                       // From any class S to any class-type T, provided S is a base class of T
+                       //
+                       if (target_type.IsSubclassOf (source_type))
+                               return true;
+
+                       //
+                       // From any interface type S to any interface T provided S is not derived from T
+                       //
+                       if (source_type.IsInterface && target_type.IsInterface){
+                               if (!target_type.IsSubclassOf (source_type))
+                                       return true;
+                       }
+                           
+                       //
+                       // From any class type S to any interface T, provided S is not sealed
+                       // and provided S does not implement T.
+                       //
+                       if (target_type.IsInterface && !source_type.IsSealed &&
+                           !TypeManager.ImplementsInterface (source_type, target_type))
+                               return true;
+
+                       //
+                       // From any interface-type S to to any class type T, provided T is not
+                       // sealed, or provided T implements S.
+                       //
+                       if (source_type.IsInterface &&
+                           (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)))
+                               return true;
+                       
+                       
+                       // From an array type S with an element type Se to an array type T with an 
+                       // element type Te provided all the following are true:
+                       //     * S and T differe only in element type, in other words, S and T
+                       //       have the same number of dimensions.
+                       //     * Both Se and Te are reference types
+                       //     * An explicit referenc conversions exist from Se to Te
+                       //
+                       if (source_type.IsArray && target_type.IsArray) {
+                               if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
+                                       
+                                       Type source_element_type = TypeManager.GetElementType (source_type);
+                                       Type target_element_type = TypeManager.GetElementType (target_type);
+                                       
+                                       if (!source_element_type.IsValueType && !target_element_type.IsValueType)
+                                               if (ExplicitReferenceConversionExists (source_element_type,
+                                                                                      target_element_type))
+                                                       return true;
+                               }
+                       }
+                       
+
+                       // From System.Array to any array-type
+                       if (source_type == TypeManager.array_type &&
+                           target_type.IsArray){
+                               return true;
+                       }
+
+                       //
+                       // From System delegate to any delegate-type
+                       //
+                       if (source_type == TypeManager.delegate_type &&
+                           target_type.IsSubclassOf (TypeManager.delegate_type))
+                               return true;
+
+                       //
+                       // From ICloneable to Array or Delegate types
+                       //
+                       if (source_type == TypeManager.icloneable_type &&
+                           (target_type == TypeManager.array_type ||
+                            target_type == TypeManager.delegate_type))
+                               return true;
+                       
+                       return false;
+               }
+
+               /// <summary>
+               ///   Implements Explicit Reference conversions
+               /// </summary>
+               static Expression ExplicitReferenceConversion (Expression source, Type target_type)
+               {
+                       Type source_type = source.Type;
+                       bool target_is_value_type = target_type.IsValueType;
+
+                       //
+                       // From object to any reference type
+                       //
+                       if (source_type == TypeManager.object_type && !target_is_value_type)
+                               return new ClassCast (source, target_type);
+
+
+                       //
+                       // From any class S to any class-type T, provided S is a base class of T
+                       //
+                       if (target_type.IsSubclassOf (source_type))
+                               return new ClassCast (source, target_type);
+
+                       //
+                       // From any interface type S to any interface T provided S is not derived from T
+                       //
+                       if (source_type.IsInterface && target_type.IsInterface){
+                               if (TypeManager.ImplementsInterface (source_type, target_type))
+                                       return null;
+                               else
+                                       return new ClassCast (source, target_type);
+                       }
+                           
+                       //
+                       // From any class type S to any interface T, provides S is not sealed
+                       // and provided S does not implement T.
+                       //
+                       if (target_type.IsInterface && !source_type.IsSealed) {
+                               if (TypeManager.ImplementsInterface (source_type, target_type))
+                                       return null;
+                               else
+                                       return new ClassCast (source, target_type);
+                               
+                       }
+
+                       //
+                       // From any interface-type S to to any class type T, provided T is not
+                       // sealed, or provided T implements S.
+                       //
+                       if (source_type.IsInterface) {
+                               if (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type))
+                                       return new ClassCast (source, target_type);
+                               else
+                                       return null;
+                       }
+                       
+                       // From an array type S with an element type Se to an array type T with an 
+                       // element type Te provided all the following are true:
+                       //     * S and T differe only in element type, in other words, S and T
+                       //       have the same number of dimensions.
+                       //     * Both Se and Te are reference types
+                       //     * An explicit referenc conversions exist from Se to Te
+                       //
+                       if (source_type.IsArray && target_type.IsArray) {
+                               if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
+                                       
+                                       Type source_element_type = TypeManager.GetElementType (source_type);
+                                       Type target_element_type = TypeManager.GetElementType (target_type);
+                                       
+                                       if (!source_element_type.IsValueType && !target_element_type.IsValueType)
+                                               if (ExplicitReferenceConversionExists (source_element_type,
+                                                                                      target_element_type))
+                                                       return new ClassCast (source, target_type);
+                               }
+                       }
+                       
+
+                       // From System.Array to any array-type
+                       if (source_type == TypeManager.array_type &&
+                           target_type.IsArray) {
+                               return new ClassCast (source, target_type);
+                       }
+
+                       //
+                       // From System delegate to any delegate-type
+                       //
+                       if (source_type == TypeManager.delegate_type &&
+                           target_type.IsSubclassOf (TypeManager.delegate_type))
+                               return new ClassCast (source, target_type);
+
+                       //
+                       // From ICloneable to Array or Delegate types
+                       //
+                       if (source_type == TypeManager.icloneable_type &&
+                           (target_type == TypeManager.array_type ||
+                            target_type == TypeManager.delegate_type))
+                               return new ClassCast (source, target_type);
+                       
+                       return null;
+               }
+               
+               /// <summary>
+               ///   Performs an explicit conversion of the expression `expr' whose
+               ///   type is expr.Type to `target_type'.
+               /// </summary>
+               static public Expression ExplicitConversion (EmitContext ec, Expression expr,
+                                                         Type target_type, Location loc)
+               {
+                       Type expr_type = expr.Type;
+                       Type original_expr_type = expr_type;
+
+                       if (expr_type.IsSubclassOf (TypeManager.enum_type)){
+                               if (target_type == TypeManager.enum_type ||
+                                   target_type == TypeManager.object_type) {
+                                       if (expr is EnumConstant)
+                                               expr = ((EnumConstant) expr).Child;
+                                       // We really need all these casts here .... :-(
+                                       expr = new BoxedCast (new EmptyCast (expr, expr_type));
+                                       return new EmptyCast (expr, target_type);
+                               } else if ((expr_type == TypeManager.enum_type) && target_type.IsValueType &&
+                                          target_type.IsSubclassOf (TypeManager.enum_type))
+                                       return new UnboxCast (expr, target_type);
+
+                               //
+                               // Notice that we have kept the expr_type unmodified, which is only
+                               // used later on to 
+                               if (expr is EnumConstant)
+                                       expr = ((EnumConstant) expr).Child;
+                               else
+                                       expr = new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type));
+                               expr_type = expr.Type;
+                       }
+
+                       Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc);
+
+                       if (ne != null)
+                               return ne;
+
+                       ne = ExplicitNumericConversion (ec, expr, target_type, loc);
+                       if (ne != null)
+                               return ne;
+
+                       //
+                       // Unboxing conversion.
+                       //
+                       if (expr_type == TypeManager.object_type && target_type.IsValueType){
+                               if (expr is NullLiteral){
+                                       Report.Error (37, "Cannot convert null to value type `" +
+                                                      TypeManager.CSharpName (expr_type) + "'");
+                                       return null;
+                               }
+                               return new UnboxCast (expr, target_type);
+                       }
+
+                       
+                       ne = ExplicitReferenceConversion (expr, target_type);
+                       if (ne != null)
+                               return ne;
+
+                       if (ec.InUnsafe){
+                               if (target_type.IsPointer){
+                                       if (expr_type.IsPointer)
+                                               return new EmptyCast (expr, target_type);
+                                       
+                                       if (expr_type == TypeManager.sbyte_type ||
+                                           expr_type == TypeManager.byte_type ||
+                                           expr_type == TypeManager.short_type ||
+                                           expr_type == TypeManager.ushort_type ||
+                                           expr_type == TypeManager.int32_type ||
+                                           expr_type == TypeManager.uint32_type ||
+                                           expr_type == TypeManager.uint64_type ||
+                                           expr_type == TypeManager.int64_type)
+                                               return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
+                               }
+                               if (expr_type.IsPointer){
+                                       Expression e = null;
+                                       
+                                       if (target_type == TypeManager.sbyte_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
+                                       else if (target_type == TypeManager.byte_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
+                                       else if (target_type == TypeManager.short_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
+                                       else if (target_type == TypeManager.ushort_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
+                                       else if (target_type == TypeManager.int32_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
+                                       else if (target_type == TypeManager.uint32_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
+                                       else if (target_type == TypeManager.uint64_type)
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
+                                       else if (target_type == TypeManager.int64_type){
+                                               e = new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
+                                       }
+
+                                       if (e != null){
+                                               Expression ci, ce;
+
+                                               ci = ImplicitConversionStandard (ec, e, target_type, loc);
+
+                                               if (ci != null)
+                                                       return ci;
+
+                                               ce = ExplicitNumericConversion (ec, e, target_type, loc);
+                                               if (ce != null)
+                                                       return ce;
+                                               //
+                                               // We should always be able to go from an uint32
+                                               // implicitly or explicitly to the other integral
+                                               // types
+                                               //
+                                               throw new Exception ("Internal compiler error");
+                                       }
+                               }
+                       }
+                       
+                       ne = ExplicitUserConversion (ec, expr, target_type, loc);
+                       if (ne != null)
+                               return ne;
+
+                       Error_CannotConvertType (loc, original_expr_type, target_type);
+                       return null;
+               }
+
+               /// <summary>
+               ///   Same as ExplicitConversion, only it doesn't include user defined conversions
+               /// </summary>
+               static public Expression ExplicitConversionStandard (EmitContext ec, Expression expr,
+                                                                 Type target_type, Location l)
+               {
+                       Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
+
+                       if (ne != null)
+                               return ne;
+
+                       ne = ExplicitNumericConversion (ec, expr, target_type, l);
+                       if (ne != null)
+                               return ne;
+
+                       ne = ExplicitReferenceConversion (expr, target_type);
+                       if (ne != null)
+                               return ne;
+
+                       Error_CannotConvertType (l, expr.Type, target_type);
+                       return null;
+               }
+       }
+}
diff --git a/mcs/gmcs/cs-parser.jay b/mcs/gmcs/cs-parser.jay
new file mode 100755 (executable)
index 0000000..bf3e835
--- /dev/null
@@ -0,0 +1,4105 @@
+
+        %{
+//
+// cs-parser.jay: The Parser for the C# compiler
+//
+// Authors: Miguel de Icaza (miguel@gnu.org)
+//          Ravi Pratap     (ravi@ximian.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+// TODO:
+//   (1) Figure out why error productions dont work.  `type-declaration' is a
+//       great spot to put an `error' because you can reproduce it with this input:
+//      "public X { }"
+//
+// Possible optimization:
+//   Run memory profiler with parsing only, and consider dropping 
+//   arraylists where not needed.   Some pieces can use linked lists.
+//
+using System.Text;
+using System.IO;
+using System;
+
+namespace Mono.CSharp
+{
+       using System.Collections;
+       using Mono.Languages;
+
+       /// <summary>
+       ///    The C# Parser
+       /// </summary>
+       public class CSharpParser : GenericParser {
+               NamespaceEntry  current_namespace;
+               TypeContainer   current_container;
+       
+               IIteratorContainer iterator_container;
+
+               // <summary>
+               //   Current block is used to add statements as we find
+               //   them.  
+               // </summary>
+
+               Block      current_block;
+
+               // <summary>
+               //   Current interface is used by the various declaration
+               //   productions in the interface declaration to "add"
+               //   the interfaces as we find them.
+               // </summary>
+               Interface  current_interface;
+
+               // <summary>
+               //   This is used by the unary_expression code to resolve
+               //   a name against a parameter.  
+               // </summary>
+               Parameters current_local_parameters;
+
+               // <summary>
+               //   Using during property parsing to describe the implicit
+               //   value parameter that is passed to the "set" and "get"accesor
+               //   methods (properties and indexers).
+               // </summary>
+               Expression implicit_value_parameter_type;
+               Parameters indexer_parameters;
+
+               // <summary>
+               //   Used to determine if we are parsing the get/set pair
+               //   of an indexer or a property
+               // </summmary>
+               bool  parsing_indexer;
+
+               //
+               // An out-of-band stack.
+               //
+               Stack oob_stack;
+
+               //
+               // Switch stack.
+               //
+               Stack switch_stack;
+
+               //
+               // The current file.
+               //
+               SourceFile file;
+%}
+
+%token EOF
+%token NONE   /* This token is never returned by our lexer */
+%token ERROR           // This is used not by the parser, but by the tokenizer.
+                       // do not remove.
+
+/*
+ *These are the C# keywords
+ */
+%token ABSTRACT        
+%token AS
+%token ADD
+%token ASSEMBLY
+%token BASE    
+%token BOOL    
+%token BREAK   
+%token BYTE    
+%token CASE    
+%token CATCH   
+%token CHAR    
+%token CHECKED 
+%token CLASS   
+%token CONST   
+%token CONTINUE        
+%token DECIMAL 
+%token DEFAULT 
+%token DELEGATE        
+%token DO      
+%token DOUBLE  
+%token ELSE    
+%token ENUM    
+%token EVENT   
+%token EXPLICIT        
+%token EXTERN  
+%token FALSE   
+%token FINALLY 
+%token FIXED   
+%token FLOAT   
+%token FOR     
+%token FOREACH 
+%token GOTO    
+%token IF      
+%token IMPLICIT        
+%token IN      
+%token INT     
+%token INTERFACE
+%token INTERNAL        
+%token IS      
+%token LOCK    
+%token LONG    
+%token NAMESPACE
+%token NEW     
+%token NULL    
+%token OBJECT  
+%token OPERATOR        
+%token OUT     
+%token OVERRIDE        
+%token PARAMS  
+%token PRIVATE 
+%token PROTECTED
+%token PUBLIC  
+%token READONLY        
+%token REF     
+%token RETURN  
+%token REMOVE
+%token SBYTE   
+%token SEALED  
+%token SHORT   
+%token SIZEOF  
+%token STACKALLOC
+%token STATIC  
+%token STRING  
+%token STRUCT  
+%token SWITCH  
+%token THIS    
+%token THROW   
+%token TRUE    
+%token TRY     
+%token TYPEOF  
+%token UINT    
+%token ULONG   
+%token UNCHECKED
+%token UNSAFE  
+%token USHORT  
+%token USING   
+%token VIRTUAL 
+%token VOID    
+%token VOLATILE
+%token WHILE   
+
+/* v2 tokens */
+%token YIELD
+
+/* C# keywords which are not really keywords */
+%token GET           "get"
+%token SET           "set"
+
+/* C# single character operators/punctuation. */
+%token OPEN_BRACE    "{"
+%token CLOSE_BRACE   "}"
+%token OPEN_BRACKET  "["
+%token CLOSE_BRACKET "]"
+%token OPEN_PARENS   "("
+%token CLOSE_PARENS  ")"
+%token DOT           "."
+%token COMMA         ","
+%token COLON         ":"
+%token SEMICOLON     ";"
+%token TILDE         "~"
+
+%token PLUS           "+"
+%token MINUS          "-"
+%token BANG           "!"
+%token ASSIGN         "="
+%token OP_LT          "<"
+%token OP_GT          ">"
+%token BITWISE_AND    "&"
+%token BITWISE_OR     "|"
+%token STAR           "*"
+%token PERCENT        "%"
+%token DIV            "/"
+%token CARRET         "^"
+%token INTERR         "?"
+
+/* C# multi-character operators. */
+%token OP_INC                 "++"
+%token OP_DEC                 "--"
+%token OP_SHIFT_LEFT          "<<"
+%token OP_SHIFT_RIGHT         ">>"
+%token OP_LE                  "<="
+%token OP_GE                  ">="
+%token OP_EQ                  "=="
+%token OP_NE                  "!="
+%token OP_AND                 "&&"
+%token OP_OR                  "||"
+%token OP_MULT_ASSIGN         "*="
+%token OP_DIV_ASSIGN          "/="
+%token OP_MOD_ASSIGN          "%="
+%token OP_ADD_ASSIGN          "+="
+%token OP_SUB_ASSIGN          "-="
+%token OP_SHIFT_LEFT_ASSIGN   "<<="
+%token OP_SHIFT_RIGHT_ASSIGN  ">>="
+%token OP_AND_ASSIGN          "&="
+%token OP_XOR_ASSIGN          "^="
+%token OP_OR_ASSIGN           "|="
+%token OP_PTR                 "->"
+
+/* Numbers */
+%token LITERAL_INTEGER           "int literal"
+%token LITERAL_FLOAT             "float literal"
+%token LITERAL_DOUBLE            "double literal"
+%token LITERAL_DECIMAL           "decimal literal"
+%token LITERAL_CHARACTER         "character literal"
+%token LITERAL_STRING            "string literal"
+
+%token IDENTIFIER
+
+/* Add precedence rules to solve dangling else s/r conflict */
+%nonassoc LOWPREC
+%nonassoc IF
+%nonassoc ELSE
+%right ASSIGN
+%left OP_OR
+%left OP_AND
+%left BITWISE_OR
+%left BITWISE_AND
+%left OP_SHIFT_LEFT OP_SHIFT_RIGHT
+%left PLUS MINUS
+%left STAR DIV PERCENT
+%right BANG CARRET UMINUS
+%nonassoc OP_INC OP_DEC
+%left OPEN_PARENS
+%left OPEN_BRACKET OPEN_BRACE
+%left DOT
+%nonassoc HIGHPREC
+
+%start compilation_unit
+%%
+
+compilation_unit
+        : outer_declarations opt_EOF
+        | outer_declarations attribute_sections opt_EOF
+        | attribute_sections opt_EOF
+       | opt_EOF /* allow empty files */
+        ;
+       
+opt_EOF
+       : /* empty */
+       | EOF
+       ;
+
+outer_declarations
+        : outer_declaration
+        | outer_declarations outer_declaration
+        ;
+outer_declaration
+        : using_directive
+        | namespace_member_declaration
+        ;
+  
+using_directives
+       : using_directive 
+       | using_directives using_directive
+       ;
+
+using_directive
+       : using_alias_directive
+       | using_namespace_directive
+       ;
+
+using_alias_directive
+       : USING IDENTIFIER ASSIGN 
+         namespace_or_type_name SEMICOLON
+         {
+                 current_namespace.UsingAlias ((string) $2, (string) $4, lexer.Location);
+         }
+       ;
+
+using_namespace_directive
+       : USING namespace_name SEMICOLON 
+         {
+               current_namespace.Using ((string) $2, lexer.Location);
+          }
+       ;
+
+//
+// Strictly speaking, namespaces don't have attributes but
+// we parse global attributes along with namespace declarations and then
+// detach them
+// 
+namespace_declaration
+       : opt_attributes NAMESPACE qualified_identifier 
+       {
+               Attributes attrs = (Attributes) $1;
+
+               if (attrs != null) {
+                       foreach (AttributeSection asec in attrs.AttributeSections)
+                               if (asec.Target == "assembly")
+                                       RootContext.AddGlobalAttributeSection (current_container, asec);
+                               else
+                                       Report.Error(1518, Lexer.Location,
+                                       "Attributes cannot be applied to namespaces."
+                                       + " Expected class, delegate, enum, interface, or struct");
+               }
+
+               current_namespace = RootContext.Tree.RecordNamespace (current_namespace, file, (string) $3);
+       } 
+         namespace_body opt_semicolon
+         { 
+               current_namespace = current_namespace.Parent;
+         }
+       ;
+
+opt_semicolon
+       : /* empty */
+       | SEMICOLON
+       ;
+
+opt_comma
+       : /* empty */
+       | COMMA
+       ;
+
+qualified_identifier
+       : IDENTIFIER
+       | qualified_identifier DOT IDENTIFIER { 
+           $$ = (($1).ToString ()) + "." + ($3.ToString ()); }
+       ;
+
+
+namespace_name
+       : namespace_or_type_name
+       ;
+
+namespace_body
+       : OPEN_BRACE
+         opt_using_directives
+         opt_namespace_member_declarations
+         CLOSE_BRACE
+         {
+         }
+       ;
+
+opt_using_directives
+       : /* empty */
+       | using_directives
+       ;
+
+opt_namespace_member_declarations
+       : /* empty */
+       | namespace_member_declarations
+       ;
+
+namespace_member_declarations
+       : namespace_member_declaration
+       | namespace_member_declarations namespace_member_declaration
+       ;
+
+namespace_member_declaration
+       : type_declaration
+         {
+               string name = "";
+               int mod_flags;
+
+               if ($1 is Class){
+                       Class c = (Class) $1;
+                       mod_flags = c.ModFlags;
+                       name = c.Name;
+               } else if ($1 is Struct){
+                       Struct s = (Struct) $1;
+                       mod_flags = s.ModFlags;
+                       name = s.Name;
+               } else
+                       break;
+
+               if ((mod_flags & (Modifiers.PRIVATE|Modifiers.PROTECTED)) != 0){
+                       Report.Error (
+                               1527, lexer.Location, 
+                               "Namespace elements cant be explicitly " +
+                               "declared private or protected in `" + name + "'");
+               }
+               current_namespace.DeclarationFound = true;
+         }
+       | namespace_declaration {
+               current_namespace.DeclarationFound = true;
+         }
+       ;
+
+type_declaration
+       : class_declaration             
+       | struct_declaration            
+       | interface_declaration         
+       | enum_declaration              
+       | delegate_declaration
+//
+// Enable this when we have handled all errors, because this acts as a generic fallback
+//
+//     | error {
+//             Report.Error (1518, lexer.Location, "Expected class, struct, interface, enum or delegate");
+//       }
+       ;
+
+//
+// Attributes 17.2
+//
+
+opt_attributes
+        : /* empty */
+       | attribute_sections { $$ = $1; }
+        ;
+attribute_sections
+       : attribute_section
+          {
+               AttributeSection sect = (AttributeSection) $1;
+
+               if (sect.Target == "assembly") 
+                       RootContext.AddGlobalAttributeSection (current_container, sect);
+               
+
+               $$ = new Attributes ((AttributeSection) $1);
+          }
+       | attribute_sections attribute_section
+         {
+               Attributes attrs = null;
+               AttributeSection sect = (AttributeSection) $2;
+
+               if (sect.Target == "assembly")
+                       RootContext.AddGlobalAttributeSection (current_container, sect);
+
+               if ($1 != null) {
+                       attrs = (Attributes) $1;
+                       attrs.AddAttributeSection (sect);
+               }
+               
+               $$ = attrs;
+         }
+       ;
+
+attribute_section
+       : OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET
+         {
+               string target = null;
+               
+               if ($2 != null)
+                       target = (string) $2;
+               
+               $$ = new AttributeSection (target, (ArrayList) $3);
+         }
+        | OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET
+         {
+               $$ = new AttributeSection (null, (ArrayList) $2);
+         }
+       ;
+attribute_target_specifier
+       : attribute_target COLON
+         {
+               $$ = $1;
+         }
+       ;
+
+attribute_target
+       : IDENTIFIER
+         {
+               CheckAttributeTarget ((string) $1);
+               $$ = $1;
+         }
+        | EVENT  { $$ = "event"; }       
+        | RETURN { $$ = "return"; }
+       ;
+
+attribute_list
+       : attribute
+         {
+               ArrayList attrs = new ArrayList (4);
+               attrs.Add ($1);
+
+               $$ = attrs;
+              
+         }
+       | attribute_list COMMA attribute
+         {
+               ArrayList attrs = (ArrayList) $1;
+               attrs.Add ($3);
+
+               $$ = attrs;
+         }
+       ;
+
+attribute
+       : attribute_name
+         {
+               $$ = lexer.Location;
+         }
+         opt_attribute_arguments
+         {
+               $$ = new Attribute ((string) $1, (ArrayList) $3, (Location) $2);
+         }
+       ;
+
+attribute_name
+       : type_name  { /* reserved attribute name or identifier: 17.4 */ }
+       ;
+
+opt_attribute_arguments
+       : /* empty */   { $$ = null; }
+       | OPEN_PARENS attribute_arguments CLOSE_PARENS
+         {
+               $$ = $2;
+         }
+       ;
+
+
+attribute_arguments
+       : opt_positional_argument_list
+         {
+               if ($1 == null)
+                       $$ = null;
+               else {
+                       ArrayList args = new ArrayList (4);
+                       args.Add ($1);
+               
+                       $$ = args;
+               }
+         }
+        | positional_argument_list COMMA named_argument_list
+         {
+               ArrayList args = new ArrayList (4);
+               args.Add ($1);
+               args.Add ($3);
+
+               $$ = args;
+         }
+        | named_argument_list
+         {
+               ArrayList args = new ArrayList (4);
+               args.Add (null);
+               args.Add ($1);
+               
+               $$ = args;
+         }
+        ;
+
+
+opt_positional_argument_list
+       : /* empty */           { $$ = null; } 
+       | positional_argument_list
+       ;
+
+positional_argument_list
+       : expression
+         {
+               ArrayList args = new ArrayList (4);
+               args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
+
+               $$ = args;
+         }
+        | positional_argument_list COMMA expression
+        {
+               ArrayList args = (ArrayList) $1;
+               args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
+
+               $$ = args;
+        }
+        ;
+
+named_argument_list
+       : named_argument
+         {
+               ArrayList args = new ArrayList (4);
+               args.Add ($1);
+
+               $$ = args;
+         }
+        | named_argument_list COMMA named_argument
+         {       
+               ArrayList args = (ArrayList) $1;
+               args.Add ($3);
+
+               $$ = args;
+         }
+        ;
+
+named_argument
+       : IDENTIFIER ASSIGN expression
+         {
+               $$ = new DictionaryEntry (
+                       (string) $1, 
+                       new Argument ((Expression) $3, Argument.AType.Expression));
+         }
+       ;
+
+                 
+class_body
+       :  OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
+       ;
+
+opt_class_member_declarations
+       : /* empty */
+       | class_member_declarations
+       ;
+
+class_member_declarations
+       : class_member_declaration
+       | class_member_declarations 
+         class_member_declaration
+       ;
+
+class_member_declaration
+       : constant_declaration                  // done
+       | field_declaration                     // done
+       | method_declaration                    // done
+       | property_declaration                  // done
+       | event_declaration                     // done
+       | indexer_declaration                   // done
+       | operator_declaration                  // done
+       | constructor_declaration               // done
+       | destructor_declaration                // done
+       | type_declaration
+       ;
+
+struct_declaration
+       : opt_attributes
+         opt_modifiers
+         STRUCT IDENTIFIER
+         { 
+               Struct new_struct;
+               string full_struct_name = MakeName ((string) $4);
+
+               new_struct = new Struct (current_container, full_struct_name, (int) $2, 
+                                        (Attributes) $1, lexer.Location);
+               current_container = new_struct;
+               current_container.Namespace = current_namespace;
+               RootContext.Tree.RecordDecl (full_struct_name, new_struct);
+         }
+         opt_class_base
+         struct_body
+         opt_semicolon
+         {
+               Struct new_struct = (Struct) current_container;
+
+               if ($6 != null)
+                       new_struct.Bases = (ArrayList) $6;
+
+               current_container = current_container.Parent;
+               CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
+               $$ = new_struct;
+         }
+       ;
+
+struct_body
+       : OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
+       ;
+
+opt_struct_member_declarations
+       : /* empty */
+       | struct_member_declarations
+       ;
+
+struct_member_declarations
+       : struct_member_declaration
+       | struct_member_declarations struct_member_declaration
+       ;
+
+struct_member_declaration
+       : constant_declaration
+       | field_declaration
+       | method_declaration
+       | property_declaration
+       | event_declaration
+       | indexer_declaration
+       | operator_declaration
+       | constructor_declaration
+       | type_declaration
+
+       /*
+        * This is only included so we can flag error 575: 
+        * destructors only allowed on class types
+        */
+       | destructor_declaration 
+       ;
+
+constant_declaration
+       : opt_attributes 
+         opt_modifiers
+         CONST
+         type
+         constant_declarators
+         SEMICOLON
+         {
+               foreach (VariableDeclaration constant in (ArrayList) $5){
+                       Location l = constant.Location;
+
+                       Const c = new Const (
+                               (Expression) $4, (string) constant.identifier, 
+                               (Expression) constant.expression_or_array_initializer, (int) $2, 
+                               (Attributes) $1, l);
+
+                       CheckDef (current_container.AddConstant (c), c.Name, l);
+               }
+         }
+       ;
+
+constant_declarators
+       : constant_declarator 
+         {
+               ArrayList constants = new ArrayList (4);
+               constants.Add ($1);
+               $$ = constants;
+         }
+       | constant_declarators COMMA constant_declarator
+         {
+               ArrayList constants = (ArrayList) $1;
+
+               constants.Add ($3);
+         }
+       ;
+
+constant_declarator
+       : IDENTIFIER ASSIGN constant_expression
+         {
+               $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
+         }
+       ;
+
+field_declaration
+       : opt_attributes
+         opt_modifiers
+         type 
+         variable_declarators
+         SEMICOLON
+         { 
+               Expression type = (Expression) $3;
+               int mod = (int) $2;
+
+               foreach (VariableDeclaration var in (ArrayList) $4){
+                       Location l = var.Location;
+
+                       Field field = new Field (type, mod, var.identifier, 
+                                                var.expression_or_array_initializer, 
+                                                (Attributes) $1, l);
+
+                       CheckDef (current_container.AddField (field), field.Name, l);
+               }
+         }
+       | opt_attributes
+         opt_modifiers
+         VOID  
+         variable_declarators
+         SEMICOLON {
+               Report.Error (670, lexer.Location, "void type is not allowed for fields");
+         }
+       ;
+
+variable_declarators
+       : variable_declarator 
+         {
+               ArrayList decl = new ArrayList (4);
+               decl.Add ($1);
+               $$ = decl;
+         }
+       | variable_declarators COMMA variable_declarator
+         {
+               ArrayList decls = (ArrayList) $1;
+               decls.Add ($3);
+               $$ = $1;
+         }
+       ;
+
+variable_declarator
+       : IDENTIFIER ASSIGN variable_initializer
+         {
+               $$ = new VariableDeclaration ((string) $1, $3, lexer.Location);
+         }
+       | IDENTIFIER
+         {
+               $$ = new VariableDeclaration ((string) $1, null, lexer.Location);
+         }
+       ;
+
+variable_initializer
+       : expression
+         {
+               $$ = $1;
+         }
+       | array_initializer
+         {
+               $$ = $1;
+         }
+       | STACKALLOC type OPEN_BRACKET expression CLOSE_BRACKET
+         {
+               $$ = new StackAlloc ((Expression) $2, (Expression) $4, lexer.Location);
+         }
+       ;
+
+method_declaration
+       : method_header {
+               iterator_container = (IIteratorContainer) $1;
+         }
+         method_body
+         {
+               Method method = (Method) $1;
+               Block b = (Block) $3;
+               const int extern_abstract = (Modifiers.EXTERN | Modifiers.ABSTRACT);
+
+               if (b == null){
+                       if ((method.ModFlags & extern_abstract) == 0){
+                               Report.Error (
+                                       501, lexer.Location,  current_container.MakeName (method.Name) +
+                                       "must declare a body because it is not marked abstract or extern");
+                       }
+               } else {
+                       if ((method.ModFlags & Modifiers.EXTERN) != 0){
+                               Report.Error (
+                                       179, lexer.Location, current_container.MakeName (method.Name) +
+                                       " is declared extern, but has a body");
+                       }
+               }
+
+               method.Block = (Block) $3;
+               CheckDef (current_container.AddMethod (method), method.Name, method.Location);
+
+               current_local_parameters = null;
+               iterator_container = null;
+         }
+       ;
+
+opt_error_modifier
+       : /* empty */
+       | modifiers 
+         {
+               int m = (int) $1;
+               int i = 1;
+
+               while (m != 0){
+                       if ((i & m) != 0){
+                               Report.Error (
+                                       1585, lexer.Location, "Member modifier `" + 
+                                       Modifiers.Name (i) + "' must precede member type and name");
+                       }
+                       m &= ~i;
+                       i = i << 1;
+               }
+         }
+       ;
+
+method_header
+       : opt_attributes
+         opt_modifiers
+         type
+         member_name
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
+         {
+               Method method = new Method ((Expression) $3, (int) $2, (string) $4, 
+                                           (Parameters) $6, (Attributes) $1, lexer.Location);
+
+               current_local_parameters = (Parameters) $6;
+
+               $$ = method;
+         }
+       | opt_attributes
+         opt_modifiers
+         VOID
+         member_name
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
+         {
+               Method method = new Method (TypeManager.system_void_expr, (int) $2, (string) $4, 
+                                           (Parameters) $6, (Attributes) $1, lexer.Location);
+
+               current_local_parameters = (Parameters) $6;
+               $$ = method;
+         }
+       ;
+
+method_body
+       : block
+       | SEMICOLON             { $$ = null; }
+       ;
+
+opt_formal_parameter_list
+       : /* empty */                   { $$ = Parameters.EmptyReadOnlyParameters; }
+       | formal_parameter_list
+       ;
+
+formal_parameter_list
+       : fixed_parameters              
+         { 
+               ArrayList pars_list = (ArrayList) $1;
+
+               Parameter [] pars = new Parameter [pars_list.Count];
+               pars_list.CopyTo (pars);
+
+               $$ = new Parameters (pars, null, lexer.Location); 
+         } 
+       | fixed_parameters COMMA parameter_array
+         {
+               ArrayList pars_list = (ArrayList) $1;
+
+               Parameter [] pars = new Parameter [pars_list.Count];
+               pars_list.CopyTo (pars);
+
+               $$ = new Parameters (pars, (Parameter) $3, lexer.Location); 
+         }
+       | parameter_array 
+         {
+               $$ = new Parameters (null, (Parameter) $1, lexer.Location);
+         }
+       ;
+
+fixed_parameters
+       : fixed_parameter       
+         {
+               ArrayList pars = new ArrayList (4);
+
+               pars.Add ($1);
+               $$ = pars;
+         }
+       | fixed_parameters COMMA fixed_parameter
+         {
+               ArrayList pars = (ArrayList) $1;
+
+               pars.Add ($3);
+               $$ = $1;
+         }
+       ;
+
+fixed_parameter
+       : opt_attributes
+         opt_parameter_modifier
+         type
+         IDENTIFIER
+         {
+               $$ = new Parameter ((Expression) $3, (string) $4, (Parameter.Modifier) $2, (Attributes) $1);
+         }
+       ;
+
+opt_parameter_modifier
+       : /* empty */           { $$ = Parameter.Modifier.NONE; }
+       | parameter_modifier
+       ;
+
+parameter_modifier
+       : REF                   { $$ = Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; }
+       | OUT                   { $$ = Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF; }
+       ;
+
+parameter_array
+       : opt_attributes PARAMS type IDENTIFIER
+         { 
+               $$ = new Parameter ((Expression) $3, (string) $4, Parameter.Modifier.PARAMS, (Attributes) $1);
+               note ("type must be a single-dimension array type"); 
+         }
+       ;
+
+member_name 
+       : qualified_identifier
+       ;
+
+property_declaration
+       : opt_attributes
+         opt_modifiers
+         type member_name
+         OPEN_BRACE 
+         {
+               implicit_value_parameter_type = (Expression) $3;
+
+               lexer.PropertyParsing = true;
+
+               $$ = lexer.Location;
+         }
+         accessor_declarations 
+         {
+               lexer.PropertyParsing = false;
+         }
+         CLOSE_BRACE
+         { 
+               Property prop;
+               Pair pair = (Pair) $7;
+               Accessor get_block = (Accessor) pair.First;
+               Accessor set_block = (Accessor) pair.Second;
+
+               Location loc = (Location) $6;
+               prop = new Property ((Expression) $3, (string) $4, (int) $2, get_block, set_block,
+                                    (Attributes) $1, loc);
+               
+               CheckDef (current_container.AddProperty (prop), prop.Name, loc);
+               implicit_value_parameter_type = null;
+         }
+       ;
+
+accessor_declarations
+       : get_accessor_declaration opt_set_accessor_declaration
+         { 
+               $$ = new Pair ($1, $2);
+         }
+       | set_accessor_declaration opt_get_accessor_declaration
+         {
+               $$ = new Pair ($2, $1);
+         }
+       ;
+
+opt_get_accessor_declaration
+       : /* empty */                   { $$ = null; }
+       | get_accessor_declaration
+       ;
+
+opt_set_accessor_declaration
+       : /* empty */                   { $$ = null; }
+       | set_accessor_declaration
+       ;
+
+get_accessor_declaration
+       : opt_attributes GET
+         {
+               // If this is not the case, then current_local_parameters has already
+               // been set in indexer_declaration
+               if (parsing_indexer == false)
+                       current_local_parameters = null;
+               else 
+                       current_local_parameters = indexer_parameters;
+               lexer.PropertyParsing = false;
+         }
+          accessor_body
+         {
+               $$ = new Accessor ((Block) $4, (Attributes) $1);
+               current_local_parameters = null;
+               lexer.PropertyParsing = true;
+         }
+       ;
+
+set_accessor_declaration
+       : opt_attributes SET 
+         {
+               Parameter [] args;
+               Parameter implicit_value_parameter = new Parameter (
+                       implicit_value_parameter_type, "value", 
+                       Parameter.Modifier.NONE, null);
+
+               if (parsing_indexer == false) {
+                       args  = new Parameter [1];
+                       args [0] = implicit_value_parameter;
+                       current_local_parameters = new Parameters (args, null, lexer.Location);
+               } else {
+                       Parameter [] fpars = indexer_parameters.FixedParameters;
+
+                       if (fpars != null){
+                               int count = fpars.Length;
+
+                               args = new Parameter [count + 1];
+                               fpars.CopyTo (args, 0);
+                               args [count] = implicit_value_parameter;
+                       } else 
+                               args = null;
+                       current_local_parameters = new Parameters (
+                               args, indexer_parameters.ArrayParameter, lexer.Location);
+               }
+               
+               lexer.PropertyParsing = false;
+         }
+         accessor_body
+         {
+               $$ = new Accessor ((Block) $4, (Attributes) $1);
+               current_local_parameters = null;
+               lexer.PropertyParsing = true;
+         }
+       ;
+
+accessor_body
+       : block 
+       | SEMICOLON             { $$ = null; }
+       ;
+
+interface_declaration
+       : opt_attributes
+         opt_modifiers
+         INTERFACE IDENTIFIER
+         {
+               Interface new_interface;
+               string full_interface_name = MakeName ((string) $4);
+
+               new_interface = new Interface (current_container, full_interface_name, (int) $2, 
+                                              (Attributes) $1, lexer.Location);
+               if (current_interface != null) {
+                       Location l = lexer.Location;
+                       Report.Error (-2, l, "Internal compiler error: interface inside interface");
+               }
+               current_interface = new_interface;
+               new_interface.Namespace = current_namespace;
+               RootContext.Tree.RecordDecl (full_interface_name, new_interface);
+         }
+         opt_interface_base
+         interface_body opt_semicolon
+         { 
+               Interface new_interface = (Interface) current_interface;
+
+               if ($6 != null)
+                       new_interface.Bases = (ArrayList) $6;
+
+               current_interface = null;
+               CheckDef (current_container.AddInterface (new_interface), 
+                         new_interface.Name, new_interface.Location);
+         }
+       ;
+
+opt_interface_base
+       : /* empty */                     { $$ = null; }
+       | interface_base
+       ;
+
+interface_base
+       : COLON interface_type_list       { $$ = $2; }
+       ;
+
+interface_type_list
+       : interface_type
+         {
+               ArrayList interfaces = new ArrayList (4);
+
+               interfaces.Add ($1);
+               $$ = interfaces;
+         }
+       | interface_type_list COMMA interface_type
+         {
+               ArrayList interfaces = (ArrayList) $1;
+               interfaces.Add ($3);
+               $$ = interfaces;
+         }
+       ;
+
+interface_body
+       : OPEN_BRACE
+         opt_interface_member_declarations
+         CLOSE_BRACE
+       ;
+
+opt_interface_member_declarations
+       : /* empty */
+       | interface_member_declarations
+       ;
+
+interface_member_declarations
+       : interface_member_declaration
+       | interface_member_declarations interface_member_declaration
+       ;
+
+interface_member_declaration
+       : interface_method_declaration          
+         { 
+               InterfaceMethod m = (InterfaceMethod) $1;
+
+               CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
+         }
+       | interface_property_declaration        
+         { 
+               InterfaceProperty p = (InterfaceProperty) $1;
+
+               CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
+          }
+       | interface_event_declaration 
+          { 
+               InterfaceEvent e = (InterfaceEvent) $1;
+
+               CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
+         }
+       | interface_indexer_declaration
+         { 
+               InterfaceIndexer i = (InterfaceIndexer) $1;
+
+               CheckDef (current_interface.AddIndexer (i), "indexer", i.Location);
+         }
+       ;
+
+opt_new
+       : /* empty */   { $$ = false; }
+       | NEW           { $$ = true; }
+       ;
+
+interface_method_declaration
+       : opt_attributes opt_new type IDENTIFIER 
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+         SEMICOLON
+         {
+               $$ = new InterfaceMethod ((Expression) $3, (string) $4, (bool) $2, 
+                                         (Parameters) $6, (Attributes) $1, lexer.Location);
+         }
+       | opt_attributes opt_new VOID IDENTIFIER 
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+         SEMICOLON
+         {
+               $$ = new InterfaceMethod (
+                       TypeManager.system_void_expr, (string) $4, (bool) $2, (Parameters) $6, 
+                                         (Attributes) $1, lexer.Location);
+         }
+       ;
+
+interface_property_declaration
+       : opt_attributes
+         opt_new
+         type IDENTIFIER 
+         OPEN_BRACE 
+         { lexer.PropertyParsing = true; }
+         interface_accesors 
+         { lexer.PropertyParsing = false; }
+         CLOSE_BRACE
+         {
+               int gs = (int) $7;
+
+               $$ = new InterfaceProperty ((Expression) $3, (string) $4, (bool) $2, 
+                                           (gs & 1) == 1, (gs & 2) == 2, (Attributes) $1,
+                                           lexer.Location);
+         }
+       ;
+
+interface_accesors
+       : opt_attributes GET SEMICOLON          { $$ = 1; }
+       | opt_attributes SET SEMICOLON          { $$ = 2; }
+       | opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON 
+         { $$ = 3; }
+       | opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
+         { $$ = 3; }
+       ;
+
+interface_event_declaration
+       : opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
+         {
+               $$ = new InterfaceEvent ((Expression) $4, (string) $5, (bool) $2, (Attributes) $1,
+                                        lexer.Location);
+         }
+       ;
+
+interface_indexer_declaration 
+       : opt_attributes opt_new type THIS 
+         OPEN_BRACKET formal_parameter_list CLOSE_BRACKET
+         OPEN_BRACE 
+         { lexer.PropertyParsing = true; }
+         interface_accesors 
+         { lexer.PropertyParsing = false; }
+         CLOSE_BRACE
+         {
+               int a_flags = (int) $10;
+
+               bool do_get = (a_flags & 1) == 1;
+               bool do_set = (a_flags & 2) == 2;
+
+               $$ = new InterfaceIndexer ((Expression) $3, (Parameters) $6, do_get, do_set,
+                                          (bool) $2, (Attributes) $1, lexer.Location);
+         }
+       ;
+
+operator_declaration
+       : opt_attributes opt_modifiers operator_declarator operator_body
+         {
+               OperatorDeclaration decl = (OperatorDeclaration) $3;
+               
+               Operator op = new Operator (decl.optype, decl.ret_type, (int) $2, decl.arg1type, decl.arg1name,
+                                           decl.arg2type, decl.arg2name, (Block) $4, (Attributes) $1, decl.location);
+
+               // Note again, checking is done in semantic analysis
+               current_container.AddOperator (op);
+
+               current_local_parameters = null;
+         }
+       ;
+
+operator_body 
+       : block
+       | SEMICOLON { $$ = null; }
+       ; 
+operator_declarator
+       : type OPERATOR overloadable_operator 
+         OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+       {
+               Operator.OpType op = (Operator.OpType) $3;
+               CheckUnaryOperator (op);
+
+               if (op == Operator.OpType.Addition)
+                       op = Operator.OpType.UnaryPlus;
+
+               if (op == Operator.OpType.Subtraction)
+                       op = Operator.OpType.UnaryNegation;
+
+               Parameter [] pars = new Parameter [1];
+
+               pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
+
+               current_local_parameters = new Parameters (pars, null, lexer.Location);
+
+               $$ = new OperatorDeclaration (op, (Expression) $1, (Expression) $5, (string) $6,
+                                             null, null, lexer.Location);
+       }
+       | type OPERATOR overloadable_operator
+         OPEN_PARENS 
+               type IDENTIFIER COMMA
+               type IDENTIFIER 
+         CLOSE_PARENS
+        {
+              CheckBinaryOperator ((Operator.OpType) $3);
+
+              Parameter [] pars = new Parameter [2];
+
+              pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
+              pars [1] = new Parameter ((Expression) $8, (string) $9, Parameter.Modifier.NONE, null);
+
+              current_local_parameters = new Parameters (pars, null, lexer.Location);
+              
+              $$ = new OperatorDeclaration ((Operator.OpType) $3, (Expression) $1, 
+                                            (Expression) $5, (string) $6,
+                                            (Expression) $8, (string) $9, lexer.Location);
+        }
+       | conversion_operator_declarator
+       ;
+
+overloadable_operator
+// Unary operators:
+       : BANG   { $$ = Operator.OpType.LogicalNot; }
+        | TILDE  { $$ = Operator.OpType.OnesComplement; }  
+        | OP_INC { $$ = Operator.OpType.Increment; }
+        | OP_DEC { $$ = Operator.OpType.Decrement; }
+        | TRUE   { $$ = Operator.OpType.True; }
+        | FALSE  { $$ = Operator.OpType.False; }
+// Unary and binary:
+        | PLUS { $$ = Operator.OpType.Addition; }
+        | MINUS { $$ = Operator.OpType.Subtraction; }
+// Binary:
+        | STAR { $$ = Operator.OpType.Multiply; }
+        | DIV {  $$ = Operator.OpType.Division; }
+        | PERCENT { $$ = Operator.OpType.Modulus; }
+        | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; }
+        | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; }
+        | CARRET { $$ = Operator.OpType.ExclusiveOr; }
+        | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; }
+        | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; }
+        | OP_EQ { $$ = Operator.OpType.Equality; }
+        | OP_NE { $$ = Operator.OpType.Inequality; }
+        | OP_GT { $$ = Operator.OpType.GreaterThan; }
+        | OP_LT { $$ = Operator.OpType.LessThan; }
+        | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; }
+        | OP_LE { $$ = Operator.OpType.LessThanOrEqual; }
+       ;
+
+conversion_operator_declarator
+       : IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+         {
+               Parameter [] pars = new Parameter [1];
+
+               pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
+
+               current_local_parameters = new Parameters (pars, null, lexer.Location);  
+                 
+               $$ = new OperatorDeclaration (Operator.OpType.Implicit, (Expression) $3, (Expression) $5, (string) $6,
+                                             null, null, lexer.Location);
+         }
+       | EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
+         {
+               Parameter [] pars = new Parameter [1];
+
+               pars [0] = new Parameter ((Expression) $5, (string) $6, Parameter.Modifier.NONE, null);
+
+               current_local_parameters = new Parameters (pars, null, lexer.Location);  
+                 
+               $$ = new OperatorDeclaration (Operator.OpType.Explicit, (Expression) $3, (Expression) $5, (string) $6,
+                                             null, null, lexer.Location);
+         }
+       | IMPLICIT error 
+         {
+               syntax_error (lexer.Location, "'operator' expected");
+         }
+       | EXPLICIT error 
+         {
+               syntax_error (lexer.Location, "'operator' expected");
+         }
+       ;
+
+constructor_declaration
+       : opt_attributes
+         opt_modifiers
+         constructor_declarator
+         constructor_body
+         { 
+               Constructor c = (Constructor) $3;
+               c.Block = (Block) $4;
+               c.OptAttributes = (Attributes) $1;
+               c.ModFlags = (int) $2;
+       
+               if (c.Name == current_container.Basename){
+                       if ((c.ModFlags & Modifiers.STATIC) != 0){
+                               if ((c.ModFlags & Modifiers.Accessibility) != 0){
+                                       Report.Error (
+                                               515, c.Location, String.Format (
+                                               "`{0}.{1}': static constructor can not have access modifiers",
+                                               c.Name, current_container.Name));
+                               }
+       
+                               c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);   
+       
+                               if (c.Initializer != null){
+                                       Report.Error (
+                                               514, c.Location, 
+                                               "Static constructors can not have an explicit this or base " +
+                                               "constructor invocations");
+                               }
+       
+                               if (!c.Parameters.Empty){
+                                       Report.Error (
+                                               132, c.Location, "Static constructors should not have parameters");
+                               }
+                       } else {
+                               c.ModFlags = Modifiers.Check (Constructor.AllowedModifiers, (int) $2, Modifiers.PRIVATE, c.Location);
+                       }
+               } else {
+                       // We let another layer check the validity of the constructor.
+                       Console.WriteLine ("{0} and {1}", c.Name, current_container.Basename);
+               }
+
+               CheckDef (current_container.AddConstructor (c), c.Name, c.Location);
+
+               current_local_parameters = null;
+         }
+       ;
+
+constructor_declarator
+       : IDENTIFIER 
+         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
+         {
+               oob_stack.Push (lexer.Location);
+
+               current_local_parameters = (Parameters) $3;
+         }
+         opt_constructor_initializer
+         {
+               Location l = (Location) oob_stack.Pop ();
+               $$ = new Constructor ((string) $1, (Parameters) $3, (ConstructorInitializer) $6, l);
+         }
+       ;
+
+constructor_body
+       : block
+       | SEMICOLON             { $$ = null; }
+       ;
+
+opt_constructor_initializer
+       : /* empty */                   { $$ = null; }
+       | constructor_initializer
+       ;
+
+constructor_initializer
+       : COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               $$ = new ConstructorBaseInitializer ((ArrayList) $4, current_local_parameters, lexer.Location);
+         }
+       | COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               $$ = new ConstructorThisInitializer ((ArrayList) $4, current_local_parameters, lexer.Location);
+         }
+       | COLON error {
+               Report.Error (1018, lexer.Location, "Keyword this or base expected");
+               $$ = null;
+         }
+       ;
+
+opt_finalizer
+        : /* EMPTY */           { $$ = 0; }
+        | UNSAFE               { $$ = Modifiers.UNSAFE; }
+       | EXTERN                { $$ = Modifiers.EXTERN; }
+        ;
+        
+destructor_declaration
+       : opt_attributes opt_finalizer TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
+         {
+               if ((string) $4 != current_container.Basename){
+                       Report.Error (574, lexer.Location, "Name of destructor must match name of class");
+               } else if (!(current_container is Class)){
+                       Report.Error (575, lexer.Location, "Destructors are only allowed in class types");
+               } else {
+                       Location l = lexer.Location;
+
+                       int m = (int) $2;
+                       if (!RootContext.StdLib && current_container.Name == "System.Object")
+                               m |= Modifiers.PROTECTED | Modifiers.VIRTUAL;
+                       else
+                               m |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
+                        
+                        if ((m & Modifiers.UNSAFE) != 0){
+                                if (!RootContext.Unsafe){
+                                        Report.Error (227, l,
+                                             "Unsafe code requires the --unsafe command " +
+                                             "line option to be specified");
+                                }
+                        }
+                        
+                       Method d = new Method (
+                               TypeManager.system_void_expr, m, "Finalize", 
+                               new Parameters (null, null, l), (Attributes) $1, l);
+                 
+                       d.Block = (Block) $7;
+                       CheckDef (current_container.AddMethod (d), d.Name, d.Location);
+               }
+         }
+       ;
+
+event_declaration
+       : opt_attributes
+         opt_modifiers
+         EVENT type variable_declarators SEMICOLON
+         {
+               foreach (VariableDeclaration var in (ArrayList) $5) {
+
+                       Event e = new Event ((Expression) $4, var.identifier, 
+                                            var.expression_or_array_initializer,
+                                            (int) $2, null, null, (Attributes) $1, lexer.Location);
+
+                       CheckDef (current_container.AddEvent (e), e.Name, e.Location);
+                                      
+               }
+         }
+       | opt_attributes
+         opt_modifiers
+         EVENT type member_name
+         OPEN_BRACE
+         {
+               implicit_value_parameter_type = (Expression) $4;  
+               lexer.EventParsing = true;
+               oob_stack.Push (lexer.Location);
+         }
+         event_accessor_declarations
+         {
+               lexer.EventParsing = false;  
+         }
+         CLOSE_BRACE
+         {
+               Location loc = (Location) oob_stack.Pop ();
+
+               Pair pair = (Pair) $8;
+               Accessor add_accessor = null;
+               Accessor rem_accessor = null;
+
+               if (pair.First != null)
+                       add_accessor = (Accessor) pair.First;
+               if (pair.Second != null)
+                       rem_accessor = (Accessor) pair.Second;
+               
+               Event e = new Event ((Expression) $4, (string) $5, null, (int) $2, add_accessor, rem_accessor,
+                                    (Attributes) $1, loc);
+               
+               CheckDef (current_container.AddEvent (e), e.Name, loc);
+               implicit_value_parameter_type = null;
+         }
+       ;
+
+event_accessor_declarations
+       : add_accessor_declaration remove_accessor_declaration
+       {
+               $$ = new Pair ($1, $2);
+       }
+       | remove_accessor_declaration add_accessor_declaration
+       {
+               $$ = new Pair ($2, $1);
+       }       
+       ;
+
+add_accessor_declaration
+       : opt_attributes ADD
+         {
+               Parameter [] args = new Parameter [1];
+               Parameter implicit_value_parameter = new Parameter (
+                       implicit_value_parameter_type, "value", 
+                       Parameter.Modifier.NONE, null);
+
+               args [0] = implicit_value_parameter;
+               
+               current_local_parameters = new Parameters (args, null, lexer.Location);  
+               lexer.EventParsing = false;
+         }
+          block
+         {
+               $$ = new Accessor ((Block) $4, (Attributes) $1);
+               lexer.EventParsing = true;
+         }
+       | opt_attributes ADD error {
+               Report.Error (73, lexer.Location, "Add or remove accessor must have a body");
+               $$ = null;
+         }
+       ;
+
+remove_accessor_declaration
+       : opt_attributes REMOVE
+         {
+               Parameter [] args = new Parameter [1];
+               Parameter implicit_value_parameter = new Parameter (
+                       implicit_value_parameter_type, "value", 
+                       Parameter.Modifier.NONE, null);
+
+               args [0] = implicit_value_parameter;
+               
+               current_local_parameters = new Parameters (args, null, lexer.Location);  
+               lexer.EventParsing = false;
+         }
+          block
+         {
+               $$ = new Accessor ((Block) $4, (Attributes) $1);
+               lexer.EventParsing = true;
+         }
+       | opt_attributes REMOVE error {
+               Report.Error (73, lexer.Location, "Add or remove accessor must have a body");
+               $$ = null;
+         }
+       ;
+
+indexer_declaration
+       : opt_attributes opt_modifiers indexer_declarator 
+         OPEN_BRACE 
+         {
+               IndexerDeclaration decl = (IndexerDeclaration) $3;
+
+               implicit_value_parameter_type = decl.type;
+               
+               lexer.PropertyParsing = true;
+               parsing_indexer  = true;
+               
+               indexer_parameters = decl.param_list;
+               oob_stack.Push (lexer.Location);
+         }
+          accessor_declarations 
+         {
+                 lexer.PropertyParsing = false;
+                 parsing_indexer  = false;
+         }
+         CLOSE_BRACE
+         { 
+               // The signature is computed from the signature of the indexer.  Look
+               // at section 3.6 on the spec
+               Location loc = (Location) oob_stack.Pop ();
+               Indexer indexer;
+               IndexerDeclaration decl = (IndexerDeclaration) $3;
+               Pair pair = (Pair) $6;
+               Accessor get_block = (Accessor) pair.First;
+               Accessor set_block = (Accessor) pair.Second;
+
+               indexer = new Indexer (decl.type, decl.interface_type, (int) $2, decl.param_list,
+                                      get_block, set_block, (Attributes) $1, loc);
+
+               // Note that there is no equivalent of CheckDef for this case
+               // We shall handle this in semantic analysis
+               
+               current_container.AddIndexer (indexer);
+               
+               current_local_parameters = null;
+               implicit_value_parameter_type = null;
+               indexer_parameters = null;
+         }
+       ;
+
+indexer_declarator
+       : type THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
+         {
+               Parameters pars = (Parameters) $4;
+
+               if (pars.FixedParameters == null && pars.ArrayParameter == null){
+                       Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
+               }
+
+               $$ = new IndexerDeclaration ((Expression) $1, null, pars);
+         }
+       | type qualified_identifier DOT THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
+         {
+               Parameters pars = (Parameters) $6;
+
+               if (pars.FixedParameters == null && pars.ArrayParameter == null){
+                       Report.Error (1551, lexer.Location, "Indexers must have at least one parameter");
+               }
+               $$ = new IndexerDeclaration ((Expression) $1, (string) $2, pars);
+         }
+       ;
+
+enum_declaration
+       : opt_attributes
+         opt_modifiers
+         ENUM IDENTIFIER 
+         opt_enum_base
+         enum_body
+         opt_semicolon
+         { 
+               Location enum_location = lexer.Location;
+
+               string full_name = MakeName ((string) $4);
+               Enum e = new Enum (current_container, (Expression) $5, (int) $2, full_name, 
+                                  (Attributes) $1, enum_location);
+               
+               foreach (VariableDeclaration ev in (ArrayList) $6) {
+                       Location loc = (Location) ev.Location;
+
+                       CheckDef (e.AddEnumMember (ev.identifier, 
+                                                  (Expression) ev.expression_or_array_initializer,
+                                                  loc, ev.OptAttributes),
+                                 ev.identifier, loc);
+               }
+
+               e.Namespace = current_namespace;
+
+               CheckDef (current_container.AddEnum (e), full_name, enum_location);
+               RootContext.Tree.RecordDecl (full_name, e);
+
+         }
+       ;
+
+opt_enum_base
+       : /* empty */           { $$ = TypeManager.system_int32_expr; }
+       | COLON type            { $$ = $2;   }
+       ;
+
+enum_body
+       : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
+         {
+               $$ = $2;
+         }
+       ;
+
+opt_enum_member_declarations
+       : /* empty */                   { $$ = new ArrayList (4); }
+       | enum_member_declarations opt_comma { $$ = $1; }
+       ;
+
+enum_member_declarations
+       : enum_member_declaration 
+         {
+               ArrayList l = new ArrayList (4);
+
+               l.Add ($1);
+               $$ = l;
+         }
+       | enum_member_declarations COMMA enum_member_declaration
+         {
+               ArrayList l = (ArrayList) $1;
+
+               l.Add ($3);
+
+               $$ = l;
+         }
+       ;
+
+enum_member_declaration
+       : opt_attributes IDENTIFIER 
+         {
+               $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
+         }
+       | opt_attributes IDENTIFIER
+         {
+                 $$ = lexer.Location;
+         }
+          ASSIGN expression
+         { 
+               $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
+         }
+       ;
+
+delegate_declaration
+       : opt_attributes
+         opt_modifiers
+         DELEGATE type   
+         IDENTIFIER OPEN_PARENS 
+         opt_formal_parameter_list
+         CLOSE_PARENS 
+         SEMICOLON
+         {
+               Location l = lexer.Location;
+               Delegate del = new Delegate (current_container, (Expression) $4, (int) $2, 
+                                            MakeName ((string) $5), (Parameters) $7, 
+                                            (Attributes) $1, l);
+                 
+               del.Namespace = current_namespace;
+               CheckDef (current_container.AddDelegate (del), del.Name, l);
+         }     
+       | opt_attributes
+         opt_modifiers
+         DELEGATE VOID   
+         IDENTIFIER OPEN_PARENS 
+         opt_formal_parameter_list
+         CLOSE_PARENS 
+         SEMICOLON
+         {
+               Location l = lexer.Location;
+               Delegate del = new Delegate (
+                       current_container,
+                       TypeManager.system_void_expr, (int) $2, MakeName ((string) $5), 
+                       (Parameters) $7, (Attributes) $1, l);
+
+               del.Namespace = current_namespace;
+               CheckDef (current_container.AddDelegate (del), del.Name, l);
+         }
+       ;
+
+type_name
+       : namespace_or_type_name
+       ;
+
+namespace_or_type_name
+       : qualified_identifier
+       ;
+
+/* 
+ * Before you think of adding a return_type, notice that we have been
+ * using two rules in the places where it matters (one rule using type
+ * and another identical one that uses VOID as the return type).  This
+ * gets rid of a shift/reduce couple
+ */
+type
+       : type_name {   /* class_type */
+               /* 
+                  This does interfaces, delegates, struct_types, class_types, 
+                  parent classes, and more! 4.2 
+                */
+               $$ = DecomposeQI ((string) $1, lexer.Location);
+         }
+       | builtin_types
+       | array_type
+       | pointer_type    
+       ;
+
+
+pointer_type
+       : type STAR
+         {
+               //
+               // Note that here only unmanaged types are allowed but we
+               // can't perform checks during this phase - we do it during
+               // semantic analysis.
+               //
+               $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
+         }
+       | VOID STAR
+         {
+               $$ = new ComposedCast (TypeManager.system_void_expr, "*", lexer.Location);
+         }
+       ;
+
+non_expression_type
+       : builtin_types 
+       | non_expression_type rank_specifier
+         {
+               $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
+         }
+       | non_expression_type STAR
+         {
+               $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
+         }
+       | expression rank_specifiers 
+         {
+               $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
+         }
+       | expression STAR 
+         {
+               $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
+         }
+       
+       //
+       // We need this because the parser will happily go and reduce IDENTIFIER STAR
+       // through this different path
+       //
+       | multiplicative_expression STAR 
+         {
+               $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
+         }
+       ;
+
+type_list
+       : type
+         {
+               ArrayList types = new ArrayList (4);
+
+               types.Add ($1);
+               $$ = types;
+         }
+       | type_list COMMA type
+         {
+               ArrayList types = (ArrayList) $1;
+
+               types.Add ($3);
+               $$ = types;
+         }
+       ;
+
+/*
+ * replaces all the productions for isolating the various
+ * simple types, but we need this to reuse it easily in local_variable_type
+ */
+builtin_types
+       : OBJECT        { $$ = TypeManager.system_object_expr; }
+       | STRING        { $$ = TypeManager.system_string_expr; }
+       | BOOL          { $$ = TypeManager.system_boolean_expr; }
+       | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
+       | FLOAT         { $$ = TypeManager.system_single_expr; }
+       | DOUBLE        { $$ = TypeManager.system_double_expr; }
+       | integral_type
+       ;
+
+integral_type
+       : SBYTE         { $$ = TypeManager.system_sbyte_expr; }
+       | BYTE          { $$ = TypeManager.system_byte_expr; }
+       | SHORT         { $$ = TypeManager.system_int16_expr; }
+       | USHORT        { $$ = TypeManager.system_uint16_expr; }
+       | INT           { $$ = TypeManager.system_int32_expr; }
+       | UINT          { $$ = TypeManager.system_uint32_expr; }
+       | LONG          { $$ = TypeManager.system_int64_expr; }
+       | ULONG         { $$ = TypeManager.system_uint64_expr; }
+       | CHAR          { $$ = TypeManager.system_char_expr; }
+       | VOID          { $$ = TypeManager.system_void_expr; }
+       ;
+
+interface_type
+       : type_name
+       ;
+
+array_type
+       : type rank_specifiers
+         {
+               $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
+         }
+       ;
+
+//
+// Expressions, section 7.5
+//
+primary_expression
+       : literal
+         {
+               // 7.5.1: Literals
+         }
+       | qualified_identifier
+         {
+               string name = (string) $1;
+
+               $$ = null;
+               $$ = DecomposeQI (name, lexer.Location);
+         }
+       | parenthesized_expression
+       | member_access
+       | invocation_expression
+       | element_access
+       | this_access
+       | base_access
+       | post_increment_expression
+       | post_decrement_expression
+       | new_expression
+       | typeof_expression
+       | sizeof_expression
+       | checked_expression
+       | unchecked_expression
+       | pointer_member_access
+       | anonymous_method_expression
+       ;
+
+literal
+       : boolean_literal
+       | integer_literal
+       | real_literal
+       | LITERAL_CHARACTER     { $$ = new CharLiteral ((char) lexer.Value); }
+       | LITERAL_STRING        { $$ = new StringLiteral ((string) lexer.Value); }
+       | NULL                  { $$ = NullLiteral.Null; }
+       ;
+
+real_literal
+       : LITERAL_FLOAT         { $$ = new FloatLiteral ((float) lexer.Value); }
+       | LITERAL_DOUBLE        { $$ = new DoubleLiteral ((double) lexer.Value); }
+       | LITERAL_DECIMAL       { $$ = new DecimalLiteral ((decimal) lexer.Value); }
+       ;
+
+integer_literal
+       : LITERAL_INTEGER       { 
+               object v = lexer.Value;
+
+               if (v is int)
+                       $$ = new IntLiteral ((Int32) v); 
+               else if (v is uint)
+                       $$ = new UIntLiteral ((UInt32) v);
+               else if (v is long)
+                       $$ = new LongLiteral ((Int64) v);
+               else if (v is ulong)
+                       $$ = new ULongLiteral ((UInt64) v);
+               else
+                       Console.WriteLine ("OOPS.  Unexpected result from scanner");
+         }
+       ;
+
+boolean_literal
+       : TRUE                  { $$ = new BoolLiteral (true); }
+       | FALSE                 { $$ = new BoolLiteral (false); }
+       ;
+
+parenthesized_expression
+       : OPEN_PARENS expression CLOSE_PARENS
+         { $$ = $2; }
+       ;
+
+member_access
+       : primary_expression DOT IDENTIFIER
+         {
+               $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
+         }
+       | predefined_type DOT IDENTIFIER
+         {
+               $$ = new MemberAccess ((Expression) $1, (string) $3, lexer.Location);
+         }
+       ;
+
+predefined_type
+       : builtin_types
+       ;
+
+invocation_expression
+       : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               if ($1 == null) {
+                       Location l = lexer.Location;
+                       Report.Error (1, l, "Parse error");
+               }
+               $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);
+         }
+       | OPEN_PARENS expression CLOSE_PARENS unary_expression
+         {
+                 $$ = new InvocationOrCast ((Expression) $2, (Expression) $4, lexer.Location);
+         }
+       ;
+
+opt_argument_list
+       : /* empty */           { $$ = null; }
+       | argument_list
+       ;
+
+argument_list
+       : argument              
+         { 
+               ArrayList list = new ArrayList (4);
+               list.Add ($1);
+               $$ = list;
+         }
+       | argument_list COMMA argument
+         {
+               ArrayList list = (ArrayList) $1;
+               list.Add ($3);
+               $$ = list;
+         }
+       ;
+
+argument
+       : expression
+         {
+               $$ = new Argument ((Expression) $1, Argument.AType.Expression);
+         }
+       | REF variable_reference 
+         { 
+               $$ = new Argument ((Expression) $2, Argument.AType.Ref);
+         }
+       | OUT variable_reference 
+         { 
+               $$ = new Argument ((Expression) $2, Argument.AType.Out);
+         }
+       ;
+
+variable_reference
+       : expression { note ("section 5.4"); $$ = $1; }
+       ;
+
+element_access
+       : primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET 
+         {
+               $$ = new ElementAccess ((Expression) $1, (ArrayList) $3, lexer.Location);
+         }
+       | primary_expression rank_specifiers
+         {
+               // So the super-trick is that primary_expression
+               // can only be either a SimpleName or a MemberAccess. 
+               // The MemberAccess case arises when you have a fully qualified type-name like :
+               // Foo.Bar.Blah i;
+               // SimpleName is when you have
+               // Blah i;
+                 
+               Expression expr = (Expression) $1;  
+               if (expr is ComposedCast){
+                       $$ = new ComposedCast (expr, (string) $2, lexer.Location);
+               } else if (!(expr is SimpleName || expr is MemberAccess)){
+                       Error_ExpectingTypeName (lexer.Location, expr);
+                       $$ = TypeManager.system_object_expr;
+               } else {
+                       //
+                       // So we extract the string corresponding to the SimpleName
+                       // or MemberAccess
+                       // 
+                       $$ = new ComposedCast (expr, (string) $2, lexer.Location);
+               }
+         }
+       ;
+
+expression_list
+       : expression
+         {
+               ArrayList list = new ArrayList (4);
+               list.Add ($1);
+               $$ = list;
+         }
+       | expression_list COMMA expression
+         {
+               ArrayList list = (ArrayList) $1;
+               list.Add ($3);
+               $$ = list;
+         }
+       ;
+
+this_access
+       : THIS
+         {
+               $$ = new This (current_block, lexer.Location);
+         }
+       ;
+
+base_access
+       : BASE DOT IDENTIFIER
+         {
+               $$ = new BaseAccess ((string) $3, lexer.Location);
+         }
+       | BASE OPEN_BRACKET expression_list CLOSE_BRACKET
+         {
+               $$ = new BaseIndexerAccess ((ArrayList) $3, lexer.Location);
+         }
+       ;
+
+post_increment_expression
+       : primary_expression OP_INC
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement,
+                                      (Expression) $1, lexer.Location);
+         }
+       ;
+
+post_decrement_expression
+       : primary_expression OP_DEC
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement,
+                                      (Expression) $1, lexer.Location);
+         }
+       ;
+
+new_expression
+       : object_or_delegate_creation_expression
+       | array_creation_expression
+       ;
+
+object_or_delegate_creation_expression
+       : NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               $$ = new New ((Expression) $2, (ArrayList) $4, lexer.Location);
+         }
+       ;
+
+array_creation_expression
+       : NEW type OPEN_BRACKET expression_list CLOSE_BRACKET 
+         opt_rank_specifier
+         opt_array_initializer
+         {
+               $$ = new ArrayCreation ((Expression) $2, (ArrayList) $4, (string) $6, (ArrayList) $7, lexer.Location);
+         }
+       | NEW type rank_specifiers array_initializer
+         {
+               $$ = new ArrayCreation ((Expression) $2, (string) $3, (ArrayList) $4, lexer.Location);
+         }
+       | NEW type error 
+         {
+               Report.Error (1526, lexer.Location, "new expression requires () or [] after type");
+         }
+       ;
+
+opt_rank_specifier
+       : /* empty */
+         {
+                 $$ = "";
+         }
+       | rank_specifiers
+         {
+                       $$ = $1;
+         }
+       ;
+
+rank_specifiers
+       : rank_specifier opt_rank_specifier
+         {
+                 $$ = (string) $2 + (string) $1;
+         }
+        ;
+
+rank_specifier
+       : OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
+         {
+               $$ = "[" + (string) $2 + "]";
+         }
+       ;
+
+opt_dim_separators
+       : /* empty */
+         {
+               $$ = "";
+         }
+       | dim_separators
+         {
+                 $$ = $1;
+         }               
+       ;
+
+dim_separators
+       : COMMA
+         {
+               $$ = ",";
+         }
+       | dim_separators COMMA
+         {
+               $$ = (string) $1 + ",";
+         }
+       ;
+
+opt_array_initializer
+       : /* empty */
+         {
+               $$ = null;
+         }
+        | array_initializer
+         {
+               $$ = $1;
+         }
+       ;
+
+array_initializer
+       : OPEN_BRACE CLOSE_BRACE
+         {
+               ArrayList list = new ArrayList (4);
+               $$ = list;
+         }
+       | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
+         {
+               $$ = (ArrayList) $2;
+         }
+       ;
+
+variable_initializer_list
+       : variable_initializer
+         {
+               ArrayList list = new ArrayList (4);
+               list.Add ($1);
+               $$ = list;
+         }
+       | variable_initializer_list COMMA variable_initializer
+         {
+               ArrayList list = (ArrayList) $1;
+               list.Add ($3);
+               $$ = list;
+         }
+       ;
+
+typeof_expression
+       : TYPEOF OPEN_PARENS VOID CLOSE_PARENS
+         {
+               $$ = new TypeOfVoid (lexer.Location);
+         }
+       | TYPEOF OPEN_PARENS type CLOSE_PARENS
+         {
+               $$ = new TypeOf ((Expression) $3, lexer.Location);
+         }
+       ;
+
+sizeof_expression
+       : SIZEOF OPEN_PARENS type CLOSE_PARENS { 
+               $$ = new SizeOf ((Expression) $3, lexer.Location);
+         }
+       ;
+
+checked_expression
+       : CHECKED OPEN_PARENS expression CLOSE_PARENS
+         {
+               $$ = new CheckedExpr ((Expression) $3, lexer.Location);
+         }
+       ;
+
+unchecked_expression
+       : UNCHECKED OPEN_PARENS expression CLOSE_PARENS
+         {
+               $$ = new UnCheckedExpr ((Expression) $3, lexer.Location);
+         }
+       ;
+
+pointer_member_access 
+       : primary_expression OP_PTR IDENTIFIER
+         {
+               Expression deref;
+
+               deref = new Unary (Unary.Operator.Indirection, (Expression) $1, lexer.Location);
+               $$ = new MemberAccess (deref, (string) $3, lexer.Location);
+         }
+       ;
+
+anonymous_method_expression
+       : DELEGATE opt_anonymous_method_signature {
+               oob_stack.Push (current_local_parameters);
+               current_local_parameters = (Parameters)$2;
+         } block {
+               if (!RootContext.V2){
+                       Report.Error (-213, lexer.Location, "Anonymous methods are only supported in V2");
+                       $$ = null;
+               } else 
+                       $$ = new AnonymousMethod ((Parameters) $2, (Block) $3, lexer.Location);
+               current_local_parameters = (Parameters) oob_stack.Pop ();
+         }
+       ;
+
+opt_anonymous_method_signature
+       : /* empty */                   { $$ = Parameters.EmptyReadOnlyParameters; }
+       | anonymous_method_signature
+       ;
+
+anonymous_method_signature
+       : OPEN_PARENS opt_anonymous_method_parameter_list CLOSE_PARENS 
+         {
+               if ($2 == null)
+                       $$ = Parameters.EmptyReadOnlyParameters;
+               else {
+                       ArrayList par_list = (ArrayList) $2;
+                       Parameter [] pars = new Parameter [par_list.Count];
+                       par_list.CopyTo (pars);
+                       $$ = new Parameters (pars, null, lexer.Location);
+               }
+         }
+       ;
+
+opt_anonymous_method_parameter_list
+       : /* empty */   { $$ = null; } 
+       | anonymous_method_parameter_list  { $$ = $1; }
+       ;
+
+anonymous_method_parameter_list
+       : anonymous_method_parameter 
+         {
+               ArrayList a = new ArrayList (4);
+               a.Add ($1);
+               $$ = a;
+         }
+       | anonymous_method_parameter_list COMMA anonymous_method_parameter 
+         {
+               ArrayList a = (ArrayList) $1;
+               a.Add ($3);
+               $$ = a;
+         }
+       ; 
+
+anonymous_method_parameter
+       : opt_parameter_modifier type IDENTIFIER {
+               $$ = new Parameter ((Expression) $2, (string) $2, (Parameter.Modifier) $1, null);
+         }
+       ;
+
+unary_expression
+       : primary_expression
+       | BANG prefixed_unary_expression
+         {
+               $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
+         }
+       | TILDE prefixed_unary_expression
+         {
+               $$ = new Unary (Unary.Operator.OnesComplement, (Expression) $2, lexer.Location);
+         }
+       | cast_expression
+       ;
+
+cast_expression
+       : OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
+         {
+                 $$ = new Cast ((Expression) $2, (Expression) $4, lexer.Location);
+         }
+       ;
+
+       //
+       // The idea to split this out is from Rhys' grammar
+       // to solve the problem with casts.
+       //
+prefixed_unary_expression
+       : unary_expression
+       | PLUS prefixed_unary_expression
+         { 
+               $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
+         } 
+       | MINUS prefixed_unary_expression 
+         { 
+               $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
+         }
+       | OP_INC prefixed_unary_expression 
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
+                                      (Expression) $2, lexer.Location);
+         }
+       | OP_DEC prefixed_unary_expression 
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
+                                      (Expression) $2, lexer.Location);
+         }
+       | STAR prefixed_unary_expression
+         {
+               $$ = new Unary (Unary.Operator.Indirection, (Expression) $2, lexer.Location);
+         }
+       | BITWISE_AND prefixed_unary_expression
+         {
+               $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, lexer.Location);
+         }
+       ;
+
+pre_increment_expression
+       : OP_INC prefixed_unary_expression 
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement,
+                                      (Expression) $2, lexer.Location);
+         }
+       ;
+
+pre_decrement_expression
+       : OP_DEC prefixed_unary_expression 
+         {
+               $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement,
+                                      (Expression) $2, lexer.Location);
+         }
+       ;
+
+multiplicative_expression
+       : prefixed_unary_expression
+       | multiplicative_expression STAR prefixed_unary_expression
+         {
+               $$ = new Binary (Binary.Operator.Multiply, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | multiplicative_expression DIV prefixed_unary_expression
+         {
+               $$ = new Binary (Binary.Operator.Division, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | multiplicative_expression PERCENT prefixed_unary_expression 
+         {
+               $$ = new Binary (Binary.Operator.Modulus, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+additive_expression
+       : multiplicative_expression
+       | additive_expression PLUS multiplicative_expression 
+         {
+               $$ = new Binary (Binary.Operator.Addition, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | additive_expression MINUS multiplicative_expression
+         {
+               $$ = new Binary (Binary.Operator.Subtraction, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+shift_expression
+       : additive_expression
+       | shift_expression OP_SHIFT_LEFT additive_expression
+         {
+               $$ = new Binary (Binary.Operator.LeftShift, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | shift_expression OP_SHIFT_RIGHT additive_expression
+         {
+               $$ = new Binary (Binary.Operator.RightShift, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ; 
+
+relational_expression
+       : shift_expression
+       | relational_expression OP_LT shift_expression
+         {
+               $$ = new Binary (Binary.Operator.LessThan, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | relational_expression OP_GT shift_expression
+         {
+               $$ = new Binary (Binary.Operator.GreaterThan, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | relational_expression OP_LE shift_expression
+         {
+               $$ = new Binary (Binary.Operator.LessThanOrEqual, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | relational_expression OP_GE shift_expression
+         {
+               $$ = new Binary (Binary.Operator.GreaterThanOrEqual, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | relational_expression IS type
+         {
+               $$ = new Is ((Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | relational_expression AS type
+         {
+               $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+equality_expression
+       : relational_expression
+       | equality_expression OP_EQ relational_expression
+         {
+               $$ = new Binary (Binary.Operator.Equality, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | equality_expression OP_NE relational_expression
+         {
+               $$ = new Binary (Binary.Operator.Inequality, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ; 
+
+and_expression
+       : equality_expression
+       | and_expression BITWISE_AND equality_expression
+         {
+               $$ = new Binary (Binary.Operator.BitwiseAnd, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+exclusive_or_expression
+       : and_expression
+       | exclusive_or_expression CARRET and_expression
+         {
+               $$ = new Binary (Binary.Operator.ExclusiveOr, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+inclusive_or_expression
+       : exclusive_or_expression
+       | inclusive_or_expression BITWISE_OR exclusive_or_expression
+         {
+               $$ = new Binary (Binary.Operator.BitwiseOr, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+conditional_and_expression
+       : inclusive_or_expression
+       | conditional_and_expression OP_AND inclusive_or_expression
+         {
+               $$ = new Binary (Binary.Operator.LogicalAnd, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+conditional_or_expression
+       : conditional_and_expression
+       | conditional_or_expression OP_OR conditional_and_expression
+         {
+               $$ = new Binary (Binary.Operator.LogicalOr, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       ;
+
+conditional_expression
+       : conditional_or_expression
+       | conditional_or_expression INTERR expression COLON expression 
+         {
+               $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
+         }
+       ;
+
+assignment_expression
+       : prefixed_unary_expression ASSIGN expression
+         {
+               $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | prefixed_unary_expression OP_MULT_ASSIGN expression
+         {
+               Location l = lexer.Location;
+
+               $$ = new CompoundAssign (
+                       Binary.Operator.Multiply, (Expression) $1, (Expression) $3, l);
+         }
+       | prefixed_unary_expression OP_DIV_ASSIGN expression
+         {
+               Location l = lexer.Location;
+
+               $$ = new CompoundAssign (
+                       Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
+         }
+       | prefixed_unary_expression OP_MOD_ASSIGN expression
+         {
+               Location l = lexer.Location;
+
+               $$ = new CompoundAssign (
+                       Binary.Operator.Modulus, (Expression) $1, (Expression) $3, l);
+         }
+       | prefixed_unary_expression OP_ADD_ASSIGN expression
+         {
+               Location l = lexer.Location;
+
+               $$ = new CompoundAssign (
+                       Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
+         }
+       | prefixed_unary_expression OP_SUB_ASSIGN expression
+         {
+               Location l = lexer.Location;
+
+               $$ = new CompoundAssign (
+                       Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l);
+         }
+       | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
+         {
+               Location l = lexer.Location;
+
+               $$ = new CompoundAssign (
+                       Binary.Operator.LeftShift, (Expression) $1, (Expression) $3, l);
+         }
+       | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
+         {
+               Location l = lexer.Location;
+
+               $$ = new CompoundAssign (
+                       Binary.Operator.RightShift, (Expression) $1, (Expression) $3, l);
+         }
+       | prefixed_unary_expression OP_AND_ASSIGN expression
+         {
+               Location l = lexer.Location;
+
+               $$ = new CompoundAssign (
+                       Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3, l);
+         }
+       | prefixed_unary_expression OP_OR_ASSIGN expression
+         {
+               Location l = lexer.Location;
+
+               $$ = new CompoundAssign (
+                       Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3, l);
+         }
+       | prefixed_unary_expression OP_XOR_ASSIGN expression
+         {
+               Location l = lexer.Location;
+
+               $$ = new CompoundAssign (
+                       Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3, l);
+         }
+       ;
+
+expression
+       : conditional_expression
+       | assignment_expression
+       ;
+
+constant_expression
+       : expression
+       ;
+
+boolean_expression
+       : expression
+       ;
+
+//
+// 10 classes
+//
+class_declaration
+       : opt_attributes
+         opt_modifiers
+         CLASS IDENTIFIER
+         {
+               Class new_class;
+               string name;
+
+               name = MakeName ((string) $4);
+
+               new_class = new Class (current_container, name, (int) $2, 
+                                      (Attributes) $1, lexer.Location);
+               current_container = new_class;
+               current_container.Namespace = current_namespace;
+               RootContext.Tree.RecordDecl (name, new_class);
+         }
+         opt_class_base
+         class_body 
+         opt_semicolon 
+         {
+               Class new_class = (Class) current_container;
+
+               if ($6 != null)
+                       new_class.Bases = (ArrayList) $6;
+
+               current_container = current_container.Parent;
+               CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
+
+               $$ = new_class;
+         }
+       ;       
+
+opt_modifiers
+       : /* empty */           { $$ = (int) 0; }
+       | modifiers
+       ;
+
+modifiers
+       : modifier
+       | modifiers modifier
+         { 
+               int m1 = (int) $1;
+               int m2 = (int) $2;
+
+               if ((m1 & m2) != 0) {
+                       Location l = lexer.Location;
+                       Report.Error (1004, l, "Duplicate modifier: `" + Modifiers.Name (m2) + "'");
+               }
+               $$ = (int) (m1 | m2);
+         }
+        ;
+
+modifier
+       : NEW                   { $$ = Modifiers.NEW; }
+       | PUBLIC                { $$ = Modifiers.PUBLIC; }
+       | PROTECTED             { $$ = Modifiers.PROTECTED; }
+       | INTERNAL              { $$ = Modifiers.INTERNAL; }
+       | PRIVATE               { $$ = Modifiers.PRIVATE; }
+       | ABSTRACT              { $$ = Modifiers.ABSTRACT; }
+       | SEALED                { $$ = Modifiers.SEALED; }
+       | STATIC                { $$ = Modifiers.STATIC; }
+       | READONLY              { $$ = Modifiers.READONLY; }
+       | VIRTUAL               { $$ = Modifiers.VIRTUAL; }
+       | OVERRIDE              { $$ = Modifiers.OVERRIDE; }
+       | EXTERN                { $$ = Modifiers.EXTERN; }
+       | VOLATILE              { $$ = Modifiers.VOLATILE; }
+       | UNSAFE                { $$ = Modifiers.UNSAFE; }
+       ;
+
+opt_class_base
+       : /* empty */           { $$ = null; }
+       | class_base            { $$ = $1;   }
+       ;
+
+class_base
+       : COLON type_list { $$ = $2; }
+       ;
+
+//
+// Statements (8.2)
+//
+
+//
+// A block is "contained" on the following places:
+//     method_body
+//     property_declaration as part of the accessor body (get/set)
+//      operator_declaration
+//     constructor_declaration
+//     destructor_declaration
+//     event_declaration as part of add_accessor_declaration or remove_accessor_declaration
+//      
+block
+       : OPEN_BRACE 
+         {
+               current_block = new Block (current_block, current_local_parameters,
+                                          lexer.Location, Location.Null);
+         } 
+         opt_statement_list CLOSE_BRACE 
+         { 
+               while (current_block.Implicit)
+                       current_block = current_block.Parent;
+               $$ = current_block;
+               current_block.SetEndLocation (lexer.Location);
+               current_block = current_block.Parent;
+         }
+       ;
+
+opt_statement_list
+       : /* empty */
+       | statement_list 
+       ;
+
+statement_list
+       : statement
+       | statement_list statement
+       ;
+
+statement
+       : declaration_statement
+         {
+               if ($1 != null && (Block) $1 != current_block){
+                       current_block.AddStatement ((Statement) $1);
+                       current_block = (Block) $1;
+               }
+         }
+       | embedded_statement
+         {
+               Statement s = (Statement) $1;
+
+
+               current_block.AddStatement ((Statement) $1);
+         }
+       | labeled_statement
+       ;
+
+embedded_statement
+       : block
+       | empty_statement
+        | expression_statement
+       | selection_statement
+       | iteration_statement
+       | jump_statement                  
+       | try_statement
+       | checked_statement
+       | unchecked_statement
+       | lock_statement
+       | using_statement
+       | unsafe_statement
+       | fixed_statement
+       ;
+
+empty_statement
+       : SEMICOLON
+         {
+                 $$ = new EmptyStatement ();
+         }
+       ;
+
+labeled_statement
+       : IDENTIFIER COLON 
+         {
+               LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
+
+               if (!current_block.AddLabel ((string) $1, labeled)){
+                       Location l = lexer.Location;
+                       Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
+               }       
+               current_block.AddStatement (labeled);
+         }
+         statement
+       ;
+
+declaration_statement
+       : local_variable_declaration SEMICOLON
+         {
+               if ($1 != null){
+                       DictionaryEntry de = (DictionaryEntry) $1;
+
+                       $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
+               }
+         }
+
+       | local_constant_declaration SEMICOLON
+         {
+               if ($1 != null){
+                       DictionaryEntry de = (DictionaryEntry) $1;
+
+                       $$ = declare_local_constant ((Expression) de.Key, (VariableDeclaration) de.Value);
+               }
+         }
+       ;
+
+/* 
+ * The following is from Rhys' grammar:
+ * > Types in local variable declarations must be recognized as 
+ * > expressions to prevent reduce/reduce errors in the grammar.
+ * > The expressions are converted into types during semantic analysis.
+ */
+local_variable_type
+       : primary_expression opt_rank_specifier
+         { 
+               // FIXME: Do something smart here regarding the composition of the type.
+
+               // Ok, the above "primary_expression" is there to get rid of
+               // both reduce/reduce and shift/reduces in the grammar, it should
+               // really just be "type_name".  If you use type_name, a reduce/reduce
+               // creeps up.  If you use qualified_identifier (which is all we need
+               // really) two shift/reduces appear.
+               // 
+
+               // So the super-trick is that primary_expression
+               // can only be either a SimpleName or a MemberAccess. 
+               // The MemberAccess case arises when you have a fully qualified type-name like :
+               // Foo.Bar.Blah i;
+               // SimpleName is when you have
+               // Blah i;
+                 
+               Expression expr = (Expression) $1;  
+               if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast)) {
+                       Error_ExpectingTypeName (lexer.Location, expr);
+                       $$ = null;
+               } else {
+                       //
+                       // So we extract the string corresponding to the SimpleName
+                       // or MemberAccess
+                       // 
+
+                       if ((string) $2 == "")
+                               $$ = $1;
+                       else
+                               $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
+               }
+         }
+       | builtin_types opt_rank_specifier
+         {
+               if ((string) $2 == "")
+                       $$ = $1;
+               else
+                       $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
+         }
+        ;
+
+local_variable_pointer_type
+       : primary_expression STAR
+         {
+               Expression expr = (Expression) $1;  
+               Location l = lexer.Location;
+
+               if (!(expr is SimpleName || expr is MemberAccess || expr is ComposedCast)) {
+                       Error_ExpectingTypeName (l, expr);
+
+                       $$ = null;
+               } else 
+                       $$ = new ComposedCast ((Expression) $1, "*", l);
+         }
+        | builtin_types STAR
+         {
+               $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);;
+         }
+        | VOID STAR
+         {
+               $$ = new ComposedCast (TypeManager.system_void_expr, "*", lexer.Location);;
+         }
+       | local_variable_pointer_type STAR
+          {
+               $$ = new ComposedCast ((Expression) $1, "*", lexer.Location);
+         }
+        ;
+
+local_variable_declaration
+       : local_variable_type variable_declarators
+         {
+               if ($1 != null)
+                       $$ = new DictionaryEntry ($1, $2);
+               else
+                       $$ = null;
+         }
+        | local_variable_pointer_type opt_rank_specifier variable_declarators
+       {
+               if ($1 != null){
+                       Expression t;
+
+                       if ((string) $2 == "")
+                               t = (Expression) $1;
+                       else
+                               t = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
+                       $$ = new DictionaryEntry (t, $3);
+               } else 
+                       $$ = null;
+       }
+       ;
+
+local_constant_declaration
+       : CONST local_variable_type constant_declarator
+         {
+               if ($2 != null)
+                       $$ = new DictionaryEntry ($2, $3);
+               else
+                       $$ = null;
+         }
+       ;
+
+expression_statement
+       : statement_expression SEMICOLON
+         {
+               $$ = $1;
+         }
+       ;
+
+       //
+       // We have to do the wrapping here and not in the case above,
+       // because statement_expression is used for example in for_statement
+       //
+statement_expression
+       : invocation_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | object_creation_expression    { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | assignment_expression         { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | post_increment_expression     { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | post_decrement_expression     { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | pre_increment_expression      { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | pre_decrement_expression      { $$ = new StatementExpression ((ExpressionStatement) $1, lexer.Location); }
+       | error {
+               Report.Error (1002, lexer.Location, "Expecting `;'");
+               $$ = null;
+         }
+       ;
+
+object_creation_expression
+       : object_or_delegate_creation_expression
+         { note ("complain if this is a delegate maybe?"); } 
+       ;
+
+selection_statement
+       : if_statement
+       | switch_statement
+       ; 
+
+if_statement
+       : if_statement_open if_statement_rest
+         {
+               $$ = $2;
+         }
+       ;
+
+if_statement_open
+       : IF OPEN_PARENS 
+         {
+               oob_stack.Push (lexer.Location);
+         }
+       ;
+
+if_statement_rest
+       : boolean_expression CLOSE_PARENS 
+         embedded_statement
+         { 
+               Location l = (Location) oob_stack.Pop ();
+
+               $$ = new If ((Expression) $1, (Statement) $3, l);
+
+               if (RootContext.WarningLevel >= 3){
+                       if ($3 is EmptyStatement)
+                               Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
+               }
+
+         }
+       | boolean_expression CLOSE_PARENS
+         embedded_statement ELSE embedded_statement
+         {
+               Location l = (Location) oob_stack.Pop ();
+
+               $$ = new If ((Expression) $1, (Statement) $3, (Statement) $5, l);
+         }
+       ;
+
+switch_statement
+       : SWITCH OPEN_PARENS 
+         { 
+               oob_stack.Push (lexer.Location);
+               switch_stack.Push (current_block);
+         }
+         expression CLOSE_PARENS 
+         switch_block
+         {
+               $$ = new Switch ((Expression) $4, (ArrayList) $6, (Location) oob_stack.Pop ());
+               current_block = (Block) switch_stack.Pop ();
+         }
+       ;
+
+switch_block
+       : OPEN_BRACE
+         opt_switch_sections
+         CLOSE_BRACE
+         {
+               $$ = $2;
+         }
+       ;
+
+opt_switch_sections
+       : /* empty */           
+          {
+               Report.Error (1522, lexer.Location, "Empty switch block"); 
+         }
+       | switch_sections
+       ;
+
+switch_sections
+       : switch_section 
+         {
+               ArrayList sections = new ArrayList (4);
+
+               sections.Add ($1);
+               $$ = sections;
+         }
+       | switch_sections switch_section
+         {
+               ArrayList sections = (ArrayList) $1;
+
+               sections.Add ($2);
+               $$ = sections;
+         }
+       ;
+
+switch_section
+       : switch_labels
+         {
+               current_block = current_block.CreateSwitchBlock (lexer.Location);
+         }
+         statement_list 
+         {
+               Block topmost = current_block;
+
+               while (topmost.Implicit)
+                       topmost = topmost.Parent;
+               $$ = new SwitchSection ((ArrayList) $1, topmost);
+         }
+       ;
+
+switch_labels
+       : switch_label 
+         {
+               ArrayList labels = new ArrayList (4);
+
+               labels.Add ($1);
+               $$ = labels;
+         }
+       | switch_labels switch_label 
+         {
+               ArrayList labels = (ArrayList) ($1);
+               labels.Add ($2);
+
+               $$ = labels;
+         }
+       ;
+
+switch_label
+       : CASE constant_expression COLON        { $$ = new SwitchLabel ((Expression) $2, lexer.Location); }
+       | DEFAULT COLON                         { $$ = new SwitchLabel (null, lexer.Location); }
+       | error {
+               Report.Error (
+                       1523, lexer.Location, 
+                       "The keyword case or default must precede code in switch block");
+         }
+       ;
+
+iteration_statement
+       : while_statement
+       | do_statement
+       | for_statement
+       | foreach_statement
+       ;
+
+while_statement
+       : WHILE OPEN_PARENS 
+       {
+               oob_stack.Push (lexer.Location);
+       }
+       boolean_expression CLOSE_PARENS embedded_statement
+       {
+               Location l = (Location) oob_stack.Pop ();
+               $$ = new While ((Expression) $4, (Statement) $6, l);
+       
+               if (RootContext.WarningLevel >= 3){
+                       if ($6 is EmptyStatement)
+                               Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
+               }
+       }
+       ;
+
+do_statement
+       : DO embedded_statement 
+         WHILE OPEN_PARENS {
+               oob_stack.Push (lexer.Location);
+         }
+         boolean_expression CLOSE_PARENS SEMICOLON
+         {
+               Location l = (Location) oob_stack.Pop ();
+
+               $$ = new Do ((Statement) $2, (Expression) $6, l);
+         }
+       ;
+
+for_statement
+       : FOR OPEN_PARENS 
+         opt_for_initializer SEMICOLON
+         {
+               Block assign_block = new Block (current_block);
+               current_block = assign_block;
+
+               if ($3 is DictionaryEntry){
+                       DictionaryEntry de = (DictionaryEntry) $3;
+                       
+                       Expression type = (Expression) de.Key;
+                       ArrayList var_declarators = (ArrayList) de.Value;
+
+                       foreach (VariableDeclaration decl in var_declarators){
+
+                               LocalInfo vi;
+
+                               vi = current_block.AddVariable (
+                                       type, decl.identifier, current_local_parameters, decl.Location);
+                               if (vi == null)
+                                       continue;
+
+                               Location l = lexer.Location;
+                               Expression expr;
+                               if (decl.expression_or_array_initializer is Expression){
+                                       expr = (Expression) decl.expression_or_array_initializer;
+                               } else if (decl.expression_or_array_initializer == null) {
+                                       expr = null;
+                               } else {
+                                       ArrayList init = (ArrayList) decl.expression_or_array_initializer;
+                                       expr = new ArrayCreation (type, "", init, decl.Location);
+                               }
+                                       
+                               LocalVariableReference var;
+                               var = new LocalVariableReference (assign_block, decl.identifier, l);
+
+                               if (expr != null) {
+                                       Assign a = new Assign (var, expr, decl.Location);
+                                       
+                                       assign_block.AddStatement (new StatementExpression (a, lexer.Location));
+                               }
+                       }
+                       
+                       $3 = null;
+               } 
+               oob_stack.Push (lexer.Location);
+         } 
+         opt_for_condition SEMICOLON
+         opt_for_iterator CLOSE_PARENS 
+         embedded_statement
+         {
+               Location l = (Location) oob_stack.Pop ();
+
+               For f = new For ((Statement) $3, (Expression) $6, (Statement) $8, (Statement) $10, l);
+
+               if (RootContext.WarningLevel >= 3){
+                       if ($10 is EmptyStatement)
+                               Report.Warning (642, lexer.Location, "Possibly mistaken empty statement");
+               }
+
+               current_block.AddStatement (f);
+               while (current_block.Implicit)
+                       current_block = current_block.Parent;
+               $$ = current_block;
+               current_block = current_block.Parent;
+         }
+       ;
+
+opt_for_initializer
+       : /* empty */           { $$ = new EmptyStatement (); }
+       | for_initializer       
+       ;
+
+for_initializer
+       : local_variable_declaration
+       | statement_expression_list
+       ;
+
+opt_for_condition
+       : /* empty */           { $$ = null; }
+       | boolean_expression
+       ;
+
+opt_for_iterator
+       : /* empty */           { $$ = new EmptyStatement (); }
+       | for_iterator
+       ;
+
+for_iterator
+       : statement_expression_list
+       ;
+
+statement_expression_list
+       : statement_expression  
+         {
+               // CHANGE: was `null'
+               Block b = new Block (current_block, Block.Flags.Implicit);   
+
+               b.AddStatement ((Statement) $1);
+               $$ = b;
+         }
+       | statement_expression_list COMMA statement_expression
+         {
+               Block b = (Block) $1;
+
+               b.AddStatement ((Statement) $3);
+               $$ = $1;
+         }
+       ;
+
+foreach_statement
+       : FOREACH OPEN_PARENS type IDENTIFIER IN 
+         {
+               oob_stack.Push (lexer.Location);
+         }
+         expression CLOSE_PARENS 
+         {
+               oob_stack.Push (current_block);
+
+               Block foreach_block = new Block (current_block, Block.Flags.Implicit);
+               LocalVariableReference v = null;
+               Location l = lexer.Location;
+               LocalInfo vi;
+
+               vi = foreach_block.AddVariable ((Expression) $3, (string) $4, current_local_parameters, l);
+               if (vi != null) {
+                       vi.ReadOnly = true;
+
+                       // Get a writable reference to this read-only variable.
+                       v = new LocalVariableReference (foreach_block, (string) $4, l, vi, false);
+               }
+               current_block = foreach_block;
+
+               oob_stack.Push (v);
+               oob_stack.Push (current_block);
+         } 
+         embedded_statement 
+         {
+               Block foreach_block = (Block) oob_stack.Pop ();
+               LocalVariableReference v = (LocalVariableReference) oob_stack.Pop ();
+               Block prev_block = (Block) oob_stack.Pop ();
+               Location l = (Location) oob_stack.Pop ();
+
+               current_block = prev_block;
+
+               if (v != null) {
+                       Foreach f = new Foreach ((Expression) $3, v, (Expression) $7, (Statement) $10, l);
+                       foreach_block.AddStatement (f);
+               }
+
+               $$ = foreach_block;
+         }
+       ;
+
+jump_statement
+       : break_statement
+       | continue_statement
+       | goto_statement
+       | return_statement
+       | throw_statement
+       | yield_statement
+       ;
+
+break_statement
+       : BREAK SEMICOLON
+         {
+               $$ = new Break (lexer.Location);
+         }
+       ;
+
+continue_statement
+       : CONTINUE SEMICOLON
+         {
+               $$ = new Continue (lexer.Location);
+         }
+       ;
+
+goto_statement
+       : GOTO IDENTIFIER SEMICOLON 
+         {
+               $$ = new Goto (current_block, (string) $2, lexer.Location);
+         }
+       | GOTO CASE constant_expression SEMICOLON
+         {
+               $$ = new GotoCase ((Expression) $3, lexer.Location);
+         }
+       | GOTO DEFAULT SEMICOLON 
+         {
+               $$ = new GotoDefault (lexer.Location);
+         }
+       ; 
+
+return_statement
+       : RETURN opt_expression SEMICOLON
+         {
+               $$ = new Return ((Expression) $2, lexer.Location);
+         }
+       ;
+
+throw_statement
+       : THROW opt_expression SEMICOLON
+         {
+               $$ = new Throw ((Expression) $2, lexer.Location);
+         }
+       ;
+
+yield_statement 
+       : YIELD expression SEMICOLON
+         {
+               if (iterator_container == null){
+                       Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
+                       $$ = null;
+               } else {
+                       iterator_container.SetYields ();
+                       $$ = new Yield ((Expression) $2, lexer.Location);
+               }
+         }
+       | YIELD BREAK SEMICOLON
+         {
+               if (iterator_container == null){
+                       Report.Error (204, lexer.Location, "yield statement can only be used within a method, operator or property");
+                       $$ = null;
+               } else {
+                       iterator_container.SetYields ();
+                       $$ = new YieldBreak (lexer.Location);
+               }
+         }
+       ;
+
+opt_expression
+       : /* empty */
+       | expression
+       ;
+
+try_statement
+       : TRY block catch_clauses 
+       {
+               Catch g = null;
+               ArrayList s = new ArrayList (4);
+               
+               foreach (Catch cc in (ArrayList) $3) {
+                       if (cc.IsGeneral)
+                               g = cc;
+                       else
+                               s.Add (cc);
+               }
+
+               // Now s contains the list of specific catch clauses
+               // and g contains the general one.
+               
+               $$ = new Try ((Block) $2, s, g, null, lexer.Location);
+       }
+       | TRY block opt_catch_clauses FINALLY block
+         {
+               Catch g = null;
+               ArrayList s = new ArrayList (4);
+               ArrayList catch_list = (ArrayList) $3;
+
+               if (catch_list != null){
+                       foreach (Catch cc in catch_list) {
+                               if (cc.IsGeneral)
+                                       g = cc;
+                               else
+                                       s.Add (cc);
+                       }
+               }
+
+               $$ = new Try ((Block) $2, s, g, (Block) $5, lexer.Location);
+         }
+       | TRY block error 
+         {
+               Report.Error (1524, lexer.Location, "Expected catch or finally");
+         }
+       ;
+
+opt_catch_clauses
+       : /* empty */  { $$ = null; }
+        | catch_clauses
+       ;
+
+catch_clauses
+       : catch_clause 
+         {
+               ArrayList l = new ArrayList (4);
+
+               l.Add ($1);
+               $$ = l;
+         }
+       | catch_clauses catch_clause
+         {
+               ArrayList l = (ArrayList) $1;
+
+               l.Add ($2);
+               $$ = l;
+         }
+       ;
+
+opt_identifier
+       : /* empty */   { $$ = null; }
+       | IDENTIFIER
+       ;
+
+catch_clause 
+       : CATCH opt_catch_args 
+       {
+               Expression type = null;
+               string id = null;
+               
+               if ($2 != null) {
+                       DictionaryEntry cc = (DictionaryEntry) $2;
+                       type = (Expression) cc.Key;
+                       id   = (string) cc.Value;
+
+                       if (id != null){
+                               ArrayList one = new ArrayList (4);
+                               Location loc = lexer.Location;
+
+                               one.Add (new VariableDeclaration (id, null, loc));
+
+                               $1 = current_block;
+                               current_block = new Block (current_block);
+                               Block b = declare_local_variables (type, one, loc);
+                               current_block = b;
+                       }
+               }
+       } block {
+               Expression type = null;
+               string id = null;
+
+               if ($2 != null){
+                       DictionaryEntry cc = (DictionaryEntry) $2;
+                       type = (Expression) cc.Key;
+                       id   = (string) cc.Value;
+
+                       if ($1 != null){
+                               //
+                               // FIXME: I can change this for an assignment.
+                               //
+                               while (current_block != (Block) $1)
+                                       current_block = current_block.Parent;
+                       }
+               }
+
+
+               $$ = new Catch (type, id , (Block) $4, lexer.Location);
+       }
+        ;
+
+opt_catch_args
+       : /* empty */ { $$ = null; }
+        | catch_args
+       ;         
+
+catch_args 
+        : OPEN_PARENS type opt_identifier CLOSE_PARENS 
+        {
+               $$ = new DictionaryEntry ($2, $3);
+       }
+        ;
+
+checked_statement
+       : CHECKED block
+         {
+               $$ = new Checked ((Block) $2);
+         }
+       ;
+
+unchecked_statement
+       : UNCHECKED block
+         {
+               $$ = new Unchecked ((Block) $2);
+         }
+       ;
+
+unsafe_statement
+       : UNSAFE 
+       {
+               if (!RootContext.Unsafe){
+                       Report.Error (227, lexer.Location, 
+                               "Unsafe code can only be used if --unsafe is used");
+               }
+       } block {
+               $$ = new Unsafe ((Block) $3);
+       }
+       ;
+
+fixed_statement
+       : FIXED OPEN_PARENS 
+         type fixed_pointer_declarators 
+         CLOSE_PARENS 
+         {
+               Block assign_block = new Block (current_block, Block.Flags.Implicit);
+               ArrayList list = (ArrayList) $4;
+               Expression type = (Expression) $3;
+               Location l = lexer.Location;
+               int top = list.Count;
+
+               for (int i = 0; i < top; i++){
+                       Pair p = (Pair) list [i];
+                       LocalInfo v;
+
+                       v = current_block.AddVariable (type, (string) p.First,current_local_parameters, l);
+                       if (v == null)
+                               continue;
+                       v.ReadOnly = true;
+                       p.First = v;
+                       list [i] = p;
+               }
+               current_block.AddStatement (assign_block);
+               current_block = assign_block;
+               oob_stack.Push (assign_block);
+               oob_stack.Push (l);
+         }
+         embedded_statement 
+         {
+               Location l = (Location) oob_stack.Pop ();
+               Block assign_block = (Block) oob_stack.Pop ();
+
+               ArrayList list = (ArrayList) $4;
+               int top = list.Count;
+
+               $$ = new Fixed ((Expression) $3, (ArrayList) $4, (Statement) $7, l);
+         }
+       ;
+
+fixed_pointer_declarators
+       : fixed_pointer_declarator      { 
+               ArrayList declarators = new ArrayList (4); 
+               declarators.Add ($1);
+               $$ = declarators;
+         }
+       | fixed_pointer_declarators COMMA fixed_pointer_declarator
+         {
+               ArrayList declarators = (ArrayList) $1;
+               declarators.Add ($3);
+               $$ = declarators;
+         }
+       ;
+
+fixed_pointer_declarator
+       : IDENTIFIER ASSIGN expression
+         {     
+               $$ = new Pair ($1, $3);
+         }
+       ;
+
+lock_statement
+       : LOCK OPEN_PARENS expression CLOSE_PARENS 
+         {
+               //
+         } 
+         embedded_statement
+         {
+               $$ = new Lock ((Expression) $3, (Statement) $6, lexer.Location);
+         }
+       ;
+
+using_statement
+       : USING OPEN_PARENS resource_acquisition CLOSE_PARENS 
+         {
+               Block assign_block = new Block (current_block);
+               current_block = assign_block;
+
+               oob_stack.Push (lexer.Location);
+               
+               if ($3 is DictionaryEntry){
+                       DictionaryEntry de = (DictionaryEntry) $3;
+                       Location l = lexer.Location;
+
+                       Expression type = (Expression) de.Key;
+                       ArrayList var_declarators = (ArrayList) de.Value;
+
+                       ArrayList vars = new ArrayList (4);
+
+                       foreach (VariableDeclaration decl in var_declarators){
+
+                               LocalInfo vi    = current_block.AddVariable (
+                                       type, decl.identifier, 
+                                       current_local_parameters, decl.Location);
+                               if (vi == null)
+                                       continue;
+                               vi.ReadOnly = true;
+
+                               Expression expr;
+                               if (decl.expression_or_array_initializer is Expression){
+                                       expr = (Expression) decl.expression_or_array_initializer;
+                               } else {
+                                       ArrayList init = (ArrayList) decl.expression_or_array_initializer;
+                                       
+                                       expr = new ArrayCreation (type, "", init, decl.Location);
+                               }
+
+                               LocalVariableReference var;
+
+                               // Get a writable reference to this read-only variable.
+                               var = new LocalVariableReference (assign_block, decl.identifier, l, vi, false);
+
+                               // This is so that it is not a warning on using variables
+                               vi.Used = true;
+
+                               vars.Add (new DictionaryEntry (var, expr));                             
+
+                               // Assign a = new Assign (var, expr, decl.Location);
+                               // assign_block.AddStatement (new StatementExpression (a, lexer.Location));
+                       }
+                       $3 = new DictionaryEntry (type, vars);
+                }
+         } 
+         embedded_statement
+         {
+               Using u = new Using ($3, (Statement) $6, (Location) oob_stack.Pop ());
+               current_block.AddStatement (u);
+               while (current_block.Implicit)
+                       current_block = current_block.Parent;
+               $$ = current_block;
+               current_block = current_block.Parent;
+         }
+       ; 
+
+resource_acquisition
+       : local_variable_declaration
+       | expression
+       ;
+
+%%
+
+// <summary>
+//   A class used to pass around variable declarations and constants
+// </summary>
+public class VariableDeclaration {
+       public string identifier;
+       public object expression_or_array_initializer;
+       public Location Location;
+       public Attributes OptAttributes;
+
+       public VariableDeclaration (string id, object eoai, Location l, Attributes opt_attrs)
+       {
+               this.identifier = id;
+               this.expression_or_array_initializer = eoai;
+               this.Location = l;
+               this.OptAttributes = opt_attrs;
+       }
+
+       public VariableDeclaration (string id, object eoai, Location l) : this (id, eoai, l, null)
+       {
+       }
+}
+
+// <summary>
+//   A class used to hold info about an indexer declarator
+// </summary>
+
+public class IndexerDeclaration {
+       public Expression type;
+       public string interface_type;
+       public Parameters param_list;
+
+       public IndexerDeclaration (Expression type, string interface_type, Parameters param_list)
+       {
+               this.type = type;
+               this.interface_type = interface_type;
+               this.param_list = param_list;
+       }
+}
+
+// <summary>
+//  A class used to hold info about an operator declarator
+// </summary>
+
+public class OperatorDeclaration {
+       public Operator.OpType optype;
+       public Expression ret_type, arg1type, arg2type;
+       public string arg1name, arg2name;
+       public Location location;
+
+       public OperatorDeclaration (Operator.OpType op, Expression ret_type, 
+                                   Expression arg1type, string arg1name,
+                                   Expression arg2type, string arg2name, Location location)
+       {
+               optype = op;
+               this.ret_type = ret_type;
+               this.arg1type = arg1type;
+               this.arg1name = arg1name;
+               this.arg2type = arg2type;
+               this.arg2name = arg2name;
+               this.location = location;
+       }
+
+}
+
+void Error_ExpectingTypeName (Location l, Expression expr)
+{
+       if (expr is Invocation){
+               Report.Error (1002, l, "; expected");
+       } else {
+               Report.Error (-1, l, "Invalid Type definition");
+       }
+}
+
+// <summary>
+//   Given the @class_name name, it creates a fully qualified name
+//   based on the containing declaration space
+// </summary>
+string 
+MakeName (string class_name)
+{
+       string ns = current_namespace.Name;
+       string container_name = current_container.Name;
+
+       if (container_name == ""){
+               if (ns != "")
+                       return ns + "." + class_name;
+               else
+                       return class_name;
+       } else
+               return container_name + "." + class_name;
+}
+
+// <summary>
+//   Used to report back to the user the result of a declaration
+//   in the current declaration space
+// </summary>
+void 
+CheckDef (AdditionResult result, string name, Location l)
+{
+       if (result == AdditionResult.Success)
+               return;
+
+       switch (result){
+       case AdditionResult.NameExists:
+               Report.Error (102, l, "The container `" + current_container.Name + 
+                                "' already contains a definition for `"+
+                                name + "'");
+               break;
+
+
+               //
+               // This is handled only for static Constructors, because
+               // in reality we handle these by the semantic analysis later
+               //
+       case AdditionResult.MethodExists:
+               Report.Error (
+                       111, l, "Class `"+current_container.Name+
+                       "' already defines a member called '" + 
+                       name + "' with the same parameter types (more than one default constructor)");
+               break;
+
+       case AdditionResult.EnclosingClash:
+               Report.Error (542, l, "Member names cannot be the same as their enclosing type");
+               break;
+               
+       case AdditionResult.NotAConstructor:
+               Report.Error (1520, l, "Class, struct, or interface method must have a return type");
+               break;
+
+       case AdditionResult.Error:
+               // Error has already been reported.
+               break;
+       }
+}
+
+void 
+CheckDef (bool result, string name, Location l)
+{
+       if (result)
+               return;
+       CheckDef (AdditionResult.NameExists, name, l);
+}
+
+Expression DecomposeQI (string name, Location loc)
+{
+       Expression o;
+
+       if (name.IndexOf ('.') == -1){
+               return new SimpleName (name, loc);
+       } else {
+               int pos = name.LastIndexOf (".");
+               string left = name.Substring (0, pos);
+               string right = name.Substring (pos + 1);
+
+               o = DecomposeQI (left, loc);
+
+               return new MemberAccess (o, right, loc);
+       }
+}
+
+// <summary>
+//  This method is used to get at the complete string representation of
+//  a fully-qualified type name, hiding inside a MemberAccess ;-)
+//  This is necessary because local_variable_type admits primary_expression
+//  as the type of the variable. So we do some extra checking
+// </summary>
+#if false
+string GetQualifiedIdentifier (Expression expr)
+{
+       if (expr is SimpleName)
+               return ((SimpleName)expr).Name;
+       else if (expr is MemberAccess)
+               return GetQualifiedIdentifier (((MemberAccess)expr).Expr) + "." + ((MemberAccess) expr).Identifier;
+       else 
+               throw new Exception ("Expr has to be either SimpleName or MemberAccess! (" + expr + ")");
+       
+}
+#endif
+
+Block declare_local_variables (Expression type, ArrayList variable_declarators, Location loc)
+{
+       Block implicit_block;
+       ArrayList inits = null;
+
+       //
+       // We use the `Used' property to check whether statements
+       // have been added to the current block.  If so, we need
+       // to create another block to contain the new declaration
+       // otherwise, as an optimization, we use the same block to
+       // add the declaration.
+       //
+       // FIXME: A further optimization is to check if the statements
+       // that were added were added as part of the initialization
+       // below.  In which case, no other statements have been executed
+       // and we might be able to reduce the number of blocks for
+       // situations like this:
+       //
+       // int j = 1;  int k = j + 1;
+       //
+       if (current_block.Used) {
+               implicit_block = new Block (current_block, Block.Flags.Implicit, loc, Location.Null);
+               implicit_block.AddChildVariableNames (current_block);
+       } else
+               implicit_block = current_block;
+
+       foreach (VariableDeclaration decl in variable_declarators){
+
+               if (implicit_block.AddVariable (type, decl.identifier, current_local_parameters, decl.Location) != null) {
+                       if (decl.expression_or_array_initializer != null){
+                               if (inits == null)
+                                       inits = new ArrayList (4);
+                               inits.Add (decl);
+                       }
+               }
+       }
+
+       if (inits == null)
+               return implicit_block;
+
+       foreach (VariableDeclaration decl in inits){
+               Assign assign;
+               Expression expr;
+               
+               if (decl.expression_or_array_initializer is Expression){
+                       expr = (Expression) decl.expression_or_array_initializer;
+
+               } else {
+                       ArrayList init = (ArrayList) decl.expression_or_array_initializer;
+                       
+                       expr = new ArrayCreation (type, "", init, decl.Location);
+               }
+
+               LocalVariableReference var;
+               var = new LocalVariableReference (implicit_block, decl.identifier, loc);
+
+               assign = new Assign (var, expr, decl.Location);
+
+               implicit_block.AddStatement (new StatementExpression (assign, lexer.Location));
+       }
+       
+       return implicit_block;
+}
+
+Block declare_local_constant (Expression type, VariableDeclaration decl)
+{
+       Block implicit_block;
+
+       if (current_block.Used)
+               implicit_block = new Block (current_block, Block.Flags.Implicit);
+       else
+               implicit_block = current_block;
+
+       if (!(implicit_block.AddConstant (type, decl.identifier, (Expression) decl.expression_or_array_initializer,
+                                         current_local_parameters, decl.Location))){
+       }
+       
+       return implicit_block;
+}
+
+void CheckAttributeTarget (string a)
+{
+       switch (a) {
+
+       case "assembly" : case "field" : case "method" : case "param" : case "property" : case "type" :
+               return;
+               
+       default :
+               Location l = lexer.Location;
+               Report.Error (658, l, "`" + a + "' is an invalid attribute target");
+               break;
+       }
+
+}
+
+void CheckUnaryOperator (Operator.OpType op)
+{
+       switch (op) {
+               
+       case Operator.OpType.LogicalNot: 
+       case Operator.OpType.OnesComplement: 
+       case Operator.OpType.Increment:
+       case Operator.OpType.Decrement:
+       case Operator.OpType.True: 
+       case Operator.OpType.False: 
+       case Operator.OpType.Addition: 
+       case Operator.OpType.Subtraction:
+               
+               break;
+               
+       default :
+               Location l = lexer.Location;
+               Report.Error (1019, l, "Overloadable unary operator expected"); 
+               break;
+               
+       }
+}
+
+void CheckBinaryOperator (Operator.OpType op)
+{
+       switch (op) {
+               
+       case Operator.OpType.Addition: 
+       case Operator.OpType.Subtraction: 
+       case Operator.OpType.Multiply:
+       case Operator.OpType.Division:
+       case Operator.OpType.Modulus: 
+       case Operator.OpType.BitwiseAnd: 
+       case Operator.OpType.BitwiseOr:
+       case Operator.OpType.ExclusiveOr: 
+       case Operator.OpType.LeftShift: 
+       case Operator.OpType.RightShift:
+       case Operator.OpType.Equality: 
+       case Operator.OpType.Inequality:
+       case Operator.OpType.GreaterThan: 
+       case Operator.OpType.LessThan: 
+       case Operator.OpType.GreaterThanOrEqual:
+       case Operator.OpType.LessThanOrEqual:
+               break;
+               
+       default :
+               Location l = lexer.Location;
+               Report.Error (1020, l, "Overloadable binary operator expected");
+               break;
+       }
+       
+}
+
+void syntax_error (Location l, string msg)
+{
+       Report.Error (1003, l, "Syntax error, " + msg);
+}
+
+void output (string s)
+{
+       Console.WriteLine (s);
+}
+
+void note (string s)
+{
+       // Used to put annotations
+}
+
+Tokenizer lexer;
+
+public Tokenizer Lexer {
+       get {
+               return lexer;
+       }
+}                 
+
+public CSharpParser (StreamReader reader, SourceFile file, ArrayList defines)
+{
+       current_namespace = new NamespaceEntry (null, file, null);
+       this.name = file.Name;
+       this.file = file;
+       current_container = RootContext.Tree.Types;
+       current_container.Namespace = current_namespace;
+       oob_stack = new Stack ();
+       switch_stack = new Stack ();
+
+       lexer = new Tokenizer (reader, file, defines);
+}
+
+public override void parse ()
+{
+       try {
+               if (yacc_verbose_flag)
+                       yyparse (lexer, new yydebug.yyDebugSimple ());
+               else
+                       yyparse (lexer);
+               Tokenizer tokenizer = lexer as Tokenizer;
+               tokenizer.cleanup ();           
+       } catch (Exception e){
+               // Please do not remove this, it is used during debugging
+               // of the grammar
+               //
+               Report.Error (-25, lexer.Location, ": Parsing error ");
+               Console.WriteLine (e);
+       }
+}
+
+/* end end end */
+}
diff --git a/mcs/gmcs/cs-tokenizer.cs b/mcs/gmcs/cs-tokenizer.cs
new file mode 100755 (executable)
index 0000000..de90a12
--- /dev/null
@@ -0,0 +1,1789 @@
+//\r
+// cs-tokenizer.cs: The Tokenizer for the C# compiler\r
+//                  This also implements the preprocessor\r
+//\r
+// Author: Miguel de Icaza (miguel@gnu.org)\r
+//\r
+// Licensed under the terms of the GNU GPL\r
+//\r
+// (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)\r
+//\r
+\r
+/*\r
+ * TODO:\r
+ *   Make sure we accept the proper Unicode ranges, per the spec.\r
+ *   Report error 1032\r
+*/\r
+\r
+using System;\r
+using System.Text;\r
+using System.Collections;\r
+using System.IO;\r
+using System.Globalization;\r
+using System.Reflection;\r
+\r
+namespace Mono.CSharp\r
+{\r
+       /// <summary>\r
+       ///    Tokenizer for C# source code. \r
+       /// </summary>\r
+\r
+       public class Tokenizer : yyParser.yyInput\r
+       {\r
+               StreamReader reader;\r
+               public SourceFile ref_name;\r
+               public SourceFile file_name;\r
+               public int ref_line = 1;\r
+               public int line = 1;\r
+               public int col = 1;\r
+               public int current_token;\r
+               bool handle_get_set = false;\r
+               bool handle_remove_add = false;\r
+               bool handle_assembly = false;\r
+\r
+               //\r
+               // Whether tokens have been seen on this line\r
+               //\r
+               bool tokens_seen = false;\r
+\r
+               //\r
+               // Whether a token has been seen on the file\r
+               // This is needed because `define' is not allowed to be used\r
+               // after a token has been seen.\r
+               //\r
+               bool any_token_seen = false;\r
+               static Hashtable tokenValues;\r
+               \r
+               private static Hashtable TokenValueName\r
+               {\r
+                       get {\r
+                               if (tokenValues == null)\r
+                                       tokenValues = GetTokenValueNameHash ();\r
+\r
+                               return tokenValues;\r
+                       }\r
+               }\r
+\r
+               private static Hashtable GetTokenValueNameHash ()\r
+               {\r
+                       Type t = typeof (Token);\r
+                       FieldInfo [] fields = t.GetFields ();\r
+                       Hashtable hash = new Hashtable ();\r
+                       foreach (FieldInfo field in fields) {\r
+                               if (field.IsLiteral && field.IsStatic && field.FieldType == typeof (int))\r
+                                       hash.Add (field.GetValue (null), field.Name);\r
+                       }\r
+                       return hash;\r
+               }\r
+               \r
+               //\r
+               // Returns a verbose representation of the current location\r
+               //\r
+               public string location {\r
+                       get {\r
+                               string det;\r
+\r
+                               if (current_token == Token.ERROR)\r
+                                       det = "detail: " + error_details;\r
+                               else\r
+                                       det = "";\r
+                               \r
+                               // return "Line:     "+line+" Col: "+col + "\n" +\r
+                               //       "VirtLine: "+ref_line +\r
+                               //       " Token: "+current_token + " " + det;\r
+                               string current_token_name = TokenValueName [current_token] as string;\r
+                               if (current_token_name == null)\r
+                                       current_token_name = current_token.ToString ();\r
+\r
+                               return String.Format ("{0} ({1},{2}), Token: {3} {4}", ref_name.Name,\r
+                                                                                      ref_line,\r
+                                                                                      col,\r
+                                                                                      current_token_name,\r
+                                                                                      det);\r
+                       }\r
+               }\r
+\r
+               public bool PropertyParsing {\r
+                       get {\r
+                               return handle_get_set;\r
+                       }\r
+\r
+                       set {\r
+                               handle_get_set = value;\r
+                       }\r
+                }\r
+\r
+               public bool AssemblyTargetParsing {\r
+                       get {\r
+                               return handle_assembly;\r
+                       }\r
+\r
+                       set {\r
+                               handle_assembly = value;\r
+                       }\r
+               }\r
+\r
+               public bool EventParsing {\r
+                       get {\r
+                               return handle_remove_add;\r
+                       }\r
+\r
+                       set {\r
+                               handle_remove_add = value;\r
+                       }\r
+               }\r
+               \r
+               //\r
+               // Class variables\r
+               // \r
+               static Hashtable keywords;\r
+               static NumberStyles styles;\r
+               static NumberFormatInfo csharp_format_info;\r
+               \r
+               //\r
+               // Values for the associated token returned\r
+               //\r
+               int putback_char;\r
+               Object val;\r
+\r
+               //\r
+               // Pre-processor\r
+               //\r
+               Hashtable defines;\r
+\r
+               const int TAKING        = 1;\r
+               const int TAKEN_BEFORE  = 2;\r
+               const int ELSE_SEEN     = 4;\r
+               const int PARENT_TAKING = 8;\r
+               const int REGION        = 16;           \r
+\r
+               //\r
+               // pre-processor if stack state:\r
+               //\r
+               Stack ifstack;\r
+\r
+               static System.Text.StringBuilder string_builder;\r
+\r
+               const int max_id_size = 512;\r
+               static char [] id_builder = new char [max_id_size];\r
+\r
+               const int max_number_size = 128;\r
+               static char [] number_builder = new char [max_number_size];\r
+               static int number_pos;\r
+               \r
+               //\r
+               // Details about the error encoutered by the tokenizer\r
+               //\r
+               string error_details;\r
+               \r
+               public string error {\r
+                       get {\r
+                               return error_details;\r
+                       }\r
+               }\r
+               \r
+               public int Line {\r
+                       get {\r
+                               return ref_line;\r
+                       }\r
+               }\r
+\r
+               public int Col {\r
+                       get {\r
+                               return col;\r
+                       }\r
+               }\r
+\r
+               static void InitTokens ()\r
+               {\r
+                       keywords = new Hashtable ();\r
+\r
+                       keywords.Add ("abstract", Token.ABSTRACT);\r
+                       keywords.Add ("as", Token.AS);\r
+                       keywords.Add ("add", Token.ADD);\r
+                       keywords.Add ("assembly", Token.ASSEMBLY);\r
+                       keywords.Add ("base", Token.BASE);\r
+                       keywords.Add ("bool", Token.BOOL);\r
+                       keywords.Add ("break", Token.BREAK);\r
+                       keywords.Add ("byte", Token.BYTE);\r
+                       keywords.Add ("case", Token.CASE);\r
+                       keywords.Add ("catch", Token.CATCH);\r
+                       keywords.Add ("char", Token.CHAR);\r
+                       keywords.Add ("checked", Token.CHECKED);\r
+                       keywords.Add ("class", Token.CLASS);\r
+                       keywords.Add ("const", Token.CONST);\r
+                       keywords.Add ("continue", Token.CONTINUE);\r
+                       keywords.Add ("decimal", Token.DECIMAL);\r
+                       keywords.Add ("default", Token.DEFAULT);\r
+                       keywords.Add ("delegate", Token.DELEGATE);\r
+                       keywords.Add ("do", Token.DO);\r
+                       keywords.Add ("double", Token.DOUBLE);\r
+                       keywords.Add ("else", Token.ELSE);\r
+                       keywords.Add ("enum", Token.ENUM);\r
+                       keywords.Add ("event", Token.EVENT);\r
+                       keywords.Add ("explicit", Token.EXPLICIT);\r
+                       keywords.Add ("extern", Token.EXTERN);\r
+                       keywords.Add ("false", Token.FALSE);\r
+                       keywords.Add ("finally", Token.FINALLY);\r
+                       keywords.Add ("fixed", Token.FIXED);\r
+                       keywords.Add ("float", Token.FLOAT);\r
+                       keywords.Add ("for", Token.FOR);\r
+                       keywords.Add ("foreach", Token.FOREACH);\r
+                       keywords.Add ("goto", Token.GOTO);\r
+                       keywords.Add ("get", Token.GET);\r
+                       keywords.Add ("if", Token.IF);\r
+                       keywords.Add ("implicit", Token.IMPLICIT);\r
+                       keywords.Add ("in", Token.IN);\r
+                       keywords.Add ("int", Token.INT);\r
+                       keywords.Add ("interface", Token.INTERFACE);\r
+                       keywords.Add ("internal", Token.INTERNAL);\r
+                       keywords.Add ("is", Token.IS);\r
+                       keywords.Add ("lock", Token.LOCK);\r
+                       keywords.Add ("long", Token.LONG);\r
+                       keywords.Add ("namespace", Token.NAMESPACE);\r
+                       keywords.Add ("new", Token.NEW);\r
+                       keywords.Add ("null", Token.NULL);\r
+                       keywords.Add ("object", Token.OBJECT);\r
+                       keywords.Add ("operator", Token.OPERATOR);\r
+                       keywords.Add ("out", Token.OUT);\r
+                       keywords.Add ("override", Token.OVERRIDE);\r
+                       keywords.Add ("params", Token.PARAMS);\r
+                       keywords.Add ("private", Token.PRIVATE);\r
+                       keywords.Add ("protected", Token.PROTECTED);\r
+                       keywords.Add ("public", Token.PUBLIC);\r
+                       keywords.Add ("readonly", Token.READONLY);\r
+                       keywords.Add ("ref", Token.REF);\r
+                       keywords.Add ("remove", Token.REMOVE);\r
+                       keywords.Add ("return", Token.RETURN);\r
+                       keywords.Add ("sbyte", Token.SBYTE);\r
+                       keywords.Add ("sealed", Token.SEALED);\r
+                       keywords.Add ("set", Token.SET);\r
+                       keywords.Add ("short", Token.SHORT);\r
+                       keywords.Add ("sizeof", Token.SIZEOF);\r
+                       keywords.Add ("stackalloc", Token.STACKALLOC);\r
+                       keywords.Add ("static", Token.STATIC);\r
+                       keywords.Add ("string", Token.STRING);\r
+                       keywords.Add ("struct", Token.STRUCT);\r
+                       keywords.Add ("switch", Token.SWITCH);\r
+                       keywords.Add ("this", Token.THIS);\r
+                       keywords.Add ("throw", Token.THROW);\r
+                       keywords.Add ("true", Token.TRUE);\r
+                       keywords.Add ("try", Token.TRY);\r
+                       keywords.Add ("typeof", Token.TYPEOF);\r
+                       keywords.Add ("uint", Token.UINT);\r
+                       keywords.Add ("ulong", Token.ULONG);\r
+                       keywords.Add ("unchecked", Token.UNCHECKED);\r
+                       keywords.Add ("unsafe", Token.UNSAFE);\r
+                       keywords.Add ("ushort", Token.USHORT);\r
+                       keywords.Add ("using", Token.USING);\r
+                       keywords.Add ("virtual", Token.VIRTUAL);\r
+                       keywords.Add ("void", Token.VOID);\r
+                       keywords.Add ("volatile", Token.VOLATILE);\r
+                       keywords.Add ("while", Token.WHILE);\r
+\r
+                       if (RootContext.V2){\r
+                               keywords.Add ("__yield", Token.YIELD);\r
+                               keywords.Add ("yield", Token.YIELD);\r
+                       }\r
+               }\r
+\r
+               //\r
+               // Class initializer\r
+               // \r
+               static Tokenizer ()\r
+               {\r
+                       InitTokens ();\r
+                       csharp_format_info = NumberFormatInfo.InvariantInfo;\r
+                       styles = NumberStyles.Float;\r
+                       \r
+                       string_builder = new System.Text.StringBuilder ();\r
+               }\r
+\r
+               int GetKeyword (string name)\r
+               {\r
+                       object o = keywords [name];\r
+\r
+                       if (o == null)\r
+                               return -1;\r
+                       \r
+                       int res = (int) o;\r
+\r
+                       if (handle_get_set == false && (res == Token.GET || res == Token.SET))\r
+                               return -1;\r
+                       if (handle_remove_add == false && (res == Token.REMOVE || res == Token.ADD))\r
+                               return -1;\r
+                       if (handle_assembly == false && res == Token.ASSEMBLY)\r
+                               return -1;\r
+                       return res;\r
+                       \r
+               }\r
+\r
+               public Location Location {\r
+                       get {\r
+                               return new Location (ref_line);\r
+                       }\r
+               }\r
+\r
+               void define (string def)\r
+               {\r
+                       if (!RootContext.AllDefines.Contains (def)){\r
+                               RootContext.AllDefines [def] = true;\r
+                       }\r
+                       if (defines.Contains (def))\r
+                               return;\r
+                       defines [def] = true;\r
+               }\r
+               \r
+               public Tokenizer (StreamReader input, SourceFile file, ArrayList defs)\r
+               {\r
+                       this.ref_name = file;\r
+                       this.file_name = file;\r
+                       reader = input;\r
+                       \r
+                       putback_char = -1;\r
+\r
+                       if (defs != null){\r
+                               defines = new Hashtable ();\r
+                               foreach (string def in defs)\r
+                                       define (def);\r
+                       }\r
+\r
+                       //\r
+                       // FIXME: This could be `Location.Push' but we have to\r
+                       // find out why the MS compiler allows this\r
+                       //\r
+                       Mono.CSharp.Location.Push (file);\r
+               }\r
+\r
+               bool is_identifier_start_character (char c)\r
+               {\r
+                       return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' || Char.IsLetter (c);\r
+               }\r
+\r
+               bool is_identifier_part_character (char c)\r
+               {\r
+                       return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9') || Char.IsLetter (c);\r
+               }\r
+\r
+               int is_punct (char c, ref bool doread)\r
+               {\r
+                       int d;\r
+                       int t;\r
+\r
+                       doread = false;\r
+\r
+                       switch (c){\r
+                       case '{':\r
+                               return Token.OPEN_BRACE;\r
+                       case '}':\r
+                               return Token.CLOSE_BRACE;\r
+                       case '[':\r
+                               return Token.OPEN_BRACKET;\r
+                       case ']':\r
+                               return Token.CLOSE_BRACKET;\r
+                       case '(':\r
+                               return Token.OPEN_PARENS;\r
+                       case ')':\r
+                               return Token.CLOSE_PARENS;\r
+                       case ',':\r
+                               return Token.COMMA;\r
+                       case ':':\r
+                               return Token.COLON;\r
+                       case ';':\r
+                               return Token.SEMICOLON;\r
+                       case '~':\r
+                               return Token.TILDE;\r
+                       case '?':\r
+                               return Token.INTERR;\r
+                       }\r
+\r
+                       d = peekChar ();\r
+                       if (c == '+'){\r
+                               \r
+                               if (d == '+')\r
+                                       t = Token.OP_INC;\r
+                               else if (d == '=')\r
+                                       t = Token.OP_ADD_ASSIGN;\r
+                               else\r
+                                       return Token.PLUS;\r
+                               doread = true;\r
+                               return t;\r
+                       }\r
+                       if (c == '-'){\r
+                               if (d == '-')\r
+                                       t = Token.OP_DEC;\r
+                               else if (d == '=')\r
+                                       t = Token.OP_SUB_ASSIGN;\r
+                               else if (d == '>')\r
+                                       t = Token.OP_PTR;\r
+                               else\r
+                                       return Token.MINUS;\r
+                               doread = true;\r
+                               return t;\r
+                       }\r
+\r
+                       if (c == '!'){\r
+                               if (d == '='){\r
+                                       doread = true;\r
+                                       return Token.OP_NE;\r
+                               }\r
+                               return Token.BANG;\r
+                       }\r
+\r
+                       if (c == '='){\r
+                               if (d == '='){\r
+                                       doread = true;\r
+                                       return Token.OP_EQ;\r
+                               }\r
+                               return Token.ASSIGN;\r
+                       }\r
+\r
+                       if (c == '&'){\r
+                               if (d == '&'){\r
+                                       doread = true;\r
+                                       return Token.OP_AND;\r
+                               } else if (d == '='){\r
+                                       doread = true;\r
+                                       return Token.OP_AND_ASSIGN;\r
+                               }\r
+                               return Token.BITWISE_AND;\r
+                       }\r
+\r
+                       if (c == '|'){\r
+                               if (d == '|'){\r
+                                       doread = true;\r
+                                       return Token.OP_OR;\r
+                               } else if (d == '='){\r
+                                       doread = true;\r
+                                       return Token.OP_OR_ASSIGN;\r
+                               }\r
+                               return Token.BITWISE_OR;\r
+                       }\r
+\r
+                       if (c == '*'){\r
+                               if (d == '='){\r
+                                       doread = true;\r
+                                       return Token.OP_MULT_ASSIGN;\r
+                               }\r
+                               return Token.STAR;\r
+                       }\r
+\r
+                       if (c == '/'){\r
+                               if (d == '='){\r
+                                       doread = true;\r
+                                       return Token.OP_DIV_ASSIGN;\r
+                               }\r
+                               return Token.DIV;\r
+                       }\r
+\r
+                       if (c == '%'){\r
+                               if (d == '='){\r
+                                       doread = true;\r
+                                       return Token.OP_MOD_ASSIGN;\r
+                               }\r
+                               return Token.PERCENT;\r
+                       }\r
+\r
+                       if (c == '^'){\r
+                               if (d == '='){\r
+                                       doread = true;\r
+                                       return Token.OP_XOR_ASSIGN;\r
+                               }\r
+                               return Token.CARRET;\r
+                       }\r
+\r
+                       if (c == '<'){\r
+                               if (d == '<'){\r
+                                       getChar ();\r
+                                       d = peekChar ();\r
+\r
+                                       if (d == '='){\r
+                                               doread = true;\r
+                                               return Token.OP_SHIFT_LEFT_ASSIGN;\r
+                                       }\r
+                                       return Token.OP_SHIFT_LEFT;\r
+                               } else if (d == '='){\r
+                                       doread = true;\r
+                                       return Token.OP_LE;\r
+                               }\r
+                               return Token.OP_LT;\r
+                       }\r
+\r
+                       if (c == '>'){\r
+                               if (d == '>'){\r
+                                       getChar ();\r
+                                       d = peekChar ();\r
+\r
+                                       if (d == '='){\r
+                                               doread = true;\r
+                                               return Token.OP_SHIFT_RIGHT_ASSIGN;\r
+                                       }\r
+                                       return Token.OP_SHIFT_RIGHT;\r
+                               } else if (d == '='){\r
+                                       doread = true;\r
+                                       return Token.OP_GE;\r
+                               }\r
+                               return Token.OP_GT;\r
+                       }\r
+                       return Token.ERROR;\r
+               }\r
+\r
+               void Error_NumericConstantTooLong ()\r
+               {\r
+                       Report.Error (1021, Location, "Numeric constant too long");                     \r
+               }\r
+               \r
+               bool decimal_digits (int c)\r
+               {\r
+                       int d;\r
+                       bool seen_digits = false;\r
+                       \r
+                       if (c != -1){\r
+                               if (number_pos == max_number_size)\r
+                                       Error_NumericConstantTooLong ();\r
+                               number_builder [number_pos++] = (char) c;\r
+                       }\r
+                       \r
+                       //\r
+                       // We use peekChar2, because decimal_digits needs to do a \r
+                       // 2-character look-ahead (5.ToString for example).\r
+                       //\r
+                       while ((d = peekChar2 ()) != -1){\r
+                               if (d >= '0' && d <= '9'){\r
+                                       if (number_pos == max_number_size)\r
+                                               Error_NumericConstantTooLong ();\r
+                                       number_builder [number_pos++] = (char) d;\r
+                                       getChar ();\r
+                                       seen_digits = true;\r
+                               } else\r
+                                       break;\r
+                       }\r
+                       \r
+                       return seen_digits;\r
+               }\r
+\r
+               bool is_hex (int e)\r
+               {\r
+                       return (e >= '0' && e <= '9') || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');\r
+               }\r
+               \r
+               void hex_digits (int c)\r
+               {\r
+                       if (c != -1)\r
+                               number_builder [number_pos++] = (char) c;\r
+                       \r
+               }\r
+               \r
+               int real_type_suffix (int c)\r
+               {\r
+                       int t;\r
+\r
+                       switch (c){\r
+                       case 'F': case 'f':\r
+                               t =  Token.LITERAL_FLOAT;\r
+                               break;\r
+                       case 'D': case 'd':\r
+                               t = Token.LITERAL_DOUBLE;\r
+                               break;\r
+                       case 'M': case 'm':\r
+                                t= Token.LITERAL_DECIMAL;\r
+                               break;\r
+                       default:\r
+                               return Token.NONE;\r
+                       }\r
+                       return t;\r
+               }\r
+\r
+               int integer_type_suffix (ulong ul, int c)\r
+               {\r
+                       bool is_unsigned = false;\r
+                       bool is_long = false;\r
+\r
+                       if (c != -1){\r
+                               bool scanning = true;\r
+                               do {\r
+                                       switch (c){\r
+                                       case 'U': case 'u':\r
+                                               if (is_unsigned)\r
+                                                       scanning = false;\r
+                                               is_unsigned = true;\r
+                                               getChar ();\r
+                                               break;\r
+\r
+                                       case 'l':\r
+                                               if (!is_unsigned){\r
+                                                       //\r
+                                                       // if we have not seen anything in between\r
+                                                       // report this error\r
+                                                       //\r
+                                                       Report.Warning (\r
+                                                               78, Location,\r
+                                                       "the 'l' suffix is easily confused with digit `1'," +\r
+                                                       " use 'L' for clarity");\r
+                                               }\r
+                                               goto case 'L';\r
+                                               \r
+                                       case 'L': \r
+                                               if (is_long)\r
+                                                       scanning = false;\r
+                                               is_long = true;\r
+                                               getChar ();\r
+                                               break;\r
+                                               \r
+                                       default:\r
+                                               scanning = false;\r
+                                               break;\r
+                                       }\r
+                                       c = peekChar ();\r
+                               } while (scanning);\r
+                       }\r
+\r
+                       if (is_long && is_unsigned){\r
+                               val = ul;\r
+                               return Token.LITERAL_INTEGER;\r
+                       } else if (is_unsigned){\r
+                               // uint if possible, or ulong else.\r
+\r
+                               if ((ul & 0xffffffff00000000) == 0)\r
+                                       val = (uint) ul;\r
+                               else\r
+                                       val = ul;\r
+                       } else if (is_long){\r
+                               // long if possible, ulong otherwise\r
+                               if ((ul & 0x8000000000000000) != 0)\r
+                                       val = ul;\r
+                               else\r
+                                       val = (long) ul;\r
+                       } else {\r
+                               // int, uint, long or ulong in that order\r
+                               if ((ul & 0xffffffff00000000) == 0){\r
+                                       uint ui = (uint) ul;\r
+                                       \r
+                                       if ((ui & 0x80000000) != 0)\r
+                                               val = ui;\r
+                                       else\r
+                                               val = (int) ui;\r
+                               } else {\r
+                                       if ((ul & 0x8000000000000000) != 0)\r
+                                               val = ul;\r
+                                       else\r
+                                               val = (long) ul;\r
+                               }\r
+                       }\r
+                       return Token.LITERAL_INTEGER;\r
+               }\r
+                               \r
+               //\r
+               // given `c' as the next char in the input decide whether\r
+               // we need to convert to a special type, and then choose\r
+               // the best representation for the integer\r
+               //\r
+               int adjust_int (int c)\r
+               {\r
+                       try {\r
+                               if (number_pos > 9){\r
+                                       ulong ul = (uint) (number_builder [0] - '0');\r
+\r
+                                       for (int i = 1; i < number_pos; i++){\r
+                                               ul = checked ((ul * 10) + ((uint)(number_builder [i] - '0')));\r
+                                       }\r
+                                       return integer_type_suffix (ul, c);\r
+                               } else {\r
+                                       uint ui = (uint) (number_builder [0] - '0');\r
+\r
+                                       for (int i = 1; i < number_pos; i++){\r
+                                               ui = checked ((ui * 10) + ((uint)(number_builder [i] - '0')));\r
+                                       }\r
+                                       return integer_type_suffix (ui, c);\r
+                               }\r
+                       } catch (OverflowException) {\r
+                               error_details = "Integral constant is too large";\r
+                               Report.Error (1021, Location, error_details);\r
+                               val = 0ul;\r
+                               return Token.LITERAL_INTEGER;\r
+                       }\r
+               }\r
+               \r
+               int adjust_real (int t)\r
+               {\r
+                       string s = new String (number_builder, 0, number_pos);\r
+\r
+                       switch (t){\r
+                       case Token.LITERAL_DECIMAL:\r
+                               try {\r
+                                       val = System.Decimal.Parse (s, styles, csharp_format_info);\r
+                               } catch (OverflowException) {\r
+                                       val = 0m;     \r
+                                       error_details = "Floating-point constant is outside the range of the type 'decimal'";\r
+                                       Report.Error (594, Location, error_details);\r
+                               }\r
+                               break;\r
+                       case Token.LITERAL_FLOAT:\r
+                               try {\r
+                                       val = (float) System.Double.Parse (s, styles, csharp_format_info);\r
+                               } catch (OverflowException) {\r
+                                       val = 0.0f;     \r
+                                       error_details = "Floating-point constant is outside the range of the type 'float'";\r
+                                       Report.Error (594, Location, error_details);\r
+                               }\r
+                               break;\r
+                               \r
+                       case Token.LITERAL_DOUBLE:\r
+                       case Token.NONE:\r
+                               t = Token.LITERAL_DOUBLE;\r
+                               try {\r
+                                       val = System.Double.Parse (s, styles, csharp_format_info);\r
+                               } catch (OverflowException) {\r
+                                       val = 0.0;     \r
+                                       error_details = "Floating-point constant is outside the range of the type 'double'";\r
+                                       Report.Error (594, Location, error_details);\r
+                               }\r
+                               break;\r
+                       }\r
+                       return t;\r
+               }\r
+\r
+               int handle_hex ()\r
+               {\r
+                       int d;\r
+                       ulong ul;\r
+                       \r
+                       getChar ();\r
+                       while ((d = peekChar ()) != -1){\r
+                               if (is_hex (d)){\r
+                                       if (number_pos == 16){\r
+                                               Report.Error (1021, Location, "Integral constant too large");\r
+                                               return Token.ERROR;\r
+                                       }\r
+                                       number_builder [number_pos++] = (char) d;\r
+                                       getChar ();\r
+                               } else\r
+                                       break;\r
+                       }\r
+                       \r
+                       string s = new String (number_builder, 0, number_pos);\r
+                       if (number_pos <= 8)\r
+                               ul = System.UInt32.Parse (s, NumberStyles.HexNumber);\r
+                       else\r
+                               ul = System.UInt64.Parse (s, NumberStyles.HexNumber);\r
+                       return integer_type_suffix (ul, peekChar ());\r
+               }\r
+\r
+               //\r
+               // Invoked if we know we have .digits or digits\r
+               //\r
+               int is_number (int c)\r
+               {\r
+                       bool is_real = false;\r
+                       int type;\r
+\r
+                       number_pos = 0;\r
+\r
+                       if (c >= '0' && c <= '9'){\r
+                               if (c == '0'){\r
+                                       int peek = peekChar ();\r
+\r
+                                       if (peek == 'x' || peek == 'X')\r
+                                               return handle_hex ();\r
+                               }\r
+                               decimal_digits (c);\r
+                               c = getChar ();\r
+                       }\r
+\r
+                       //\r
+                       // We need to handle the case of\r
+                       // "1.1" vs "1.string" (LITERAL_FLOAT vs NUMBER DOT IDENTIFIER)\r
+                       //\r
+                       if (c == '.'){\r
+                               if (decimal_digits ('.')){\r
+                                       is_real = true;\r
+                                       c = getChar ();\r
+                               } else {\r
+                                       putback ('.');\r
+                                       number_pos--;\r
+                                       return adjust_int (-1);\r
+                               }\r
+                       }\r
+                       \r
+                       if (c == 'e' || c == 'E'){\r
+                               is_real = true;\r
+                               if (number_pos == max_number_size)\r
+                                       Error_NumericConstantTooLong ();\r
+                               number_builder [number_pos++] = 'e';\r
+                               c = getChar ();\r
+                               \r
+                               if (c == '+'){\r
+                                       if (number_pos == max_number_size)\r
+                                               Error_NumericConstantTooLong ();\r
+                                       number_builder [number_pos++] = '+';\r
+                                       c = -1;\r
+                               } else if (c == '-') {\r
+                                       if (number_pos == max_number_size)\r
+                                               Error_NumericConstantTooLong ();\r
+                                       number_builder [number_pos++] = '-';\r
+                                       c = -1;\r
+                               } else {\r
+                                       if (number_pos == max_number_size)\r
+                                               Error_NumericConstantTooLong ();\r
+                                       number_builder [number_pos++] = '+';\r
+                               }\r
+                                       \r
+                               decimal_digits (c);\r
+                               c = getChar ();\r
+                       }\r
+\r
+                       type = real_type_suffix (c);\r
+                       if (type == Token.NONE && !is_real){\r
+                               putback (c);\r
+                               return adjust_int (c);\r
+                       } else \r
+                               is_real = true;\r
+\r
+                       if (type == Token.NONE){\r
+                               putback (c);\r
+                       }\r
+                       \r
+                       if (is_real)\r
+                               return adjust_real (type);\r
+\r
+                       Console.WriteLine ("This should not be reached");\r
+                       throw new Exception ("Is Number should never reach this point");\r
+               }\r
+\r
+               //\r
+               // Accepts exactly count (4 or 8) hex, no more no less\r
+               //\r
+               int getHex (int count, out bool error)\r
+               {\r
+                       int [] buffer = new int [8];\r
+                       int i;\r
+                       int total = 0;\r
+                       int c;\r
+                       int top = count != -1 ? count : 4;\r
+                       \r
+                       getChar ();\r
+                       error = false;\r
+                       for (i = 0; i < top; i++){\r
+                               c = getChar ();\r
+                               \r
+                               if (c >= '0' && c <= '9')\r
+                                       c = (int) c - (int) '0';\r
+                               else if (c >= 'A' && c <= 'F')\r
+                                       c = (int) c - (int) 'A' + 10;\r
+                               else if (c >= 'a' && c <= 'f')\r
+                                       c = (int) c - (int) 'a' + 10;\r
+                               else {\r
+                                       error = true;\r
+                                       return 0;\r
+                               }\r
+                               \r
+                               total = (total * 16) + c;\r
+                               if (count == -1){\r
+                                       int p = peekChar ();\r
+                                       if (p == -1)\r
+                                               break;\r
+                                       if (!is_hex ((char)p))\r
+                                               break;\r
+                               }\r
+                       }\r
+                       return total;\r
+               }\r
+\r
+               int escape (int c)\r
+               {\r
+                       bool error;\r
+                       int d;\r
+                       int v;\r
+\r
+                       d = peekChar ();\r
+                       if (c != '\\')\r
+                               return c;\r
+                       \r
+                       switch (d){\r
+                       case 'a':\r
+                               v = '\a'; break;\r
+                       case 'b':\r
+                               v = '\b'; break;\r
+                       case 'n':\r
+                               v = '\n'; break;\r
+                       case 't':\r
+                               v = '\t'; break;\r
+                       case 'v':\r
+                               v = '\v'; break;\r
+                       case 'r':\r
+                               v = '\r'; break;\r
+                       case '\\':\r
+                               v = '\\'; break;\r
+                       case 'f':\r
+                               v = '\f'; break;\r
+                       case '0':\r
+                               v = 0; break;\r
+                       case '"':\r
+                               v = '"'; break;\r
+                       case '\'':\r
+                               v = '\''; break;\r
+                       case 'x':\r
+                               v = getHex (-1, out error);\r
+                               if (error)\r
+                                       goto default;\r
+                               return v;\r
+                       case 'u':\r
+                               v = getHex (4, out error);\r
+                               if (error)\r
+                                       goto default;\r
+                               return v;\r
+                       case 'U':\r
+                               v = getHex (8, out error);\r
+                               if (error)\r
+                                       goto default;\r
+                               return v;\r
+                       default:\r
+                               Report.Error (1009, Location, "Unrecognized escape sequence in " + (char)d);\r
+                               return d;\r
+                       }\r
+                       getChar ();\r
+                       return v;\r
+               }\r
+\r
+               int getChar ()\r
+               {\r
+                       if (putback_char != -1){\r
+                               int x = putback_char;\r
+                               putback_char = -1;\r
+\r
+                               return x;\r
+                       }\r
+                       return reader.Read ();\r
+               }\r
+\r
+               int peekChar ()\r
+               {\r
+                       if (putback_char != -1)\r
+                               return putback_char;\r
+                       putback_char = reader.Read ();\r
+                       return putback_char;\r
+               }\r
+\r
+               int peekChar2 ()\r
+               {\r
+                       if (putback_char != -1)\r
+                               return putback_char;\r
+                       return reader.Peek ();\r
+               }\r
+               \r
+               void putback (int c)\r
+               {\r
+                       if (putback_char != -1){\r
+                               Console.WriteLine ("Col: " + col);\r
+                               Console.WriteLine ("Row: " + line);\r
+                               Console.WriteLine ("Name: " + ref_name.Name);\r
+                               Console.WriteLine ("Current [{0}] putting back [{1}]  ", putback_char, c);\r
+                               throw new Exception ("This should not happen putback on putback");\r
+                       }\r
+                       putback_char = c;\r
+               }\r
+\r
+               public bool advance ()\r
+               {\r
+                       return peekChar () != -1;\r
+               }\r
+\r
+               public Object Value {\r
+                       get {\r
+                               return val;\r
+                       }\r
+               }\r
+\r
+               public Object value ()\r
+               {\r
+                       return val;\r
+               }\r
+               \r
+               public int token ()\r
+               {\r
+                       current_token = xtoken ();\r
+                       return current_token;\r
+               }\r
+\r
+               static StringBuilder static_cmd_arg = new System.Text.StringBuilder ();\r
+               \r
+               void get_cmd_arg (out string cmd, out string arg)\r
+               {\r
+                       int c;\r
+                       \r
+                       tokens_seen = false;\r
+                       arg = "";\r
+                       static_cmd_arg.Length = 0;\r
+                               \r
+                       while ((c = getChar ()) != -1 && (c != '\n') && (c != ' ') && (c != '\t') && (c != '\r')){\r
+                               static_cmd_arg.Append ((char) c);\r
+                       }\r
+\r
+                       cmd = static_cmd_arg.ToString ();\r
+\r
+                       if (c == '\n'){\r
+                               line++;\r
+                               ref_line++;\r
+                               return;\r
+                       } else if (c == '\r')\r
+                               col = 0;\r
+\r
+                       // skip over white space\r
+                       while ((c = getChar ()) != -1 && (c != '\n') && ((c == '\r') || (c == ' ') || (c == '\t')))\r
+                               ;\r
+\r
+                       if (c == '\n'){\r
+                               line++;\r
+                               ref_line++;\r
+                               return;\r
+                       } else if (c == '\r'){\r
+                               col = 0;\r
+                               return;\r
+                       }\r
+                       \r
+                       static_cmd_arg.Length = 0;\r
+                       static_cmd_arg.Append ((char) c);\r
+                       \r
+                       while ((c = getChar ()) != -1 && (c != '\n') && (c != '\r')){\r
+                               static_cmd_arg.Append ((char) c);\r
+                       }\r
+\r
+                       if (c == '\n'){\r
+                               line++;\r
+                               ref_line++;\r
+                       } else if (c == '\r')\r
+                               col = 0;\r
+                       arg = static_cmd_arg.ToString ().Trim ();\r
+               }\r
+\r
+               //\r
+               // Handles the #line directive\r
+               //\r
+               bool PreProcessLine (string arg)\r
+               {\r
+                       if (arg == "")\r
+                               return false;\r
+\r
+                       if (arg == "default"){\r
+                               ref_line = line;\r
+                               ref_name = file_name;\r
+                               Location.Push (ref_name);\r
+                               return true;\r
+                       }\r
+                       \r
+                       try {\r
+                               int pos;\r
+\r
+                               if ((pos = arg.IndexOf (' ')) != -1 && pos != 0){\r
+                                       ref_line = System.Int32.Parse (arg.Substring (0, pos));\r
+                                       pos++;\r
+                                       \r
+                                       char [] quotes = { '\"' };\r
+                                       \r
+                                       string name = arg.Substring (pos). Trim (quotes);\r
+                                       ref_name = Location.LookupFile (name);\r
+                                       Location.Push (ref_name);\r
+                               } else {\r
+                                       ref_line = System.Int32.Parse (arg);\r
+                               }\r
+                       } catch {\r
+                               return false;\r
+                       }\r
+                       \r
+                       return true;\r
+               }\r
+\r
+               //\r
+               // Handles #define and #undef\r
+               //\r
+               void PreProcessDefinition (bool is_define, string arg)\r
+               {\r
+                       if (arg == "" || arg == "true" || arg == "false"){\r
+                               Report.Error (1001, Location, "Missing identifer to pre-processor directive");\r
+                               return;\r
+                       }\r
+\r
+                       char[] whitespace = { ' ', '\t' };\r
+                       if (arg.IndexOfAny (whitespace) != -1){\r
+                               Report.Error (1025, Location, "Single-line comment or end-of-line expected");\r
+                               return;\r
+                       }\r
+\r
+                       foreach (char c in arg){\r
+                               if (!Char.IsLetter (c) && (c != '_')){\r
+                                       Report.Error (1001, Location, "Identifier expected");\r
+                                       return;\r
+                               }\r
+                       }\r
+\r
+                       if (is_define){\r
+                               if (defines == null)\r
+                                       defines = new Hashtable ();\r
+                               define (arg);\r
+                       } else {\r
+                               if (defines == null)\r
+                                       return;\r
+                               if (defines.Contains (arg))\r
+                                       defines.Remove (arg);\r
+                       }\r
+               }\r
+\r
+               bool eval_val (string s)\r
+               {\r
+                       if (s == "true")\r
+                               return true;\r
+                       if (s == "false")\r
+                               return false;\r
+                       \r
+                       if (defines == null)\r
+                               return false;\r
+                       if (defines.Contains (s))\r
+                               return true;\r
+\r
+                       return false;\r
+               }\r
+\r
+               bool pp_primary (ref string s)\r
+               {\r
+                       s = s.Trim ();\r
+                       int len = s.Length;\r
+\r
+                       if (len > 0){\r
+                               char c = s [0];\r
+                               \r
+                               if (c == '('){\r
+                                       s = s.Substring (1);\r
+                                       bool val = pp_expr (ref s);\r
+                                       if (s.Length > 0 && s [0] == ')'){\r
+                                               s = s.Substring (1);\r
+                                               return val;\r
+                                       }\r
+                                       Error_InvalidDirective ();\r
+                                       return false;\r
+                               }\r
+                               \r
+                               if (is_identifier_start_character (c)){\r
+                                       int j = 1;\r
+\r
+                                       while (j < len){\r
+                                               c = s [j];\r
+                                               \r
+                                               if (is_identifier_part_character (c)){\r
+                                                       j++;\r
+                                                       continue;\r
+                                               }\r
+                                               bool v = eval_val (s.Substring (0, j));\r
+                                               s = s.Substring (j);\r
+                                               return v;\r
+                                       }\r
+                                       bool vv = eval_val (s);\r
+                                       s = "";\r
+                                       return vv;\r
+                               }\r
+                       }\r
+                       Error_InvalidDirective ();\r
+                       return false;\r
+               }\r
+               \r
+               bool pp_unary (ref string s)\r
+               {\r
+                       s = s.Trim ();\r
+                       int len = s.Length;\r
+\r
+                       if (len > 0){\r
+                               if (s [0] == '!'){\r
+                                       if (len > 1 && s [1] == '='){\r
+                                               Error_InvalidDirective ();\r
+                                               return false;\r
+                                       }\r
+                                       s = s.Substring (1);\r
+                                       return ! pp_primary (ref s);\r
+                               } else\r
+                                       return pp_primary (ref s);\r
+                       } else {\r
+                               Error_InvalidDirective ();\r
+                               return false;\r
+                       }\r
+               }\r
+               \r
+               bool pp_eq (ref string s)\r
+               {\r
+                       bool va = pp_unary (ref s);\r
+\r
+                       s = s.Trim ();\r
+                       int len = s.Length;\r
+                       if (len > 0){\r
+                               if (s [0] == '='){\r
+                                       if (len > 2 && s [1] == '='){\r
+                                               s = s.Substring (2);\r
+                                               return va == pp_unary (ref s);\r
+                                       } else {\r
+                                               Error_InvalidDirective ();\r
+                                               return false;\r
+                                       }\r
+                               } else if (s [0] == '!' && len > 1 && s [1] == '='){\r
+                                       s = s.Substring (2);\r
+\r
+                                       return va != pp_unary (ref s);\r
+\r
+                               } \r
+                       }\r
+\r
+                       return va;\r
+                               \r
+               }\r
+               \r
+               bool pp_and (ref string s)\r
+               {\r
+                       bool va = pp_eq (ref s);\r
+\r
+                       s = s.Trim ();\r
+                       int len = s.Length;\r
+                       if (len > 0){\r
+                               if (s [0] == '&'){\r
+                                       if (len > 2 && s [1] == '&'){\r
+                                               s = s.Substring (2);\r
+                                               return (va & pp_eq (ref s));\r
+                                       } else {\r
+                                               Error_InvalidDirective ();\r
+                                               return false;\r
+                                       }\r
+                               } \r
+                       }\r
+                       return va;\r
+               }\r
+               \r
+               //\r
+               // Evaluates an expression for `#if' or `#elif'\r
+               //\r
+               bool pp_expr (ref string s)\r
+               {\r
+                       bool va = pp_and (ref s);\r
+                       s = s.Trim ();\r
+                       int len = s.Length;\r
+                       if (len > 0){\r
+                               char c = s [0];\r
+                               \r
+                               if (c == '|'){\r
+                                       if (len > 2 && s [1] == '|'){\r
+                                               s = s.Substring (2);\r
+                                               return va | pp_expr (ref s);\r
+                                       } else {\r
+                                               Error_InvalidDirective ();\r
+                                               return false;\r
+                                       }\r
+                               } \r
+                       }\r
+                       \r
+                       return va;\r
+               }\r
+\r
+               bool eval (string s)\r
+               {\r
+                       bool v = pp_expr (ref s);\r
+                       s = s.Trim ();\r
+                       if (s.Length != 0){\r
+                               Error_InvalidDirective ();\r
+                               return false;\r
+                       }\r
+\r
+                       return v;\r
+               }\r
+               \r
+               void Error_InvalidDirective ()\r
+               {\r
+                       Report.Error (1517, Location, "Invalid pre-processor directive");\r
+               }\r
+\r
+               void Error_UnexpectedDirective (string extra)\r
+               {\r
+                       Report.Error (\r
+                               1028, Location,\r
+                               "Unexpected processor directive (" + extra + ")");\r
+               }\r
+\r
+               void Error_TokensSeen ()\r
+               {\r
+                       Report.Error (\r
+                               1032, Location,\r
+                               "Cannot define or undefine pre-processor symbols after a token in the file");\r
+               }\r
+               \r
+               //\r
+               // if true, then the code continues processing the code\r
+               // if false, the code stays in a loop until another directive is\r
+               // reached.\r
+               //\r
+               bool handle_preprocessing_directive (bool caller_is_taking)\r
+               {\r
+                       char [] blank = { ' ', '\t' };\r
+                       string cmd, arg;\r
+                       bool region_directive = false;\r
+\r
+                       get_cmd_arg (out cmd, out arg);\r
+\r
+                       // Eat any trailing whitespaces and single-line comments\r
+                       if (arg.IndexOf ("//") != -1)\r
+                               arg = arg.Substring (0, arg.IndexOf ("//"));\r
+                       arg = arg.TrimEnd (' ', '\t');\r
+\r
+                       //\r
+                       // The first group of pre-processing instructions is always processed\r
+                       //\r
+                       switch (cmd){\r
+                       case "line":\r
+                               if (!PreProcessLine (arg))\r
+                                       Report.Error (\r
+                                               1576, Location,\r
+                                               "Argument to #line directive is missing or invalid");\r
+                               return true;\r
+\r
+                       case "region":\r
+                               region_directive = true;\r
+                               arg = "true";\r
+                               goto case "if";\r
+\r
+                       case "endregion":\r
+                               region_directive = true;\r
+                               goto case "endif";\r
+                               \r
+                       case "if":\r
+                               if (arg == ""){\r
+                                       Error_InvalidDirective ();\r
+                                       return true;\r
+                               }\r
+                               bool taking = false;\r
+                               if (ifstack == null)\r
+                                       ifstack = new Stack ();\r
+\r
+                               if (ifstack.Count == 0){\r
+                                       taking = true;\r
+                               } else {\r
+                                       int state = (int) ifstack.Peek ();\r
+                                       if ((state & TAKING) != 0)\r
+                                               taking = true;\r
+                               }\r
+\r
+                               if (eval (arg) && taking){\r
+                                       int push = TAKING | TAKEN_BEFORE | PARENT_TAKING;\r
+                                       if (region_directive)\r
+                                               push |= REGION;\r
+                                       ifstack.Push (push);\r
+                                       return true;\r
+                               } else {\r
+                                       int push = (taking ? PARENT_TAKING : 0);\r
+                                       if (region_directive)\r
+                                               push |= REGION;\r
+                                       ifstack.Push (push);\r
+                                       return false;\r
+                               }\r
+                               \r
+                       case "endif":\r
+                               if (ifstack == null || ifstack.Count == 0){\r
+                                       Error_UnexpectedDirective ("no #if for this #endif");\r
+                                       return true;\r
+                               } else {\r
+                                       int pop = (int) ifstack.Pop ();\r
+                                       \r
+                                       if (region_directive && ((pop & REGION) == 0))\r
+                                               Report.Error (1027, Location, "#endif directive expected");\r
+                                       else if (!region_directive && ((pop & REGION) != 0))\r
+                                               Report.Error (1038, Location, "#endregion directive expected");\r
+                                       \r
+                                       if (ifstack.Count == 0)\r
+                                               return true;\r
+                                       else {\r
+                                               int state = (int) ifstack.Peek ();\r
+\r
+                                               if ((state & TAKING) != 0)\r
+                                                       return true;\r
+                                               else\r
+                                                       return false;\r
+                                       }\r
+                               }\r
+\r
+                       case "elif":\r
+                               if (ifstack == null || ifstack.Count == 0){\r
+                                       Error_UnexpectedDirective ("no #if for this #elif");\r
+                                       return true;\r
+                               } else {\r
+                                       int state = (int) ifstack.Peek ();\r
+\r
+                                       if ((state & REGION) != 0) {\r
+                                               Report.Error (1038, Location, "#endregion directive expected");\r
+                                               return true;\r
+                                       }\r
+\r
+                                       if ((state & ELSE_SEEN) != 0){\r
+                                               Error_UnexpectedDirective ("#elif not valid after #else");\r
+                                               return true;\r
+                                       }\r
+\r
+                                       if ((state & (TAKEN_BEFORE | TAKING)) != 0)\r
+                                               return false;\r
+\r
+                                       if (eval (arg) && ((state & PARENT_TAKING) != 0)){\r
+                                               state = (int) ifstack.Pop ();\r
+                                               ifstack.Push (state | TAKING | TAKEN_BEFORE);\r
+                                               return true;\r
+                                       } else \r
+                                               return false;\r
+                               }\r
+\r
+                       case "else":\r
+                               if (ifstack == null || ifstack.Count == 0){\r
+                                       Report.Error (\r
+                                               1028, Location,\r
+                                               "Unexpected processor directive (no #if for this #else)");\r
+                                       return true;\r
+                               } else {\r
+                                       int state = (int) ifstack.Peek ();\r
+\r
+                                       if ((state & REGION) != 0) {\r
+                                               Report.Error (1038, Location, "#endregion directive expected");\r
+                                               return true;\r
+                                       }\r
+\r
+                                       if ((state & ELSE_SEEN) != 0){\r
+                                               Error_UnexpectedDirective ("#else within #else");\r
+                                               return true;\r
+                                       }\r
+\r
+                                       ifstack.Pop ();\r
+\r
+                                       bool ret;\r
+                                       if ((state & TAKEN_BEFORE) == 0){\r
+                                               ret = ((state & PARENT_TAKING) != 0);\r
+                                       } else\r
+                                               ret = false;\r
+                                       \r
+                                       if (ret)\r
+                                               state |= TAKING;\r
+                                       else\r
+                                               state &= ~TAKING;\r
+                                       \r
+                                       ifstack.Push (state | ELSE_SEEN);\r
+                                       \r
+                                       return ret;\r
+                               }\r
+                       }\r
+\r
+                       //\r
+                       // These are only processed if we are in a `taking' block\r
+                       //\r
+                       if (!caller_is_taking)\r
+                               return false;\r
+                                       \r
+                       switch (cmd){\r
+                       case "define":\r
+                               if (any_token_seen){\r
+                                       Error_TokensSeen ();\r
+                                       return true;\r
+                               }\r
+                               PreProcessDefinition (true, arg);\r
+                               return true;\r
+\r
+                       case "undef":\r
+                               if (any_token_seen){\r
+                                       Error_TokensSeen ();\r
+                                       return true;\r
+                               }\r
+                               PreProcessDefinition (false, arg);\r
+                               return true;\r
+\r
+                       case "error":\r
+                               Report.Error (1029, Location, "#error: '" + arg + "'");\r
+                               return true;\r
+\r
+                       case "warning":\r
+                               Report.Warning (1030, Location, "#warning: '" + arg + "'");\r
+                               return true;\r
+                       }\r
+\r
+                       Report.Error (1024, Location, "Preprocessor directive expected (got: " + cmd + ")");\r
+                       return true;\r
+\r
+               }\r
+\r
+               private int consume_string (bool quoted) \r
+               {\r
+                       int c;\r
+                       string_builder.Length = 0;\r
+                                                               \r
+                       while ((c = getChar ()) != -1){\r
+                               if (c == '"'){\r
+                                       if (quoted && peekChar () == '"'){\r
+                                               string_builder.Append ((char) c);\r
+                                               getChar ();\r
+                                               continue;\r
+                                       } else {\r
+                                               val = string_builder.ToString ();\r
+                                               return Token.LITERAL_STRING;\r
+                                       }\r
+                               }\r
+\r
+                               if (c == '\n'){\r
+                                       if (!quoted)\r
+                                               Report.Error (1010, Location, "Newline in constant");\r
+                                       line++;\r
+                                       ref_line++;\r
+                                       col = 0;\r
+                               } else\r
+                                       col++;\r
+\r
+                               if (!quoted){\r
+                                       c = escape (c);\r
+                                       if (c == -1)\r
+                                               return Token.ERROR;\r
+                               }\r
+                               string_builder.Append ((char) c);\r
+                       }\r
+\r
+                       Report.Error (1039, Location, "Unterminated string literal");\r
+                       return Token.EOF;\r
+               }\r
+\r
+               private int consume_identifier (int s, bool quoted) \r
+               {\r
+                       int pos = 1;\r
+                       int c;\r
+                       \r
+                       id_builder [0] = (char) s;\r
+                                       \r
+                       while ((c = reader.Read ()) != -1) {\r
+                               if (is_identifier_part_character ((char) c)){\r
+                                       if (pos == max_id_size){\r
+                                               Report.Error (645, Location, "Identifier too long (limit is 512 chars)");\r
+                                               return Token.ERROR;\r
+                                       }\r
+                                       \r
+                                       id_builder [pos++] = (char) c;\r
+                                       putback_char = -1;\r
+                                       col++;\r
+                               } else {\r
+                                       putback_char = c;\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       string ids = new String (id_builder, 0, pos);\r
+\r
+                       //\r
+                       // Optimization: avoids doing the keyword lookup\r
+                       // on uppercase letters and _\r
+                       //\r
+                       if (s >= 'a'){\r
+                               int keyword = GetKeyword (ids);\r
+                               if (keyword == -1 || quoted){\r
+                                       val = ids;\r
+                                       return Token.IDENTIFIER;\r
+                               }\r
+                               return keyword;\r
+                       }\r
+                       val = ids;\r
+                       return Token.IDENTIFIER;\r
+               }\r
+               \r
+               public int xtoken ()\r
+               {\r
+                       int t;\r
+                       bool doread = false;\r
+                       int c;\r
+\r
+                       val = null;\r
+                       // optimization: eliminate col and implement #directive semantic correctly.\r
+                       for (;(c = getChar ()) != -1; col++) {\r
+                               if (c == ' ' || c == '\t' || c == '\f' || c == '\v' || c == '\r' || c == 0xa0){\r
+                                       \r
+                                       if (c == '\t')\r
+                                               col = (((col + 8) / 8) * 8) - 1;\r
+                                       continue;\r
+                               }\r
+\r
+                               // Handle double-slash comments.\r
+                               if (c == '/'){\r
+                                       int d = peekChar ();\r
+                               \r
+                                       if (d == '/'){\r
+                                               getChar ();\r
+                                               while ((d = getChar ()) != -1 && (d != '\n') && d != '\r')\r
+                                                       col++;\r
+                                               if (d == '\n'){\r
+                                                       line++;\r
+                                                       ref_line++;\r
+                                                       col = 0;\r
+                                               }\r
+                                               any_token_seen |= tokens_seen;\r
+                                               tokens_seen = false;\r
+                                               continue;\r
+                                       } else if (d == '*'){\r
+                                               getChar ();\r
+\r
+                                               while ((d = getChar ()) != -1){\r
+                                                       if (d == '*' && peekChar () == '/'){\r
+                                                               getChar ();\r
+                                                               col++;\r
+                                                               break;\r
+                                                       }\r
+                                                       if (d == '\n'){\r
+                                                               line++;\r
+                                                               ref_line++;\r
+                                                               col = 0;\r
+                                                               any_token_seen |= tokens_seen;\r
+                                                               tokens_seen = false;\r
+                                                       }\r
+                                               }\r
+                                               continue;\r
+                                       }\r
+                                       goto is_punct_label;\r
+                               }\r
+\r
+                               \r
+                               if (is_identifier_start_character ((char)c)){\r
+                                       tokens_seen = true;\r
+                                       return consume_identifier (c, false);\r
+                               }\r
+\r
+                       is_punct_label:\r
+                               if ((t = is_punct ((char)c, ref doread)) != Token.ERROR){\r
+                                       tokens_seen = true;\r
+                                       if (doread){\r
+                                               getChar ();\r
+                                               col++;\r
+                                       }\r
+                                       return t;\r
+                               }\r
+\r
+                               // white space\r
+                               if (c == '\n'){\r
+                                       line++;\r
+                                       ref_line++;\r
+                                       col = 0;\r
+                                       any_token_seen |= tokens_seen;\r
+                                       tokens_seen = false;\r
+                                       continue;\r
+                               }\r
+\r
+                               if (c >= '0' && c <= '9'){\r
+                                       tokens_seen = true;\r
+                                       return is_number (c);\r
+                               }\r
+\r
+                               if (c == '.'){\r
+                                       tokens_seen = true;\r
+                                       int peek = peekChar ();\r
+                                       if (peek >= '0' && peek <= '9')\r
+                                               return is_number (c);\r
+                                       return Token.DOT;\r
+                               }\r
+                               \r
+                               /* For now, ignore pre-processor commands */\r
+                               // FIXME: In C# the '#' is not limited to appear\r
+                               // on the first column.\r
+                               if (c == '#' && !tokens_seen){\r
+                                       bool cont = true;\r
+                                       \r
+                               start_again:\r
+                                       \r
+                                       cont = handle_preprocessing_directive (cont);\r
+\r
+                                       if (cont){\r
+                                               col = 0;\r
+                                               continue;\r
+                                       }\r
+                                       col = 1;\r
+\r
+                                       bool skipping = false;\r
+                                       for (;(c = getChar ()) != -1; col++){\r
+                                               if (c == '\n'){\r
+                                                       col = 0;\r
+                                                       line++;\r
+                                                       ref_line++;\r
+                                                       skipping = false;\r
+                                               } else if (c == ' ' || c == '\t' || c == '\v' || c == '\r' || c == 0xa0)\r
+                                                       continue;\r
+                                               else if (c != '#')\r
+                                                       skipping = true;\r
+                                               if (c == '#' && !skipping)\r
+                                                       goto start_again;\r
+                                       }\r
+                                       any_token_seen |= tokens_seen;\r
+                                       tokens_seen = false;\r
+                                       if (c == -1)\r
+                                               Report.Error (1027, Location, "#endif/#endregion expected");\r
+                                       continue;\r
+                               }\r
+                               \r
+                               if (c == '"') \r
+                                       return consume_string (false);\r
+\r
+                               if (c == '\''){\r
+                                       c = getChar ();\r
+                                       tokens_seen = true;\r
+                                       if (c == '\''){\r
+                                               error_details = "Empty character literal";\r
+                                               Report.Error (1011, Location, error_details);\r
+                                               return Token.ERROR;\r
+                                       }\r
+                                       c = escape (c);\r
+                                       if (c == -1)\r
+                                               return Token.ERROR;\r
+                                       val = new System.Char ();\r
+                                       val = (char) c;\r
+                                       c = getChar ();\r
+\r
+                                       if (c != '\''){\r
+                                               error_details = "Too many characters in character literal";\r
+                                               Report.Error (1012, Location, error_details);\r
+\r
+                                               // Try to recover, read until newline or next "'"\r
+                                               while ((c = getChar ()) != -1){\r
+                                                       if (c == '\n' || c == '\''){\r
+                                                               line++;\r
+                                                               ref_line++;\r
+                                                               col = 0;\r
+                                                               break;\r
+                                                       } else\r
+                                                               col++;\r
+                                                       \r
+                                               }\r
+                                               return Token.ERROR;\r
+                                       }\r
+                                       return Token.LITERAL_CHARACTER;\r
+                               }\r
+                               \r
+                               if (c == '@') {\r
+                                       c = getChar ();\r
+                                       if (c == '"') {\r
+                                               tokens_seen = true;\r
+                                               return consume_string (true);\r
+                                       } else if (is_identifier_start_character ((char) c)){\r
+                                               return consume_identifier (c, true);\r
+                                       } else {\r
+                                               Report.Error (1033, Location, "'@' must be followed by string constant or identifier");\r
+                                       }\r
+                               }\r
+\r
+                               error_details = ((char)c).ToString ();\r
+                               \r
+                               return Token.ERROR;\r
+                       }\r
+\r
+                       return Token.EOF;\r
+               }\r
+\r
+               public void cleanup ()\r
+               {\r
+                       if (ifstack != null && ifstack.Count >= 1) {\r
+                               int state = (int) ifstack.Pop ();\r
+                               if ((state & REGION) != 0)\r
+                                       Report.Error (1038, "#endregion directive expected");\r
+                               else \r
+                                       Report.Error (1027, "#endif directive expected");\r
+                       }\r
+                               \r
+               }\r
+\r
+       }\r
+}\r
+\r
diff --git a/mcs/gmcs/decl.cs b/mcs/gmcs/decl.cs
new file mode 100755 (executable)
index 0000000..0231646
--- /dev/null
@@ -0,0 +1,1420 @@
+//
+// decl.cs: Declaration base class for structs, classes, enums and interfaces.
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+// TODO: Move the method verification stuff from the class.cs and interface.cs here
+//
+
+using System;
+using System.Collections;
+using System.Reflection.Emit;
+using System.Reflection;
+
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///   Base representation for members.  This is only used to keep track
+       ///   of Name, Location and Modifier flags.
+       /// </summary>
+       public abstract class MemberCore {
+               /// <summary>
+               ///   Public name
+               /// </summary>
+               public string Name;
+
+               /// <summary>
+               ///   Modifier flags that the user specified in the source code
+               /// </summary>
+               public int ModFlags;
+
+               /// <summary>
+               ///   Location where this declaration happens
+               /// </summary>
+               public readonly Location Location;
+
+               public MemberCore (string name, Location loc)
+               {
+                       Name = name;
+                       Location = loc;
+               }
+
+               protected void WarningNotHiding (TypeContainer parent)
+               {
+                       Report.Warning (
+                               109, Location,
+                               "The member " + parent.MakeName (Name) + " does not hide an " +
+                               "inherited member.  The keyword new is not required");
+                                                          
+               }
+
+               void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
+                                                       string name)
+               {
+                       //
+                       // FIXME: report the old/new permissions?
+                       //
+                       Report.Error (
+                               507, Location, parent.MakeName (Name) +
+                               ": can't change the access modifiers when overriding inherited " +
+                               "member `" + name + "'");
+               }
+               
+               //
+               // Performs various checks on the MethodInfo `mb' regarding the modifier flags
+               // that have been defined.
+               //
+               // `name' is the user visible name for reporting errors (this is used to
+               // provide the right name regarding method names and properties)
+               //
+               protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
+                                                      MethodInfo mb, string name)
+               {
+                       bool ok = true;
+                       
+                       if ((ModFlags & Modifiers.OVERRIDE) != 0){
+                               if (!(mb.IsAbstract || mb.IsVirtual)){
+                                       Report.Error (
+                                               506, Location, parent.MakeName (Name) +
+                                               ": cannot override inherited member `" +
+                                               name + "' because it is not " +
+                                               "virtual, abstract or override");
+                                       ok = false;
+                               }
+                               
+                               // Now we check that the overriden method is not final
+                               
+                               if (mb.IsFinal) {
+                                       // This happens when implementing interface methods.
+                                       if (mb.IsHideBySig && mb.IsVirtual) {
+                                               Report.Error (
+                                                       506, Location, parent.MakeName (Name) +
+                                                       ": cannot override inherited member `" +
+                                                       name + "' because it is not " +
+                                                       "virtual, abstract or override");
+                                       } else
+                                               Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
+                                                             "override inherited member `" + name +
+                                                             "' because it is sealed.");
+                                       ok = false;
+                               }
+                               //
+                               // Check that the permissions are not being changed
+                               //
+                               MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
+                               MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
+
+                               //
+                               // special case for "protected internal"
+                               //
+
+                               if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
+                                       //
+                                       // when overriding protected internal, the method can be declared
+                                       // protected internal only within the same assembly
+                                       //
+
+                                       if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
+                                               if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
+                                                       //
+                                                       // assemblies differ - report an error
+                                                       //
+                                                       
+                                                       Error_CannotChangeAccessModifiers (parent, mb, name);
+                                                   ok = false;
+                                               } else if (thisp != parentp) {
+                                                       //
+                                                       // same assembly, but other attributes differ - report an error
+                                                       //
+                                                       
+                                                       Error_CannotChangeAccessModifiers (parent, mb, name);
+                                                       ok = false;
+                                               };
+                                       } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
+                                               //
+                                               // if it's not "protected internal", it must be "protected"
+                                               //
+
+                                               Error_CannotChangeAccessModifiers (parent, mb, name);
+                                               ok = false;
+                                       } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
+                                               //
+                                               // protected within the same assembly - an error
+                                               //
+                                               Error_CannotChangeAccessModifiers (parent, mb, name);
+                                               ok = false;
+                                       } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) != 
+                                                  (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
+                                               //
+                                               // protected ok, but other attributes differ - report an error
+                                               //
+                                               Error_CannotChangeAccessModifiers (parent, mb, name);
+                                               ok = false;
+                                       }
+                               } else {
+                                       if (thisp != parentp){
+                                               Error_CannotChangeAccessModifiers (parent, mb, name);
+                                               ok = false;
+                                       }
+                               }
+                       }
+
+                       if (mb.IsVirtual || mb.IsAbstract){
+                               if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
+                                       if (Name != "Finalize"){
+                                               Report.Warning (
+                                                       114, 2, Location, parent.MakeName (Name) + 
+                                                       " hides inherited member `" + name +
+                                                       "'.  To make the current member override that " +
+                                                       "implementation, add the override keyword, " +
+                                                       "otherwise use the new keyword");
+                                               ModFlags |= Modifiers.NEW;
+                                       }
+                               }
+                       } else {
+                               if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
+                                       if (Name != "Finalize"){
+                                               Report.Warning (
+                                                       108, 1, Location, "The keyword new is required on " +
+                                                       parent.MakeName (Name) + " because it hides " +
+                                                       "inherited member `" + name + "'");
+                                               ModFlags |= Modifiers.NEW;
+                                       }
+                               }
+                       }
+
+                       return ok;
+               }
+
+               public abstract bool Define (TypeContainer parent);
+
+               // 
+               // Whehter is it ok to use an unsafe pointer in this type container
+               //
+               public bool UnsafeOK (DeclSpace parent)
+               {
+                       //
+                       // First check if this MemberCore modifier flags has unsafe set
+                       //
+                       if ((ModFlags & Modifiers.UNSAFE) != 0)
+                               return true;
+
+                       if (parent.UnsafeContext)
+                               return true;
+
+                       Expression.UnsafeError (Location);
+                       return false;
+               }
+       }
+
+       //
+       // FIXME: This is temporary outside DeclSpace, because I have to fix a bug
+       // in MCS that makes it fail the lookup for the enum
+       //
+
+               /// <summary>
+               ///   The result value from adding an declaration into
+               ///   a struct or a class
+               /// </summary>
+               public enum AdditionResult {
+                       /// <summary>
+                       /// The declaration has been successfully
+                       /// added to the declation space.
+                       /// </summary>
+                       Success,
+
+                       /// <summary>
+                       ///   The symbol has already been defined.
+                       /// </summary>
+                       NameExists,
+
+                       /// <summary>
+                       ///   Returned if the declation being added to the
+                       ///   name space clashes with its container name.
+                       ///
+                       ///   The only exceptions for this are constructors
+                       ///   and static constructors
+                       /// </summary>
+                       EnclosingClash,
+
+                       /// <summary>
+                       ///   Returned if a constructor was created (because syntactically
+                       ///   it looked like a constructor) but was not (because the name
+                       ///   of the method is not the same as the container class
+                       /// </summary>
+                       NotAConstructor,
+
+                       /// <summary>
+                       ///   This is only used by static constructors to emit the
+                       ///   error 111, but this error for other things really
+                       ///   happens at another level for other functions.
+                       /// </summary>
+                       MethodExists,
+
+                       /// <summary>
+                       ///   Some other error.
+                       /// </summary>
+                       Error
+               }
+
+       /// <summary>
+       ///   Base class for structs, classes, enumerations and interfaces.  
+       /// </summary>
+       /// <remarks>
+       ///   They all create new declaration spaces.  This
+       ///   provides the common foundation for managing those name
+       ///   spaces.
+       /// </remarks>
+       public abstract class DeclSpace : MemberCore {
+               /// <summary>
+               ///   this points to the actual definition that is being
+               ///   created with System.Reflection.Emit
+               /// </summary>
+               public TypeBuilder TypeBuilder;
+
+               /// <summary>
+               ///   This variable tracks whether we have Closed the type
+               /// </summary>
+               public bool Created = false;
+               
+               //
+               // This is the namespace in which this typecontainer
+               // was declared.  We use this to resolve names.
+               //
+               public NamespaceEntry Namespace;
+
+               public Hashtable Cache = new Hashtable ();
+               
+               public string Basename;
+               
+               /// <summary>
+               ///   defined_names is used for toplevel objects
+               /// </summary>
+               protected Hashtable defined_names;
+
+               TypeContainer parent;           
+
+               public DeclSpace (TypeContainer parent, string name, Location l)
+                       : base (name, l)
+               {
+                       Basename = name.Substring (1 + name.LastIndexOf ('.'));
+                       defined_names = new Hashtable ();
+                       this.parent = parent;
+               }
+
+               /// <summary>
+               ///   Returns a status code based purely on the name
+               ///   of the member being added
+               /// </summary>
+               protected AdditionResult IsValid (string basename, string name)
+               {
+                       if (basename == Basename)
+                               return AdditionResult.EnclosingClash;
+
+                       if (defined_names.Contains (name))
+                               return AdditionResult.NameExists;
+
+                       return AdditionResult.Success;
+               }
+
+               public static int length;
+               public static int small;
+               
+               /// <summary>
+               ///   Introduce @name into this declaration space and
+               ///   associates it with the object @o.  Note that for
+               ///   methods this will just point to the first method. o
+               /// </summary>
+               protected void DefineName (string name, object o)
+               {
+                       defined_names.Add (name, o);
+
+#if DEBUGME
+                       int p = name.LastIndexOf (".");
+                       int l = name.Length;
+                       length += l;
+                       small += l -p;
+#endif
+               }
+
+               /// <summary>
+               ///   Returns the object associated with a given name in the declaration
+               ///   space.  This is the inverse operation of `DefineName'
+               /// </summary>
+               public object GetDefinition (string name)
+               {
+                       return defined_names [name];
+               }
+               
+               bool in_transit = false;
+               
+               /// <summary>
+               ///   This function is used to catch recursive definitions
+               ///   in declarations.
+               /// </summary>
+               public bool InTransit {
+                       get {
+                               return in_transit;
+                       }
+
+                       set {
+                               in_transit = value;
+                       }
+               }
+
+               public TypeContainer Parent {
+                       get {
+                               return parent;
+                       }
+               }
+
+               /// <summary>
+               ///   Looks up the alias for the name
+               /// </summary>
+               public string LookupAlias (string name)
+               {
+                       if (Namespace != null)
+                               return Namespace.LookupAlias (name);
+                       else
+                               return null;
+               }
+               
+               // 
+               // root_types contains all the types.  All TopLevel types
+               // hence have a parent that points to `root_types', that is
+               // why there is a non-obvious test down here.
+               //
+               public bool IsTopLevel {
+                       get {
+                               if (parent != null){
+                                       if (parent.parent == null)
+                                               return true;
+                               }
+                               return false;
+                       }
+               }
+
+               public virtual void CloseType ()
+               {
+                       if (!Created){
+                               try {
+                                       TypeBuilder.CreateType ();
+                               } catch {
+                                       //
+                                       // The try/catch is needed because
+                                       // nested enumerations fail to load when they
+                                       // are defined.
+                                       //
+                                       // Even if this is the right order (enumerations
+                                       // declared after types).
+                                       //
+                                       // Note that this still creates the type and
+                                       // it is possible to save it
+                               }
+                               Created = true;
+                       }
+               }
+
+               /// <remarks>
+               ///  Should be overriten by the appropriate declaration space
+               /// </remarks>
+               public abstract TypeBuilder DefineType ();
+               
+               /// <summary>
+               ///   Define all members, but don't apply any attributes or do anything which may
+               ///   access not-yet-defined classes.  This method also creates the MemberCache.
+               /// </summary>
+               public abstract bool DefineMembers (TypeContainer parent);
+
+               //
+               // Whether this is an `unsafe context'
+               //
+               public bool UnsafeContext {
+                       get {
+                               if ((ModFlags & Modifiers.UNSAFE) != 0)
+                                       return true;
+                               if (parent != null)
+                                       return parent.UnsafeContext;
+                               return false;
+                       }
+               }
+
+               public static string MakeFQN (string nsn, string name)
+               {
+                       if (nsn == "")
+                               return name;
+                       return String.Concat (nsn, ".", name);
+               }
+
+               EmitContext type_resolve_ec;
+               EmitContext GetTypeResolveEmitContext (TypeContainer parent, Location loc)
+               {
+                       type_resolve_ec = new EmitContext (parent, this, loc, null, null, ModFlags, false);
+                       type_resolve_ec.ResolvingTypeTree = true;
+
+                       return type_resolve_ec;
+               }
+
+               // <summary>
+               //    Looks up the type, as parsed into the expression `e' 
+               // </summary>
+               public Type ResolveType (Expression e, bool silent, Location loc)
+               {
+                       if (type_resolve_ec == null)
+                               type_resolve_ec = GetTypeResolveEmitContext (parent, loc);
+                       type_resolve_ec.loc = loc;
+                       type_resolve_ec.ContainerType = TypeBuilder;
+
+                       int errors = Report.Errors;
+                       Expression d = e.ResolveAsTypeTerminal (type_resolve_ec);
+                       
+                       if (d == null || d.eclass != ExprClass.Type){
+                               if (!silent && errors == Report.Errors){
+                                       Report.Error (246, loc, "Cannot find type `"+ e.ToString () +"'");
+                               }
+                               return null;
+                       }
+
+                       if (!CheckAccessLevel (d.Type)) {
+                               Report. Error (122, loc,  "`" + d.Type + "' " +
+                                      "is inaccessible because of its protection level");
+                               return null;
+                       }
+
+                       return d.Type;
+               }
+
+               // <summary>
+               //    Resolves the expression `e' for a type, and will recursively define
+               //    types. 
+               // </summary>
+               public Expression ResolveTypeExpr (Expression e, bool silent, Location loc)
+               {
+                       if (type_resolve_ec == null)
+                               type_resolve_ec = GetTypeResolveEmitContext (parent, loc);
+                       type_resolve_ec.loc = loc;
+                       type_resolve_ec.ContainerType = TypeBuilder;
+
+                       Expression d = e.ResolveAsTypeTerminal (type_resolve_ec);
+                        
+                       if (d == null || d.eclass != ExprClass.Type){
+                               if (!silent){
+                                       Report.Error (246, loc, "Cannot find type `"+ e +"'");
+                               }
+                               return null;
+                       }
+
+                       return d;
+               }
+               
+               public bool CheckAccessLevel (Type check_type) 
+               {
+                       if (check_type == TypeBuilder)
+                               return true;
+                       
+                       TypeAttributes check_attr = check_type.Attributes & TypeAttributes.VisibilityMask;
+                       
+                       //
+                       // Broken Microsoft runtime, return public for arrays, no matter what 
+                       // the accessibility is for their underlying class, and they return 
+                       // NonPublic visibility for pointers
+                       //
+                       if (check_type.IsArray || check_type.IsPointer)
+                               return CheckAccessLevel (TypeManager.GetElementType (check_type));
+
+                       switch (check_attr){
+                       case TypeAttributes.Public:
+                               return true;
+
+                       case TypeAttributes.NotPublic:
+                               //
+                               // This test should probably use the declaringtype.
+                               //
+                               if (check_type.Assembly == TypeBuilder.Assembly){
+                                       return true;
+                               }
+                               return false;
+                               
+                       case TypeAttributes.NestedPublic:
+                               return true;
+
+                       case TypeAttributes.NestedPrivate:
+                               string check_type_name = check_type.FullName;
+                               string type_name = TypeBuilder.FullName;
+                               
+                               int cio = check_type_name.LastIndexOf ("+");
+                               string container = check_type_name.Substring (0, cio);
+
+                               //
+                               // Check if the check_type is a nested class of the current type
+                               //
+                               if (check_type_name.StartsWith (type_name + "+")){
+                                       return true;
+                               }
+                               
+                               if (type_name.StartsWith (container)){
+                                       return true;
+                               }
+
+                               return false;
+
+                       case TypeAttributes.NestedFamily:
+                               //
+                               // Only accessible to methods in current type or any subtypes
+                               //
+                               return FamilyAccessible (check_type);
+
+                       case TypeAttributes.NestedFamANDAssem:
+                               return (check_type.Assembly == TypeBuilder.Assembly) &&
+                                       FamilyAccessible (check_type);
+
+                       case TypeAttributes.NestedFamORAssem:
+                               return (check_type.Assembly == TypeBuilder.Assembly) ||
+                                       FamilyAccessible (check_type);
+
+                       case TypeAttributes.NestedAssembly:
+                               return check_type.Assembly == TypeBuilder.Assembly;
+                       }
+
+                       Console.WriteLine ("HERE: " + check_attr);
+                       return false;
+
+               }
+
+               protected bool FamilyAccessible (Type check_type)
+               {
+                       Type declaring = check_type.DeclaringType;
+                       if (TypeBuilder.IsSubclassOf (declaring))
+                               return true;
+
+                       string check_type_name = check_type.FullName;
+                       string type_name = TypeBuilder.FullName;
+                       
+                       int cio = check_type_name.LastIndexOf ("+");
+                       string container = check_type_name.Substring (0, cio);
+                       
+                       //
+                       // Check if the check_type is a nested class of the current type
+                       //
+                       if (check_type_name.StartsWith (container + "+"))
+                               return true;
+
+                       return false;
+               }
+               
+               
+               Type LookupInterfaceOrClass (string ns, string name, out bool error)
+               {
+                       DeclSpace parent;
+                       Type t;
+
+                       error = false;
+
+                       name = MakeFQN (ns, name);
+
+                       t  = TypeManager.LookupType (name);
+                       if (t != null)
+                               return t;
+
+                       parent = (DeclSpace) RootContext.Tree.Decls [name];
+                       if (parent == null)
+                               return null;
+                       
+                       t = parent.DefineType ();
+                       if (t == null){
+                               Report.Error (146, Location, "Class definition is circular: `"+name+"'");
+                               error = true;
+                               return null;
+                       }
+                       return t;
+               }
+
+               public static void Error_AmbiguousTypeReference (Location loc, string name, Type t1, Type t2)
+               {
+                       Report.Error (104, loc,
+                                     String.Format ("`{0}' is an ambiguous reference ({1} or {2}) ", name,
+                                                    t1.FullName, t2.FullName));
+               }
+
+               /// <summary>
+               ///   GetType is used to resolve type names at the DeclSpace level.
+               ///   Use this to lookup class/struct bases, interface bases or 
+               ///   delegate type references
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   Contrast this to LookupType which is used inside method bodies to 
+               ///   lookup types that have already been defined.  GetType is used
+               ///   during the tree resolution process and potentially define
+               ///   recursively the type
+               /// </remarks>
+               public Type FindType (Location loc, string name)
+               {
+                       Type t;
+                       bool error;
+
+                       //
+                       // For the case the type we are looking for is nested within this one
+                       // or is in any base class
+                       //
+                       DeclSpace containing_ds = this;
+
+                       while (containing_ds != null){
+                               Type container_type = containing_ds.TypeBuilder;
+                               Type current_type = container_type;
+
+                               while (current_type != null) {
+                                       string pre = current_type.FullName;
+
+                                       t = LookupInterfaceOrClass (pre, name, out error);
+                                       if (error)
+                                               return null;
+                               
+                                       if ((t != null) && containing_ds.CheckAccessLevel (t))
+                                               return t;
+
+                                       current_type = current_type.BaseType;
+                               }
+                               containing_ds = containing_ds.Parent;
+                       }
+
+                       //
+                       // Attempt to lookup the class on our namespace and all it's implicit parents
+                       //
+                       for (NamespaceEntry ns = Namespace; ns != null; ns = ns.ImplicitParent) {
+                               t = LookupInterfaceOrClass (ns.Name, name, out error);
+                               if (error)
+                                       return null;
+                               
+                               if (t != null) 
+                                       return t;
+                       }
+                       
+                       //
+                       // Attempt to do a direct unqualified lookup
+                       //
+                       t = LookupInterfaceOrClass ("", name, out error);
+                       if (error)
+                               return null;
+                       
+                       if (t != null)
+                               return t;
+                       
+                       //
+                       // Attempt to lookup the class on any of the `using'
+                       // namespaces
+                       //
+
+                       for (NamespaceEntry ns = Namespace; ns != null; ns = ns.Parent){
+
+                               t = LookupInterfaceOrClass (ns.Name, name, out error);
+                               if (error)
+                                       return null;
+
+                               if (t != null)
+                                       return t;
+
+                               //
+                               // Now check the using clause list
+                               //
+                               Type match = null;
+                               foreach (Namespace using_ns in ns.GetUsingTable ()) {
+                                       match = LookupInterfaceOrClass (using_ns.Name, name, out error);
+                                       if (error)
+                                               return null;
+
+                                       if (match != null){
+                                               if (t != null){
+                                                       if (CheckAccessLevel (match)) {
+                                                               Error_AmbiguousTypeReference (loc, name, t, match);
+                                                               return null;
+                                                       }
+                                                       continue;
+                                               }
+                                               
+                                               t = match;
+                                       }
+                               }
+                               if (t != null)
+                                       return t;
+                       }
+
+                       //Report.Error (246, Location, "Can not find type `"+name+"'");
+                       return null;
+               }
+
+               /// <remarks>
+               ///   This function is broken and not what you're looking for.  It should only
+               ///   be used while the type is still being created since it doesn't use the cache
+               ///   and relies on the filter doing the member name check.
+               /// </remarks>
+               public abstract MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                                       MemberFilter filter, object criteria);
+
+               /// <remarks>
+               ///   If we have a MemberCache, return it.  This property may return null if the
+               ///   class doesn't have a member cache or while it's still being created.
+               /// </remarks>
+               public abstract MemberCache MemberCache {
+                       get;
+               }
+       }
+
+       /// <summary>
+       ///   This is a readonly list of MemberInfo's.      
+       /// </summary>
+       public class MemberList : IList {
+               public readonly IList List;
+               int count;
+
+               /// <summary>
+               ///   Create a new MemberList from the given IList.
+               /// </summary>
+               public MemberList (IList list)
+               {
+                       if (list != null)
+                               this.List = list;
+                       else
+                               this.List = new ArrayList ();
+                       count = List.Count;
+               }
+
+               /// <summary>
+               ///   Concatenate the ILists `first' and `second' to a new MemberList.
+               /// </summary>
+               public MemberList (IList first, IList second)
+               {
+                       ArrayList list = new ArrayList ();
+                       list.AddRange (first);
+                       list.AddRange (second);
+                       count = list.Count;
+                       List = list;
+               }
+
+               public static readonly MemberList Empty = new MemberList (new ArrayList ());
+
+               /// <summary>
+               ///   Cast the MemberList into a MemberInfo[] array.
+               /// </summary>
+               /// <remarks>
+               ///   This is an expensive operation, only use it if it's really necessary.
+               /// </remarks>
+               public static explicit operator MemberInfo [] (MemberList list)
+               {
+                       Timer.StartTimer (TimerType.MiscTimer);
+                       MemberInfo [] result = new MemberInfo [list.Count];
+                       list.CopyTo (result, 0);
+                       Timer.StopTimer (TimerType.MiscTimer);
+                       return result;
+               }
+
+               // ICollection
+
+               public int Count {
+                       get {
+                               return count;
+                       }
+               }
+
+               public bool IsSynchronized {
+                       get {
+                               return List.IsSynchronized;
+                       }
+               }
+
+               public object SyncRoot {
+                       get {
+                               return List.SyncRoot;
+                       }
+               }
+
+               public void CopyTo (Array array, int index)
+               {
+                       List.CopyTo (array, index);
+               }
+
+               // IEnumerable
+
+               public IEnumerator GetEnumerator ()
+               {
+                       return List.GetEnumerator ();
+               }
+
+               // IList
+
+               public bool IsFixedSize {
+                       get {
+                               return true;
+                       }
+               }
+
+               public bool IsReadOnly {
+                       get {
+                               return true;
+                       }
+               }
+
+               object IList.this [int index] {
+                       get {
+                               return List [index];
+                       }
+
+                       set {
+                               throw new NotSupportedException ();
+                       }
+               }
+
+               // FIXME: try to find out whether we can avoid the cast in this indexer.
+               public MemberInfo this [int index] {
+                       get {
+                               return (MemberInfo) List [index];
+                       }
+               }
+
+               public int Add (object value)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public void Clear ()
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public bool Contains (object value)
+               {
+                       return List.Contains (value);
+               }
+
+               public int IndexOf (object value)
+               {
+                       return List.IndexOf (value);
+               }
+
+               public void Insert (int index, object value)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public void Remove (object value)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public void RemoveAt (int index)
+               {
+                       throw new NotSupportedException ();
+               }
+       }
+
+       /// <summary>
+       ///   This interface is used to get all members of a class when creating the
+       ///   member cache.  It must be implemented by all DeclSpace derivatives which
+       ///   want to support the member cache and by TypeHandle to get caching of
+       ///   non-dynamic types.
+       /// </summary>
+       public interface IMemberContainer {
+               /// <summary>
+               ///   The name of the IMemberContainer.  This is only used for
+               ///   debugging purposes.
+               /// </summary>
+               string Name {
+                       get;
+               }
+
+               /// <summary>
+               ///   The type of this IMemberContainer.
+               /// </summary>
+               Type Type {
+                       get;
+               }
+
+               /// <summary>
+               ///   Returns the IMemberContainer of the parent class or null if this
+               ///   is an interface or TypeManger.object_type.
+               ///   This is used when creating the member cache for a class to get all
+               ///   members from the parent class.
+               /// </summary>
+               IMemberContainer Parent {
+                       get;
+               }
+
+               /// <summary>
+               ///   Whether this is an interface.
+               /// </summary>
+               bool IsInterface {
+                       get;
+               }
+
+               /// <summary>
+               ///   Returns all members of this class with the corresponding MemberTypes
+               ///   and BindingFlags.
+               /// </summary>
+               /// <remarks>
+               ///   When implementing this method, make sure not to return any inherited
+               ///   members and check the MemberTypes and BindingFlags properly.
+               ///   Unfortunately, System.Reflection is lame and doesn't provide a way to
+               ///   get the BindingFlags (static/non-static,public/non-public) in the
+               ///   MemberInfo class, but the cache needs this information.  That's why
+               ///   this method is called multiple times with different BindingFlags.
+               /// </remarks>
+               MemberList GetMembers (MemberTypes mt, BindingFlags bf);
+
+               /// <summary>
+               ///   Return the container's member cache.
+               /// </summary>
+               MemberCache MemberCache {
+                       get;
+               }
+       }
+
+       /// <summary>
+       ///   The MemberCache is used by dynamic and non-dynamic types to speed up
+       ///   member lookups.  It has a member name based hash table; it maps each member
+       ///   name to a list of CacheEntry objects.  Each CacheEntry contains a MemberInfo
+       ///   and the BindingFlags that were initially used to get it.  The cache contains
+       ///   all members of the current class and all inherited members.  If this cache is
+       ///   for an interface types, it also contains all inherited members.
+       ///
+       ///   There are two ways to get a MemberCache:
+       ///   * if this is a dynamic type, lookup the corresponding DeclSpace and then
+       ///     use the DeclSpace.MemberCache property.
+       ///   * if this not a dynamic type, call TypeHandle.GetTypeHandle() to get a
+       ///     TypeHandle instance for the type and then use TypeHandle.MemberCache.
+       /// </summary>
+       public class MemberCache {
+               public readonly IMemberContainer Container;
+               protected Hashtable member_hash;
+               protected Hashtable method_hash;
+               protected Hashtable interface_hash;
+
+               /// <summary>
+               ///   Create a new MemberCache for the given IMemberContainer `container'.
+               /// </summary>
+               public MemberCache (IMemberContainer container)
+               {
+                       this.Container = container;
+
+                       Timer.IncrementCounter (CounterType.MemberCache);
+                       Timer.StartTimer (TimerType.CacheInit);
+
+                       interface_hash = new Hashtable ();
+
+                       // If we have a parent class (we have a parent class unless we're
+                       // TypeManager.object_type), we deep-copy its MemberCache here.
+                       if (Container.Parent != null) {
+                               member_hash = SetupCache (Container.Parent.MemberCache);
+                       } else if (Container.IsInterface)
+                               member_hash = SetupCacheForInterface ();
+                       else
+                               member_hash = new Hashtable ();
+
+                       // If this is neither a dynamic type nor an interface, create a special
+                       // method cache with all declared and inherited methods.
+                       Type type = container.Type;
+                       if (!(type is TypeBuilder) && !type.IsInterface) {
+                               method_hash = new Hashtable ();
+                               AddMethods (type);
+                       }
+
+                       // Add all members from the current class.
+                       AddMembers (Container);
+
+                       Timer.StopTimer (TimerType.CacheInit);
+               }
+
+               /// <summary>
+               ///   Bootstrap this member cache by doing a deep-copy of our parent.
+               /// </summary>
+               Hashtable SetupCache (MemberCache parent)
+               {
+                       Hashtable hash = new Hashtable ();
+
+                       IDictionaryEnumerator it = parent.member_hash.GetEnumerator ();
+                       while (it.MoveNext ()) {
+                               hash [it.Key] = ((ArrayList) it.Value).Clone ();
+                        }
+                                
+                       return hash;
+               }
+
+               void AddInterfaces (MemberCache parent)
+               {
+                       foreach (Type iface in parent.interface_hash.Keys) {
+                               if (!interface_hash.Contains (iface))
+                                       interface_hash.Add (iface, true);
+                       }
+               }
+
+               /// <summary>
+               ///   Add the contents of `new_hash' to `hash'.
+               /// </summary>
+               void AddHashtable (Hashtable hash, Hashtable new_hash)
+               {
+                       IDictionaryEnumerator it = new_hash.GetEnumerator ();
+                       while (it.MoveNext ()) {
+                               ArrayList list = (ArrayList) hash [it.Key];
+                               if (list != null)
+                                       list.AddRange ((ArrayList) it.Value);
+                               else
+                                       hash [it.Key] = ((ArrayList) it.Value).Clone ();
+                       }
+               }
+
+               /// <summary>
+               ///   Bootstrap the member cache for an interface type.
+               ///   Type.GetMembers() won't return any inherited members for interface types,
+               ///   so we need to do this manually.  Interfaces also inherit from System.Object.
+               /// </summary>
+               Hashtable SetupCacheForInterface ()
+               {
+                       Hashtable hash = SetupCache (TypeHandle.ObjectType.MemberCache);
+                       Type [] ifaces = TypeManager.GetInterfaces (Container.Type);
+
+                       foreach (Type iface in ifaces) {
+                               if (interface_hash.Contains (iface))
+                                       continue;
+                               interface_hash.Add (iface, true);
+
+                               IMemberContainer iface_container =
+                                       TypeManager.LookupMemberContainer (iface);
+
+                               MemberCache iface_cache = iface_container.MemberCache;
+                               AddHashtable (hash, iface_cache.member_hash);
+                               AddInterfaces (iface_cache);
+                       }
+
+                       return hash;
+               }
+
+               /// <summary>
+               ///   Add all members from class `container' to the cache.
+               /// </summary>
+               void AddMembers (IMemberContainer container)
+               {
+                       // We need to call AddMembers() with a single member type at a time
+                       // to get the member type part of CacheEntry.EntryType right.
+                       AddMembers (MemberTypes.Constructor, container);
+                       AddMembers (MemberTypes.Field, container);
+                       AddMembers (MemberTypes.Method, container);
+                       AddMembers (MemberTypes.Property, container);
+                       AddMembers (MemberTypes.Event, container);
+                       // Nested types are returned by both Static and Instance searches.
+                       AddMembers (MemberTypes.NestedType,
+                                   BindingFlags.Static | BindingFlags.Public, container);
+                       AddMembers (MemberTypes.NestedType,
+                                   BindingFlags.Static | BindingFlags.NonPublic, container);
+               }
+
+               void AddMembers (MemberTypes mt, IMemberContainer container)
+               {
+                       AddMembers (mt, BindingFlags.Static | BindingFlags.Public, container);
+                       AddMembers (mt, BindingFlags.Static | BindingFlags.NonPublic, container);
+                       AddMembers (mt, BindingFlags.Instance | BindingFlags.Public, container);
+                       AddMembers (mt, BindingFlags.Instance | BindingFlags.NonPublic, container);
+               }
+
+               /// <summary>
+               ///   Add all members from class `container' with the requested MemberTypes and
+               ///   BindingFlags to the cache.  This method is called multiple times with different
+               ///   MemberTypes and BindingFlags.
+               /// </summary>
+               void AddMembers (MemberTypes mt, BindingFlags bf, IMemberContainer container)
+               {
+                       MemberList members = container.GetMembers (mt, bf);
+                       BindingFlags new_bf = (container == Container) ?
+                               bf | BindingFlags.DeclaredOnly : bf;
+
+                       foreach (MemberInfo member in members) {
+                               string name = member.Name;
+
+                               // We use a name-based hash table of ArrayList's.
+                               ArrayList list = (ArrayList) member_hash [name];
+                               if (list == null) {
+                                       list = new ArrayList ();
+                                       member_hash.Add (name, list);
+                               }
+
+                               // When this method is called for the current class, the list will
+                               // already contain all inherited members from our parent classes.
+                               // We cannot add new members in front of the list since this'd be an
+                               // expensive operation, that's why the list is sorted in reverse order
+                               // (ie. members from the current class are coming last).
+                               list.Add (new CacheEntry (container, member, mt, bf));
+                       }
+               }
+
+               /// <summary>
+               ///   Add all declared and inherited methods from class `type' to the method cache.
+               /// </summary>
+               void AddMethods (Type type)
+               {
+                       AddMethods (BindingFlags.Static | BindingFlags.Public |
+                                   BindingFlags.FlattenHierarchy, type);
+                       AddMethods (BindingFlags.Static | BindingFlags.NonPublic |
+                                   BindingFlags.FlattenHierarchy, type);
+                       AddMethods (BindingFlags.Instance | BindingFlags.Public, type);
+                       AddMethods (BindingFlags.Instance | BindingFlags.NonPublic, type);
+               }
+
+               void AddMethods (BindingFlags bf, Type type)
+               {
+                       MemberInfo [] members = type.GetMethods (bf);
+
+                       foreach (MethodBase member in members) {
+                               string name = member.Name;
+
+                               // Varargs methods aren't allowed in C# code.
+                               if ((member.CallingConvention & CallingConventions.VarArgs) != 0)
+                                       continue;
+
+                               // We use a name-based hash table of ArrayList's.
+                               ArrayList list = (ArrayList) method_hash [name];
+                               if (list == null) {
+                                       list = new ArrayList ();
+                                       method_hash.Add (name, list);
+                               }
+
+                               // Unfortunately, the elements returned by Type.GetMethods() aren't
+                               // sorted so we need to do this check for every member.
+                               BindingFlags new_bf = bf;
+                               if (member.DeclaringType == type)
+                                       new_bf |= BindingFlags.DeclaredOnly;
+
+                               list.Add (new CacheEntry (Container, member, MemberTypes.Method, new_bf));
+                       }
+               }
+
+               /// <summary>
+               ///   Compute and return a appropriate `EntryType' magic number for the given
+               ///   MemberTypes and BindingFlags.
+               /// </summary>
+               protected static EntryType GetEntryType (MemberTypes mt, BindingFlags bf)
+               {
+                       EntryType type = EntryType.None;
+
+                       if ((mt & MemberTypes.Constructor) != 0)
+                               type |= EntryType.Constructor;
+                       if ((mt & MemberTypes.Event) != 0)
+                               type |= EntryType.Event;
+                       if ((mt & MemberTypes.Field) != 0)
+                               type |= EntryType.Field;
+                       if ((mt & MemberTypes.Method) != 0)
+                               type |= EntryType.Method;
+                       if ((mt & MemberTypes.Property) != 0)
+                               type |= EntryType.Property;
+                       // Nested types are returned by static and instance searches.
+                       if ((mt & MemberTypes.NestedType) != 0)
+                               type |= EntryType.NestedType | EntryType.Static | EntryType.Instance;
+
+                       if ((bf & BindingFlags.Instance) != 0)
+                               type |= EntryType.Instance;
+                       if ((bf & BindingFlags.Static) != 0)
+                               type |= EntryType.Static;
+                       if ((bf & BindingFlags.Public) != 0)
+                               type |= EntryType.Public;
+                       if ((bf & BindingFlags.NonPublic) != 0)
+                               type |= EntryType.NonPublic;
+                       if ((bf & BindingFlags.DeclaredOnly) != 0)
+                               type |= EntryType.Declared;
+
+                       return type;
+               }
+
+               /// <summary>
+               ///   The `MemberTypes' enumeration type is a [Flags] type which means that it may
+               ///   denote multiple member types.  Returns true if the given flags value denotes a
+               ///   single member types.
+               /// </summary>
+               public static bool IsSingleMemberType (MemberTypes mt)
+               {
+                       switch (mt) {
+                       case MemberTypes.Constructor:
+                       case MemberTypes.Event:
+                       case MemberTypes.Field:
+                       case MemberTypes.Method:
+                       case MemberTypes.Property:
+                       case MemberTypes.NestedType:
+                               return true;
+
+                       default:
+                               return false;
+                       }
+               }
+
+               /// <summary>
+               ///   We encode the MemberTypes and BindingFlags of each members in a "magic"
+               ///   number to speed up the searching process.
+               /// </summary>
+               [Flags]
+               protected enum EntryType {
+                       None            = 0x000,
+
+                       Instance        = 0x001,
+                       Static          = 0x002,
+                       MaskStatic      = Instance|Static,
+
+                       Public          = 0x004,
+                       NonPublic       = 0x008,
+                       MaskProtection  = Public|NonPublic,
+
+                       Declared        = 0x010,
+
+                       Constructor     = 0x020,
+                       Event           = 0x040,
+                       Field           = 0x080,
+                       Method          = 0x100,
+                       Property        = 0x200,
+                       NestedType      = 0x400,
+
+                       MaskType        = Constructor|Event|Field|Method|Property|NestedType
+               }
+
+               protected struct CacheEntry {
+                       public readonly IMemberContainer Container;
+                       public readonly EntryType EntryType;
+                       public readonly MemberInfo Member;
+
+                       public CacheEntry (IMemberContainer container, MemberInfo member,
+                                          MemberTypes mt, BindingFlags bf)
+                       {
+                               this.Container = container;
+                               this.Member = member;
+                               this.EntryType = GetEntryType (mt, bf);
+                       }
+               }
+
+               /// <summary>
+               ///   This is called each time we're walking up one level in the class hierarchy
+               ///   and checks whether we can abort the search since we've already found what
+               ///   we were looking for.
+               /// </summary>
+               protected bool DoneSearching (ArrayList list)
+               {
+                       //
+                       // We've found exactly one member in the current class and it's not
+                       // a method or constructor.
+                       //
+                       if (list.Count == 1 && !(list [0] is MethodBase))
+                               return true;
+
+                       //
+                       // Multiple properties: we query those just to find out the indexer
+                       // name
+                       //
+                       if ((list.Count > 0) && (list [0] is PropertyInfo))
+                               return true;
+
+                       return false;
+               }
+
+               /// <summary>
+               ///   Looks up members with name `name'.  If you provide an optional
+               ///   filter function, it'll only be called with members matching the
+               ///   requested member name.
+               ///
+               ///   This method will try to use the cache to do the lookup if possible.
+               ///
+               ///   Unlike other FindMembers implementations, this method will always
+               ///   check all inherited members - even when called on an interface type.
+               ///
+               ///   If you know that you're only looking for methods, you should use
+               ///   MemberTypes.Method alone since this speeds up the lookup a bit.
+               ///   When doing a method-only search, it'll try to use a special method
+               ///   cache (unless it's a dynamic type or an interface) and the returned
+               ///   MemberInfo's will have the correct ReflectedType for inherited methods.
+               ///   The lookup process will automatically restart itself in method-only
+               ///   search mode if it discovers that it's about to return methods.
+               /// </summary>
+               public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
+                                              MemberFilter filter, object criteria)
+               {
+                       bool declared_only = (bf & BindingFlags.DeclaredOnly) != 0;
+                       bool method_search = mt == MemberTypes.Method;
+                       // If we have a method cache and we aren't already doing a method-only search,
+                       // then we restart a method search if the first match is a method.
+                       bool do_method_search = !method_search && (method_hash != null);
+
+                       ArrayList applicable;
+
+                       // If this is a method-only search, we try to use the method cache if
+                       // possible; a lookup in the method cache will return a MemberInfo with
+                       // the correct ReflectedType for inherited methods.
+                       
+                       if (method_search && (method_hash != null))
+                               applicable = (ArrayList) method_hash [name];
+                       else
+                               applicable = (ArrayList) member_hash [name];
+                       
+                       if (applicable == null)
+                               return MemberList.Empty;
+
+                       //
+                       // 32  slots gives 53 rss/54 size
+                       // 2/4 slots gives 55 rss
+                       //
+                       // Strange: from 25,000 calls, only 1,800
+                       // are above 2.  Why does this impact it?
+                       //
+                       ArrayList list = new ArrayList ();
+
+                       Timer.StartTimer (TimerType.CachedLookup);
+
+                       EntryType type = GetEntryType (mt, bf);
+
+                       IMemberContainer current = Container;
+
+                       // `applicable' is a list of all members with the given member name `name'
+                       // in the current class and all its parent classes.  The list is sorted in
+                       // reverse order due to the way how the cache is initialy created (to speed
+                       // things up, we're doing a deep-copy of our parent).
+
+                       for (int i = applicable.Count-1; i >= 0; i--) {
+                               CacheEntry entry = (CacheEntry) applicable [i];
+
+                               // This happens each time we're walking one level up in the class
+                               // hierarchy.  If we're doing a DeclaredOnly search, we must abort
+                               // the first time this happens (this may already happen in the first
+                               // iteration of this loop if there are no members with the name we're
+                               // looking for in the current class).
+                               if (entry.Container != current) {
+                                       if (declared_only || DoneSearching (list))
+                                               break;
+
+                                       current = entry.Container;
+                               }
+
+                               // Is the member of the correct type ?
+                               if ((entry.EntryType & type & EntryType.MaskType) == 0)
+                                       continue;
+
+                               // Is the member static/non-static ?
+                               if ((entry.EntryType & type & EntryType.MaskStatic) == 0)
+                                       continue;
+
+                               // Apply the filter to it.
+                               if (filter (entry.Member, criteria)) {
+                                       if ((entry.EntryType & EntryType.MaskType) != EntryType.Method)
+                                               do_method_search = false;
+                                       list.Add (entry.Member);
+                               }
+                       }
+
+                       Timer.StopTimer (TimerType.CachedLookup);
+
+                       // If we have a method cache and we aren't already doing a method-only
+                       // search, we restart in method-only search mode if the first match is
+                       // a method.  This ensures that we return a MemberInfo with the correct
+                       // ReflectedType for inherited methods.
+                       if (do_method_search && (list.Count > 0)){
+                               return FindMembers (MemberTypes.Method, bf, name, filter, criteria);
+                       }
+
+                       return new MemberList (list);
+               }
+       }
+}
diff --git a/mcs/gmcs/delegate.cs b/mcs/gmcs/delegate.cs
new file mode 100644 (file)
index 0000000..f46b7c8
--- /dev/null
@@ -0,0 +1,819 @@
+//\r
+// delegate.cs: Delegate Handler\r
+//\r
+// Authors:\r
+//     Ravi Pratap (ravi@ximian.com)\r
+//     Miguel de Icaza (miguel@ximian.com)\r
+//\r
+// Licensed under the terms of the GNU GPL\r
+//\r
+// (C) 2001 Ximian, Inc (http://www.ximian.com)\r
+//\r
+//\r
+\r
+using System;\r
+using System.Collections;\r
+using System.Reflection;\r
+using System.Reflection.Emit;\r
+using System.Text;\r
+\r
+namespace Mono.CSharp {\r
+\r
+       /// <summary>\r
+       ///   Holds Delegates\r
+       /// </summary>\r
+       public class Delegate : DeclSpace {\r
+               public Expression ReturnType;\r
+               public Parameters      Parameters;\r
+               public Attributes      OptAttributes;\r
+\r
+               public ConstructorBuilder ConstructorBuilder;\r
+               public MethodBuilder      InvokeBuilder;\r
+               public MethodBuilder      BeginInvokeBuilder;\r
+               public MethodBuilder      EndInvokeBuilder;\r
+               \r
+               Type [] param_types;\r
+               Type ret_type;\r
+               \r
+               Expression instance_expr;\r
+               MethodBase delegate_method;\r
+       \r
+               const int AllowedModifiers =\r
+                       Modifiers.NEW |\r
+                       Modifiers.PUBLIC |\r
+                       Modifiers.PROTECTED |\r
+                       Modifiers.INTERNAL |\r
+                       Modifiers.UNSAFE |\r
+                       Modifiers.PRIVATE;\r
+\r
+               public Delegate (TypeContainer parent, Expression type, int mod_flags,\r
+                                string name, Parameters param_list,\r
+                                Attributes attrs, Location l)\r
+                       : base (parent, name, l)\r
+               {\r
+                       this.ReturnType = type;\r
+                       ModFlags        = Modifiers.Check (AllowedModifiers, mod_flags,\r
+                                                          IsTopLevel ? Modifiers.INTERNAL :\r
+                                                          Modifiers.PRIVATE, l);\r
+                       Parameters      = param_list;\r
+                       OptAttributes   = attrs;\r
+               }\r
+\r
+               public override TypeBuilder DefineType ()\r
+               {\r
+                       if (TypeBuilder != null)\r
+                               return TypeBuilder;\r
+\r
+                       TypeAttributes attr = Modifiers.TypeAttr (ModFlags, IsTopLevel) |\r
+                               TypeAttributes.Class | TypeAttributes.Sealed;\r
+\r
+                       if (IsTopLevel) {\r
+                               if (TypeManager.NamespaceClash (Name, Location))\r
+                                       return null;\r
+                               \r
+                               ModuleBuilder builder = CodeGen.ModuleBuilder;\r
+\r
+                               TypeBuilder = builder.DefineType (\r
+                                       Name, attr, TypeManager.multicast_delegate_type);\r
+                       } else {\r
+                               TypeBuilder builder = Parent.TypeBuilder;\r
+\r
+                               string name = Name.Substring (1 + Name.LastIndexOf ('.'));\r
+                               TypeBuilder = builder.DefineNestedType (\r
+                                       name, attr, TypeManager.multicast_delegate_type);\r
+                       }\r
+\r
+                       TypeManager.AddDelegateType (Name, TypeBuilder, this);\r
+\r
+                       return TypeBuilder;\r
+               }\r
+\r
+               public override bool DefineMembers (TypeContainer container)\r
+               {\r
+                       return true;\r
+               }\r
+\r
+               public override bool Define (TypeContainer container)\r
+               {\r
+                       MethodAttributes mattr;\r
+                       int i;\r
+                       ParameterBuilder pb;\r
+                       Attributes cattr;\r
+                       EmitContext ec = new EmitContext (this, this, Location, null,\r
+                                                         null, ModFlags, false);\r
+\r
+                       // FIXME: POSSIBLY make this static, as it is always constant\r
+                       //\r
+                       Type [] const_arg_types = new Type [2];\r
+                       const_arg_types [0] = TypeManager.object_type;\r
+                       const_arg_types [1] = TypeManager.intptr_type;\r
+\r
+                       mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |\r
+                               MethodAttributes.HideBySig | MethodAttributes.Public;\r
+\r
+                       ConstructorBuilder = TypeBuilder.DefineConstructor (mattr,\r
+                                                                           CallingConventions.Standard,\r
+                                                                           const_arg_types);\r
+\r
+                       ConstructorBuilder.DefineParameter (1, ParameterAttributes.None, "object");\r
+                       ConstructorBuilder.DefineParameter (2, ParameterAttributes.None, "method");\r
+                       //\r
+                       // HACK because System.Reflection.Emit is lame\r
+                       //\r
+                       //\r
+                       // FIXME: POSSIBLY make these static, as they are always the same\r
+                       Parameter [] fixed_pars = new Parameter [2];\r
+                       fixed_pars [0] = new Parameter (null, null, Parameter.Modifier.NONE, null);\r
+                       fixed_pars [1] = new Parameter (null, null, Parameter.Modifier.NONE, null);\r
+                       Parameters const_parameters = new Parameters (fixed_pars, null, Location);\r
+                       \r
+                       TypeManager.RegisterMethod (\r
+                               ConstructorBuilder,\r
+                               new InternalParameters (const_arg_types, const_parameters),\r
+                               const_arg_types);\r
+                               \r
+                       \r
+                       ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);\r
+\r
+                       //\r
+                       // Here the various methods like Invoke, BeginInvoke etc are defined\r
+                       //\r
+                       // First, call the `out of band' special method for\r
+                       // defining recursively any types we need:\r
+                       \r
+                       if (!Parameters.ComputeAndDefineParameterTypes (this))\r
+                               return false;\r
+                       \r
+                       param_types = Parameters.GetParameterInfo (this);\r
+                       if (param_types == null)\r
+                               return false;\r
+\r
+                       //\r
+                       // Invoke method\r
+                       //\r
+\r
+                       // Check accessibility\r
+                       foreach (Type partype in param_types){\r
+                               if (!container.AsAccessible (partype, ModFlags)) {\r
+                                       Report.Error (59, Location,\r
+                                                     "Inconsistent accessibility: parameter type `" +\r
+                                                     TypeManager.CSharpName (partype) + "` is less " +\r
+                                                     "accessible than delegate `" + Name + "'");\r
+                                       return false;\r
+                               }\r
+                               if (partype.IsPointer && !UnsafeOK (container))\r
+                                       return false;\r
+                       }\r
+                       \r
+                       ReturnType = ResolveTypeExpr (ReturnType, false, Location);\r
+                       ret_type = ReturnType.Type;\r
+                       if (ret_type == null)\r
+                               return false;\r
+\r
+                       if (!container.AsAccessible (ret_type, ModFlags)) {\r
+                               Report.Error (58, Location,\r
+                                             "Inconsistent accessibility: return type `" +\r
+                                             TypeManager.CSharpName (ret_type) + "` is less " +\r
+                                             "accessible than delegate `" + Name + "'");\r
+                               return false;\r
+                       }\r
+\r
+                       if (ret_type.IsPointer && !UnsafeOK (container))\r
+                               return false;\r
+\r
+                       //\r
+                       // We don't have to check any others because they are all\r
+                       // guaranteed to be accessible - they are standard types.\r
+                       //\r
+                       \r
+                       CallingConventions cc = Parameters.GetCallingConvention ();\r
+\r
+                       mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;\r
+\r
+                       InvokeBuilder = TypeBuilder.DefineMethod ("Invoke", \r
+                                                                 mattr,                     \r
+                                                                 cc,\r
+                                                                 ret_type,                  \r
+                                                                 param_types);\r
+\r
+                       //\r
+                       // Define parameters, and count out/ref parameters\r
+                       //\r
+                       int out_params = 0;\r
+                       i = 0;\r
+                       if (Parameters.FixedParameters != null){\r
+                               int top = Parameters.FixedParameters.Length;\r
+                               Parameter p;\r
+                               \r
+                               for (; i < top; i++) {\r
+                                       p = Parameters.FixedParameters [i];\r
+                                       pb = InvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);\r
+                                       cattr = p.OptAttributes;\r
+                                       if (cattr != null)\r
+                                               Attribute.ApplyAttributes (ec, pb, pb, cattr);\r
+\r
+                                       if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)\r
+                                               out_params++;\r
+                               }\r
+                       }\r
+                       if (Parameters.ArrayParameter != null){\r
+                               Parameter p = Parameters.ArrayParameter;\r
+                               \r
+                               pb = InvokeBuilder.DefineParameter (\r
+                                       i+1, p.Attributes, p.Name);\r
+                               cattr = p.OptAttributes;\r
+                               if (cattr != null)\r
+                                       Attribute.ApplyAttributes (ec, pb, pb, cattr);\r
+                       }\r
+                       \r
+                       InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);\r
+\r
+                       TypeManager.RegisterMethod (InvokeBuilder,\r
+                                                   new InternalParameters (container, Parameters),\r
+                                                   param_types);\r
+\r
+                       //\r
+                       // BeginInvoke\r
+                       //\r
+                       int params_num = param_types.Length;\r
+                       Type [] async_param_types = new Type [params_num + 2];\r
+\r
+                       param_types.CopyTo (async_param_types, 0);\r
+\r
+                       async_param_types [params_num] = TypeManager.asynccallback_type;\r
+                       async_param_types [params_num + 1] = TypeManager.object_type;\r
+\r
+                       mattr = MethodAttributes.Public | MethodAttributes.HideBySig |\r
+                               MethodAttributes.Virtual | MethodAttributes.NewSlot;\r
+                       \r
+                       BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke",\r
+                                                                      mattr,\r
+                                                                      cc,\r
+                                                                      TypeManager.iasyncresult_type,\r
+                                                                      async_param_types);\r
+\r
+                       i = 0;\r
+                       if (Parameters.FixedParameters != null){\r
+                               int top = Parameters.FixedParameters.Length;\r
+                               Parameter p;\r
+                               \r
+                               for (i = 0 ; i < top; i++) {\r
+                                       p = Parameters.FixedParameters [i];\r
+\r
+                                       pb = BeginInvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);\r
+                                       cattr = p.OptAttributes;\r
+                                       if (cattr != null)\r
+                                               Attribute.ApplyAttributes (ec, pb, pb, cattr);\r
+                               }\r
+                       }\r
+                       if (Parameters.ArrayParameter != null){\r
+                               Parameter p = Parameters.ArrayParameter;\r
+                               \r
+                               pb = BeginInvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);\r
+                               cattr = p.OptAttributes;\r
+                               if (cattr != null)\r
+                                       Attribute.ApplyAttributes (ec, pb, pb, cattr);\r
+                               i++;\r
+                       }\r
+\r
+                       BeginInvokeBuilder.DefineParameter (i + 1, ParameterAttributes.None, "callback");\r
+                       BeginInvokeBuilder.DefineParameter (i + 2, ParameterAttributes.None, "object");\r
+                       \r
+                       BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);\r
+\r
+                       Parameter [] async_params = new Parameter [params_num + 2];\r
+                       int n = 0;\r
+                       if (Parameters.FixedParameters != null){\r
+                               Parameters.FixedParameters.CopyTo (async_params, 0);\r
+                               n = Parameters.FixedParameters.Length;\r
+                       }\r
+                       if (Parameters.ArrayParameter != null)\r
+                               async_params [n] = Parameters.ArrayParameter;\r
+                       \r
+                       async_params [params_num] = new Parameter (\r
+                               TypeManager.system_asynccallback_expr, "callback",\r
+                                                                  Parameter.Modifier.NONE, null);\r
+                       async_params [params_num + 1] = new Parameter (\r
+                               TypeManager.system_object_expr, "object",\r
+                                                                  Parameter.Modifier.NONE, null);\r
+\r
+                       Parameters async_parameters = new Parameters (async_params, null, Location);\r
+                       async_parameters.ComputeAndDefineParameterTypes (this);\r
+                       \r
+                       async_parameters.ComputeAndDefineParameterTypes (this);\r
+                       TypeManager.RegisterMethod (BeginInvokeBuilder,\r
+                                                   new InternalParameters (container, async_parameters),\r
+                                                   async_param_types);\r
+\r
+                       //\r
+                       // EndInvoke is a bit more interesting, all the parameters labeled as\r
+                       // out or ref have to be duplicated here.\r
+                       //\r
+                       \r
+                       Type [] end_param_types = new Type [out_params + 1];\r
+                       Parameter [] end_params = new Parameter [out_params + 1];\r
+                       int param = 0; \r
+                       if (out_params > 0){\r
+                               int top = Parameters.FixedParameters.Length;\r
+                               for (i = 0; i < top; i++){\r
+                                       Parameter p = Parameters.FixedParameters [i];\r
+                                       if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)\r
+                                               continue;\r
+\r
+                                       end_param_types [param] = param_types [i];\r
+                                       end_params [param] = p;\r
+                                       param++;\r
+                               }\r
+                       }\r
+                       end_param_types [out_params] = TypeManager.iasyncresult_type;\r
+                       end_params [out_params] = new Parameter (TypeManager.system_iasyncresult_expr, "result", Parameter.Modifier.NONE, null);\r
+\r
+                       //\r
+                       // Create method, define parameters, register parameters with type system\r
+                       //\r
+                       EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_param_types);\r
+                       EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);\r
+\r
+                       //\r
+                       // EndInvoke: Label the parameters\r
+                       //\r
+                       EndInvokeBuilder.DefineParameter (out_params + 1, ParameterAttributes.None, "result");\r
+                       for (i = 0; i < end_params.Length-1; i++){\r
+                               EndInvokeBuilder.DefineParameter (i + 1, end_params [i].Attributes, end_params [i].Name);\r
+                       }\r
+\r
+                       Parameters end_parameters = new Parameters (end_params, null, Location);\r
+                       end_parameters.ComputeAndDefineParameterTypes (this);\r
+\r
+                       TypeManager.RegisterMethod (\r
+                               EndInvokeBuilder,\r
+                               new InternalParameters (container, end_parameters),\r
+                               end_param_types);\r
+\r
+                       return true;\r
+               }\r
+\r
+               /// <summary>\r
+               ///  Verifies whether the method in question is compatible with the delegate\r
+               ///  Returns the method itself if okay and null if not.\r
+               /// </summary>\r
+               public static MethodBase VerifyMethod (EmitContext ec, Type delegate_type, MethodBase mb,\r
+                                                      Location loc)\r
+               {\r
+                       ParameterData pd = Invocation.GetParameterData (mb);\r
+\r
+                       int pd_count = pd.Count;\r
+\r
+                       Expression ml = Expression.MemberLookup (\r
+                               ec, delegate_type, "Invoke", loc);\r
+\r
+                       if (!(ml is MethodGroupExpr)) {\r
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
+                               return null;\r
+                       }\r
+\r
+                       MethodBase invoke_mb = ((MethodGroupExpr) ml).Methods [0];\r
+\r
+                       ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);\r
+\r
+                       if (invoke_pd.Count != pd_count)\r
+                               return null;\r
+\r
+                       for (int i = pd_count; i > 0; ) {\r
+                               i--;\r
+\r
+                               if (invoke_pd.ParameterType (i) == pd.ParameterType (i) &&\r
+                                   invoke_pd.ParameterModifier (i) == pd.ParameterModifier (i))\r
+                                       continue;\r
+                               else {\r
+                                       return null;\r
+                               }\r
+                       }\r
+\r
+                       if (((MethodInfo) invoke_mb).ReturnType == ((MethodInfo) mb).ReturnType)\r
+                               return mb;\r
+                       else\r
+                               return null;\r
+               }\r
+\r
+               // <summary>\r
+               //  Verifies whether the invocation arguments are compatible with the\r
+               //  delegate's target method\r
+               // </summary>\r
+               public static bool VerifyApplicability (EmitContext ec,\r
+                                                       Type delegate_type,\r
+                                                       ArrayList args,\r
+                                                       Location loc)\r
+               {\r
+                       int arg_count;\r
+\r
+                       if (args == null)\r
+                               arg_count = 0;\r
+                       else\r
+                               arg_count = args.Count;\r
+\r
+                       Expression ml = Expression.MemberLookup (\r
+                               ec, delegate_type, "Invoke", loc);\r
+\r
+                       if (!(ml is MethodGroupExpr)) {\r
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!" + delegate_type);\r
+                               return false;\r
+                       }\r
+                       \r
+                       MethodBase mb = ((MethodGroupExpr) ml).Methods [0];\r
+                       ParameterData pd = Invocation.GetParameterData (mb);\r
+\r
+                       int pd_count = pd.Count;\r
+\r
+                       bool not_params_method = (pd_count == 0) ||\r
+                               (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS);\r
+\r
+                       if (not_params_method && pd_count != arg_count) {\r
+                               Report.Error (1593, loc,\r
+                                             "Delegate '" + delegate_type.ToString ()\r
+                                             + "' does not take '" + arg_count + "' arguments");\r
+                               return false;\r
+                       }\r
+\r
+                       return Invocation.VerifyArgumentsCompat (ec, args, arg_count, mb, !not_params_method,\r
+                                                                delegate_type, loc);\r
+               }\r
+               \r
+               /// <summary>\r
+               ///  Verifies whether the delegate in question is compatible with this one in\r
+               ///  order to determine if instantiation from the same is possible.\r
+               /// </summary>\r
+               public static bool VerifyDelegate (EmitContext ec, Type delegate_type, Type probe_type, Location loc)\r
+               {\r
+                       Expression ml = Expression.MemberLookup (\r
+                               ec, delegate_type, "Invoke", loc);\r
+                       \r
+                       if (!(ml is MethodGroupExpr)) {\r
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
+                               return false;\r
+                       }\r
+                       \r
+                       MethodBase mb = ((MethodGroupExpr) ml).Methods [0];\r
+                       ParameterData pd = Invocation.GetParameterData (mb);\r
+\r
+                       Expression probe_ml = Expression.MemberLookup (\r
+                               ec, delegate_type, "Invoke", loc);\r
+                       \r
+                       if (!(probe_ml is MethodGroupExpr)) {\r
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
+                               return false;\r
+                       }\r
+                       \r
+                       MethodBase probe_mb = ((MethodGroupExpr) probe_ml).Methods [0];\r
+                       ParameterData probe_pd = Invocation.GetParameterData (probe_mb);\r
+                       \r
+                       if (((MethodInfo) mb).ReturnType != ((MethodInfo) probe_mb).ReturnType)\r
+                               return false;\r
+\r
+                       if (pd.Count != probe_pd.Count)\r
+                               return false;\r
+\r
+                       for (int i = pd.Count; i > 0; ) {\r
+                               i--;\r
+\r
+                               if (pd.ParameterType (i) != probe_pd.ParameterType (i) ||\r
+                                   pd.ParameterModifier (i) != probe_pd.ParameterModifier (i))\r
+                                       return false;\r
+                       }\r
+                       \r
+                       return true;\r
+               }\r
+               \r
+               public static string FullDelegateDesc (Type del_type, MethodBase mb, ParameterData pd)\r
+               {\r
+                       StringBuilder sb = new StringBuilder (TypeManager.CSharpName (((MethodInfo) mb).ReturnType));\r
+                       \r
+                       sb.Append (" " + del_type.ToString ());\r
+                       sb.Append (" (");\r
+\r
+                       int length = pd.Count;\r
+                       \r
+                       for (int i = length; i > 0; ) {\r
+                               i--;\r
+\r
+                               sb.Append (pd.ParameterDesc (length - i - 1));\r
+                               if (i != 0)\r
+                                       sb.Append (", ");\r
+                       }\r
+                       \r
+                       sb.Append (")");\r
+                       return sb.ToString ();\r
+                       \r
+               }\r
+               \r
+               // Hack around System.Reflection as found everywhere else\r
+               public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,\r
+                                                       MemberFilter filter, object criteria)\r
+               {\r
+                       ArrayList members = new ArrayList ();\r
+\r
+                       if ((mt & MemberTypes.Method) != 0) {\r
+                               if (ConstructorBuilder != null)\r
+                               if (filter (ConstructorBuilder, criteria))\r
+                                       members.Add (ConstructorBuilder);\r
+\r
+                               if (InvokeBuilder != null)\r
+                               if (filter (InvokeBuilder, criteria))\r
+                                       members.Add (InvokeBuilder);\r
+\r
+                               if (BeginInvokeBuilder != null)\r
+                               if (filter (BeginInvokeBuilder, criteria))\r
+                                       members.Add (BeginInvokeBuilder);\r
+\r
+                               if (EndInvokeBuilder != null)\r
+                               if (filter (EndInvokeBuilder, criteria))\r
+                                       members.Add (EndInvokeBuilder);\r
+                       }\r
+\r
+                       return new MemberList (members);\r
+               }\r
+\r
+               public override MemberCache MemberCache {\r
+                       get {\r
+                               return null;\r
+                       }\r
+               }\r
+\r
+               public Expression InstanceExpression {\r
+                       get {\r
+                               return instance_expr;\r
+                       }\r
+                       set {\r
+                               instance_expr = value;\r
+                       }\r
+               }\r
+\r
+               public MethodBase TargetMethod {\r
+                       get {\r
+                               return delegate_method;\r
+                       }\r
+                       set {\r
+                               delegate_method = value;\r
+                       }\r
+               }\r
+\r
+               public Type TargetReturnType {\r
+                       get {\r
+                               return ret_type;\r
+                       }\r
+               }\r
+\r
+               public Type [] ParameterTypes {\r
+                       get {\r
+                               return param_types;\r
+                       }\r
+               }\r
+               \r
+       }\r
+\r
+       public class NewDelegate : Expression {\r
+\r
+               public ArrayList Arguments;\r
+\r
+               MethodBase constructor_method;\r
+               MethodBase delegate_method;\r
+               Expression delegate_instance_expr;\r
+\r
+               public NewDelegate (Type type, ArrayList Arguments, Location loc)\r
+               {\r
+                       this.type = type;\r
+                       this.Arguments = Arguments;\r
+                       this.loc  = loc; \r
+               }\r
+\r
+               public override Expression DoResolve (EmitContext ec)\r
+               {\r
+                       if (Arguments == null || Arguments.Count != 1) {\r
+                               Report.Error (149, loc,\r
+                                             "Method name expected");\r
+                               return null;\r
+                       }\r
+\r
+                       Expression ml = Expression.MemberLookup (\r
+                               ec, type, ".ctor", loc);\r
+\r
+                       if (!(ml is MethodGroupExpr)) {\r
+                               Report.Error (-100, loc, "Internal error: Could not find delegate constructor!");\r
+                               return null;\r
+                       }\r
+\r
+                       constructor_method = ((MethodGroupExpr) ml).Methods [0];\r
+                       Argument a = (Argument) Arguments [0];\r
+                       \r
+                       if (!a.ResolveMethodGroup (ec, Location))\r
+                               return null;\r
+                       \r
+                       Expression e = a.Expr;\r
+\r
+                       Expression invoke_method = Expression.MemberLookup (\r
+                               ec, type, "Invoke", MemberTypes.Method,\r
+                               Expression.AllBindingFlags, loc);\r
+\r
+                       if (invoke_method == null) {\r
+                               Report.Error (-200, loc, "Internal error ! Could not find Invoke method!");\r
+                               return null;\r
+                       }\r
+\r
+                       if (e is MethodGroupExpr) {\r
+                               MethodGroupExpr mg = (MethodGroupExpr) e;\r
+\r
+                               foreach (MethodInfo mi in mg.Methods){\r
+                                       delegate_method  = Delegate.VerifyMethod (ec, type, mi, loc);\r
+\r
+                                       if (delegate_method != null)\r
+                                               break;\r
+                               }\r
+                                       \r
+                               if (delegate_method == null) {\r
+                                       string method_desc;\r
+                                       if (mg.Methods.Length > 1)\r
+                                               method_desc = mg.Methods [0].Name;\r
+                                       else\r
+                                               method_desc = Invocation.FullMethodDesc (mg.Methods [0]);\r
+\r
+                                       MethodBase dm = ((MethodGroupExpr) invoke_method).Methods [0];\r
+                                       ParameterData param = Invocation.GetParameterData (dm);\r
+                                       string delegate_desc = Delegate.FullDelegateDesc (type, dm, param);\r
+\r
+                                       Report.Error (123, loc, "Method '" + method_desc + "' does not " +\r
+                                                     "match delegate '" + delegate_desc + "'");\r
+\r
+                                       return null;\r
+                               }\r
+\r
+                               //\r
+                               // Check safe/unsafe of the delegate\r
+                               //\r
+                               if (!ec.InUnsafe){\r
+                                       ParameterData param = Invocation.GetParameterData (delegate_method);\r
+                                       int count = param.Count;\r
+                                       \r
+                                       for (int i = 0; i < count; i++){\r
+                                               if (param.ParameterType (i).IsPointer){\r
+                                                       Expression.UnsafeError (loc);\r
+                                                       return null;\r
+                                               }\r
+                                       }\r
+                               }\r
+                                               \r
+                               if (mg.InstanceExpression != null)\r
+                                       delegate_instance_expr = mg.InstanceExpression.Resolve (ec);\r
+                               else {\r
+                                       if (ec.IsStatic){\r
+                                               if (!delegate_method.IsStatic){\r
+                                                       Report.Error (120, loc,\r
+                                                                     "An object reference is required for the non-static method " +\r
+                                                                     delegate_method.Name);\r
+                                                       return null;\r
+                                               }\r
+                                               delegate_instance_expr = null;\r
+                                       } else\r
+                                               delegate_instance_expr = ec.GetThis (loc);\r
+                               }\r
+\r
+                               if (delegate_instance_expr != null)\r
+                                       if (delegate_instance_expr.Type.IsValueType)\r
+                                               delegate_instance_expr = new BoxedCast (delegate_instance_expr);\r
+                               \r
+                               eclass = ExprClass.Value;\r
+                               return this;\r
+                       }\r
+\r
+                       Type e_type = e.Type;\r
+\r
+                       if (!TypeManager.IsDelegateType (e_type)) {\r
+                               e.Error_UnexpectedKind ("method");\r
+                               return null;\r
+                       }\r
+\r
+                       // This is what MS' compiler reports. We could always choose\r
+                       // to be more verbose and actually give delegate-level specifics\r
+                       \r
+                       if (!Delegate.VerifyDelegate (ec, type, e_type, loc)) {\r
+                               Report.Error (29, loc, "Cannot implicitly convert type '" + e_type + "' " +\r
+                                             "to type '" + type + "'");\r
+                               return null;\r
+                       }\r
+                               \r
+                       delegate_instance_expr = e;\r
+                       delegate_method = ((MethodGroupExpr) invoke_method).Methods [0];\r
+                       \r
+                       eclass = ExprClass.Value;\r
+                       return this;\r
+               }\r
+               \r
+               public override void Emit (EmitContext ec)\r
+               {\r
+                       if (delegate_instance_expr == null ||\r
+                           delegate_method.IsStatic)\r
+                               ec.ig.Emit (OpCodes.Ldnull);\r
+                       else\r
+                               delegate_instance_expr.Emit (ec);\r
+                       \r
+                       if (delegate_method.IsVirtual) {\r
+                               ec.ig.Emit (OpCodes.Dup);\r
+                               ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method);\r
+                       } else\r
+                               ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);\r
+                       ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method);\r
+               }\r
+       }\r
+\r
+       public class DelegateInvocation : ExpressionStatement {\r
+\r
+               public Expression InstanceExpr;\r
+               public ArrayList  Arguments;\r
+\r
+               MethodBase method;\r
+               \r
+               public DelegateInvocation (Expression instance_expr, ArrayList args, Location loc)\r
+               {\r
+                       this.InstanceExpr = instance_expr;\r
+                       this.Arguments = args;\r
+                       this.loc = loc;\r
+               }\r
+\r
+               public override Expression DoResolve (EmitContext ec)\r
+               {\r
+                       if (InstanceExpr is EventExpr) {\r
+                               \r
+                               EventInfo ei = ((EventExpr) InstanceExpr).EventInfo;\r
+                               \r
+                               Expression ml = MemberLookup (\r
+                                       ec, ec.ContainerType, ei.Name,\r
+                                       MemberTypes.Event, AllBindingFlags | BindingFlags.DeclaredOnly, loc);\r
+\r
+                               if (ml == null) {\r
+                                       //\r
+                                       // If this is the case, then the Event does not belong \r
+                                       // to this Type and so, according to the spec\r
+                                       // cannot be accessed directly\r
+                                       //\r
+                                       // Note that target will not appear as an EventExpr\r
+                                       // in the case it is being referenced within the same type container;\r
+                                       // it will appear as a FieldExpr in that case.\r
+                                       //\r
+                                       \r
+                                       Assign.error70 (ei, loc);\r
+                                       return null;\r
+                               }\r
+                       }\r
+                       \r
+                       \r
+                       Type del_type = InstanceExpr.Type;\r
+                       if (del_type == null)\r
+                               return null;\r
+                       \r
+                       if (Arguments != null){\r
+                               foreach (Argument a in Arguments){\r
+                                       if (!a.Resolve (ec, loc))\r
+                                               return null;\r
+                               }\r
+                       }\r
+                       \r
+                       if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc))\r
+                               return null;\r
+\r
+                       Expression lookup = Expression.MemberLookup (ec, del_type, "Invoke", loc);\r
+                       if (!(lookup is MethodGroupExpr)) {\r
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
+                               return null;\r
+                       }\r
+                       \r
+                       method = ((MethodGroupExpr) lookup).Methods [0];\r
+                       type = ((MethodInfo) method).ReturnType;\r
+                       eclass = ExprClass.Value;\r
+                       \r
+                       return this;\r
+               }\r
+\r
+               public override void Emit (EmitContext ec)\r
+               {\r
+                       Delegate del = TypeManager.LookupDelegate (InstanceExpr.Type);\r
+\r
+                       //\r
+                       // Invocation on delegates call the virtual Invoke member\r
+                       // so we are always `instance' calls\r
+                       //\r
+                       Invocation.EmitCall (ec, false, false, InstanceExpr, method, Arguments, loc);\r
+               }\r
+\r
+               public override void EmitStatement (EmitContext ec)\r
+               {\r
+                       Emit (ec);\r
+                       // \r
+                       // Pop the return value if there is one\r
+                       //\r
+                       if (method is MethodInfo){\r
+                               if (((MethodInfo) method).ReturnType != TypeManager.void_type)\r
+                                       ec.ig.Emit (OpCodes.Pop);\r
+                       }\r
+               }\r
+\r
+       }\r
+}\r
diff --git a/mcs/gmcs/driver.cs b/mcs/gmcs/driver.cs
new file mode 100755 (executable)
index 0000000..7fa7e56
--- /dev/null
@@ -0,0 +1,1422 @@
+//
+// driver.cs: The compiler command line driver.
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
+//
+
+namespace Mono.CSharp
+{
+       using System;
+       using System.Reflection;
+       using System.Reflection.Emit;
+       using System.Collections;
+       using System.IO;
+       using System.Text;
+       using System.Globalization;
+       using Mono.Languages;
+
+       enum Target {
+               Library, Exe, Module, WinExe
+       };
+       
+       /// <summary>
+       ///    The compiler driver.
+       /// </summary>
+       public class Driver
+       {
+               
+               //
+               // Assemblies references to be linked.   Initialized with
+               // mscorlib.dll here.
+               static ArrayList references;
+
+               //
+               // If any of these fail, we ignore the problem.  This is so
+               // that we can list all the assemblies in Windows and not fail
+               // if they are missing on Linux.
+               //
+               static ArrayList soft_references;
+
+               // Lookup paths
+               static ArrayList link_paths;
+
+               // Whether we want Yacc to output its progress
+               static bool yacc_verbose = false;
+
+               // Whether we want to only run the tokenizer
+               static bool tokenize = false;
+               
+               static string first_source;
+
+               static Target target = Target.Exe;
+               static string target_ext = ".exe";
+
+               static bool want_debugging_support = false;
+
+               static bool parse_only = false;
+               static bool timestamps = false;
+               static bool pause = false;
+               static bool show_counters = false;
+               
+               //
+               // Whether to load the initial config file (what CSC.RSP has by default)
+               // 
+               static bool load_default_config = true;
+
+               static Hashtable response_file_list;
+
+               //
+               // A list of resource files
+               //
+               static ArrayList resources;
+               static ArrayList embedded_resources;
+               
+               //
+               // An array of the defines from the command line
+               //
+               static ArrayList defines;
+
+               //
+               // Output file
+               //
+               static string output_file = null;
+
+               //
+               // Last time we took the time
+               //
+               static DateTime last_time, first_time;
+
+               //
+               // Encoding: ISO-Latin1 is 28591
+               //
+               static Encoding encoding;
+
+               //
+               // Whether the user has specified a different encoder manually
+               //
+               static bool using_default_encoder = true;
+               
+               public static void ShowTime (string msg)
+               {
+                       if (!timestamps)
+                               return;
+
+                       DateTime now = DateTime.Now;
+                       TimeSpan span = now - last_time;
+                       last_time = now;
+
+                       Console.WriteLine (
+                               "[{0:00}:{1:000}] {2}",
+                               (int) span.TotalSeconds, span.Milliseconds, msg);
+
+                       if (pause)
+                               Console.ReadLine ();
+               }
+
+               public static void ShowTotalTime (string msg)
+               {
+                       if (!timestamps)
+                               return;
+
+                       DateTime now = DateTime.Now;
+                       TimeSpan span = now - first_time;
+                       last_time = now;
+
+                       Console.WriteLine (
+                               "[{0:00}:{1:000}] {2}",
+                               (int) span.TotalSeconds, span.Milliseconds, msg);
+               }              
+              
+               static void tokenize_file (SourceFile file)
+               {
+                       Stream input;
+
+                       try {
+                               input = File.OpenRead (file.Name);
+                       } catch {
+                               Report.Error (2001, "Source file '" + file.Name + "' could not be opened");
+                               return;
+                       }
+
+                       using (input){
+                               StreamReader reader = new StreamReader (input, encoding, using_default_encoder);
+                               Tokenizer lexer = new Tokenizer (reader, file, defines);
+                               int token, tokens = 0, errors = 0;
+
+                               while ((token = lexer.token ()) != Token.EOF){
+                                       Location l = lexer.Location;
+                                       tokens++;
+                                       if (token == Token.ERROR)
+                                               errors++;
+                               }
+                               Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors");
+                       }
+                       
+                       return;
+               }
+
+               // MonoTODO("Change error code for aborted compilation to something reasonable")]               
+               static void parse (SourceFile file)
+               {
+                       CSharpParser parser;
+                       Stream input;
+
+                       try {
+                               input = File.OpenRead (file.Name);
+                       } catch {
+                               Report.Error (2001, "Source file '" + file.Name + "' could not be opened");
+                               return;
+                       }
+
+                       StreamReader reader = new StreamReader (input, encoding, using_default_encoder);
+                               
+                       parser = new CSharpParser (reader, file, defines);
+                       parser.yacc_verbose = yacc_verbose;
+                       try {
+                               parser.parse ();
+                       } catch (Exception ex) {
+                               Report.Error(666, "Compilation aborted: " + ex);
+                       } finally {
+                               input.Close ();
+                       }
+               }
+               
+               static void Usage ()
+               {
+                       Console.WriteLine (
+                               "Mono C# compiler, (C) 2001 - 2003 Ximian, Inc.\n" +
+                               "mcs [options] source-files\n" +
+                               "   --about            About the Mono C# compiler\n" +
+                               "   -checked[+|-]      Set default context to checked\n" +
+                               "   -codepage:ID       Sets code page to the one in ID\n" +
+                               "                      (number, `utf8' or `reset')\n" +
+                               "   -define:S1[;S2]    Defines one or more symbols (short: /d:)\n" +
+                               "   -debug[+-]         Generate debugging information\n" + 
+                               "   -doc:FILE          XML Documentation file to generate\n" + 
+                               "   -g                 Generate debugging information\n" +
+                               "   --fatal            Makes errors fatal\n" +
+                               "   -lib:PATH1,PATH2   Adds the paths to the assembly link path\n" +
+                               "   -main:class        Specified the class that contains the entry point\n" +
+                               "   -noconfig[+|-]     Disables implicit references to assemblies\n" +
+                               "   -nostdlib[+|-]     Does not load core libraries\n" +
+                               "   -nowarn:W1[,W2]    Disables one or more warnings\n" + 
+                               "   -out:FNAME         Specifies output file\n" +
+                               "   --parse            Only parses the source file\n" +
+                               "   --expect-error X   Expect that error X will be encountered\n" +
+                               "   -recurse:SPEC      Recursively compiles the files in SPEC ([dir]/file)\n" + 
+                               "   -reference:ASS     References the specified assembly (-r:ASS)\n" +
+                               "   --stacktrace       Shows stack trace at error location\n" +
+                               "   -target:KIND       Specifies the target (KIND is one of: exe, winexe,\n" +
+                               "                      library, module), (short: /t:)\n" +
+                               "   --timestamp        Displays time stamps of various compiler events\n" +
+                               "   -unsafe[+|-]       Allows unsafe code\n" +
+                               "   -warnaserror[+|-]  Treat warnings as errors\n" +
+                               "   -warn:LEVEL        Sets warning level (the highest is 4, the default)\n" +
+                               "   -v                 Verbose parsing (for debugging the parser)\n" +
+                               "\n" +
+                               "Resources:\n" +
+                               "   -linkresource:FILE[,ID] Links FILE as a resource\n" +
+                               "   -resource:FILE[,ID]     Embed FILE as a resource\n" +
+                               "   --mcs-debug X      Sets MCS debugging level to X\n" +
+                                "   @file              Read response file for more options\n\n" +
+                               "Options can be of the form -option or /option");
+               }
+
+               static void TargetUsage ()
+               {
+                       Report.Error (2019, "Valid options for -target: are exe, winexe, library or module");
+               }
+               
+               static void About ()
+               {
+                       Console.WriteLine (
+                               "The Mono C# compiler is (C) 2001, 2002, 2003 Ximian, Inc.\n\n" +
+                               "The compiler source code is released under the terms of the GNU GPL\n\n" +
+
+                               "For more information on Mono, visit the project Web site\n" +
+                               "   http://www.go-mono.com\n\n" +
+
+                               "The compiler was written by Miguel de Icaza, Ravi Pratap and Martin Baulig");
+                       Environment.Exit (0);
+               }
+
+               public static int counter1, counter2;
+               
+               public static int Main (string[] args)
+               {
+                       bool ok = MainDriver (args);
+                       
+                       if (ok && Report.Errors == 0) {
+                               Console.Write("Compilation succeeded");
+                               if (Report.Warnings > 0) {
+                                       Console.Write(" - {0} warning(s)", Report.Warnings);
+                               }
+                               Console.WriteLine();
+                               if (show_counters){
+                                       Console.WriteLine ("Counter1: " + counter1);
+                                       Console.WriteLine ("Counter2: " + counter2);
+                               }
+                               return 0;
+                       } else {
+                               Console.WriteLine("Compilation failed: {0} error(s), {1} warnings",
+                                       Report.Errors, Report.Warnings);
+                               return 1;
+                       }
+               }
+
+               static public void LoadAssembly (string assembly, bool soft)
+               {
+                       Assembly a;
+                       string total_log = "";
+
+                       try {
+                               char[] path_chars = { '/', '\\', '.' };
+
+                               if (assembly.IndexOfAny (path_chars) != -1) {
+                                       a = Assembly.LoadFrom (assembly);
+                               } else {
+                                       a = Assembly.Load (assembly);
+                               }
+                               TypeManager.AddAssembly (a);
+
+                       } catch (FileNotFoundException){
+                               foreach (string dir in link_paths){
+                                       string full_path = Path.Combine (dir, assembly);
+                                       if (!assembly.EndsWith (".dll"))
+                                               full_path += ".dll";
+
+                                       try {
+                                               a = Assembly.LoadFrom (full_path);
+                                               TypeManager.AddAssembly (a);
+                                               return;
+                                       } catch (FileNotFoundException ff) {
+                                               total_log += ff.FusionLog;
+                                               continue;
+                                       }
+                               }
+                               if (!soft) {
+                                       Report.Error (6, "Cannot find assembly `" + assembly + "'" );
+                                       Console.WriteLine ("Log: \n" + total_log);
+                               }
+                       } catch (BadImageFormatException f) {
+                               Report.Error(6, "Cannot load assembly (bad file format)" + f.FusionLog);
+                       } catch (FileLoadException f){
+                               Report.Error(6, "Cannot load assembly " + f.FusionLog);
+                       } catch (ArgumentNullException){
+                               Report.Error(6, "Cannot load assembly (null argument)");
+                       }
+               }
+
+               /// <summary>
+               ///   Loads all assemblies referenced on the command line
+               /// </summary>
+               static public void LoadReferences ()
+               {
+                       foreach (string r in references)
+                               LoadAssembly (r, false);
+
+                       foreach (string r in soft_references)
+                               LoadAssembly (r, true);
+                       
+                       return;
+               }
+
+               static void SetupDefaultDefines ()
+               {
+                       defines = new ArrayList ();
+                       defines.Add ("__MonoCS__");
+               }
+
+               static string [] LoadArgs (string file)
+               {
+                       StreamReader f;
+                       ArrayList args = new ArrayList ();
+                       string line;
+                       try {
+                               f = new StreamReader (file);
+                       } catch {
+                               return null;
+                       }
+
+                       StringBuilder sb = new StringBuilder ();
+                       
+                       while ((line = f.ReadLine ()) != null){
+                               int t = line.Length;
+
+                               for (int i = 0; i < t; i++){
+                                       char c = line [i];
+                                       
+                                       if (c == '"' || c == '\''){
+                                               char end = c;
+                                               
+                                               for (i++; i < t; i++){
+                                                       c = line [i];
+
+                                                       if (c == end)
+                                                               break;
+                                                       sb.Append (c);
+                                               }
+                                       } else if (c == ' '){
+                                               if (sb.Length > 0){
+                                                       args.Add (sb.ToString ());
+                                                       sb.Length = 0;
+                                               }
+                                       } else
+                                               sb.Append (c);
+                               }
+                               if (sb.Length > 0){
+                                       args.Add (sb.ToString ());
+                                       sb.Length = 0;
+                               }
+                       }
+
+                       string [] ret_value = new string [args.Count];
+                       args.CopyTo (ret_value, 0);
+
+                       return ret_value;
+               }
+
+               //
+               // Returns the directory where the system assemblies are installed
+               //
+               static string GetSystemDir ()
+               {
+                       Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
+
+                       foreach (Assembly a in assemblies){
+                               string codebase = a.Location;
+                               if (codebase.EndsWith ("corlib.dll")){
+                                       return codebase.Substring (0, codebase.LastIndexOf (System.IO.Path.DirectorySeparatorChar));
+                               }
+                       }
+
+                       Report.Error (-15, "Can not compute my system path");
+                       return "";
+               }
+
+               //
+               // Given a path specification, splits the path from the file/pattern
+               //
+               static void SplitPathAndPattern (string spec, out string path, out string pattern)
+               {
+                       int p = spec.LastIndexOf ("/");
+                       if (p != -1){
+                               //
+                               // Windows does not like /file.cs, switch that to:
+                               // "\", "file.cs"
+                               //
+                               if (p == 0){
+                                       path = "\\";
+                                       pattern = spec.Substring (1);
+                               } else {
+                                       path = spec.Substring (0, p);
+                                       pattern = spec.Substring (p + 1);
+                               }
+                               return;
+                       }
+
+                       p = spec.LastIndexOf ("\\");
+                       if (p != -1){
+                               path = spec.Substring (0, p);
+                               pattern = spec.Substring (p + 1);
+                               return;
+                       }
+
+                       path = ".";
+                       pattern = spec;
+               }
+
+               static void ProcessFile (string f)
+               {
+                       if (first_source == null)
+                               first_source = f;
+
+                       Location.AddFile (f);
+               }
+
+               static void ProcessFiles ()
+               {
+                       Location.Initialize ();
+
+                       foreach (SourceFile file in Location.SourceFiles) {
+                               if (tokenize) {
+                                       tokenize_file (file);
+                               } else {
+                                       parse (file);
+                               }
+                       }
+               }
+
+               static void CompileFiles (string spec, bool recurse)
+               {
+                       string path, pattern;
+
+                       SplitPathAndPattern (spec, out path, out pattern);
+                       if (pattern.IndexOf ("*") == -1){
+                               ProcessFile (spec);
+                               return;
+                       }
+
+                       string [] files = null;
+                       try {
+                               files = Directory.GetFiles (path, pattern);
+                       } catch (System.IO.DirectoryNotFoundException) {
+                               Report.Error (2001, "Source file `" + spec + "' could not be found");
+                               return;
+                       } catch (System.IO.IOException){
+                               Report.Error (2001, "Source file `" + spec + "' could not be found");
+                               return;
+                       }
+                       foreach (string f in files) {
+                               ProcessFile (f);
+                       }
+
+                       if (!recurse)
+                               return;
+                       
+                       string [] dirs = null;
+
+                       try {
+                               dirs = Directory.GetDirectories (path);
+                       } catch {
+                       }
+                       
+                       foreach (string d in dirs) {
+                                       
+                               // Don't include path in this string, as each
+                               // directory entry already does
+                               CompileFiles (d + "/" + pattern, true);
+                       }
+               }
+
+               static void DefineDefaultConfig ()
+               {
+                       //
+                       // For now the "default config" is harcoded into the compiler
+                       // we can move this outside later
+                       //
+                       string [] default_config = {
+                               "System",
+                               "System.Xml",
+#if false
+                               //
+                               // Is it worth pre-loading all this stuff?
+                               //
+                               "Accessibility",
+                               "System.Configuration.Install",
+                               "System.Data",
+                               "System.Design",
+                               "System.DirectoryServices",
+                               "System.Drawing.Design",
+                               "System.Drawing",
+                               "System.EnterpriseServices",
+                               "System.Management",
+                               "System.Messaging",
+                               "System.Runtime.Remoting",
+                               "System.Runtime.Serialization.Formatters.Soap",
+                               "System.Security",
+                               "System.ServiceProcess",
+                               "System.Web",
+                               "System.Web.RegularExpressions",
+                               "System.Web.Services",
+                               "System.Windows.Forms"
+#endif
+                       };
+                       
+                       int p = 0;
+                       foreach (string def in default_config)
+                               soft_references.Insert (p++, def);
+               }
+
+               static void SetOutputFile (string name)
+               {
+                       output_file = name;
+               }
+
+               static void SetWarningLevel (string s)
+               {
+                       int level = 0;
+
+                       try {
+                               level = Int32.Parse (s);
+                       } catch {
+                               Report.Error (
+                                       1900,
+                                       "--wlevel requires an value from 0 to 4");
+                               Environment.Exit (1);
+                       }
+                       if (level < 0 || level > 4){
+                               Report.Error (1900, "Warning level must be 0 to 4");
+                               Environment.Exit (1);
+                       } else
+                               RootContext.WarningLevel = level;
+               }
+
+               static void SetupV2 ()
+               {
+                       RootContext.V2 = true;
+                       defines.Add ("__V2__");
+               }
+               
+               static void Version ()
+               {
+                       string version = Assembly.GetExecutingAssembly ().GetName ().Version.ToString ();
+                       Console.WriteLine ("Mono C# compiler version {0}", version);
+                       Environment.Exit (0);
+               }
+               
+               //
+               // Currently handles the Unix-like command line options, but will be
+               // deprecated in favor of the CSCParseOption, which will also handle the
+               // options that start with a dash in the future.
+               //
+               static bool UnixParseOption (string arg, ref string [] args, ref int i)
+               {
+                       switch (arg){
+                       case "-v":
+                               yacc_verbose = true;
+                               return true;
+
+                       case "--version":
+                               Version ();
+                               return true;
+                               
+                       case "--parse":
+                               parse_only = true;
+                               return true;
+                               
+                       case "--main": case "-m":
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               RootContext.MainClass = args [++i];
+                               return true;
+                               
+                       case "--unsafe":
+                               RootContext.Unsafe = true;
+                               return true;
+                               
+                       case "/?": case "/h": case "/help":
+                       case "--help":
+                               Usage ();
+                               Environment.Exit (0);
+                               return true;
+                               
+                       case "--define":
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               defines.Add (args [++i]);
+                               return true;
+
+                       case "--show-counters":
+                               show_counters = true;
+                               return true;
+                               
+                       case "--expect-error": {
+                               int code = 0;
+                               
+                               try {
+                                       code = Int32.Parse (
+                                               args [++i], NumberStyles.AllowLeadingSign);
+                                       Report.ExpectedError = code;
+                               } catch {
+                                       Report.Error (-14, "Invalid number specified");
+                               } 
+                               return true;
+                       }
+                               
+                       case "--tokenize": 
+                               tokenize = true;
+                               return true;
+                               
+                       case "-o": 
+                       case "--output":
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               SetOutputFile (args [++i]);
+                               return true;
+                               
+                       case "--checked":
+                               RootContext.Checked = true;
+                               return true;
+                               
+                       case "--stacktrace":
+                               Report.Stacktrace = true;
+                               return true;
+                               
+                       case "--linkresource":
+                       case "--linkres":
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Report.Error (5, "Missing argument to --linkres"); 
+                                       Environment.Exit (1);
+                               }
+                               if (resources == null)
+                                       resources = new ArrayList ();
+                               
+                               resources.Add (args [++i]);
+                               return true;
+                               
+                       case "--resource":
+                       case "--res":
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Report.Error (5, "Missing argument to --resource"); 
+                                       Environment.Exit (1);
+                               }
+                               if (embedded_resources == null)
+                                       embedded_resources = new ArrayList ();
+                               
+                               embedded_resources.Add (args [++i]);
+                               return true;
+                               
+                       case "--target":
+                               if ((i + 1) >= args.Length){
+                                       Environment.Exit (1);
+                                       return true;
+                               }
+                               
+                               string type = args [++i];
+                               switch (type){
+                               case "library":
+                                       target = Target.Library;
+                                       target_ext = ".dll";
+                                       break;
+                                       
+                               case "exe":
+                                       target = Target.Exe;
+                                       break;
+                                       
+                               case "winexe":
+                                       target = Target.WinExe;
+                                       break;
+                                       
+                               case "module":
+                                       target = Target.Module;
+                                       target_ext = ".dll";
+                                       break;
+                               default:
+                                       TargetUsage ();
+                                       Environment.Exit (1);
+                                       break;
+                               }
+                               return true;
+                               
+                       case "-r":
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               
+                               references.Add (args [++i]);
+                               return true;
+                               
+                       case "-L":
+                               if ((i + 1) >= args.Length){
+                                       Usage ();       
+                                       Environment.Exit (1);
+                               }
+                               link_paths.Add (args [++i]);
+                               return true;
+                               
+                       case "--nostdlib":
+                               RootContext.StdLib = false;
+                               return true;
+                               
+                       case "--fatal":
+                               Report.Fatal = true;
+                               return true;
+                               
+                       case "--werror":
+                               Report.WarningsAreErrors = true;
+                               return true;
+                               
+                       case "--nowarn":
+                               if ((i + 1) >= args.Length){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               int warn = 0;
+                               
+                               try {
+                                       warn = Int32.Parse (args [++i]);
+                               } catch {
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               Report.SetIgnoreWarning (warn);
+                               return true;
+                               
+                       case "--wlevel":
+                               if ((i + 1) >= args.Length){
+                                       Report.Error (
+                                               1900,
+                                               "--wlevel requires an value from 0 to 4");
+                                       Environment.Exit (1);
+                               }
+
+                               SetWarningLevel (args [++i]);
+                               return true;
+
+                       case "--mcs-debug":
+                               if ((i + 1) >= args.Length){
+                                       Report.Error (5, "--mcs-debug requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               try {
+                                       Report.DebugFlags = Int32.Parse (args [++i]);
+                               } catch {
+                                       Report.Error (5, "Invalid argument to --mcs-debug");
+                                       Environment.Exit (1);
+                               }
+                               return true;
+                               
+                       case "--about":
+                               About ();
+                               return true;
+                               
+                       case "--recurse":
+                               if ((i + 1) >= args.Length){
+                                       Report.Error (5, "--recurse requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               CompileFiles (args [++i], true); 
+                               return true;
+                               
+                       case "--timestamp":
+                               timestamps = true;
+                               last_time = first_time = DateTime.Now;
+                               return true;
+
+                       case "--pause":
+                               pause = true;
+                               return true;
+                               
+                       case "--debug": case "-g":
+                               want_debugging_support = true;
+                               return true;
+                               
+                       case "--noconfig":
+                               load_default_config = false;
+                               return true;
+                       }
+
+                       return false;
+               }
+
+               //
+               // Currently it is very basic option parsing, but eventually, this will
+               // be the complete option parser
+               //
+               static bool CSCParseOption (string option, ref string [] args, ref int i)
+               {
+                       int idx = option.IndexOf (":");
+                       string arg, value;
+
+                       if (idx == -1){
+                               arg = option;
+                               value = "";
+                       } else {
+                               arg = option.Substring (0, idx);
+
+                               value = option.Substring (idx + 1);
+                       }
+
+                       switch (arg){
+                       case "/nologo":
+                               return true;
+
+                       case "/t":
+                       case "/target":
+                               switch (value){
+                               case "exe":
+                                       target = Target.Exe;
+                                       break;
+
+                               case "winexe":
+                                       target = Target.WinExe;
+                                       break;
+
+                               case "library":
+                                       target = Target.Library;
+                                       target_ext = ".dll";
+                                       break;
+
+                               case "module":
+                                       target = Target.Module;
+                                       target_ext = ".netmodule";
+                                       break;
+
+                               default:
+                                       TargetUsage ();
+                                       Environment.Exit (1);
+                                       break;
+                               }
+                               return true;
+
+                       case "/out":
+                               if (value == ""){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+                               SetOutputFile (value);
+                               return true;
+
+                       case "/optimize":
+                       case "/optimize+":
+                       case "/optimize-":
+                       case "/incremental":
+                       case "/incremental+":
+                       case "/incremental-":
+                               // nothing.
+                               return true;
+
+                       case "/d":
+                       case "/define": {
+                               string [] defs;
+
+                               if (value == ""){
+                                       Usage ();
+                                       Environment.Exit (1);
+                               }
+
+                               defs = value.Split (new Char [] {';', ','});
+                               foreach (string d in defs){
+                                       defines.Add (d);
+                               }
+                               return true;
+                       }
+
+                       case "/linkres":
+                       case "/linkresource":
+                               if (value == ""){
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               if (resources == null)
+                                       resources = new ArrayList ();
+                               
+                               resources.Add (value);
+                               return true;
+                               
+                       case "/res":
+                       case "/resource":
+                               if (value == ""){
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               if (embedded_resources == null)
+                                       embedded_resources = new ArrayList ();
+                               
+                               embedded_resources.Add (value);
+                               return true;
+                               
+                       case "/recurse":
+                               if (value == ""){
+                                       Report.Error (5, "/recurse requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               CompileFiles (value, true); 
+                               return true;
+
+                       case "/r":
+                       case "/reference": {
+                               if (value == ""){
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               string [] refs = value.Split (new char [] { ';', ',' });
+                               foreach (string r in refs){
+                                       references.Add (r);
+                               }
+                               return true;
+                       }
+                       case "/doc": {
+                               if (value == ""){
+                                       Report.Error (5, arg + " requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               // TODO handle the /doc argument to generate xml doc
+                               return true;
+                       }
+                       case "/lib": {
+                               string [] libdirs;
+                               
+                               if (value == ""){
+                                       Report.Error (5, "/lib requires an argument");
+                                       Environment.Exit (1);
+                               }
+
+                               libdirs = value.Split (new Char [] { ',' });
+                               foreach (string dir in libdirs)
+                                       link_paths.Add (dir);
+                               return true;
+                       }
+                               
+                       case "/debug":
+                       case "/debug+":
+                               want_debugging_support = true;
+                               return true;
+
+                       case "/checked":
+                       case "/checked+":
+                               RootContext.Checked = true;
+                               return true;
+
+                       case "/checked-":
+                               RootContext.Checked = false;
+                               return true;
+
+                       case "/unsafe":
+                       case "/unsafe+":
+                               RootContext.Unsafe = true;
+                               return true;
+
+                       case "/unsafe-":
+                               RootContext.Unsafe = false;
+                               return true;
+
+                       case "/warnaserror":
+                       case "/warnaserror+":
+                               Report.WarningsAreErrors = true;
+                               return true;
+
+                       case "/warnaserror-":
+                               Report.WarningsAreErrors = false;
+                               return true;
+
+                       case "/warn":
+                               SetWarningLevel (value);
+                               return true;
+
+                       case "/nowarn": {
+                               string [] warns;
+
+                               if (value == ""){
+                                       Report.Error (5, "/nowarn requires an argument");
+                                       Environment.Exit (1);
+                               }
+                               
+                               warns = value.Split (new Char [] {','});
+                               foreach (string wc in warns){
+                                       int warn = 0;
+                                       
+                                       try {
+                                               warn = Int32.Parse (wc);
+                                       } catch {
+                                               Usage ();
+                                               Environment.Exit (1);
+                                       }
+                                       Report.SetIgnoreWarning (warn);
+                               }
+                               return true;
+                       }
+
+                       case "/noconfig-":
+                               load_default_config = true;
+                               return true;
+                               
+                       case "/noconfig":
+                       case "/noconfig+":
+                               load_default_config = false;
+                               return true;
+
+                       case "/help":
+                       case "/?":
+                               Usage ();
+                               Environment.Exit (0);
+                               return true;
+
+                       case "/main":
+                       case "/m":
+                               if (value == ""){
+                                       Report.Error (5, arg + " requires an argument");                                        
+                                       Environment.Exit (1);
+                               }
+                               RootContext.MainClass = value;
+                               return true;
+
+                       case "/nostdlib":
+                       case "/nostdlib+":
+                               RootContext.StdLib = false;
+                               return true;
+
+                       case "/nostdlib-":
+                               RootContext.StdLib = true;
+                               return true;
+
+                       case "/fullpaths":
+                               return true;
+
+                       case "/win32icon":
+                               Report.Error (5, "/win32icon is currently not supported");
+                               return true;
+                               
+                       case "/v2":
+                               SetupV2 ();
+                               return true;
+                               
+                       case "/codepage":
+                               int cp = -1;
+
+                               if (value == "utf8"){
+                                       encoding = new UTF8Encoding();
+                                       using_default_encoder = false;
+                                       return true;
+                               }
+                               if (value == "reset"){
+                                       //
+                                       // 28591 is the code page for ISO-8859-1 encoding.
+                                       //
+                                       cp = 28591;
+                                       using_default_encoder = true;
+                               }
+                               
+                               try {
+                                       cp = Int32.Parse (value);
+                               } catch { }
+                               
+                               if (cp == -1){
+                                       Console.WriteLine ("Invalid code-page requested");
+                                       Usage ();
+                               }
+
+                               try {
+                                       encoding = Encoding.GetEncoding (cp);
+                                       using_default_encoder = false;
+                               } catch {
+                                       Console.WriteLine ("Code page: {0} not supported", cp);
+                               }
+                               return true;
+
+                       }
+                       return false;
+               }
+               
+               /// <summary>
+               ///    Parses the arguments, and drives the compilation
+               ///    process.
+               /// </summary>
+               ///
+               /// <remarks>
+               ///    TODO: Mostly structured to debug the compiler
+               ///    now, needs to be turned into a real driver soon.
+               /// </remarks>
+               // [MonoTODO("Change error code for unknown argument to something reasonable")]
+               static bool MainDriver (string [] args)
+               {
+                       int i;
+                       bool parsing_options = true;
+
+                       try {
+                               encoding = Encoding.GetEncoding (28591);
+                       } catch {
+                               Console.WriteLine ("Error: could not load encoding 28591, trying 1252");
+                               encoding = Encoding.GetEncoding (1252);
+                       }
+                       
+                       references = new ArrayList ();
+                       soft_references = new ArrayList ();
+                       link_paths = new ArrayList ();
+
+                       SetupDefaultDefines ();
+                       
+                       //
+                       // Setup defaults
+                       //
+                       // This is not required because Assembly.Load knows about this
+                       // path.
+                       //
+
+                       int argc = args.Length;
+                       for (i = 0; i < argc; i++){
+                               string arg = args [i];
+
+                               if (arg.StartsWith ("@")){
+                                       string [] new_args, extra_args;
+                                       string response_file = arg.Substring (1);
+
+                                       if (response_file_list == null)
+                                               response_file_list = new Hashtable ();
+                                       
+                                       if (response_file_list.Contains (response_file)){
+                                               Report.Error (
+                                                       1515, "Response file `" + response_file +
+                                                       "' specified multiple times");
+                                               Environment.Exit (1);
+                                       }
+                                       
+                                       response_file_list.Add (response_file, response_file);
+                                                   
+                                       extra_args = LoadArgs (response_file);
+                                       if (extra_args == null){
+                                               Report.Error (2011, "Unable to open response file: " +
+                                                             response_file);
+                                               return false;
+                                       }
+
+                                       new_args = new string [extra_args.Length + argc];
+                                       args.CopyTo (new_args, 0);
+                                       extra_args.CopyTo (new_args, argc);
+                                       args = new_args;
+                                       argc = new_args.Length;
+                                       continue;
+                               }
+
+                               if (parsing_options){
+                                       if (arg == "--"){
+                                               parsing_options = false;
+                                               continue;
+                                       }
+                                       
+                                       if (arg.StartsWith ("-")){
+                                               if (UnixParseOption (arg, ref args, ref i))
+                                                       continue;
+
+                                               // Try a -CSCOPTION
+                                               string csc_opt = "/" + arg.Substring (1);
+                                               if (CSCParseOption (csc_opt, ref args, ref i))
+                                                       continue;
+                                       } else {
+                                               if (arg.StartsWith ("/")){
+                                                       if (CSCParseOption (arg, ref args, ref i))
+                                                               continue;
+                                               }
+                                       }
+                               }
+
+                               CompileFiles (arg, false); 
+                       }
+
+                       ProcessFiles ();
+
+                       if (tokenize)
+                               return true;
+                       
+                       if (first_source == null){
+                               Report.Error (2008, "No files to compile were specified");
+                               return false;
+                       }
+
+                       if (Report.Errors > 0)
+                               return false;
+                       
+                       if (parse_only)
+                               return true;
+                       
+                       //
+                       // Load Core Library for default compilation
+                       //
+                       if (RootContext.StdLib)
+                               references.Insert (0, "mscorlib");
+
+                       if (load_default_config)
+                               DefineDefaultConfig ();
+
+                       if (Report.Errors > 0){
+                               return false;
+                       }
+
+                       //
+                       // Load assemblies required
+                       //
+                       if (timestamps)
+                               ShowTime ("Loading references");
+                       link_paths.Add (GetSystemDir ());
+                       LoadReferences ();
+                       
+                       if (timestamps)
+                               ShowTime ("   References loaded");
+                       
+                       if (Report.Errors > 0){
+                               return false;
+                       }
+
+                       //
+                       // Quick hack
+                       //
+                       if (output_file == null){
+                               int pos = first_source.LastIndexOf (".");
+
+                               if (pos > 0)
+                                       output_file = first_source.Substring (0, pos) + target_ext;
+                               else
+                                       output_file = first_source + target_ext;
+                       }
+
+                       CodeGen.Init (output_file, output_file, want_debugging_support);
+
+                       TypeManager.AddModule (CodeGen.ModuleBuilder);
+
+                       DateTime start = DateTime.Now;
+                       TypeManager.ComputeNamespaces ();
+                       DateTime end = DateTime.Now;
+                       
+                       //
+                       // Before emitting, we need to get the core
+                       // types emitted from the user defined types
+                       // or from the system ones.
+                       //
+                       if (timestamps)
+                               ShowTime ("Initializing Core Types");
+                       if (!RootContext.StdLib){
+                               RootContext.ResolveCore ();
+                               if (Report.Errors > 0)
+                                       return false;
+                       }
+                       
+                       TypeManager.InitCoreTypes ();
+                       if (timestamps)
+                               ShowTime ("   Core Types done");
+
+                       //
+                       // The second pass of the compiler
+                       //
+                       if (timestamps)
+                               ShowTime ("Resolving tree");
+                       RootContext.ResolveTree ();
+                       if (timestamps)
+                               ShowTime ("Populate tree");
+                       if (!RootContext.StdLib)
+                               RootContext.BootCorlib_PopulateCoreTypes ();
+                       RootContext.PopulateTypes ();
+                       RootContext.DefineTypes ();
+                       
+                       TypeManager.InitCodeHelpers ();
+
+                       //
+                       // Verify using aliases now
+                       //
+                       Namespace.VerifyUsing ();
+                       
+                       if (Report.Errors > 0){
+                               return false;
+                       }
+                       
+                       //
+                       // The code generator
+                       //
+                       if (timestamps)
+                               ShowTime ("Emitting code");
+                       ShowTotalTime ("Total so far");
+                       RootContext.EmitCode ();
+                       if (timestamps)
+                               ShowTime ("   done");
+
+                       if (Report.Errors > 0){
+                               return false;
+                       }
+
+                       if (timestamps)
+                               ShowTime ("Closing types");
+
+                       RootContext.CloseTypes ();
+
+                       PEFileKinds k = PEFileKinds.ConsoleApplication;
+                               
+                       if (target == Target.Library || target == Target.Module){
+                               k = PEFileKinds.Dll;
+
+                               if (RootContext.MainClass != null)
+                                       Report.Error (2017, "Can not specify -main: when building module or library");
+                       } else if (target == Target.Exe)
+                               k = PEFileKinds.ConsoleApplication;
+                       else if (target == Target.WinExe)
+                               k = PEFileKinds.WindowApplication;
+
+                       if (target == Target.Exe || target == Target.WinExe){
+                               MethodInfo ep = RootContext.EntryPoint;
+
+                               if (ep == null){
+                                       if (Report.Errors == 0)
+                                               Report.Error (5001, "Program " + output_file +
+                                                             " does not have an entry point defined");
+                                       return false;
+                               }
+                               
+                               CodeGen.AssemblyBuilder.SetEntryPoint (ep, k);
+                       }
+
+                       //
+                       // Add the resources
+                       //
+                       if (resources != null){
+                               foreach (string spec in resources){
+                                       string file, res;
+                                       int cp;
+                                       
+                                       cp = spec.IndexOf (',');
+                                       if (cp != -1){
+                                               file = spec.Substring (0, cp);
+                                               res = spec.Substring (cp + 1);
+                                       } else
+                                               file = res = spec;
+
+                                       CodeGen.AssemblyBuilder.AddResourceFile (res, file);
+                               }
+                       }
+                       
+                       if (embedded_resources != null){
+                               object[] margs = new object [2];
+                               Type[] argst = new Type [2];
+                               argst [0] = argst [1] = typeof (string);
+                               MethodInfo embed_res = typeof (AssemblyBuilder).GetMethod ("EmbedResourceFile", argst);
+                               if (embed_res == null) {
+                                       Report.Warning (0, new Location (-1), "Cannot embed resources on this runtime: try the Mono runtime instead.");
+                               } else {
+                                       foreach (string spec in embedded_resources) {
+                                               int cp;
+
+                                               cp = spec.IndexOf (',');
+                                               if (cp != -1){
+                                                       margs [0] = spec.Substring (cp + 1);
+                                                       margs [1] = spec.Substring (0, cp);
+                                               } else
+                                                       margs [0] = margs [1] = spec;
+
+                                               if (File.Exists ((string) margs [1]))
+                                                       embed_res.Invoke (CodeGen.AssemblyBuilder, margs);
+                                               else {
+                                                       Report.Error (1566, "Can not find the resource " + margs [1]);
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (Report.Errors > 0)
+                               return false;
+                       
+                       CodeGen.Save (output_file);
+                       if (timestamps) {
+                               ShowTime ("Saved output");
+                               ShowTotalTime ("Total");
+                       }
+
+                       Timer.ShowTimers ();
+                       
+                       if (Report.ExpectedError != 0){
+                               Console.WriteLine("Failed to report expected error " + Report.ExpectedError);
+                               Environment.Exit (1);
+                               return false;
+                       }
+
+#if DEBUGME
+                       Console.WriteLine ("Size of strings held: " + DeclSpace.length);
+                       Console.WriteLine ("Size of strings short: " + DeclSpace.small);
+#endif
+                       return (Report.Errors == 0);
+               }
+
+       }
+}
diff --git a/mcs/gmcs/ecore.cs b/mcs/gmcs/ecore.cs
new file mode 100755 (executable)
index 0000000..60f583b
--- /dev/null
@@ -0,0 +1,3105 @@
+//
+// ecore.cs: Core of the Expression representation for the intermediate tree.
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+//
+//
+
+namespace Mono.CSharp {
+       using System;
+       using System.Collections;
+       using System.Diagnostics;
+       using System.Reflection;
+       using System.Reflection.Emit;
+       using System.Text;
+
+       /// <remarks>
+       ///   The ExprClass class contains the is used to pass the 
+       ///   classification of an expression (value, variable, namespace,
+       ///   type, method group, property access, event access, indexer access,
+       ///   nothing).
+       /// </remarks>
+       public enum ExprClass : byte {
+               Invalid,
+               
+               Value,
+               Variable,
+               Namespace,
+               Type,
+               MethodGroup,
+               PropertyAccess,
+               EventAccess,
+               IndexerAccess,
+               Nothing, 
+       }
+
+       /// <remarks>
+       ///   This is used to tell Resolve in which types of expressions we're
+       ///   interested.
+       /// </remarks>
+       [Flags]
+       public enum ResolveFlags {
+               // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
+               VariableOrValue         = 1,
+
+               // Returns a type expression.
+               Type                    = 2,
+
+               // Returns a method group.
+               MethodGroup             = 4,
+
+               // Allows SimpleNames to be returned.
+               // This is used by MemberAccess to construct long names that can not be
+               // partially resolved (namespace-qualified names for example).
+               SimpleName              = 8,
+
+               // Mask of all the expression class flags.
+               MaskExprClass           = 15,
+
+               // Disable control flow analysis while resolving the expression.
+               // This is used when resolving the instance expression of a field expression.
+               DisableFlowAnalysis     = 16
+       }
+
+       //
+       // This is just as a hint to AddressOf of what will be done with the
+       // address.
+       [Flags]
+       public enum AddressOp {
+               Store = 1,
+               Load  = 2,
+               LoadStore = 3
+       };
+       
+       /// <summary>
+       ///   This interface is implemented by variables
+       /// </summary>
+       public interface IMemoryLocation {
+               /// <summary>
+               ///   The AddressOf method should generate code that loads
+               ///   the address of the object and leaves it on the stack.
+               ///
+               ///   The `mode' argument is used to notify the expression
+               ///   of whether this will be used to read from the address or
+               ///   write to the address.
+               ///
+               ///   This is just a hint that can be used to provide good error
+               ///   reporting, and should have no other side effects. 
+               /// </summary>
+               void AddressOf (EmitContext ec, AddressOp mode);
+       }
+
+       /// <summary>
+       ///   This interface is implemented by variables
+       /// </summary>
+       public interface IVariable {
+               VariableInfo VariableInfo {
+                       get;
+               }
+
+               bool VerifyFixed (bool is_expression);
+       }
+
+       /// <summary>
+       ///   This interface denotes an expression which evaluates to a member
+       ///   of a struct or a class.
+       /// </summary>
+       public interface IMemberExpr
+       {
+               /// <summary>
+               ///   The name of this member.
+               /// </summary>
+               string Name {
+                       get;
+               }
+
+               /// <summary>
+               ///   Whether this is an instance member.
+               /// </summary>
+               bool IsInstance {
+                       get;
+               }
+
+               /// <summary>
+               ///   Whether this is a static member.
+               /// </summary>
+               bool IsStatic {
+                       get;
+               }
+
+               /// <summary>
+               ///   The type which declares this member.
+               /// </summary>
+               Type DeclaringType {
+                       get;
+               }
+
+               /// <summary>
+               ///   The instance expression associated with this member, if it's a
+               ///   non-static member.
+               /// </summary>
+               Expression InstanceExpression {
+                       get; set;
+               }
+       }
+
+       /// <remarks>
+       ///   Base class for expressions
+       /// </remarks>
+       public abstract class Expression {
+               public ExprClass eclass;
+               protected Type type;
+               protected Location loc;
+               
+               public Type Type {
+                       get {
+                               return type;
+                       }
+
+                       set {
+                               type = value;
+                       }
+               }
+
+               public Location Location {
+                       get {
+                               return loc;
+                       }
+               }
+
+               /// <summary>
+               ///   Utility wrapper routine for Error, just to beautify the code
+               /// </summary>
+               public void Error (int error, string s)
+               {
+                       if (!Location.IsNull (loc))
+                               Report.Error (error, loc, s);
+                       else
+                               Report.Error (error, s);
+               }
+
+               /// <summary>
+               ///   Utility wrapper routine for Warning, just to beautify the code
+               /// </summary>
+               public void Warning (int warning, string s)
+               {
+                       if (!Location.IsNull (loc))
+                               Report.Warning (warning, loc, s);
+                       else
+                               Report.Warning (warning, s);
+               }
+
+               /// <summary>
+               ///   Utility wrapper routine for Warning, only prints the warning if
+               ///   warnings of level `level' are enabled.
+               /// </summary>
+               public void Warning (int warning, int level, string s)
+               {
+                       if (level <= RootContext.WarningLevel)
+                               Warning (warning, s);
+               }
+
+               /// <summary>
+               ///   Performs semantic analysis on the Expression
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   The Resolve method is invoked to perform the semantic analysis
+               ///   on the node.
+               ///
+               ///   The return value is an expression (it can be the
+               ///   same expression in some cases) or a new
+               ///   expression that better represents this node.
+               ///   
+               ///   For example, optimizations of Unary (LiteralInt)
+               ///   would return a new LiteralInt with a negated
+               ///   value.
+               ///   
+               ///   If there is an error during semantic analysis,
+               ///   then an error should be reported (using Report)
+               ///   and a null value should be returned.
+               ///   
+               ///   There are two side effects expected from calling
+               ///   Resolve(): the the field variable "eclass" should
+               ///   be set to any value of the enumeration
+               ///   `ExprClass' and the type variable should be set
+               ///   to a valid type (this is the type of the
+               ///   expression).
+               /// </remarks>
+               public abstract Expression DoResolve (EmitContext ec);
+
+               public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       return DoResolve (ec);
+               }
+
+               //
+               // This is used if the expression should be resolved as a type.
+               // the default implementation fails.   Use this method in
+               // those participants in the SimpleName chain system.
+               //
+               public virtual Expression ResolveAsTypeStep (EmitContext ec)
+               {
+                       return null;
+               }
+
+               //
+               // This is used to resolve the expression as a type, a null
+               // value will be returned if the expression is not a type
+               // reference
+               //
+               public Expression ResolveAsTypeTerminal (EmitContext ec)
+               {
+                       Expression e = ResolveAsTypeStep (ec);
+
+                       if (e == null)
+                               return null;
+                       if (e is SimpleName)
+                               return null;
+                       return e;
+               }
+              
+               /// <summary>
+               ///   Resolves an expression and performs semantic analysis on it.
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   Currently Resolve wraps DoResolve to perform sanity
+               ///   checking and assertion checking on what we expect from Resolve.
+               /// </remarks>
+               public Expression Resolve (EmitContext ec, ResolveFlags flags)
+               {
+                       if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) 
+                               return ResolveAsTypeStep (ec);
+
+                       bool old_do_flow_analysis = ec.DoFlowAnalysis;
+                       if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
+                               ec.DoFlowAnalysis = false;
+
+                       Expression e;
+                       if (this is SimpleName)
+                               e = ((SimpleName) this).DoResolveAllowStatic (ec);
+                       else 
+                               e = DoResolve (ec);
+
+                       ec.DoFlowAnalysis = old_do_flow_analysis;
+
+                       if (e == null)
+                               return null;
+
+                       if (e is SimpleName){
+                               SimpleName s = (SimpleName) e;
+
+                               if ((flags & ResolveFlags.SimpleName) == 0) {
+                                       MemberLookupFailed (ec, null, ec.ContainerType, s.Name,
+                                                           ec.DeclSpace.Name, loc);
+                                       return null;
+                               }
+
+                               return s;
+                       }
+
+                       if ((e is TypeExpr) || (e is ComposedCast)) {
+                               if ((flags & ResolveFlags.Type) == 0) {
+                                       e.Error_UnexpectedKind (flags);
+                                       return null;
+                               }
+
+                               return e;
+                       }
+
+                       switch (e.eclass) {
+                       case ExprClass.Type:
+                               if ((flags & ResolveFlags.VariableOrValue) == 0) {
+                                       e.Error_UnexpectedKind (flags);
+                                       return null;
+                               }
+                               break;
+
+                       case ExprClass.MethodGroup:
+                               if ((flags & ResolveFlags.MethodGroup) == 0) {
+                                       ((MethodGroupExpr) e).ReportUsageError ();
+                                       return null;
+                               }
+                               break;
+
+                       case ExprClass.Value:
+                       case ExprClass.Variable:
+                       case ExprClass.PropertyAccess:
+                       case ExprClass.EventAccess:
+                       case ExprClass.IndexerAccess:
+                               if ((flags & ResolveFlags.VariableOrValue) == 0) {
+                                       Console.WriteLine ("I got: {0} and {1}", e.GetType (), e);
+                                       Console.WriteLine ("I am {0} and {1}", this.GetType (), this);
+                                       FieldInfo fi = ((FieldExpr) e).FieldInfo;
+                                       
+                                       Console.WriteLine ("{0} and {1}", fi.DeclaringType, fi.Name);
+                                       e.Error_UnexpectedKind (flags);
+                                       return null;
+                               }
+                               break;
+
+                       default:
+                               throw new Exception ("Expression " + e.GetType () +
+                                                    " ExprClass is Invalid after resolve");
+                       }
+
+                       if (e.type == null)
+                               throw new Exception (
+                                       "Expression " + e.GetType () +
+                                       " did not set its type after Resolve\n" +
+                                       "called from: " + this.GetType ());
+
+                       return e;
+               }
+
+               /// <summary>
+               ///   Resolves an expression and performs semantic analysis on it.
+               /// </summary>
+               public Expression Resolve (EmitContext ec)
+               {
+                       return Resolve (ec, ResolveFlags.VariableOrValue);
+               }
+
+               /// <summary>
+               ///   Resolves an expression for LValue assignment
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   Currently ResolveLValue wraps DoResolveLValue to perform sanity
+               ///   checking and assertion checking on what we expect from Resolve
+               /// </remarks>
+               public Expression ResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       Expression e = DoResolveLValue (ec, right_side);
+
+                       if (e != null){
+                               if (e is SimpleName){
+                                       SimpleName s = (SimpleName) e;
+                                       MemberLookupFailed (ec, null, ec.ContainerType, s.Name,
+                                                           ec.DeclSpace.Name, loc);
+                                       return null;
+                               }
+
+                               if (e.eclass == ExprClass.Invalid)
+                                       throw new Exception ("Expression " + e +
+                                                            " ExprClass is Invalid after resolve");
+
+                               if (e.eclass == ExprClass.MethodGroup) {
+                                       ((MethodGroupExpr) e).ReportUsageError ();
+                                       return null;
+                               }
+
+                               if (e.type == null)
+                                       throw new Exception ("Expression " + e +
+                                                            " did not set its type after Resolve");
+                       }
+
+                       return e;
+               }
+               
+               /// <summary>
+               ///   Emits the code for the expression
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   The Emit method is invoked to generate the code
+               ///   for the expression.  
+               /// </remarks>
+               public abstract void Emit (EmitContext ec);
+
+               /// <summary>
+               ///   Protected constructor.  Only derivate types should
+               ///   be able to be created
+               /// </summary>
+
+               protected Expression ()
+               {
+                       eclass = ExprClass.Invalid;
+                       type = null;
+               }
+
+               /// <summary>
+               ///   Returns a literalized version of a literal FieldInfo
+               /// </summary>
+               ///
+               /// <remarks>
+               ///   The possible return values are:
+               ///      IntConstant, UIntConstant
+               ///      LongLiteral, ULongConstant
+               ///      FloatConstant, DoubleConstant
+               ///      StringConstant
+               ///
+               ///   The value returned is already resolved.
+               /// </remarks>
+               public static Constant Constantify (object v, Type t)
+               {
+                       if (t == TypeManager.int32_type)
+                               return new IntConstant ((int) v);
+                       else if (t == TypeManager.uint32_type)
+                               return new UIntConstant ((uint) v);
+                       else if (t == TypeManager.int64_type)
+                               return new LongConstant ((long) v);
+                       else if (t == TypeManager.uint64_type)
+                               return new ULongConstant ((ulong) v);
+                       else if (t == TypeManager.float_type)
+                               return new FloatConstant ((float) v);
+                       else if (t == TypeManager.double_type)
+                               return new DoubleConstant ((double) v);
+                       else if (t == TypeManager.string_type)
+                               return new StringConstant ((string) v);
+                       else if (t == TypeManager.short_type)
+                               return new ShortConstant ((short)v);
+                       else if (t == TypeManager.ushort_type)
+                               return new UShortConstant ((ushort)v);
+                       else if (t == TypeManager.sbyte_type)
+                               return new SByteConstant (((sbyte)v));
+                       else if (t == TypeManager.byte_type)
+                               return new ByteConstant ((byte)v);
+                       else if (t == TypeManager.char_type)
+                               return new CharConstant ((char)v);
+                       else if (t == TypeManager.bool_type)
+                               return new BoolConstant ((bool) v);
+                       else if (TypeManager.IsEnumType (t)){
+                               Constant e = Constantify (v, TypeManager.TypeToCoreType (v.GetType ()));
+
+                               return new EnumConstant (e, t);
+                       } else
+                               throw new Exception ("Unknown type for constant (" + t +
+                                                    "), details: " + v);
+               }
+
+               /// <summary>
+               ///   Returns a fully formed expression after a MemberLookup
+               /// </summary>
+               public static Expression ExprClassFromMemberInfo (EmitContext ec, MemberInfo mi, Location loc)
+               {
+                       if (mi is EventInfo)
+                               return new EventExpr ((EventInfo) mi, loc);
+                       else if (mi is FieldInfo)
+                               return new FieldExpr ((FieldInfo) mi, loc);
+                       else if (mi is PropertyInfo)
+                               return new PropertyExpr (ec, (PropertyInfo) mi, loc);
+                       else if (mi is Type){
+                               return new TypeExpr ((System.Type) mi, loc);
+                       }
+
+                       return null;
+               }
+
+               //
+               // FIXME: Probably implement a cache for (t,name,current_access_set)?
+               //
+               // This code could use some optimizations, but we need to do some
+               // measurements.  For example, we could use a delegate to `flag' when
+               // something can not any longer be a method-group (because it is something
+               // else).
+               //
+               // Return values:
+               //     If the return value is an Array, then it is an array of
+               //     MethodBases
+               //   
+               //     If the return value is an MemberInfo, it is anything, but a Method
+               //
+               //     null on error.
+               //
+               // FIXME: When calling MemberLookup inside an `Invocation', we should pass
+               // the arguments here and have MemberLookup return only the methods that
+               // match the argument count/type, unlike we are doing now (we delay this
+               // decision).
+               //
+               // This is so we can catch correctly attempts to invoke instance methods
+               // from a static body (scan for error 120 in ResolveSimpleName).
+               //
+               //
+               // FIXME: Potential optimization, have a static ArrayList
+               //
+
+               public static Expression MemberLookup (EmitContext ec, Type queried_type, string name,
+                                                      MemberTypes mt, BindingFlags bf, Location loc)
+               {
+                       return MemberLookup (ec, ec.ContainerType, null, queried_type, name, mt, bf, loc);
+               }
+
+               //
+               // Lookup type `queried_type' for code in class `container_type' with a qualifier of
+               // `qualifier_type' or null to lookup members in the current class.
+               //
+
+               public static Expression MemberLookup (EmitContext ec, Type container_type,
+                                                      Type qualifier_type, Type queried_type,
+                                                      string name, MemberTypes mt,
+                                                      BindingFlags bf, Location loc)
+               {
+                       MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
+                                                                    queried_type, mt, bf, name);
+
+                       if (mi == null)
+                               return null;
+
+                       int count = mi.Length;
+
+                       if (mi [0] is MethodBase)
+                               return new MethodGroupExpr (mi, loc);
+
+                       if (count > 1)
+                               return null;
+
+                       return ExprClassFromMemberInfo (ec, mi [0], loc);
+               }
+
+               public const MemberTypes AllMemberTypes =
+                       MemberTypes.Constructor |
+                       MemberTypes.Event       |
+                       MemberTypes.Field       |
+                       MemberTypes.Method      |
+                       MemberTypes.NestedType  |
+                       MemberTypes.Property;
+               
+               public const BindingFlags AllBindingFlags =
+                       BindingFlags.Public |
+                       BindingFlags.Static |
+                       BindingFlags.Instance;
+
+               public static Expression MemberLookup (EmitContext ec, Type queried_type,
+                                                      string name, Location loc)
+               {
+                       return MemberLookup (ec, ec.ContainerType, null, queried_type, name,
+                                            AllMemberTypes, AllBindingFlags, loc);
+               }
+
+               public static Expression MemberLookup (EmitContext ec, Type qualifier_type,
+                                                      Type queried_type, string name, Location loc)
+               {
+                       return MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type,
+                                            name, AllMemberTypes, AllBindingFlags, loc);
+               }
+
+               public static Expression MethodLookup (EmitContext ec, Type queried_type,
+                                                      string name, Location loc)
+               {
+                       return MemberLookup (ec, ec.ContainerType, null, queried_type, name,
+                                            MemberTypes.Method, AllBindingFlags, loc);
+               }
+
+               /// <summary>
+               ///   This is a wrapper for MemberLookup that is not used to "probe", but
+               ///   to find a final definition.  If the final definition is not found, we
+               ///   look for private members and display a useful debugging message if we
+               ///   find it.
+               /// </summary>
+               public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
+                                                           Type queried_type, string name, Location loc)
+               {
+                       return MemberLookupFinal (ec, qualifier_type, queried_type, name,
+                                                 AllMemberTypes, AllBindingFlags, loc);
+               }
+
+               public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
+                                                           Type queried_type, string name,
+                                                           MemberTypes mt, BindingFlags bf,
+                                                           Location loc)
+               {
+                       Expression e;
+
+                       int errors = Report.Errors;
+
+                       e = MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type,
+                                         name, mt, bf, loc);
+
+                       if (e != null)
+                               return e;
+
+                       // Error has already been reported.
+                       if (errors < Report.Errors)
+                               return null;
+
+                       MemberLookupFailed (ec, qualifier_type, queried_type, name, null, loc);
+                       return null;
+               }
+
+               public static void MemberLookupFailed (EmitContext ec, Type qualifier_type,
+                                                      Type queried_type, string name,
+                                                      string class_name, Location loc)
+               {
+                       object lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
+                                                                 AllMemberTypes, AllBindingFlags |
+                                                                 BindingFlags.NonPublic, name);
+
+                       if (lookup == null) {
+                               if (class_name != null)
+                                       Report.Error (103, loc, "The name `" + name + "' could not be " +
+                                                     "found in `" + class_name + "'");
+                               else
+                                       Report.Error (
+                                               117, loc, "`" + queried_type + "' does not contain a " +
+                                               "definition for `" + name + "'");
+                               return;
+                       }
+
+                       if ((qualifier_type != null) && (qualifier_type != ec.ContainerType) &&
+                           ec.ContainerType.IsSubclassOf (qualifier_type)) {
+                               // Although a derived class can access protected members of
+                               // its base class it cannot do so through an instance of the
+                               // base class (CS1540).  If the qualifier_type is a parent of the
+                               // ec.ContainerType and the lookup succeeds with the latter one,
+                               // then we are in this situation.
+
+                               lookup = TypeManager.MemberLookup (
+                                       ec.ContainerType, ec.ContainerType, ec.ContainerType,
+                                       AllMemberTypes, AllBindingFlags, name);
+
+                               if (lookup != null) {
+                                       Report.Error (
+                                               1540, loc, "Cannot access protected member `" +
+                                               TypeManager.CSharpName (qualifier_type) + "." +
+                                               name + "' " + "via a qualifier of type `" +
+                                               TypeManager.CSharpName (qualifier_type) + "'; the " +
+                                               "qualifier must be of type `" +
+                                               TypeManager.CSharpName (ec.ContainerType) + "' " +
+                                               "(or derived from it)");
+                                       return;
+                               }
+                       }
+
+                       if (qualifier_type != null)
+                               Report.Error (
+                                       122, loc, "`" + TypeManager.CSharpName (qualifier_type) + "." +
+                                       name + "' is inaccessible due to its protection level");
+                       else
+                               Report.Error (
+                                       122, loc, "`" + name + "' is inaccessible due to its " +
+                                       "protection level");
+               }
+
+               static public MemberInfo GetFieldFromEvent (EventExpr event_expr)
+               {
+                       EventInfo ei = event_expr.EventInfo;
+
+                       return TypeManager.GetPrivateFieldOfEvent (ei);
+               }
+               
+               /// <summary>
+               ///   Returns an expression that can be used to invoke operator true
+               ///   on the expression if it exists.
+               /// </summary>
+               static public StaticCallExpr GetOperatorTrue (EmitContext ec, Expression e, Location loc)
+               {
+                       return GetOperatorTrueOrFalse (ec, e, true, loc);
+               }
+
+               /// <summary>
+               ///   Returns an expression that can be used to invoke operator false
+               ///   on the expression if it exists.
+               /// </summary>
+               static public StaticCallExpr GetOperatorFalse (EmitContext ec, Expression e, Location loc)
+               {
+                       return GetOperatorTrueOrFalse (ec, e, false, loc);
+               }
+
+               static StaticCallExpr GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
+               {
+                       MethodBase method;
+                       Expression operator_group;
+
+                       operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc);
+                       if (operator_group == null)
+                               return null;
+
+                       ArrayList arguments = new ArrayList ();
+                       arguments.Add (new Argument (e, Argument.AType.Expression));
+                       method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc);
+
+                       if (method == null)
+                               return null;
+
+                       return new StaticCallExpr ((MethodInfo) method, arguments, loc);
+               }
+
+               /// <summary>
+               ///   Resolves the expression `e' into a boolean expression: either through
+               ///   an implicit conversion, or through an `operator true' invocation
+               /// </summary>
+               public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
+               {
+                       e = e.Resolve (ec);
+                       if (e == null)
+                               return null;
+
+                       Expression converted = e;
+                       if (e.Type != TypeManager.bool_type)
+                               converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, new Location (-1));
+
+                       //
+                       // If no implicit conversion to bool exists, try using `operator true'
+                       //
+                       if (converted == null){
+                               Expression operator_true = Expression.GetOperatorTrue (ec, e, loc);
+                               if (operator_true == null){
+                                       Report.Error (
+                                               31, loc, "Can not convert the expression to a boolean");
+                                       return null;
+                               }
+                               e = operator_true;
+                       } else
+                               e = converted;
+
+                       return e;
+               }
+               
+               static string ExprClassName (ExprClass c)
+               {
+                       switch (c){
+                       case ExprClass.Invalid:
+                               return "Invalid";
+                       case ExprClass.Value:
+                               return "value";
+                       case ExprClass.Variable:
+                               return "variable";
+                       case ExprClass.Namespace:
+                               return "namespace";
+                       case ExprClass.Type:
+                               return "type";
+                       case ExprClass.MethodGroup:
+                               return "method group";
+                       case ExprClass.PropertyAccess:
+                               return "property access";
+                       case ExprClass.EventAccess:
+                               return "event access";
+                       case ExprClass.IndexerAccess:
+                               return "indexer access";
+                       case ExprClass.Nothing:
+                               return "null";
+                       }
+                       throw new Exception ("Should not happen");
+               }
+               
+               /// <summary>
+               ///   Reports that we were expecting `expr' to be of class `expected'
+               /// </summary>
+               public void Error_UnexpectedKind (string expected)
+               {
+                       string kind = "Unknown";
+                       
+                       kind = ExprClassName (eclass);
+
+                       Error (118, "Expression denotes a `" + kind +
+                              "' where a `" + expected + "' was expected");
+               }
+
+               public void Error_UnexpectedKind (ResolveFlags flags)
+               {
+                       ArrayList valid = new ArrayList (10);
+
+                       if ((flags & ResolveFlags.VariableOrValue) != 0) {
+                               valid.Add ("variable");
+                               valid.Add ("value");
+                       }
+
+                       if ((flags & ResolveFlags.Type) != 0)
+                               valid.Add ("type");
+
+                       if ((flags & ResolveFlags.MethodGroup) != 0)
+                               valid.Add ("method group");
+
+                       if ((flags & ResolveFlags.SimpleName) != 0)
+                               valid.Add ("simple name");
+
+                       if (valid.Count == 0)
+                               valid.Add ("unknown");
+
+                       StringBuilder sb = new StringBuilder ();
+                       for (int i = 0; i < valid.Count; i++) {
+                               if (i > 0)
+                                       sb.Append (", ");
+                               else if (i == valid.Count)
+                                       sb.Append (" or ");
+                               sb.Append (valid [i]);
+                       }
+
+                       string kind = ExprClassName (eclass);
+
+                       Error (119, "Expression denotes a `" + kind + "' where " +
+                              "a `" + sb.ToString () + "' was expected");
+               }
+               
+               static void Error_ConstantValueCannotBeConverted (Location l, string val, Type t)
+               {
+                       Report.Error (31, l, "Constant value `" + val + "' cannot be converted to " +
+                                     TypeManager.CSharpName (t));
+               }
+
+               public static void UnsafeError (Location loc)
+               {
+                       Report.Error (214, loc, "Pointers may only be used in an unsafe context");
+               }
+               
+               /// <summary>
+               ///   Converts the IntConstant, UIntConstant, LongConstant or
+               ///   ULongConstant into the integral target_type.   Notice
+               ///   that we do not return an `Expression' we do return
+               ///   a boxed integral type.
+               ///
+               ///   FIXME: Since I added the new constants, we need to
+               ///   also support conversions from CharConstant, ByteConstant,
+               ///   SByteConstant, UShortConstant, ShortConstant
+               ///
+               ///   This is used by the switch statement, so the domain
+               ///   of work is restricted to the literals above, and the
+               ///   targets are int32, uint32, char, byte, sbyte, ushort,
+               ///   short, uint64 and int64
+               /// </summary>
+               public static object ConvertIntLiteral (Constant c, Type target_type, Location loc)
+               {
+                       if (!Convert.ImplicitStandardConversionExists (c, target_type)){
+                               Convert.Error_CannotImplicitConversion (loc, c.Type, target_type);
+                               return null;
+                       }
+                       
+                       string s = "";
+
+                       if (c.Type == target_type)
+                               return ((Constant) c).GetValue ();
+
+                       //
+                       // Make into one of the literals we handle, we dont really care
+                       // about this value as we will just return a few limited types
+                       // 
+                       if (c is EnumConstant)
+                               c = ((EnumConstant)c).WidenToCompilerConstant ();
+
+                       if (c is IntConstant){
+                               int v = ((IntConstant) c).Value;
+                               
+                               if (target_type == TypeManager.uint32_type){
+                                       if (v >= 0)
+                                               return (uint) v;
+                               } else if (target_type == TypeManager.char_type){
+                                       if (v >= Char.MinValue && v <= Char.MaxValue)
+                                               return (char) v;
+                               } else if (target_type == TypeManager.byte_type){
+                                       if (v >= Byte.MinValue && v <= Byte.MaxValue)
+                                               return (byte) v;
+                               } else if (target_type == TypeManager.sbyte_type){
+                                       if (v >= SByte.MinValue && v <= SByte.MaxValue)
+                                               return (sbyte) v;
+                               } else if (target_type == TypeManager.short_type){
+                                       if (v >= Int16.MinValue && v <= UInt16.MaxValue)
+                                               return (short) v;
+                               } else if (target_type == TypeManager.ushort_type){
+                                       if (v >= UInt16.MinValue && v <= UInt16.MaxValue)
+                                               return (ushort) v;
+                               } else if (target_type == TypeManager.int64_type)
+                                       return (long) v;
+                               else if (target_type == TypeManager.uint64_type){
+                                       if (v > 0)
+                                               return (ulong) v;
+                               }
+
+                               s = v.ToString ();
+                       } else if (c is UIntConstant){
+                               uint v = ((UIntConstant) c).Value;
+
+                               if (target_type == TypeManager.int32_type){
+                                       if (v <= Int32.MaxValue)
+                                               return (int) v;
+                               } else if (target_type == TypeManager.char_type){
+                                       if (v >= Char.MinValue && v <= Char.MaxValue)
+                                               return (char) v;
+                               } else if (target_type == TypeManager.byte_type){
+                                       if (v <= Byte.MaxValue)
+                                               return (byte) v;
+                               } else if (target_type == TypeManager.sbyte_type){
+                                       if (v <= SByte.MaxValue)
+                                               return (sbyte) v;
+                               } else if (target_type == TypeManager.short_type){
+                                       if (v <= UInt16.MaxValue)
+                                               return (short) v;
+                               } else if (target_type == TypeManager.ushort_type){
+                                       if (v <= UInt16.MaxValue)
+                                               return (ushort) v;
+                               } else if (target_type == TypeManager.int64_type)
+                                       return (long) v;
+                               else if (target_type == TypeManager.uint64_type)
+                                       return (ulong) v;
+                               s = v.ToString ();
+                       } else if (c is LongConstant){ 
+                               long v = ((LongConstant) c).Value;
+
+                               if (target_type == TypeManager.int32_type){
+                                       if (v >= UInt32.MinValue && v <= UInt32.MaxValue)
+                                               return (int) v;
+                               } else if (target_type == TypeManager.uint32_type){
+                                       if (v >= 0 && v <= UInt32.MaxValue)
+                                               return (uint) v;
+                               } else if (target_type == TypeManager.char_type){
+                                       if (v >= Char.MinValue && v <= Char.MaxValue)
+                                               return (char) v;
+                               } else if (target_type == TypeManager.byte_type){
+                                       if (v >= Byte.MinValue && v <= Byte.MaxValue)
+                                               return (byte) v;
+                               } else if (target_type == TypeManager.sbyte_type){
+                                       if (v >= SByte.MinValue && v <= SByte.MaxValue)
+                                               return (sbyte) v;
+                               } else if (target_type == TypeManager.short_type){
+                                       if (v >= Int16.MinValue && v <= UInt16.MaxValue)
+                                               return (short) v;
+                               } else if (target_type == TypeManager.ushort_type){
+                                       if (v >= UInt16.MinValue && v <= UInt16.MaxValue)
+                                               return (ushort) v;
+                               } else if (target_type == TypeManager.uint64_type){
+                                       if (v > 0)
+                                               return (ulong) v;
+                               }
+                               s = v.ToString ();
+                       } else if (c is ULongConstant){
+                               ulong v = ((ULongConstant) c).Value;
+
+                               if (target_type == TypeManager.int32_type){
+                                       if (v <= Int32.MaxValue)
+                                               return (int) v;
+                               } else if (target_type == TypeManager.uint32_type){
+                                       if (v <= UInt32.MaxValue)
+                                               return (uint) v;
+                               } else if (target_type == TypeManager.char_type){
+                                       if (v >= Char.MinValue && v <= Char.MaxValue)
+                                               return (char) v;
+                               } else if (target_type == TypeManager.byte_type){
+                                       if (v >= Byte.MinValue && v <= Byte.MaxValue)
+                                               return (byte) v;
+                               } else if (target_type == TypeManager.sbyte_type){
+                                       if (v <= (int) SByte.MaxValue)
+                                               return (sbyte) v;
+                               } else if (target_type == TypeManager.short_type){
+                                       if (v <= UInt16.MaxValue)
+                                               return (short) v;
+                               } else if (target_type == TypeManager.ushort_type){
+                                       if (v <= UInt16.MaxValue)
+                                               return (ushort) v;
+                               } else if (target_type == TypeManager.int64_type){
+                                       if (v <= Int64.MaxValue)
+                                               return (long) v;
+                               }
+                               s = v.ToString ();
+                       } else if (c is ByteConstant){
+                               byte v = ((ByteConstant) c).Value;
+                               
+                               if (target_type == TypeManager.int32_type)
+                                       return (int) v;
+                               else if (target_type == TypeManager.uint32_type)
+                                       return (uint) v;
+                               else if (target_type == TypeManager.char_type)
+                                       return (char) v;
+                               else if (target_type == TypeManager.sbyte_type){
+                                       if (v <= SByte.MaxValue)
+                                               return (sbyte) v;
+                               } else if (target_type == TypeManager.short_type)
+                                       return (short) v;
+                               else if (target_type == TypeManager.ushort_type)
+                                       return (ushort) v;
+                               else if (target_type == TypeManager.int64_type)
+                                       return (long) v;
+                               else if (target_type == TypeManager.uint64_type)
+                                       return (ulong) v;
+                               s = v.ToString ();
+                       } else if (c is SByteConstant){
+                               sbyte v = ((SByteConstant) c).Value;
+                               
+                               if (target_type == TypeManager.int32_type)
+                                       return (int) v;
+                               else if (target_type == TypeManager.uint32_type){
+                                       if (v >= 0)
+                                               return (uint) v;
+                               } else if (target_type == TypeManager.char_type){
+                                       if (v >= 0)
+                                               return (char) v;
+                               } else if (target_type == TypeManager.byte_type){
+                                       if (v >= 0)
+                                               return (byte) v;
+                               } else if (target_type == TypeManager.short_type)
+                                       return (short) v;
+                               else if (target_type == TypeManager.ushort_type){
+                                       if (v >= 0)
+                                               return (ushort) v;
+                               } else if (target_type == TypeManager.int64_type)
+                                       return (long) v;
+                               else if (target_type == TypeManager.uint64_type){
+                                       if (v >= 0)
+                                               return (ulong) v;
+                               }
+                               s = v.ToString ();
+                       } else if (c is ShortConstant){
+                               short v = ((ShortConstant) c).Value;
+                               
+                               if (target_type == TypeManager.int32_type){
+                                       return (int) v;
+                               } else if (target_type == TypeManager.uint32_type){
+                                       if (v >= 0)
+                                               return (uint) v;
+                               } else if (target_type == TypeManager.char_type){
+                                       if (v >= 0)
+                                               return (char) v;
+                               } else if (target_type == TypeManager.byte_type){
+                                       if (v >= Byte.MinValue && v <= Byte.MaxValue)
+                                               return (byte) v;
+                               } else if (target_type == TypeManager.sbyte_type){
+                                       if (v >= SByte.MinValue && v <= SByte.MaxValue)
+                                               return (sbyte) v;
+                               } else if (target_type == TypeManager.ushort_type){
+                                       if (v >= 0)
+                                               return (ushort) v;
+                               } else if (target_type == TypeManager.int64_type)
+                                       return (long) v;
+                               else if (target_type == TypeManager.uint64_type)
+                                       return (ulong) v;
+
+                               s = v.ToString ();
+                       } else if (c is UShortConstant){
+                               ushort v = ((UShortConstant) c).Value;
+                               
+                               if (target_type == TypeManager.int32_type)
+                                       return (int) v;
+                               else if (target_type == TypeManager.uint32_type)
+                                       return (uint) v;
+                               else if (target_type == TypeManager.char_type){
+                                       if (v >= Char.MinValue && v <= Char.MaxValue)
+                                               return (char) v;
+                               } else if (target_type == TypeManager.byte_type){
+                                       if (v >= Byte.MinValue && v <= Byte.MaxValue)
+                                               return (byte) v;
+                               } else if (target_type == TypeManager.sbyte_type){
+                                       if (v <= SByte.MaxValue)
+                                               return (byte) v;
+                               } else if (target_type == TypeManager.short_type){
+                                       if (v <= Int16.MaxValue)
+                                               return (short) v;
+                               } else if (target_type == TypeManager.int64_type)
+                                       return (long) v;
+                               else if (target_type == TypeManager.uint64_type)
+                                       return (ulong) v;
+
+                               s = v.ToString ();
+                       } else if (c is CharConstant){
+                               char v = ((CharConstant) c).Value;
+                               
+                               if (target_type == TypeManager.int32_type)
+                                       return (int) v;
+                               else if (target_type == TypeManager.uint32_type)
+                                       return (uint) v;
+                               else if (target_type == TypeManager.byte_type){
+                                       if (v >= Byte.MinValue && v <= Byte.MaxValue)
+                                               return (byte) v;
+                               } else if (target_type == TypeManager.sbyte_type){
+                                       if (v <= SByte.MaxValue)
+                                               return (sbyte) v;
+                               } else if (target_type == TypeManager.short_type){
+                                       if (v <= Int16.MaxValue)
+                                               return (short) v;
+                               } else if (target_type == TypeManager.ushort_type)
+                                       return (short) v;
+                               else if (target_type == TypeManager.int64_type)
+                                       return (long) v;
+                               else if (target_type == TypeManager.uint64_type)
+                                       return (ulong) v;
+
+                               s = v.ToString ();
+                       }
+                       Error_ConstantValueCannotBeConverted (loc, s, target_type);
+                       return null;
+               }
+
+               //
+               // Load the object from the pointer.  
+               //
+               public static void LoadFromPtr (ILGenerator ig, Type t)
+               {
+                       if (t == TypeManager.int32_type)
+                               ig.Emit (OpCodes.Ldind_I4);
+                       else if (t == TypeManager.uint32_type)
+                               ig.Emit (OpCodes.Ldind_U4);
+                       else if (t == TypeManager.short_type)
+                               ig.Emit (OpCodes.Ldind_I2);
+                       else if (t == TypeManager.ushort_type)
+                               ig.Emit (OpCodes.Ldind_U2);
+                       else if (t == TypeManager.char_type)
+                               ig.Emit (OpCodes.Ldind_U2);
+                       else if (t == TypeManager.byte_type)
+                               ig.Emit (OpCodes.Ldind_U1);
+                       else if (t == TypeManager.sbyte_type)
+                               ig.Emit (OpCodes.Ldind_I1);
+                       else if (t == TypeManager.uint64_type)
+                               ig.Emit (OpCodes.Ldind_I8);
+                       else if (t == TypeManager.int64_type)
+                               ig.Emit (OpCodes.Ldind_I8);
+                       else if (t == TypeManager.float_type)
+                               ig.Emit (OpCodes.Ldind_R4);
+                       else if (t == TypeManager.double_type)
+                               ig.Emit (OpCodes.Ldind_R8);
+                       else if (t == TypeManager.bool_type)
+                               ig.Emit (OpCodes.Ldind_I1);
+                       else if (t == TypeManager.intptr_type)
+                               ig.Emit (OpCodes.Ldind_I);
+                       else if (TypeManager.IsEnumType (t)) {
+                               if (t == TypeManager.enum_type)
+                                       ig.Emit (OpCodes.Ldind_Ref);
+                               else
+                                       LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
+                       } else if (t.IsValueType)
+                               ig.Emit (OpCodes.Ldobj, t);
+                       else if (t.IsPointer)
+                               ig.Emit (OpCodes.Ldind_I);
+                       else 
+                               ig.Emit (OpCodes.Ldind_Ref);
+               }
+
+               //
+               // The stack contains the pointer and the value of type `type'
+               //
+               public static void StoreFromPtr (ILGenerator ig, Type type)
+               {
+                       if (TypeManager.IsEnumType (type))
+                               type = TypeManager.EnumToUnderlying (type);
+                       if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
+                               ig.Emit (OpCodes.Stind_I4);
+                       else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
+                               ig.Emit (OpCodes.Stind_I8);
+                       else if (type == TypeManager.char_type || type == TypeManager.short_type ||
+                                type == TypeManager.ushort_type)
+                               ig.Emit (OpCodes.Stind_I2);
+                       else if (type == TypeManager.float_type)
+                               ig.Emit (OpCodes.Stind_R4);
+                       else if (type == TypeManager.double_type)
+                               ig.Emit (OpCodes.Stind_R8);
+                       else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
+                                type == TypeManager.bool_type)
+                               ig.Emit (OpCodes.Stind_I1);
+                       else if (type == TypeManager.intptr_type)
+                               ig.Emit (OpCodes.Stind_I);
+                       else if (type.IsValueType)
+                               ig.Emit (OpCodes.Stobj, type);
+                       else
+                               ig.Emit (OpCodes.Stind_Ref);
+               }
+               
+               //
+               // Returns the size of type `t' if known, otherwise, 0
+               //
+               public static int GetTypeSize (Type t)
+               {
+                       t = TypeManager.TypeToCoreType (t);
+                       if (t == TypeManager.int32_type ||
+                           t == TypeManager.uint32_type ||
+                           t == TypeManager.float_type)
+                               return 4;
+                       else if (t == TypeManager.int64_type ||
+                                t == TypeManager.uint64_type ||
+                                t == TypeManager.double_type)
+                               return 8;
+                       else if (t == TypeManager.byte_type ||
+                                t == TypeManager.sbyte_type ||
+                                t == TypeManager.bool_type)    
+                               return 1;
+                       else if (t == TypeManager.short_type ||
+                                t == TypeManager.char_type ||
+                                t == TypeManager.ushort_type)
+                               return 2;
+                       else if (t == TypeManager.decimal_type)
+                               return 16;
+                       else
+                               return 0;
+               }
+
+               //
+               // Default implementation of IAssignMethod.CacheTemporaries
+               //
+               public void CacheTemporaries (EmitContext ec)
+               {
+               }
+
+               static void Error_NegativeArrayIndex (Location loc)
+               {
+                       Report.Error (284, loc, "Can not create array with a negative size");
+               }
+               
+               //
+               // Converts `source' to an int, uint, long or ulong.
+               //
+               public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
+               {
+                       Expression target;
+                       
+                       bool old_checked = ec.CheckState;
+                       ec.CheckState = true;
+                       
+                       target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
+                       if (target == null){
+                               target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
+                               if (target == null){
+                                       target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
+                                       if (target == null){
+                                               target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
+                                               if (target == null)
+                                                       Convert.Error_CannotImplicitConversion (loc, source.Type, TypeManager.int32_type);
+                                       }
+                               }
+                       } 
+                       ec.CheckState = old_checked;
+
+                       //
+                       // Only positive constants are allowed at compile time
+                       //
+                       if (target is Constant){
+                               if (target is IntConstant){
+                                       if (((IntConstant) target).Value < 0){
+                                               Error_NegativeArrayIndex (loc);
+                                               return null;
+                                       }
+                               }
+
+                               if (target is LongConstant){
+                                       if (((LongConstant) target).Value < 0){
+                                               Error_NegativeArrayIndex (loc);
+                                               return null;
+                                       }
+                               }
+                               
+                       }
+
+                       return target;
+               }
+               
+       }
+
+       /// <summary>
+       ///   This is just a base class for expressions that can
+       ///   appear on statements (invocations, object creation,
+       ///   assignments, post/pre increment and decrement).  The idea
+       ///   being that they would support an extra Emition interface that
+       ///   does not leave a result on the stack.
+       /// </summary>
+       public abstract class ExpressionStatement : Expression {
+
+               public virtual ExpressionStatement ResolveStatement (EmitContext ec)
+               {
+                       Expression e = Resolve (ec);
+                       if (e == null)
+                               return null;
+
+                       ExpressionStatement es = e as ExpressionStatement;
+                       if (es == null)
+                               Error (201, "Only assignment, call, increment, decrement and new object " +
+                                      "expressions can be used as a statement");
+
+                       return es;
+               }
+
+               /// <summary>
+               ///   Requests the expression to be emitted in a `statement'
+               ///   context.  This means that no new value is left on the
+               ///   stack after invoking this method (constrasted with
+               ///   Emit that will always leave a value on the stack).
+               /// </summary>
+               public abstract void EmitStatement (EmitContext ec);
+       }
+
+       /// <summary>
+       ///   This kind of cast is used to encapsulate the child
+       ///   whose type is child.Type into an expression that is
+       ///   reported to return "return_type".  This is used to encapsulate
+       ///   expressions which have compatible types, but need to be dealt
+       ///   at higher levels with.
+       ///
+       ///   For example, a "byte" expression could be encapsulated in one
+       ///   of these as an "unsigned int".  The type for the expression
+       ///   would be "unsigned int".
+       ///
+       /// </summary>
+       public class EmptyCast : Expression {
+               protected Expression child;
+               
+               public EmptyCast (Expression child, Type return_type)
+               {
+                       eclass = child.eclass;
+                       type = return_type;
+                       this.child = child;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       child.Emit (ec);
+               }
+       }
+
+        //
+       // We need to special case this since an empty cast of
+       // a NullLiteral is still a Constant
+       //
+       public class NullCast : Constant {
+               protected Expression child;
+                               
+               public NullCast (Expression child, Type return_type)
+               {
+                       eclass = child.eclass;
+                       type = return_type;
+                       this.child = child;
+               }
+
+               override public string AsString ()
+               {
+                       return "null";
+               }
+
+               public override object GetValue ()
+               {
+                       return null;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       child.Emit (ec);
+               }
+       }
+
+
+       /// <summary>
+       ///  This class is used to wrap literals which belong inside Enums
+       /// </summary>
+       public class EnumConstant : Constant {
+               public Constant Child;
+
+               public EnumConstant (Constant child, Type enum_type)
+               {
+                       eclass = child.eclass;
+                       this.Child = child;
+                       type = enum_type;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Child.Emit (ec);
+               }
+
+               public override object GetValue ()
+               {
+                       return Child.GetValue ();
+               }
+
+               //
+               // Converts from one of the valid underlying types for an enumeration
+               // (int32, uint32, int64, uint64, short, ushort, byte, sbyte) to
+               // one of the internal compiler literals: Int/UInt/Long/ULong Literals.
+               //
+               public Constant WidenToCompilerConstant ()
+               {
+                       Type t = TypeManager.EnumToUnderlying (Child.Type);
+                       object v = ((Constant) Child).GetValue ();;
+                       
+                       if (t == TypeManager.int32_type)
+                               return new IntConstant ((int) v);
+                       if (t == TypeManager.uint32_type)
+                               return new UIntConstant ((uint) v);
+                       if (t == TypeManager.int64_type)
+                               return new LongConstant ((long) v);
+                       if (t == TypeManager.uint64_type)
+                               return new ULongConstant ((ulong) v);
+                       if (t == TypeManager.short_type)
+                               return new ShortConstant ((short) v);
+                       if (t == TypeManager.ushort_type)
+                               return new UShortConstant ((ushort) v);
+                       if (t == TypeManager.byte_type)
+                               return new ByteConstant ((byte) v);
+                       if (t == TypeManager.sbyte_type)
+                               return new SByteConstant ((sbyte) v);
+
+                       throw new Exception ("Invalid enumeration underlying type: " + t);
+               }
+
+               //
+               // Extracts the value in the enumeration on its native representation
+               //
+               public object GetPlainValue ()
+               {
+                       Type t = TypeManager.EnumToUnderlying (Child.Type);
+                       object v = ((Constant) Child).GetValue ();;
+                       
+                       if (t == TypeManager.int32_type)
+                               return (int) v;
+                       if (t == TypeManager.uint32_type)
+                               return (uint) v;
+                       if (t == TypeManager.int64_type)
+                               return (long) v;
+                       if (t == TypeManager.uint64_type)
+                               return (ulong) v;
+                       if (t == TypeManager.short_type)
+                               return (short) v;
+                       if (t == TypeManager.ushort_type)
+                               return (ushort) v;
+                       if (t == TypeManager.byte_type)
+                               return (byte) v;
+                       if (t == TypeManager.sbyte_type)
+                               return (sbyte) v;
+
+                       return null;
+               }
+               
+               public override string AsString ()
+               {
+                       return Child.AsString ();
+               }
+
+               public override DoubleConstant ConvertToDouble ()
+               {
+                       return Child.ConvertToDouble ();
+               }
+
+               public override FloatConstant ConvertToFloat ()
+               {
+                       return Child.ConvertToFloat ();
+               }
+
+               public override ULongConstant ConvertToULong ()
+               {
+                       return Child.ConvertToULong ();
+               }
+
+               public override LongConstant ConvertToLong ()
+               {
+                       return Child.ConvertToLong ();
+               }
+
+               public override UIntConstant ConvertToUInt ()
+               {
+                       return Child.ConvertToUInt ();
+               }
+
+               public override IntConstant ConvertToInt ()
+               {
+                       return Child.ConvertToInt ();
+               }
+       }
+
+       /// <summary>
+       ///   This kind of cast is used to encapsulate Value Types in objects.
+       ///
+       ///   The effect of it is to box the value type emitted by the previous
+       ///   operation.
+       /// </summary>
+       public class BoxedCast : EmptyCast {
+
+               public BoxedCast (Expression expr)
+                       : base (expr, TypeManager.object_type) 
+               {
+               }
+
+               public BoxedCast (Expression expr, Type target_type)
+                       : base (expr, target_type)
+               {
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+                       
+                       ec.ig.Emit (OpCodes.Box, child.Type);
+               }
+       }
+
+       public class UnboxCast : EmptyCast {
+               public UnboxCast (Expression expr, Type return_type)
+                       : base (expr, return_type)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Type t = type;
+                       ILGenerator ig = ec.ig;
+                       
+                       base.Emit (ec);
+                       ig.Emit (OpCodes.Unbox, t);
+
+                       LoadFromPtr (ig, t);
+               }
+       }
+       
+       /// <summary>
+       ///   This is used to perform explicit numeric conversions.
+       ///
+       ///   Explicit numeric conversions might trigger exceptions in a checked
+       ///   context, so they should generate the conv.ovf opcodes instead of
+       ///   conv opcodes.
+       /// </summary>
+       public class ConvCast : EmptyCast {
+               public enum Mode : byte {
+                       I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
+                       U1_I1, U1_CH,
+                       I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
+                       U2_I1, U2_U1, U2_I2, U2_CH,
+                       I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
+                       U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
+                       I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
+                       U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
+                       CH_I1, CH_U1, CH_I2,
+                       R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
+                       R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
+               }
+
+               Mode mode;
+               bool checked_state;
+               
+               public ConvCast (EmitContext ec, Expression child, Type return_type, Mode m)
+                       : base (child, return_type)
+               {
+                       checked_state = ec.CheckState;
+                       mode = m;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("ConvCast ({0}, {1})", mode, child);
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       base.Emit (ec);
+
+                       if (checked_state){
+                               switch (mode){
+                               case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+
+                               case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
+                               case Mode.U1_CH: /* nothing */ break;
+
+                               case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
+                               case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+
+                               case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
+                               case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
+                               case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
+                               case Mode.U2_CH: /* nothing */ break;
+
+                               case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
+                               case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
+                               case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+
+                               case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
+                               case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
+                               case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
+                               case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
+                               case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
+                               case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
+
+                               case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
+                               case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
+                               case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
+                               case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+
+                               case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
+                               case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
+                               case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
+                               case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
+                               case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
+                               case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
+                               case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
+                               case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
+
+                               case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
+                               case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
+                               case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
+
+                               case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
+                               case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
+                               case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
+                               case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
+                               case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+
+                               case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
+                               case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
+                               case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
+                               case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
+                               case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
+                               case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
+                               case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
+                               case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
+                               case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
+                               }
+                       } else {
+                               switch (mode){
+                               case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
+                               case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
+                               case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.U2_CH: /* nothing */ break;
+
+                               case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.I4_U4: /* nothing */ break;
+                               case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
+                               case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.U4_I4: /* nothing */ break;
+                               case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
+                               case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.I8_U8: /* nothing */ break;
+                               case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
+                               case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.U8_I8: /* nothing */ break;
+                               case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
+
+                               case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
+                               case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
+                               case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
+                               case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
+
+                               case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
+                               case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
+                               case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
+                               case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
+                               case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
+                               case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
+                               case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
+                               case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
+                               case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
+                               }
+                       }
+               }
+       }
+       
+       public class OpcodeCast : EmptyCast {
+               OpCode op, op2;
+               bool second_valid;
+               
+               public OpcodeCast (Expression child, Type return_type, OpCode op)
+                       : base (child, return_type)
+                       
+               {
+                       this.op = op;
+                       second_valid = false;
+               }
+
+               public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
+                       : base (child, return_type)
+                       
+               {
+                       this.op = op;
+                       this.op2 = op2;
+                       second_valid = true;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+                       ec.ig.Emit (op);
+
+                       if (second_valid)
+                               ec.ig.Emit (op2);
+               }                       
+       }
+
+       /// <summary>
+       ///   This kind of cast is used to encapsulate a child and cast it
+       ///   to the class requested
+       /// </summary>
+       public class ClassCast : EmptyCast {
+               public ClassCast (Expression child, Type return_type)
+                       : base (child, return_type)
+                       
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+
+                       ec.ig.Emit (OpCodes.Castclass, type);
+               }                       
+               
+       }
+       
+       /// <summary>
+       ///   SimpleName expressions are initially formed of a single
+       ///   word and it only happens at the beginning of the expression.
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   The expression will try to be bound to a Field, a Method
+       ///   group or a Property.  If those fail we pass the name to our
+       ///   caller and the SimpleName is compounded to perform a type
+       ///   lookup.  The idea behind this process is that we want to avoid
+       ///   creating a namespace map from the assemblies, as that requires
+       ///   the GetExportedTypes function to be called and a hashtable to
+       ///   be constructed which reduces startup time.  If later we find
+       ///   that this is slower, we should create a `NamespaceExpr' expression
+       ///   that fully participates in the resolution process. 
+       ///   
+       ///   For example `System.Console.WriteLine' is decomposed into
+       ///   MemberAccess (MemberAccess (SimpleName ("System"), "Console"), "WriteLine")
+       ///   
+       ///   The first SimpleName wont produce a match on its own, so it will
+       ///   be turned into:
+       ///   MemberAccess (SimpleName ("System.Console"), "WriteLine").
+       ///   
+       ///   System.Console will produce a TypeExpr match.
+       ///   
+       ///   The downside of this is that we might be hitting `LookupType' too many
+       ///   times with this scheme.
+       /// </remarks>
+       public class SimpleName : Expression {
+               public string Name;
+
+               //
+               // If true, then we are a simple name, not composed with a ".
+               //
+               bool is_base;
+
+               public SimpleName (string a, string b, Location l)
+               {
+                       Name = String.Concat (a, ".", b);
+                       loc = l;
+                       is_base = false;
+               }
+               
+               public SimpleName (string name, Location l)
+               {
+                       Name = name;
+                       loc = l;
+                       is_base = true;
+               }
+
+               public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
+               {
+                       if (ec.IsFieldInitializer)
+                               Report.Error (
+                                       236, l,
+                                       "A field initializer cannot reference the non-static field, " +
+                                       "method or property `"+name+"'");
+                       else
+                               Report.Error (
+                                       120, l,
+                                       "An object reference is required " +
+                                       "for the non-static field `"+name+"'");
+               }
+               
+               //
+               // Checks whether we are trying to access an instance
+               // property, method or field from a static body.
+               //
+               Expression MemberStaticCheck (EmitContext ec, Expression e)
+               {
+                       if (e is IMemberExpr){
+                               IMemberExpr member = (IMemberExpr) e;
+                               
+                               if (!member.IsStatic){
+                                       Error_ObjectRefRequired (ec, loc, Name);
+                                       return null;
+                               }
+                       }
+
+                       return e;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return SimpleNameResolve (ec, null, false);
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       return SimpleNameResolve (ec, right_side, false);
+               }
+               
+
+               public Expression DoResolveAllowStatic (EmitContext ec)
+               {
+                       return SimpleNameResolve (ec, null, true);
+               }
+
+               public override Expression ResolveAsTypeStep (EmitContext ec)
+               {
+                       DeclSpace ds = ec.DeclSpace;
+                       NamespaceEntry ns = ds.Namespace;
+                       Type t;
+                       string alias_value;
+
+                       //
+                       // Since we are cheating: we only do the Alias lookup for
+                       // namespaces if the name does not include any dots in it
+                       //
+                       if (ns != null && is_base)
+                               alias_value = ns.LookupAlias (Name);
+                       else
+                               alias_value = null;
+
+                       if (ec.ResolvingTypeTree){
+                               if (alias_value != null){
+                                       if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
+                                               return new TypeExpr (t, loc);
+                               }
+
+                               int errors = Report.Errors;
+                               Type dt = ec.DeclSpace.FindType (loc, Name);
+                               
+                               if (Report.Errors != errors)
+                                       return null;
+                               
+                               if (dt != null)
+                                       return new TypeExpr (dt, loc);
+                       }
+
+                       //
+                       // First, the using aliases
+                       //
+                       if (alias_value != null){
+                               if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
+                                       return new TypeExpr (t, loc);
+                               
+                               // we have alias value, but it isn't Type, so try if it's namespace
+                               return new SimpleName (alias_value, loc);
+                       }
+                       
+                       //
+                       // Stage 2: Lookup up if we are an alias to a type
+                       // or a namespace.
+                       //
+
+                       if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
+                               return new TypeExpr (t, loc);
+                               
+                       // No match, maybe our parent can compose us
+                       // into something meaningful.
+                       return this;
+               }
+
+               /// <remarks>
+               ///   7.5.2: Simple Names. 
+               ///
+               ///   Local Variables and Parameters are handled at
+               ///   parse time, so they never occur as SimpleNames.
+               ///
+               ///   The `allow_static' flag is used by MemberAccess only
+               ///   and it is used to inform us that it is ok for us to 
+               ///   avoid the static check, because MemberAccess might end
+               ///   up resolving the Name as a Type name and the access as
+               ///   a static type access.
+               ///
+               ///   ie: Type Type; .... { Type.GetType (""); }
+               ///
+               ///   Type is both an instance variable and a Type;  Type.GetType
+               ///   is the static method not an instance method of type.
+               /// </remarks>
+               Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool allow_static)
+               {
+                       Expression e = null;
+
+                       //
+                       // Since we are cheating (is_base is our hint
+                       // that we are the beginning of the name): we
+                       // only do the Alias lookup for namespaces if
+                       // the name does not include any dots in it
+                       //
+                       NamespaceEntry ns = ec.DeclSpace.Namespace;
+                       if (is_base && ns != null){
+                               string alias_value = ns.LookupAlias (Name);
+                               if (alias_value != null){
+                                       Name = alias_value;
+                                       Type t;
+
+                                       if ((t = TypeManager.LookupType (Name)) != null)
+                                               return new TypeExpr (t, loc);
+                                       
+                                       // No match, maybe our parent can compose us
+                                       // into something meaningful.
+                                       return this;
+                               }
+                       }
+                       
+                       
+                       //
+                       // Stage 1: Performed by the parser (binding to locals or parameters).
+                       //
+                       Block current_block = ec.CurrentBlock;
+                       if (current_block != null){
+                               LocalInfo vi = current_block.GetLocalInfo (Name);
+                               if (vi != null){
+                                       Expression var;
+                                       
+                                       var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
+                                       
+                                       if (right_side != null)
+                                               return var.ResolveLValue (ec, right_side);
+                                       else
+                                               return var.Resolve (ec);
+                               }
+
+                               int idx = -1;
+                               Parameter par = null;
+                               Parameters pars = current_block.Parameters;
+                               if (pars != null)
+                                       par = pars.GetParameterByName (Name, out idx);
+
+                               if (par != null) {
+                                       ParameterReference param;
+                                       
+                                       param = new ParameterReference (pars, current_block, idx, Name, loc);
+
+                                       if (right_side != null)
+                                               return param.ResolveLValue (ec, right_side);
+                                       else
+                                               return param.Resolve (ec);
+                               }
+                       }
+                       
+                       //
+                       // Stage 2: Lookup members 
+                       //
+
+                       DeclSpace lookup_ds = ec.DeclSpace;
+                       do {
+                               if (lookup_ds.TypeBuilder == null)
+                                       break;
+
+                               e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
+                               if (e != null)
+                                       break;
+
+                               lookup_ds =lookup_ds.Parent;
+                       } while (lookup_ds != null);
+                               
+                       if (e == null && ec.ContainerType != null)
+                               e = MemberLookup (ec, ec.ContainerType, Name, loc);
+
+                       if (e == null)
+                               return ResolveAsTypeStep (ec);
+
+                       if (e is TypeExpr)
+                               return e;
+
+                       if (e is IMemberExpr) {
+                               e = MemberAccess.ResolveMemberAccess (ec, e, null, loc, this);
+                               if (e == null)
+                                       return null;
+
+                               IMemberExpr me = e as IMemberExpr;
+                               if (me == null)
+                                       return e;
+
+                               // This fails if ResolveMemberAccess() was unable to decide whether
+                               // it's a field or a type of the same name.
+                               if (!me.IsStatic && (me.InstanceExpression == null))
+                                       return e;
+
+                               if (!me.IsStatic &&
+                                   TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType) &&
+                                   !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType)) {
+                                       Error (38, "Cannot access nonstatic member `" + me.Name + "' of " +
+                                              "outer type `" + me.DeclaringType + "' via nested type `" +
+                                              me.InstanceExpression.Type + "'");
+                                       return null;
+                               }
+
+                               if (right_side != null)
+                                       e = e.DoResolveLValue (ec, right_side);
+                               else
+                                       e = e.DoResolve (ec);
+
+                               return e;                               
+                       }
+
+                       if (ec.IsStatic || ec.IsFieldInitializer){
+                               if (allow_static)
+                                       return e;
+
+                               return MemberStaticCheck (ec, e);
+                       } else
+                               return e;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       //
+                       // If this is ever reached, then we failed to
+                       // find the name as a namespace
+                       //
+
+                       Error (103, "The name `" + Name +
+                              "' does not exist in the class `" +
+                              ec.DeclSpace.Name + "'");
+               }
+
+               public override string ToString ()
+               {
+                       return Name;
+               }
+       }
+       
+       /// <summary>
+       ///   Fully resolved expression that evaluates to a type
+       /// </summary>
+       public class TypeExpr : Expression {
+               public TypeExpr (Type t, Location l)
+               {
+                       Type = t;
+                       eclass = ExprClass.Type;
+                       loc = l;
+               }
+
+               public override Expression ResolveAsTypeStep (EmitContext ec)
+               {
+                       return this;
+               }
+
+               override public Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               override public void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should never be called");
+               }
+
+               public override string ToString ()
+               {
+                       return Type.ToString ();
+               }
+       }
+
+       /// <summary>
+       ///   Used to create types from a fully qualified name.  These are just used
+       ///   by the parser to setup the core types.  A TypeLookupExpression is always
+       ///   classified as a type.
+       /// </summary>
+       public class TypeLookupExpression : TypeExpr {
+               string name;
+               
+               public TypeLookupExpression (string name) : base (null, Location.Null)
+               {
+                       this.name = name;
+               }
+
+               public override Expression ResolveAsTypeStep (EmitContext ec)
+               {
+                       if (type == null)
+                               type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null);
+                       return this;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return ResolveAsTypeStep (ec);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should never be called");
+               }
+
+               public override string ToString ()
+               {
+                       return name;
+               }
+       }
+
+       /// <summary>
+       ///   MethodGroup Expression.
+       ///  
+       ///   This is a fully resolved expression that evaluates to a type
+       /// </summary>
+       public class MethodGroupExpr : Expression, IMemberExpr {
+               public MethodBase [] Methods;
+               Expression instance_expression = null;
+               bool is_explicit_impl = false;
+               
+               public MethodGroupExpr (MemberInfo [] mi, Location l)
+               {
+                       Methods = new MethodBase [mi.Length];
+                       mi.CopyTo (Methods, 0);
+                       eclass = ExprClass.MethodGroup;
+                       type = TypeManager.object_type;
+                       loc = l;
+               }
+
+               public MethodGroupExpr (ArrayList list, Location l)
+               {
+                       Methods = new MethodBase [list.Count];
+
+                       try {
+                               list.CopyTo (Methods, 0);
+                       } catch {
+                               foreach (MemberInfo m in list){
+                                       if (!(m is MethodBase)){
+                                               Console.WriteLine ("Name " + m.Name);
+                                               Console.WriteLine ("Found a: " + m.GetType ().FullName);
+                                       }
+                               }
+                               throw;
+                       }
+
+                       loc = l;
+                       eclass = ExprClass.MethodGroup;
+                       type = TypeManager.object_type;
+               }
+
+               public Type DeclaringType {
+                       get {
+                                //
+                                // We assume that the top-level type is in the end
+                                //
+                               return Methods [Methods.Length - 1].DeclaringType;
+                                //return Methods [0].DeclaringType;
+                       }
+               }
+               
+               //
+               // `A method group may have associated an instance expression' 
+               // 
+               public Expression InstanceExpression {
+                       get {
+                               return instance_expression;
+                       }
+
+                       set {
+                               instance_expression = value;
+                       }
+               }
+
+               public bool IsExplicitImpl {
+                       get {
+                               return is_explicit_impl;
+                       }
+
+                       set {
+                               is_explicit_impl = value;
+                       }
+               }
+
+               public string Name {
+                       get {
+                               //return Methods [0].Name;
+                                return Methods [Methods.Length - 1].Name;
+                       }
+               }
+
+               public bool IsInstance {
+                       get {
+                               foreach (MethodBase mb in Methods)
+                                       if (!mb.IsStatic)
+                                               return true;
+
+                               return false;
+                       }
+               }
+
+               public bool IsStatic {
+                       get {
+                               foreach (MethodBase mb in Methods)
+                                       if (mb.IsStatic)
+                                               return true;
+
+                               return false;
+                       }
+               }
+               
+               override public Expression DoResolve (EmitContext ec)
+               {
+                       if (!IsInstance)
+                               instance_expression = null;
+
+                       if (instance_expression != null) {
+                               instance_expression = instance_expression.DoResolve (ec);
+                               if (instance_expression == null)
+                                       return null;
+                       }
+
+                       return this;
+               }
+
+               public void ReportUsageError ()
+               {
+                       Report.Error (654, loc, "Method `" + DeclaringType + "." +
+                                     Name + "()' is referenced without parentheses");
+               }
+
+               override public void Emit (EmitContext ec)
+               {
+                       ReportUsageError ();
+               }
+
+               bool RemoveMethods (bool keep_static)
+               {
+                       ArrayList smethods = new ArrayList ();
+
+                       foreach (MethodBase mb in Methods){
+                               if (mb.IsStatic == keep_static)
+                                       smethods.Add (mb);
+                       }
+
+                       if (smethods.Count == 0)
+                               return false;
+
+                       Methods = new MethodBase [smethods.Count];
+                       smethods.CopyTo (Methods, 0);
+
+                       return true;
+               }
+               
+               /// <summary>
+               ///   Removes any instance methods from the MethodGroup, returns
+               ///   false if the resulting set is empty.
+               /// </summary>
+               public bool RemoveInstanceMethods ()
+               {
+                       return RemoveMethods (true);
+               }
+
+               /// <summary>
+               ///   Removes any static methods from the MethodGroup, returns
+               ///   false if the resulting set is empty.
+               /// </summary>
+               public bool RemoveStaticMethods ()
+               {
+                       return RemoveMethods (false);
+               }
+       }
+
+       /// <summary>
+       ///   Fully resolved expression that evaluates to a Field
+       /// </summary>
+       public class FieldExpr : Expression, IAssignMethod, IMemoryLocation, IMemberExpr, IVariable {
+               public readonly FieldInfo FieldInfo;
+               Expression instance_expr;
+               VariableInfo variable_info;
+               
+               public FieldExpr (FieldInfo fi, Location l)
+               {
+                       FieldInfo = fi;
+                       eclass = ExprClass.Variable;
+                       type = fi.FieldType;
+                       loc = l;
+               }
+
+               public string Name {
+                       get {
+                               return FieldInfo.Name;
+                       }
+               }
+
+               public bool IsInstance {
+                       get {
+                               return !FieldInfo.IsStatic;
+                       }
+               }
+
+               public bool IsStatic {
+                       get {
+                               return FieldInfo.IsStatic;
+                       }
+               }
+
+               public Type DeclaringType {
+                       get {
+                               return FieldInfo.DeclaringType;
+                       }
+               }
+
+               public Expression InstanceExpression {
+                       get {
+                               return instance_expr;
+                       }
+
+                       set {
+                               instance_expr = value;
+                       }
+               }
+
+               public VariableInfo VariableInfo {
+                       get {
+                               return variable_info;
+                       }
+               }
+
+               override public Expression DoResolve (EmitContext ec)
+               {
+                       if (!FieldInfo.IsStatic){
+                               if (instance_expr == null){
+                                       //
+                                       // This can happen when referencing an instance field using
+                                       // a fully qualified type expression: TypeName.InstanceField = xxx
+                                       // 
+                                       SimpleName.Error_ObjectRefRequired (ec, loc, FieldInfo.Name);
+                                       return null;
+                               }
+
+                               // Resolve the field's instance expression while flow analysis is turned
+                               // off: when accessing a field "a.b", we must check whether the field
+                               // "a.b" is initialized, not whether the whole struct "a" is initialized.
+                               instance_expr = instance_expr.Resolve (ec, ResolveFlags.VariableOrValue |
+                                                                      ResolveFlags.DisableFlowAnalysis);
+                               if (instance_expr == null)
+                                       return null;
+                       }
+
+                       // If the instance expression is a local variable or parameter.
+                       IVariable var = instance_expr as IVariable;
+                       if ((var == null) || (var.VariableInfo == null))
+                               return this;
+
+                       VariableInfo vi = var.VariableInfo;
+                       if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
+                               return null;
+
+                       variable_info = vi.GetSubStruct (FieldInfo.Name);
+                       return this;
+               }
+
+               void Report_AssignToReadonly (bool is_instance)
+               {
+                       string msg;
+                       
+                       if (is_instance)
+                               msg = "Readonly field can not be assigned outside " +
+                               "of constructor or variable initializer";
+                       else
+                               msg = "A static readonly field can only be assigned in " +
+                               "a static constructor";
+
+                       Report.Error (is_instance ? 191 : 198, loc, msg);
+               }
+               
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       IVariable var = instance_expr as IVariable;
+                       if ((var != null) && (var.VariableInfo != null))
+                               var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
+
+                       Expression e = DoResolve (ec);
+
+                       if (e == null)
+                               return null;
+
+                       if (!FieldInfo.IsStatic && (instance_expr.Type.IsValueType && !(instance_expr is IMemoryLocation))) {
+                               // FIXME: Provide better error reporting.
+                               Error (1612, "Cannot modify expression because it is not a variable.");
+                               return null;
+                       }
+
+                       if (!FieldInfo.IsInitOnly)
+                               return this;
+
+                       //
+                       // InitOnly fields can only be assigned in constructors
+                       //
+
+                       if (ec.IsConstructor){
+                               if (ec.ContainerType == FieldInfo.DeclaringType)
+                                       return this;
+                       }
+
+                       Report_AssignToReadonly (true);
+                       
+                       return null;
+               }
+
+               public bool VerifyFixed (bool is_expression)
+               {
+                       IVariable variable = instance_expr as IVariable;
+                       if ((variable == null) || !variable.VerifyFixed (true))
+                               return false;
+
+                       return true;
+               }
+
+               override public void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       bool is_volatile = false;
+
+                       if (FieldInfo is FieldBuilder){
+                               FieldBase f = TypeManager.GetField (FieldInfo);
+
+                               if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+                                       is_volatile = true;
+                               
+                               f.status |= Field.Status.USED;
+                       } 
+                       
+                       if (FieldInfo.IsStatic){
+                               if (is_volatile)
+                                       ig.Emit (OpCodes.Volatile);
+                               
+                               ig.Emit (OpCodes.Ldsfld, FieldInfo);
+                               return;
+                       }
+                       
+                       if (instance_expr.Type.IsValueType){
+                               IMemoryLocation ml;
+                               LocalTemporary tempo = null;
+                               
+                               if (!(instance_expr is IMemoryLocation)){
+                                       tempo = new LocalTemporary (ec, instance_expr.Type);
+                                       
+                                       if (ec.RemapToProxy)
+                                               ec.EmitThis ();
+                       
+                                       InstanceExpression.Emit (ec);
+                                       tempo.Store (ec);
+                                       ml = tempo;
+                               } else
+                                       ml = (IMemoryLocation) instance_expr;
+                               
+                               ml.AddressOf (ec, AddressOp.Load);
+                       } else {
+                               if (ec.RemapToProxy)
+                                       ec.EmitThis ();
+                               else
+                                       instance_expr.Emit (ec);
+                       }
+                       if (is_volatile)
+                               ig.Emit (OpCodes.Volatile);
+                       
+                       ig.Emit (OpCodes.Ldfld, FieldInfo);
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       FieldAttributes fa = FieldInfo.Attributes;
+                       bool is_static = (fa & FieldAttributes.Static) != 0;
+                       bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
+                       ILGenerator ig = ec.ig;
+
+                       if (is_readonly && !ec.IsConstructor){
+                               Report_AssignToReadonly (!is_static);
+                               return;
+                       }
+                       
+                       if (!is_static){
+                               Expression instance = instance_expr;
+
+                               if (instance.Type.IsValueType){
+                                       IMemoryLocation ml = (IMemoryLocation) instance;
+
+                                       ml.AddressOf (ec, AddressOp.Store);
+                               } else {
+                                       if (ec.RemapToProxy)
+                                               ec.EmitThis ();
+                                       else
+                                               instance.Emit (ec);
+                               }
+                       }
+
+                       source.Emit (ec);
+
+                       if (FieldInfo is FieldBuilder){
+                               FieldBase f = TypeManager.GetField (FieldInfo);
+                               
+                               if ((f.ModFlags & Modifiers.VOLATILE) != 0)
+                                       ig.Emit (OpCodes.Volatile);
+                               
+                               f.status |= Field.Status.ASSIGNED;
+                       } 
+
+                       if (is_static)
+                               ig.Emit (OpCodes.Stsfld, FieldInfo);
+                       else 
+                               ig.Emit (OpCodes.Stfld, FieldInfo);
+               }
+               
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       if (FieldInfo is FieldBuilder){
+                               FieldBase f = TypeManager.GetField (FieldInfo);
+                               if ((f.ModFlags & Modifiers.VOLATILE) != 0){
+                                       Error (676, "volatile variable: can not take its address, or pass as ref/out parameter");
+                                       return;
+                               }
+                               
+                               if ((mode & AddressOp.Store) != 0)
+                                       f.status |= Field.Status.ASSIGNED;
+                               if ((mode & AddressOp.Load) != 0)
+                                       f.status |= Field.Status.USED;
+                       } 
+
+                       //
+                       // Handle initonly fields specially: make a copy and then
+                       // get the address of the copy.
+                       //
+                       if (FieldInfo.IsInitOnly && !ec.IsConstructor){
+                               LocalBuilder local;
+                               
+                               Emit (ec);
+                               local = ig.DeclareLocal (type);
+                               ig.Emit (OpCodes.Stloc, local);
+                               ig.Emit (OpCodes.Ldloca, local);
+                               return;
+                       }
+
+                       if (FieldInfo.IsStatic)
+                               ig.Emit (OpCodes.Ldsflda, FieldInfo);
+                       else {
+                               //
+                               // In the case of `This', we call the AddressOf method, which will
+                               // only load the pointer, and not perform an Ldobj immediately after
+                               // the value has been loaded into the stack.
+                               //
+                               if (instance_expr is This)
+                                       ((This)instance_expr).AddressOf (ec, AddressOp.LoadStore);
+                               else if (instance_expr.Type.IsValueType && instance_expr is IMemoryLocation){
+                                       IMemoryLocation ml = (IMemoryLocation) instance_expr;
+
+                                       ml.AddressOf (ec, AddressOp.LoadStore);
+                               } else
+                                       instance_expr.Emit (ec);
+                               ig.Emit (OpCodes.Ldflda, FieldInfo);
+                       }
+               }
+       }
+
+       /// <summary>
+       ///   Expression that evaluates to a Property.  The Assign class
+       ///   might set the `Value' expression if we are in an assignment.
+       ///
+       ///   This is not an LValue because we need to re-write the expression, we
+       ///   can not take data from the stack and store it.  
+       /// </summary>
+       public class PropertyExpr : ExpressionStatement, IAssignMethod, IMemberExpr {
+               public readonly PropertyInfo PropertyInfo;
+
+               //
+               // This is set externally by the  `BaseAccess' class
+               //
+               public bool IsBase;
+               MethodInfo getter, setter;
+               bool is_static;
+               bool must_do_cs1540_check;
+               
+               Expression instance_expr;
+
+               public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
+               {
+                       PropertyInfo = pi;
+                       eclass = ExprClass.PropertyAccess;
+                       is_static = false;
+                       loc = l;
+
+                       type = TypeManager.TypeToCoreType (pi.PropertyType);
+
+                       ResolveAccessors (ec);
+               }
+
+               public string Name {
+                       get {
+                               return PropertyInfo.Name;
+                       }
+               }
+
+               public bool IsInstance {
+                       get {
+                               return !is_static;
+                       }
+               }
+
+               public bool IsStatic {
+                       get {
+                               return is_static;
+                       }
+               }
+               
+               public Type DeclaringType {
+                       get {
+                               return PropertyInfo.DeclaringType;
+                       }
+               }
+
+               //
+               // The instance expression associated with this expression
+               //
+               public Expression InstanceExpression {
+                       set {
+                               instance_expr = value;
+                       }
+
+                       get {
+                               return instance_expr;
+                       }
+               }
+
+               public bool VerifyAssignable ()
+               {
+                       if (setter == null) {
+                               Report.Error (200, loc, 
+                                             "The property `" + PropertyInfo.Name +
+                                             "' can not be assigned to, as it has not set accessor");
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               MethodInfo GetAccessor (Type invocation_type, string accessor_name)
+               {
+                       BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
+                               BindingFlags.Static | BindingFlags.Instance;
+                       MemberInfo[] group;
+
+                       group = TypeManager.MemberLookup (
+                               invocation_type, invocation_type, PropertyInfo.DeclaringType,
+                               MemberTypes.Method, flags, accessor_name + "_" + PropertyInfo.Name);
+
+                       //
+                       // The first method is the closest to us
+                       //
+                       if (group == null)
+                               return null;
+
+                       foreach (MethodInfo mi in group) {
+                               MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
+
+                               //
+                               // If only accessible to the current class or children
+                               //
+                               if (ma == MethodAttributes.Private) {
+                                       Type declaring_type = mi.DeclaringType;
+                                       
+                                       if (invocation_type != declaring_type){
+                                               if (TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
+                                                       return mi;
+                                               else
+                                                       continue;
+                                       } else
+                                               return mi;
+                               }
+                               //
+                               // FamAndAssem requires that we not only derivate, but we are on the
+                               // same assembly.  
+                               //
+                               if (ma == MethodAttributes.FamANDAssem){
+                                       if (mi.DeclaringType.Assembly != invocation_type.Assembly)
+                                               continue;
+                                       else
+                                               return mi;
+                               }
+
+                               // Assembly and FamORAssem succeed if we're in the same assembly.
+                               if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
+                                       if (mi.DeclaringType.Assembly != invocation_type.Assembly)
+                                               continue;
+                                       else
+                                               return mi;
+                               }
+
+                               // We already know that we aren't in the same assembly.
+                               if (ma == MethodAttributes.Assembly)
+                                       continue;
+
+                               // Family and FamANDAssem require that we derive.
+                               if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
+                                       if (!TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType))
+                                               continue;
+                                       else {
+                                               must_do_cs1540_check = true;
+
+                                               return mi;
+                                       }
+                               }
+
+                               return mi;
+                       }
+
+                       return null;
+               }
+
+               //
+               // We also perform the permission checking here, as the PropertyInfo does not
+               // hold the information for the accessibility of its setter/getter
+               //
+               void ResolveAccessors (EmitContext ec)
+               {
+                       getter = GetAccessor (ec.ContainerType, "get");
+                       if ((getter != null) && getter.IsStatic)
+                               is_static = true;
+
+                       setter = GetAccessor (ec.ContainerType, "set");
+                       if ((setter != null) && setter.IsStatic)
+                               is_static = true;
+
+                       if (setter == null && getter == null){
+                               Error (122, "`" + PropertyInfo.Name + "' " +
+                                      "is inaccessible because of its protection level");
+                               
+                       }
+               }
+
+               bool InstanceResolve (EmitContext ec)
+               {
+                       if ((instance_expr == null) && ec.IsStatic && !is_static) {
+                               SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
+                               return false;
+                       }
+
+                       if (instance_expr != null) {
+                               instance_expr = instance_expr.DoResolve (ec);
+                               if (instance_expr == null)
+                                       return false;
+                       }
+
+                       if (must_do_cs1540_check && (instance_expr != null)) {
+                               if ((instance_expr.Type != ec.ContainerType) &&
+                                   ec.ContainerType.IsSubclassOf (instance_expr.Type)) {
+                                       Report.Error (1540, loc, "Cannot access protected member `" +
+                                                     PropertyInfo.DeclaringType + "." + PropertyInfo.Name + 
+                                                     "' via a qualifier of type `" +
+                                                     TypeManager.CSharpName (instance_expr.Type) +
+                                                     "'; the qualifier must be of type `" +
+                                                     TypeManager.CSharpName (ec.ContainerType) +
+                                                     "' (or derived from it)");
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+               
+               override public Expression DoResolve (EmitContext ec)
+               {
+                       if (getter == null){
+                               //
+                               // The following condition happens if the PropertyExpr was
+                               // created, but is invalid (ie, the property is inaccessible),
+                               // and we did not want to embed the knowledge about this in
+                               // the caller routine.  This only avoids double error reporting.
+                               //
+                               if (setter == null)
+                                       return null;
+                               
+                               Report.Error (154, loc, 
+                                             "The property `" + PropertyInfo.Name +
+                                             "' can not be used in " +
+                                             "this context because it lacks a get accessor");
+                               return null;
+                       } 
+
+                       if (!InstanceResolve (ec))
+                               return null;
+
+                       //
+                       // Only base will allow this invocation to happen.
+                       //
+                       if (IsBase && getter.IsAbstract){
+                               Report.Error (205, loc, "Cannot call an abstract base property: " +
+                                             PropertyInfo.DeclaringType + "." +PropertyInfo.Name);
+                               return null;
+                       }
+
+                       return this;
+               }
+
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       if (setter == null){
+                               //
+                               // The following condition happens if the PropertyExpr was
+                               // created, but is invalid (ie, the property is inaccessible),
+                               // and we did not want to embed the knowledge about this in
+                               // the caller routine.  This only avoids double error reporting.
+                               //
+                               if (getter == null)
+                                       return null;
+                               
+                               Report.Error (154, loc, 
+                                             "The property `" + PropertyInfo.Name +
+                                             "' can not be used in " +
+                                             "this context because it lacks a set accessor");
+                               return null;
+                       }
+
+                       if (!InstanceResolve (ec))
+                               return null;
+                       
+                       //
+                       // Only base will allow this invocation to happen.
+                       //
+                       if (IsBase && setter.IsAbstract){
+                               Report.Error (205, loc, "Cannot call an abstract base property: " +
+                                             PropertyInfo.DeclaringType + "." +PropertyInfo.Name);
+                               return null;
+                       }
+                       return this;
+               }
+
+               override public void Emit (EmitContext ec)
+               {
+                       //
+                       // Special case: length of single dimension array property is turned into ldlen
+                       //
+                       if ((getter == TypeManager.system_int_array_get_length) ||
+                           (getter == TypeManager.int_array_get_length)){
+                               Type iet = instance_expr.Type;
+
+                               //
+                               // System.Array.Length can be called, but the Type does not
+                               // support invoking GetArrayRank, so test for that case first
+                               //
+                               if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){
+                                       instance_expr.Emit (ec);
+                                       ec.ig.Emit (OpCodes.Ldlen);
+                                       return;
+                               }
+                       }
+
+                       Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, getter, null, loc);
+                       
+               }
+
+               //
+               // Implements the IAssignMethod interface for assignments
+               //
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       Argument arg = new Argument (source, Argument.AType.Expression);
+                       ArrayList args = new ArrayList ();
+
+                       args.Add (arg);
+                       Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, setter, args, loc);
+               }
+
+               override public void EmitStatement (EmitContext ec)
+               {
+                       Emit (ec);
+                       ec.ig.Emit (OpCodes.Pop);
+               }
+       }
+
+       /// <summary>
+       ///   Fully resolved expression that evaluates to an Event
+       /// </summary>
+       public class EventExpr : Expression, IMemberExpr {
+               public readonly EventInfo EventInfo;
+               public Expression instance_expr;
+
+               bool is_static;
+               MethodInfo add_accessor, remove_accessor;
+               
+               public EventExpr (EventInfo ei, Location loc)
+               {
+                       EventInfo = ei;
+                       this.loc = loc;
+                       eclass = ExprClass.EventAccess;
+
+                       add_accessor = TypeManager.GetAddMethod (ei);
+                       remove_accessor = TypeManager.GetRemoveMethod (ei);
+                       
+                       if (add_accessor.IsStatic || remove_accessor.IsStatic)
+                               is_static = true;
+
+                       if (EventInfo is MyEventBuilder){
+                               MyEventBuilder eb = (MyEventBuilder) EventInfo;
+                               type = eb.EventType;
+                               eb.SetUsed ();
+                       } else
+                               type = EventInfo.EventHandlerType;
+               }
+
+               public string Name {
+                       get {
+                               return EventInfo.Name;
+                       }
+               }
+
+               public bool IsInstance {
+                       get {
+                               return !is_static;
+                       }
+               }
+
+               public bool IsStatic {
+                       get {
+                               return is_static;
+                       }
+               }
+
+               public Type DeclaringType {
+                       get {
+                               return EventInfo.DeclaringType;
+                       }
+               }
+
+               public Expression InstanceExpression {
+                       get {
+                               return instance_expr;
+                       }
+
+                       set {
+                               instance_expr = value;
+                       }
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (instance_expr != null) {
+                               instance_expr = instance_expr.DoResolve (ec);
+                               if (instance_expr == null)
+                                       return null;
+                       }
+
+                       
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Report.Error (70, loc, "The event `" + Name + "' can only appear on the left hand side of += or -= (except on the defining type)");
+               }
+
+               public void EmitAddOrRemove (EmitContext ec, Expression source)
+               {
+                       Expression handler = ((Binary) source).Right;
+                       
+                       Argument arg = new Argument (handler, Argument.AType.Expression);
+                       ArrayList args = new ArrayList ();
+                               
+                       args.Add (arg);
+                       
+                       if (((Binary) source).Oper == Binary.Operator.Addition)
+                               Invocation.EmitCall (
+                                       ec, false, IsStatic, instance_expr, add_accessor, args, loc);
+                       else
+                               Invocation.EmitCall (
+                                       ec, false, IsStatic, instance_expr, remove_accessor, args, loc);
+               }
+       }
+}      
diff --git a/mcs/gmcs/enum.cs b/mcs/gmcs/enum.cs
new file mode 100755 (executable)
index 0000000..c6f613b
--- /dev/null
@@ -0,0 +1,654 @@
+//
+// enum.cs: Enum handling.
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//         Ravi Pratap     (ravi@ximian.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///   Enumeration container
+       /// </summary>
+       public class Enum : DeclSpace {
+               ArrayList ordered_enums;
+               
+               public Expression BaseType;
+               public Attributes  OptAttributes;
+               
+               public Type UnderlyingType;
+
+               Hashtable member_to_location;
+               Hashtable member_to_attributes;
+
+               //
+               // This is for members that have been defined
+               //
+               Hashtable member_to_value;
+
+               //
+               // This is used to mark members we're currently defining
+               //
+               Hashtable in_transit;
+               
+               ArrayList field_builders;
+               
+               public const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE;
+
+               public Enum (TypeContainer parent, Expression type, int mod_flags, string name, Attributes attrs, Location l)
+                       : base (parent, name, l)
+               {
+                       this.BaseType = type;
+                       ModFlags = Modifiers.Check (AllowedModifiers, mod_flags,
+                                                   IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE, l);
+                       OptAttributes = attrs;
+
+                       ordered_enums = new ArrayList ();
+                       member_to_location = new Hashtable ();
+                       member_to_value = new Hashtable ();
+                       in_transit = new Hashtable ();
+                       field_builders = new ArrayList ();
+               }
+
+               /// <summary>
+               ///   Adds @name to the enumeration space, with @expr
+               ///   being its definition.  
+               /// </summary>
+               public AdditionResult AddEnumMember (string name, Expression expr, Location loc,
+                                                    Attributes opt_attrs)
+               {
+                       if (defined_names.Contains (name))
+                               return AdditionResult.NameExists;
+
+                       if (name == "value__") {
+                               Report.Error (76, loc, "An item in an enumeration can't have an identifier `value__'");
+                               return AdditionResult.Error;
+                       }
+
+                       DefineName (name, expr);
+
+                       ordered_enums.Add (name);
+                       member_to_location.Add (name, loc);
+
+                       if (member_to_attributes == null)
+                               member_to_attributes = new Hashtable ();
+
+                       member_to_attributes.Add (name, opt_attrs);
+                       
+                       return AdditionResult.Success;
+               }
+
+               //
+               // This is used by corlib compilation: we map from our
+               // type to a type that is consumable by the DefineField
+               //
+               Type MapToInternalType (Type t)
+               {
+                       if (t == TypeManager.int32_type)
+                               return typeof (int);
+                       if (t == TypeManager.int64_type)
+                               return typeof (long);
+                       if (t == TypeManager.uint32_type)
+                               return typeof (uint);
+                       if (t == TypeManager.uint64_type)
+                               return typeof (ulong);
+                       if (t == TypeManager.float_type)
+                               return typeof (float);
+                       if (t == TypeManager.double_type)
+                               return typeof (double);
+                       if (t == TypeManager.byte_type)
+                               return typeof (byte);
+                       if (t == TypeManager.sbyte_type)
+                               return typeof (sbyte);
+                       if (t == TypeManager.char_type)
+                               return typeof (char);
+                       if (t == TypeManager.short_type)
+                               return typeof (short);
+                       if (t == TypeManager.ushort_type)
+                               return typeof (ushort);
+
+                       throw new Exception ();
+               }
+               
+               public override TypeBuilder DefineType ()
+               {
+                       if (TypeBuilder != null)
+                               return TypeBuilder;
+
+                       TypeAttributes attr = Modifiers.TypeAttr (ModFlags, IsTopLevel);
+
+                       attr |= TypeAttributes.Class | TypeAttributes.Sealed;
+
+                       UnderlyingType = ResolveType (BaseType, false, Location);
+
+                       if (UnderlyingType != TypeManager.int32_type &&
+                           UnderlyingType != TypeManager.uint32_type &&
+                           UnderlyingType != TypeManager.int64_type &&
+                           UnderlyingType != TypeManager.uint64_type &&
+                           UnderlyingType != TypeManager.short_type &&
+                           UnderlyingType != TypeManager.ushort_type &&
+                           UnderlyingType != TypeManager.byte_type  &&
+                           UnderlyingType != TypeManager.char_type  &&
+                           UnderlyingType != TypeManager.sbyte_type) {
+                               Report.Error (1008, Location,
+                                             "Type byte, sbyte, short, char, ushort, int, uint, " +
+                                             "long, or ulong expected (got: " +
+                                             TypeManager.CSharpName (UnderlyingType) + ")");
+                               return null;
+                       }
+
+                       if (IsTopLevel) {
+                               if (TypeManager.NamespaceClash (Name, Location))
+                                       return null;
+                               
+                               ModuleBuilder builder = CodeGen.ModuleBuilder;
+
+                               TypeBuilder = builder.DefineType (Name, attr, TypeManager.enum_type);
+                       } else {
+                               TypeBuilder builder = Parent.TypeBuilder;
+
+                               TypeBuilder = builder.DefineNestedType (
+                                       Basename, attr, TypeManager.enum_type);
+                       }
+
+                       //
+                       // Call MapToInternalType for corlib
+                       //
+                       TypeBuilder.DefineField ("value__", UnderlyingType,
+                                                FieldAttributes.Public | FieldAttributes.SpecialName
+                                                | FieldAttributes.RTSpecialName);
+
+                       TypeManager.AddEnumType (Name, TypeBuilder, this);
+
+                       return TypeBuilder;
+               }
+
+               bool IsValidEnumConstant (Expression e)
+               {
+                       if (!(e is Constant))
+                               return false;
+
+                       if (e is IntConstant || e is UIntConstant || e is LongConstant ||
+                           e is ByteConstant || e is SByteConstant || e is ShortConstant ||
+                           e is UShortConstant || e is ULongConstant || e is EnumConstant ||
+                           e is CharConstant)
+                               return true;
+                       else
+                               return false;
+               }
+
+               object GetNextDefaultValue (object default_value)
+               {
+                       if (UnderlyingType == TypeManager.int32_type) {
+                               int i = (int) default_value;
+                               
+                               if (i < System.Int32.MaxValue)
+                                       return ++i;
+                               else
+                                       return null;
+                       } else if (UnderlyingType == TypeManager.uint32_type) {
+                               uint i = (uint) default_value;
+
+                               if (i < System.UInt32.MaxValue)
+                                       return ++i;
+                               else
+                                       return null;
+                       } else if (UnderlyingType == TypeManager.int64_type) {
+                               long i = (long) default_value;
+
+                               if (i < System.Int64.MaxValue)
+                                       return ++i;
+                               else
+                                       return null;
+                       } else if (UnderlyingType == TypeManager.uint64_type) {
+                               ulong i = (ulong) default_value;
+
+                               if (i < System.UInt64.MaxValue)
+                                       return ++i;
+                               else
+                                       return null;
+                       } else if (UnderlyingType == TypeManager.short_type) {
+                               short i = (short) default_value;
+
+                               if (i < System.Int16.MaxValue)
+                                       return ++i;
+                               else
+                                       return null;
+                       } else if (UnderlyingType == TypeManager.ushort_type) {
+                               ushort i = (ushort) default_value;
+
+                               if (i < System.UInt16.MaxValue)
+                                       return ++i;
+                               else
+                                       return null;
+                       } else if (UnderlyingType == TypeManager.byte_type) {
+                               byte i = (byte) default_value;
+
+                               if (i < System.Byte.MaxValue)
+                                       return ++i;
+                               else
+                                       return null;
+                       } else if (UnderlyingType == TypeManager.sbyte_type) {
+                               sbyte i = (sbyte) default_value;
+
+                               if (i < System.SByte.MaxValue)
+                                       return ++i;
+                               else
+                                       return null;
+                       }
+
+                       return null;
+               }
+
+               void Error_ConstantValueCannotBeConverted (object val, Location loc)
+               {
+                       if (val is Constant)
+                               Report.Error (31, loc, "Constant value '" + ((Constant) val).AsString () +
+                                             "' cannot be converted" +
+                                             " to a " + TypeManager.CSharpName (UnderlyingType));
+                       else 
+                               Report.Error (31, loc, "Constant value '" + val +
+                                             "' cannot be converted" +
+                                             " to a " + TypeManager.CSharpName (UnderlyingType));
+                       return;
+               }
+
+               /// <summary>
+               ///  Determines if a standard implicit conversion exists from
+               ///  expr_type to target_type
+               /// </summary>
+               public static bool ImplicitConversionExists (Type expr_type, Type target_type)
+               {
+                       expr_type = TypeManager.TypeToCoreType (expr_type);
+
+                       if (expr_type == TypeManager.void_type)
+                               return false;
+                       
+                       if (expr_type == target_type)
+                               return true;
+
+                       // First numeric conversions 
+
+                       if (expr_type == TypeManager.sbyte_type){
+                               //
+                               // From sbyte to short, int, long, float, double.
+                               //
+                               if ((target_type == TypeManager.int32_type) || 
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type)  ||
+                                   (target_type == TypeManager.short_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                               
+                       } else if (expr_type == TypeManager.byte_type){
+                               //
+                               // From byte to short, ushort, int, uint, long, ulong, float, double
+                               // 
+                               if ((target_type == TypeManager.short_type) ||
+                                   (target_type == TypeManager.ushort_type) ||
+                                   (target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.uint32_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+       
+                       } else if (expr_type == TypeManager.short_type){
+                               //
+                               // From short to int, long, float, double
+                               // 
+                               if ((target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                                       
+                       } else if (expr_type == TypeManager.ushort_type){
+                               //
+                               // From ushort to int, uint, long, ulong, float, double
+                               //
+                               if ((target_type == TypeManager.uint32_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                                   
+                       } else if (expr_type == TypeManager.int32_type){
+                               //
+                               // From int to long, float, double
+                               //
+                               if ((target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                                       
+                       } else if (expr_type == TypeManager.uint32_type){
+                               //
+                               // From uint to long, ulong, float, double
+                               //
+                               if ((target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                                       
+                       } else if ((expr_type == TypeManager.uint64_type) ||
+                                  (expr_type == TypeManager.int64_type)) {
+                               //
+                               // From long/ulong to float, double
+                               //
+                               if ((target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+                                   
+                       } else if (expr_type == TypeManager.char_type){
+                               //
+                               // From char to ushort, int, uint, long, ulong, float, double
+                               // 
+                               if ((target_type == TypeManager.ushort_type) ||
+                                   (target_type == TypeManager.int32_type) ||
+                                   (target_type == TypeManager.uint32_type) ||
+                                   (target_type == TypeManager.uint64_type) ||
+                                   (target_type == TypeManager.int64_type) ||
+                                   (target_type == TypeManager.float_type) ||
+                                   (target_type == TypeManager.double_type) ||
+                                   (target_type == TypeManager.decimal_type))
+                                       return true;
+
+                       } else if (expr_type == TypeManager.float_type){
+                               //
+                               // float to double
+                               //
+                               if (target_type == TypeManager.double_type)
+                                       return true;
+                       }       
+                       
+                       return false;
+               }
+
+               //
+               // Horrible, horrible.  But there is no other way we can pass the EmitContext
+               // to the recursive definition triggered by the evaluation of a forward
+               // expression
+               //
+               static EmitContext current_ec = null;
+               
+               /// <summary>
+               ///  This is used to lookup the value of an enum member. If the member is undefined,
+               ///  it attempts to define it and return its value
+               /// </summary>
+               public object LookupEnumValue (EmitContext ec, string name, Location loc)
+               {
+                       
+                       object default_value = null;
+                       Constant c = null;
+
+                       default_value = member_to_value [name];
+
+                       if (default_value != null)
+                               return default_value;
+
+                       //
+                       // This may happen if we're calling a method in System.Enum, for instance
+                       // Enum.IsDefined().
+                       //
+                       if (!defined_names.Contains (name))
+                               return null;
+
+                       if (in_transit.Contains (name)) {
+                               Report.Error (110, loc, "The evaluation of the constant value for `" +
+                                             Name + "." + name + "' involves a circular definition.");
+                               return null;
+                       }
+
+                       //
+                       // So if the above doesn't happen, we have a member that is undefined
+                       // We now proceed to define it 
+                       //
+                       Expression val = this [name];
+
+                       if (val == null) {
+                               
+                               int idx = ordered_enums.IndexOf (name);
+
+                               if (idx == 0)
+                                       default_value = 0;
+                               else {
+                                       for (int i = 0; i < idx; ++i) {
+                                               string n = (string) ordered_enums [i];
+                                               Location m_loc = (Mono.CSharp.Location)
+                                                       member_to_location [n];
+                                               in_transit.Add (name, true);
+
+                                               EmitContext old_ec = current_ec;
+                                               current_ec = ec;
+                       
+                                               default_value = LookupEnumValue (ec, n, m_loc);
+
+                                               current_ec = old_ec;
+                                               
+                                               in_transit.Remove (name);
+                                               if (default_value == null)
+                                                       return null;
+                                       }
+                                       
+                                       default_value = GetNextDefaultValue (default_value);
+                               }
+                               
+                       } else {
+                               bool old = ec.InEnumContext;
+                               ec.InEnumContext = true;
+                               in_transit.Add (name, true);
+
+                               EmitContext old_ec = current_ec;
+                               current_ec = ec;
+                               val = val.Resolve (ec);
+                               current_ec = old_ec;
+                               
+                               in_transit.Remove (name);
+                               ec.InEnumContext = old;
+
+                               if (val == null)
+                                       return null;
+
+                               if (!IsValidEnumConstant (val)) {
+                                       Report.Error (
+                                               1008, loc,
+                                               "Type byte, sbyte, short, ushort, int, uint, long, or " +
+                                               "ulong expected (have: " + val + ")");
+                                       return null;
+                               }
+
+                               c = (Constant) val;
+                               default_value = c.GetValue ();
+
+                               if (default_value == null) {
+                                       Error_ConstantValueCannotBeConverted (c, loc);
+                                       return null;
+                               }
+
+                               if (val is EnumConstant){
+                                       Type etype = TypeManager.EnumToUnderlying (c.Type);
+                                       
+                                       if (!ImplicitConversionExists (etype, UnderlyingType)){
+                                               Convert.Error_CannotImplicitConversion (
+                                                       loc, c.Type, UnderlyingType);
+                                               return null;
+                                       }
+                               }
+                       }
+
+                       FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static
+                                       | FieldAttributes.Literal;
+                       
+                       FieldBuilder fb = TypeBuilder.DefineField (name, TypeBuilder, attr);
+
+                       bool fail;
+                       default_value = TypeManager.ChangeType (default_value, UnderlyingType, out fail);
+                       if (fail){
+                               Error_ConstantValueCannotBeConverted (c, loc);
+                               return null;
+                       }
+
+                       fb.SetConstant (default_value);
+                       field_builders.Add (fb);
+                       member_to_value [name] = default_value;
+
+                       if (!TypeManager.RegisterFieldValue (fb, default_value))
+                               return null;
+
+                       //
+                       // Now apply attributes
+                       //
+                       Attribute.ApplyAttributes (ec, fb, fb, (Attributes) member_to_attributes [name]); 
+                       
+                       return default_value;
+               }
+
+               public override bool DefineMembers (TypeContainer parent)
+               {
+                       return true;
+               }
+               
+               public override bool Define (TypeContainer parent)
+               {
+                       //
+                       // If there was an error during DefineEnum, return
+                       //
+                       if (TypeBuilder == null)
+                               return false;
+                       
+                       EmitContext ec = new EmitContext (this, this, Location, null,
+                                                         UnderlyingType, ModFlags, false);
+
+                       
+                       object default_value = 0;
+                       
+                       FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static
+                                            | FieldAttributes.Literal;
+
+                       
+                       foreach (string name in ordered_enums) {
+                               //
+                               // Have we already been defined, thanks to some cross-referencing ?
+                               // 
+                               if (member_to_value.Contains (name))
+                                       continue;
+                               
+                               Location loc = (Mono.CSharp.Location) member_to_location [name];
+
+                               if (this [name] != null) {
+                                       default_value = LookupEnumValue (ec, name, loc);
+
+                                       if (default_value == null)
+                                               return true;
+                               } else {
+                                       if (name == "value__"){
+                                               Report.Error (76, loc, "The name `value__' is reserved for enumerations");
+                                               return false;
+                                       }
+
+                                       FieldBuilder fb = TypeBuilder.DefineField (
+                                               name, TypeBuilder, attr);
+                                       
+                                       if (default_value == null) {
+                                          Report.Error (543, loc, "Enumerator value for '" + name + "' is too large to " +
+                                                             "fit in its type");
+                                               return false;
+                                       }
+
+                                       bool fail;
+                                       default_value = TypeManager.ChangeType (default_value, UnderlyingType, out fail);
+                                       if (fail){
+                                               Error_ConstantValueCannotBeConverted (default_value, loc);
+                                               return false;
+                                       }
+
+                                       fb.SetConstant (default_value);
+                                       field_builders.Add (fb);
+                                       member_to_value [name] = default_value;
+                                       
+                                       if (!TypeManager.RegisterFieldValue (fb, default_value))
+                                               return false;
+
+                                       //
+                                       // Apply attributes on the enum member
+                                       //
+                                       Attribute.ApplyAttributes (ec, fb, fb, (Attributes) member_to_attributes [name]);
+                               }
+
+                               default_value = GetNextDefaultValue (default_value);
+                       }
+                       
+                       Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
+
+                       return true;
+               }
+               
+               //
+               // IMemberFinder
+               //
+               public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                                       MemberFilter filter, object criteria)
+               {
+                       ArrayList members = new ArrayList ();
+
+                       if ((mt & MemberTypes.Field) != 0) {
+                               if (criteria is string){
+                                       if (member_to_value [criteria] == null && current_ec != null){
+                                               LookupEnumValue (current_ec, (string) criteria, Location.Null);
+                                       }
+                               }
+                               
+                               foreach (FieldBuilder fb in field_builders)
+                                       if (filter (fb, criteria) == true)
+                                               members.Add (fb);
+                       }
+
+                       return new MemberList (members);
+               }
+
+               public override MemberCache MemberCache {
+                       get {
+                               return null;
+                       }
+               }
+
+               public ArrayList ValueNames {
+                       get {
+                               return ordered_enums;
+                       }
+               }
+
+               // indexer
+               public Expression this [string name] {
+                       get {
+                               return (Expression) defined_names [name];
+                       }
+               }
+       }
+}
diff --git a/mcs/gmcs/errors.cs b/mcs/gmcs/errors.cs
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/mcs/gmcs/expression.cs b/mcs/gmcs/expression.cs
new file mode 100755 (executable)
index 0000000..50f367f
--- /dev/null
@@ -0,0 +1,8029 @@
+//
+// expression.cs: Expression representation for the IL tree.
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc.
+//
+//
+#define USE_OLD
+
+namespace Mono.CSharp {
+       using System;
+       using System.Collections;
+       using System.Reflection;
+       using System.Reflection.Emit;
+       using System.Text;
+
+       /// <summary>
+       ///   This is just a helper class, it is generated by Unary, UnaryMutator
+       ///   when an overloaded method has been found.  It just emits the code for a
+       ///   static call.
+       /// </summary>
+       public class StaticCallExpr : ExpressionStatement {
+               ArrayList args;
+               MethodInfo mi;
+
+               public StaticCallExpr (MethodInfo m, ArrayList a, Location l)
+               {
+                       mi = m;
+                       args = a;
+
+                       type = m.ReturnType;
+                       eclass = ExprClass.Value;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       if (args != null) 
+                               Invocation.EmitArguments (ec, mi, args);
+
+                       ec.ig.Emit (OpCodes.Call, mi);
+                       return;
+               }
+               
+               static public Expression MakeSimpleCall (EmitContext ec, MethodGroupExpr mg,
+                                                        Expression e, Location loc)
+               {
+                       ArrayList args;
+                       MethodBase method;
+                       
+                       args = new ArrayList (1);
+                       Argument a = new Argument (e, Argument.AType.Expression);
+
+                        // We need to resolve the arguments before sending them in !
+                        if (!a.Resolve (ec, loc))
+                                return null;
+
+                        args.Add (a);
+                       method = Invocation.OverloadResolve (ec, (MethodGroupExpr) mg, args, loc);
+
+                       if (method == null)
+                               return null;
+
+                       return new StaticCallExpr ((MethodInfo) method, args, loc);
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       Emit (ec);
+                       if (TypeManager.TypeToCoreType (type) != TypeManager.void_type)
+                               ec.ig.Emit (OpCodes.Pop);
+               }
+       }
+       
+       /// <summary>
+       ///   Unary expressions.  
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   Unary implements unary expressions.   It derives from
+       ///   ExpressionStatement becuase the pre/post increment/decrement
+       ///   operators can be used in a statement context.
+       /// </remarks>
+       public class Unary : Expression {
+               public enum Operator : byte {
+                       UnaryPlus, UnaryNegation, LogicalNot, OnesComplement,
+                       Indirection, AddressOf,  TOP
+               }
+
+               public Operator Oper;
+               public Expression Expr;
+               
+               public Unary (Operator op, Expression expr, Location loc)
+               {
+                       this.Oper = op;
+                       this.Expr = expr;
+                       this.loc = loc;
+               }
+
+               /// <summary>
+               ///   Returns a stringified representation of the Operator
+               /// </summary>
+               static public string OperName (Operator oper)
+               {
+                       switch (oper){
+                       case Operator.UnaryPlus:
+                               return "+";
+                       case Operator.UnaryNegation:
+                               return "-";
+                       case Operator.LogicalNot:
+                               return "!";
+                       case Operator.OnesComplement:
+                               return "~";
+                       case Operator.AddressOf:
+                               return "&";
+                       case Operator.Indirection:
+                               return "*";
+                       }
+
+                       return oper.ToString ();
+               }
+
+               public static readonly string [] oper_names;
+
+               static Unary ()
+               {
+                       oper_names = new string [(int)Operator.TOP];
+
+                       oper_names [(int) Operator.UnaryPlus] = "op_UnaryPlus";
+                       oper_names [(int) Operator.UnaryNegation] = "op_UnaryNegation";
+                       oper_names [(int) Operator.LogicalNot] = "op_LogicalNot";
+                       oper_names [(int) Operator.OnesComplement] = "op_OnesComplement";
+                       oper_names [(int) Operator.Indirection] = "op_Indirection";
+                       oper_names [(int) Operator.AddressOf] = "op_AddressOf";
+               }
+
+               void Error23 (Type t)
+               {
+                       Error (
+                               23, "Operator " + OperName (Oper) +
+                               " cannot be applied to operand of type `" +
+                               TypeManager.CSharpName (t) + "'");
+               }
+
+               /// <remarks>
+               ///   The result has been already resolved:
+               ///
+               ///   FIXME: a minus constant -128 sbyte cant be turned into a
+               ///   constant byte.
+               /// </remarks>
+               static Expression TryReduceNegative (Constant expr)
+               {
+                       Expression e = null;
+
+                       if (expr is IntConstant)
+                               e = new IntConstant (-((IntConstant) expr).Value);
+                       else if (expr is UIntConstant){
+                               uint value = ((UIntConstant) expr).Value;
+
+                               if (value < 2147483649)
+                                       return new IntConstant (-(int)value);
+                               else
+                                       e = new LongConstant (-value);
+                       }
+                       else if (expr is LongConstant)
+                               e = new LongConstant (-((LongConstant) expr).Value);
+                       else if (expr is ULongConstant){
+                               ulong value = ((ULongConstant) expr).Value;
+
+                               if (value < 9223372036854775809)
+                                       return new LongConstant(-(long)value);
+                       }
+                       else if (expr is FloatConstant)
+                               e = new FloatConstant (-((FloatConstant) expr).Value);
+                       else if (expr is DoubleConstant)
+                               e = new DoubleConstant (-((DoubleConstant) expr).Value);
+                       else if (expr is DecimalConstant)
+                               e = new DecimalConstant (-((DecimalConstant) expr).Value);
+                       else if (expr is ShortConstant)
+                               e = new IntConstant (-((ShortConstant) expr).Value);
+                       else if (expr is UShortConstant)
+                               e = new IntConstant (-((UShortConstant) expr).Value);
+                       return e;
+               }
+
+               // <summary>
+               //   This routine will attempt to simplify the unary expression when the
+               //   argument is a constant.  The result is returned in `result' and the
+               //   function returns true or false depending on whether a reduction
+               //   was performed or not
+               // </summary>
+               bool Reduce (EmitContext ec, Constant e, out Expression result)
+               {
+                       Type expr_type = e.Type;
+                       
+                       switch (Oper){
+                       case Operator.UnaryPlus:
+                               result = e;
+                               return true;
+                               
+                       case Operator.UnaryNegation:
+                               result = TryReduceNegative (e);
+                               return true;
+                               
+                       case Operator.LogicalNot:
+                               if (expr_type != TypeManager.bool_type) {
+                                       result = null;
+                                       Error23 (expr_type);
+                                       return false;
+                               }
+                               
+                               BoolConstant b = (BoolConstant) e;
+                               result = new BoolConstant (!(b.Value));
+                               return true;
+                               
+                       case Operator.OnesComplement:
+                               if (!((expr_type == TypeManager.int32_type) ||
+                                     (expr_type == TypeManager.uint32_type) ||
+                                     (expr_type == TypeManager.int64_type) ||
+                                     (expr_type == TypeManager.uint64_type) ||
+                                     (expr_type.IsSubclassOf (TypeManager.enum_type)))){
+
+                                       result = null;
+                                       if (Convert.ImplicitConversionExists (ec, e, TypeManager.int32_type)){
+                                               result = new Cast (new TypeExpr (TypeManager.int32_type, loc), e, loc);
+                                               result = result.Resolve (ec);
+                                       } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint32_type)){
+                                               result = new Cast (new TypeExpr (TypeManager.uint32_type, loc), e, loc);
+                                               result = result.Resolve (ec);
+                                       } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.int64_type)){
+                                               result = new Cast (new TypeExpr (TypeManager.int64_type, loc), e, loc);
+                                               result = result.Resolve (ec);
+                                       } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint64_type)){
+                                               result = new Cast (new TypeExpr (TypeManager.uint64_type, loc), e, loc);
+                                               result = result.Resolve (ec);
+                                       }
+
+                                       if (result == null || !(result is Constant)){
+                                               result = null;
+                                               Error23 (expr_type);
+                                               return false;
+                                       }
+
+                                       expr_type = result.Type;
+                                       e = (Constant) result;
+                               }
+
+                               if (e is EnumConstant){
+                                       EnumConstant enum_constant = (EnumConstant) e;
+                                       Expression reduced;
+                                       
+                                       if (Reduce (ec, enum_constant.Child, out reduced)){
+                                               result = new EnumConstant ((Constant) reduced, enum_constant.Type);
+                                               return true;
+                                       } else {
+                                               result = null;
+                                               return false;
+                                       }
+                               }
+
+                               if (expr_type == TypeManager.int32_type){
+                                       result = new IntConstant (~ ((IntConstant) e).Value);
+                               } else if (expr_type == TypeManager.uint32_type){
+                                       result = new UIntConstant (~ ((UIntConstant) e).Value);
+                               } else if (expr_type == TypeManager.int64_type){
+                                       result = new LongConstant (~ ((LongConstant) e).Value);
+                               } else if (expr_type == TypeManager.uint64_type){
+                                       result = new ULongConstant (~ ((ULongConstant) e).Value);
+                               } else {
+                                       result = null;
+                                       Error23 (expr_type);
+                                       return false;
+                               }
+                               return true;
+
+                       case Operator.AddressOf:
+                               result = this;
+                               return false;
+
+                       case Operator.Indirection:
+                               result = this;
+                               return false;
+                       }
+                       throw new Exception ("Can not constant fold: " + Oper.ToString());
+               }
+
+               Expression ResolveOperator (EmitContext ec)
+               {
+                       Type expr_type = Expr.Type;
+
+                       //
+                       // Step 1: Perform Operator Overload location
+                       //
+                       Expression mg;
+                       string op_name;
+                       
+                       op_name = oper_names [(int) Oper];
+
+                       mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+                       
+                       if (mg != null) {
+                               Expression e = StaticCallExpr.MakeSimpleCall (
+                                       ec, (MethodGroupExpr) mg, Expr, loc);
+
+                               if (e == null){
+                                       Error23 (expr_type);
+                                       return null;
+                               }
+                               
+                               return e;
+                       }
+
+                       // Only perform numeric promotions on:
+                       // +, - 
+
+                       if (expr_type == null)
+                               return null;
+                       
+                       //
+                       // Step 2: Default operations on CLI native types.
+                       //
+
+                       // Attempt to use a constant folding operation.
+                       if (Expr is Constant){
+                               Expression result;
+                               
+                               if (Reduce (ec, (Constant) Expr, out result))
+                                       return result;
+                       }
+
+                       switch (Oper){
+                       case Operator.LogicalNot:
+                               if (expr_type != TypeManager.bool_type) {
+                                       Expr = ResolveBoolean (ec, Expr, loc);
+                                       if (Expr == null){
+                                               Error23 (expr_type);
+                                               return null;
+                                       }
+                               }
+                               
+                               type = TypeManager.bool_type;
+                               return this;
+
+                       case Operator.OnesComplement:
+                               if (!((expr_type == TypeManager.int32_type) ||
+                                     (expr_type == TypeManager.uint32_type) ||
+                                     (expr_type == TypeManager.int64_type) ||
+                                     (expr_type == TypeManager.uint64_type) ||
+                                     (expr_type.IsSubclassOf (TypeManager.enum_type)))){
+                                       Expression e;
+
+                                       e = Convert.ImplicitConversion (ec, Expr, TypeManager.int32_type, loc);
+                                       if (e != null){
+                                               type = TypeManager.int32_type;
+                                               return this;
+                                       }
+                                       e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint32_type, loc);
+                                       if (e != null){
+                                               type = TypeManager.uint32_type;
+                                               return this;
+                                       }
+                                       e = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc);
+                                       if (e != null){
+                                               type = TypeManager.int64_type;
+                                               return this;
+                                       }
+                                       e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint64_type, loc);
+                                       if (e != null){
+                                               type = TypeManager.uint64_type;
+                                               return this;
+                                       }
+                                       Error23 (expr_type);
+                                       return null;
+                               }
+                               type = expr_type;
+                               return this;
+
+                       case Operator.AddressOf:
+                               if (Expr.eclass != ExprClass.Variable){
+                                       Error (211, "Cannot take the address of non-variables");
+                                       return null;
+                               }
+                               
+                               if (!ec.InUnsafe) {
+                                       UnsafeError (loc); 
+                                       return null;
+                               }
+                               
+                               if (!TypeManager.VerifyUnManaged (Expr.Type, loc)){
+                                       return null;
+                               }
+
+                               IVariable variable = Expr as IVariable;
+                               if (!ec.InFixedInitializer && ((variable == null) || !variable.VerifyFixed (false))) {
+                                       Error (212, "You can only take the address of an unfixed expression inside " +
+                                              "of a fixed statement initializer");
+                                       return null;
+                               }
+
+                               // According to the specs, a variable is considered definitely assigned if you take
+                               // its address.
+                               if ((variable != null) && (variable.VariableInfo != null))
+                                       variable.VariableInfo.SetAssigned (ec);
+
+                               type = TypeManager.GetPointerType (Expr.Type);
+                               return this;
+
+                       case Operator.Indirection:
+                               if (!ec.InUnsafe){
+                                       UnsafeError (loc);
+                                       return null;
+                               }
+                               
+                               if (!expr_type.IsPointer){
+                                       Error (193, "The * or -> operator can only be applied to pointers");
+                                       return null;
+                               }
+                               
+                               //
+                               // We create an Indirection expression, because
+                               // it can implement the IMemoryLocation.
+                               // 
+                               return new Indirection (Expr, loc);
+                       
+                       case Operator.UnaryPlus:
+                               //
+                               // A plus in front of something is just a no-op, so return the child.
+                               //
+                               return Expr;
+
+                       case Operator.UnaryNegation:
+                               //
+                               // Deals with -literals
+                               // int     operator- (int x)
+                               // long    operator- (long x)
+                               // float   operator- (float f)
+                               // double  operator- (double d)
+                               // decimal operator- (decimal d)
+                               //
+                               Expression expr = null;
+
+                               //
+                               // transform - - expr into expr
+                               //
+                               if (Expr is Unary){
+                                       Unary unary = (Unary) Expr;
+                                       
+                                       if (unary.Oper == Operator.UnaryNegation)
+                                               return unary.Expr;
+                               }
+
+                               //
+                               // perform numeric promotions to int,
+                               // long, double.
+                               //
+                               //
+                               // The following is inneficient, because we call
+                               // ImplicitConversion too many times.
+                               //
+                               // It is also not clear if we should convert to Float
+                               // or Double initially.
+                               //
+                               if (expr_type == TypeManager.uint32_type){
+                                       //
+                                       // FIXME: handle exception to this rule that
+                                       // permits the int value -2147483648 (-2^31) to
+                                       // bt wrote as a decimal interger literal
+                                       //
+                                       type = TypeManager.int64_type;
+                                       Expr = Convert.ImplicitConversion (ec, Expr, type, loc);
+                                       return this;
+                               }
+
+                               if (expr_type == TypeManager.uint64_type){
+                                       //
+                                       // FIXME: Handle exception of `long value'
+                                       // -92233720368547758087 (-2^63) to be wrote as
+                                       // decimal integer literal.
+                                       //
+                                       Error23 (expr_type);
+                                       return null;
+                               }
+
+                               if (expr_type == TypeManager.float_type){
+                                       type = expr_type;
+                                       return this;
+                               }
+                               
+                               expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int32_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
+                                       return this;
+                               } 
+
+                               expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
+                                       return this;
+                               }
+
+                               expr = Convert.ImplicitConversion (ec, Expr, TypeManager.double_type, loc);
+                               if (expr != null){
+                                       Expr = expr;
+                                       type = expr.Type;
+                                       return this;
+                               }
+                               
+                               Error23 (expr_type);
+                               return null;
+                       }
+
+                       Error (187, "No such operator '" + OperName (Oper) + "' defined for type '" +
+                              TypeManager.CSharpName (expr_type) + "'");
+                       return null;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (Oper == Operator.AddressOf)
+                               Expr = Expr.ResolveLValue (ec, new EmptyExpression ());
+                       else
+                               Expr = Expr.Resolve (ec);
+                       
+                       if (Expr == null)
+                               return null;
+
+                       eclass = ExprClass.Value;
+                       return ResolveOperator (ec);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Type expr_type = Expr.Type;
+                       
+                       switch (Oper) {
+                       case Operator.UnaryPlus:
+                               throw new Exception ("This should be caught by Resolve");
+                               
+                       case Operator.UnaryNegation:
+                               Expr.Emit (ec);
+                               ig.Emit (OpCodes.Neg);
+                               break;
+                               
+                       case Operator.LogicalNot:
+                               Expr.Emit (ec);
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               ig.Emit (OpCodes.Ceq);
+                               break;
+                               
+                       case Operator.OnesComplement:
+                               Expr.Emit (ec);
+                               ig.Emit (OpCodes.Not);
+                               break;
+                               
+                       case Operator.AddressOf:
+                               ((IMemoryLocation)Expr).AddressOf (ec, AddressOp.LoadStore);
+                               break;
+                               
+                       default:
+                               throw new Exception ("This should not happen: Operator = "
+                                                    + Oper.ToString ());
+                       }
+               }
+
+               /// <summary>
+               ///   This will emit the child expression for `ec' avoiding the logical
+               ///   not.  The parent will take care of changing brfalse/brtrue
+               /// </summary>
+               public void EmitLogicalNot (EmitContext ec)
+               {
+                       if (Oper != Operator.LogicalNot)
+                               throw new Exception ("EmitLogicalNot can only be called with !expr");
+
+                       Expr.Emit (ec);
+               }
+
+               public override string ToString ()
+               {
+                       return "Unary (" + Oper + ", " + Expr + ")";
+               }
+               
+       }
+
+       //
+       // Unary operators are turned into Indirection expressions
+       // after semantic analysis (this is so we can take the address
+       // of an indirection).
+       //
+       public class Indirection : Expression, IMemoryLocation, IAssignMethod {
+               Expression expr;
+               LocalTemporary temporary;
+               bool have_temporary;
+               
+               public Indirection (Expression expr, Location l)
+               {
+                       this.expr = expr;
+                       this.type = TypeManager.GetElementType (expr.Type);
+                       eclass = ExprClass.Variable;
+                       loc = l;
+               }
+
+               void LoadExprValue (EmitContext ec)
+               {
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       if (temporary != null){
+                               if (have_temporary){
+                                       temporary.Emit (ec);
+                                       return;
+                               }
+                               expr.Emit (ec);
+                               ec.ig.Emit (OpCodes.Dup);
+                               temporary.Store (ec);
+                               have_temporary = true;
+                       } else
+                               expr.Emit (ec);
+                       
+                       LoadFromPtr (ig, Type);
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       if (temporary != null){
+                               if (have_temporary)
+                                       temporary.Emit (ec);
+                               else {
+                                       expr.Emit (ec);
+                                       ec.ig.Emit (OpCodes.Dup);
+                                       temporary.Store (ec);
+                                       have_temporary = true;
+                               }
+                       } else 
+                               expr.Emit (ec);
+
+                       source.Emit (ec);
+                       StoreFromPtr (ec.ig, type);
+               }
+               
+               public void AddressOf (EmitContext ec, AddressOp Mode)
+               {
+                       if (temporary != null){
+                               if (have_temporary){
+                                       temporary.Emit (ec);
+                                       return;
+                               }
+                               expr.Emit (ec);
+                               ec.ig.Emit (OpCodes.Dup);
+                               temporary.Store (ec);
+                               have_temporary = true;
+                       } else
+                               expr.Emit (ec);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // Born fully resolved
+                       //
+                       return this;
+               }
+
+               public new void CacheTemporaries (EmitContext ec)
+               {
+                       temporary = new LocalTemporary (ec, type);
+               }
+
+               public override string ToString ()
+               {
+                       return "*(" + expr + ")";
+               }
+       }
+       
+       /// <summary>
+       ///   Unary Mutator expressions (pre and post ++ and --)
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   UnaryMutator implements ++ and -- expressions.   It derives from
+       ///   ExpressionStatement becuase the pre/post increment/decrement
+       ///   operators can be used in a statement context.
+       ///
+       /// FIXME: Idea, we could split this up in two classes, one simpler
+       /// for the common case, and one with the extra fields for more complex
+       /// classes (indexers require temporary access;  overloaded require method)
+       ///
+       /// </remarks>
+       public class UnaryMutator : ExpressionStatement {
+               [Flags]
+               public enum Mode : byte {
+                       IsIncrement    = 0,
+                       IsDecrement    = 1,
+                       IsPre          = 0,
+                       IsPost         = 2,
+                       
+                       PreIncrement   = 0,
+                       PreDecrement   = IsDecrement,
+                       PostIncrement  = IsPost,
+                       PostDecrement  = IsPost | IsDecrement
+               }
+               
+               Mode mode;
+               Expression expr;
+               LocalTemporary temp_storage;
+
+               //
+               // This is expensive for the simplest case.
+               //
+               Expression method;
+                       
+               public UnaryMutator (Mode m, Expression e, Location l)
+               {
+                       mode = m;
+                       loc = l;
+                       expr = e;
+               }
+
+               static string OperName (Mode mode)
+               {
+                       return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?
+                               "++" : "--";
+               }
+               
+               void Error23 (Type t)
+               {
+                       Error (
+                               23, "Operator " + OperName (mode) + 
+                               " cannot be applied to operand of type `" +
+                               TypeManager.CSharpName (t) + "'");
+               }
+
+               /// <summary>
+               ///   Returns whether an object of type `t' can be incremented
+               ///   or decremented with add/sub (ie, basically whether we can
+               ///   use pre-post incr-decr operations on it, but it is not a
+               ///   System.Decimal, which we require operator overloading to catch)
+               /// </summary>
+               static bool IsIncrementableNumber (Type t)
+               {
+                       return (t == TypeManager.sbyte_type) ||
+                               (t == TypeManager.byte_type) ||
+                               (t == TypeManager.short_type) ||
+                               (t == TypeManager.ushort_type) ||
+                               (t == TypeManager.int32_type) ||
+                               (t == TypeManager.uint32_type) ||
+                               (t == TypeManager.int64_type) ||
+                               (t == TypeManager.uint64_type) ||
+                               (t == TypeManager.char_type) ||
+                               (t.IsSubclassOf (TypeManager.enum_type)) ||
+                               (t == TypeManager.float_type) ||
+                               (t == TypeManager.double_type) ||
+                               (t.IsPointer && t != TypeManager.void_ptr_type);
+               }
+
+               Expression ResolveOperator (EmitContext ec)
+               {
+                       Type expr_type = expr.Type;
+
+                       //
+                       // Step 1: Perform Operator Overload location
+                       //
+                       Expression mg;
+                       string op_name;
+                       
+                       if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)
+                               op_name = "op_Increment";
+                       else 
+                               op_name = "op_Decrement";
+
+                       mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+
+                       if (mg == null && expr_type.BaseType != null)
+                               mg = MemberLookup (ec, expr_type.BaseType, op_name,
+                                                  MemberTypes.Method, AllBindingFlags, loc);
+                       
+                       if (mg != null) {
+                               method = StaticCallExpr.MakeSimpleCall (
+                                       ec, (MethodGroupExpr) mg, expr, loc);
+
+                               type = method.Type;
+                               return this;
+                       }
+
+                       //
+                       // The operand of the prefix/postfix increment decrement operators
+                       // should be an expression that is classified as a variable,
+                       // a property access or an indexer access
+                       //
+                       type = expr_type;
+                       if (expr.eclass == ExprClass.Variable){
+                               if (IsIncrementableNumber (expr_type) ||
+                                   expr_type == TypeManager.decimal_type){
+                                       return this;
+                               }
+                       } else if (expr.eclass == ExprClass.IndexerAccess){
+                               IndexerAccess ia = (IndexerAccess) expr;
+                               
+                               temp_storage = new LocalTemporary (ec, expr.Type);
+                               
+                               expr = ia.ResolveLValue (ec, temp_storage);
+                               if (expr == null)
+                                       return null;
+
+                               return this;
+                       } else if (expr.eclass == ExprClass.PropertyAccess){
+                               PropertyExpr pe = (PropertyExpr) expr;
+
+                               if (pe.VerifyAssignable ())
+                                       return this;
+
+                               return null;
+                       } else {
+                               expr.Error_UnexpectedKind ("variable, indexer or property access");
+                               return null;
+                       }
+
+                       Error (187, "No such operator '" + OperName (mode) + "' defined for type '" +
+                              TypeManager.CSharpName (expr_type) + "'");
+                       return null;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       expr = expr.Resolve (ec);
+                       
+                       if (expr == null)
+                               return null;
+
+                       eclass = ExprClass.Value;
+                       return ResolveOperator (ec);
+               }
+
+               static int PtrTypeSize (Type t)
+               {
+                       return GetTypeSize (TypeManager.GetElementType (t));
+               }
+
+               //
+               // Loads the proper "1" into the stack based on the type, then it emits the
+               // opcode for the operation requested
+               //
+               void LoadOneAndEmitOp (EmitContext ec, Type t)
+               {
+                       //
+                       // Measure if getting the typecode and using that is more/less efficient
+                       // that comparing types.  t.GetTypeCode() is an internal call.
+                       //
+                       ILGenerator ig = ec.ig;
+                                                    
+                       if (t == TypeManager.uint64_type || t == TypeManager.int64_type)
+                               LongConstant.EmitLong (ig, 1);
+                       else if (t == TypeManager.double_type)
+                               ig.Emit (OpCodes.Ldc_R8, 1.0);
+                       else if (t == TypeManager.float_type)
+                               ig.Emit (OpCodes.Ldc_R4, 1.0F);
+                       else if (t.IsPointer){
+                               int n = PtrTypeSize (t);
+                               
+                               if (n == 0)
+                                       ig.Emit (OpCodes.Sizeof, t);
+                               else
+                                       IntConstant.EmitInt (ig, n);
+                       } else 
+                               ig.Emit (OpCodes.Ldc_I4_1);
+
+                       //
+                       // Now emit the operation
+                       //
+                       if (ec.CheckState){
+                               if (t == TypeManager.int32_type ||
+                                   t == TypeManager.int64_type){
+                                       if ((mode & Mode.IsDecrement) != 0)
+                                               ig.Emit (OpCodes.Sub_Ovf);
+                                       else
+                                               ig.Emit (OpCodes.Add_Ovf);
+                               } else if (t == TypeManager.uint32_type ||
+                                          t == TypeManager.uint64_type){
+                                       if ((mode & Mode.IsDecrement) != 0)
+                                               ig.Emit (OpCodes.Sub_Ovf_Un);
+                                       else
+                                               ig.Emit (OpCodes.Add_Ovf_Un);
+                               } else {
+                                       if ((mode & Mode.IsDecrement) != 0)
+                                               ig.Emit (OpCodes.Sub_Ovf);
+                                       else
+                                               ig.Emit (OpCodes.Add_Ovf);
+                               }
+                       } else {
+                               if ((mode & Mode.IsDecrement) != 0)
+                                       ig.Emit (OpCodes.Sub);
+                               else
+                                       ig.Emit (OpCodes.Add);
+                       }
+
+                       if (t == TypeManager.sbyte_type){
+                               if (ec.CheckState)
+                                       ig.Emit (OpCodes.Conv_Ovf_I1);
+                               else
+                                       ig.Emit (OpCodes.Conv_I1);
+                       } else if (t == TypeManager.byte_type){
+                               if (ec.CheckState)
+                                       ig.Emit (OpCodes.Conv_Ovf_U1);
+                               else
+                                       ig.Emit (OpCodes.Conv_U1);
+                       } else if (t == TypeManager.short_type){
+                               if (ec.CheckState)
+                                       ig.Emit (OpCodes.Conv_Ovf_I2);
+                               else
+                                       ig.Emit (OpCodes.Conv_I2);
+                       } else if (t == TypeManager.ushort_type || t == TypeManager.char_type){
+                               if (ec.CheckState)
+                                       ig.Emit (OpCodes.Conv_Ovf_U2);
+                               else
+                                       ig.Emit (OpCodes.Conv_U2);
+                       }
+                       
+               }
+
+               static EmptyExpression empty_expr;
+               
+               void EmitCode (EmitContext ec, bool is_expr)
+               {
+                       ILGenerator ig = ec.ig;
+                       IAssignMethod ia = (IAssignMethod) expr;
+                       Type expr_type = expr.Type;
+
+                       ia.CacheTemporaries (ec);
+
+                       if (temp_storage == null){
+                               //
+                               // Temporary improvement: if we are dealing with something that does
+                               // not require complicated instance setup, avoid using a temporary
+                               //
+                               // For now: only localvariables when not remapped
+                               //
+
+                               if (method == null && 
+                                   (expr is LocalVariableReference && ec.RemapToProxy == false) ||
+                                   (expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic)){
+                                       if (empty_expr == null)
+                                               empty_expr = new EmptyExpression ();
+                                       
+                                       switch (mode){
+                                       case Mode.PreIncrement:
+                                       case Mode.PreDecrement:
+                                               expr.Emit (ec);
+                                       
+                                               LoadOneAndEmitOp (ec, expr_type);
+                                               if (is_expr)
+                                                       ig.Emit (OpCodes.Dup);
+                                               ia.EmitAssign (ec, empty_expr);
+                                               break;
+                                               
+                                       case Mode.PostIncrement:
+                                       case Mode.PostDecrement:
+                                               expr.Emit (ec);
+                                               if (is_expr)
+                                                       ig.Emit (OpCodes.Dup);
+                                               
+                                               LoadOneAndEmitOp (ec, expr_type);
+                                               ia.EmitAssign (ec, empty_expr);
+                                               break;
+                                       }
+                                       return;
+                               }
+                               temp_storage = new LocalTemporary (ec, expr_type);
+                       }
+                       
+                       switch (mode){
+                       case Mode.PreIncrement:
+                       case Mode.PreDecrement:
+                               if (method == null){
+                                       expr.Emit (ec);
+                                       
+                                       LoadOneAndEmitOp (ec, expr_type);
+                               } else 
+                                       method.Emit (ec);
+                               
+                               temp_storage.Store (ec);
+                               ia.EmitAssign (ec, temp_storage);
+                               if (is_expr)
+                                       temp_storage.Emit (ec);
+                               break;
+                               
+                       case Mode.PostIncrement:
+                       case Mode.PostDecrement:
+                               if (is_expr)
+                                       expr.Emit (ec);
+                               
+                               if (method == null){
+                                       if (!is_expr)
+                                               expr.Emit (ec);
+                                       else
+                                               ig.Emit (OpCodes.Dup);
+                                       
+                                       LoadOneAndEmitOp (ec, expr_type);
+                               } else {
+                                       method.Emit (ec);
+                               }
+                               
+                               temp_storage.Store (ec);
+                               ia.EmitAssign (ec, temp_storage);
+                               break;
+                       }
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       EmitCode (ec, true);
+                       
+               }
+               
+               public override void EmitStatement (EmitContext ec)
+               {
+                       EmitCode (ec, false);
+               }
+
+       }
+
+       /// <summary>
+       ///   Base class for the `Is' and `As' classes. 
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   FIXME: Split this in two, and we get to save the `Operator' Oper
+       ///   size. 
+       /// </remarks>
+       public abstract class Probe : Expression {
+               public readonly Expression ProbeType;
+               protected Expression expr;
+               protected Type probe_type;
+               
+               public Probe (Expression expr, Expression probe_type, Location l)
+               {
+                       ProbeType = probe_type;
+                       loc = l;
+                       this.expr = expr;
+               }
+
+               public Expression Expr {
+                       get {
+                               return expr;
+                       }
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       probe_type = ec.DeclSpace.ResolveType (ProbeType, false, loc);
+
+                       if (probe_type == null)
+                               return null;
+
+                       expr = expr.Resolve (ec);
+                       
+                       return this;
+               }
+       }
+
+       /// <summary>
+       ///   Implementation of the `is' operator.
+       /// </summary>
+       public class Is : Probe {
+               public Is (Expression expr, Expression probe_type, Location l)
+                       : base (expr, probe_type, l)
+               {
+               }
+
+               enum Action {
+                       AlwaysTrue, AlwaysNull, AlwaysFalse, LeaveOnStack, Probe
+               }
+
+               Action action;
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       expr.Emit (ec);
+
+                       switch (action){
+                       case Action.AlwaysFalse:
+                               ig.Emit (OpCodes.Pop);
+                               IntConstant.EmitInt (ig, 0);
+                               return;
+                       case Action.AlwaysTrue:
+                               ig.Emit (OpCodes.Pop);
+                               IntConstant.EmitInt (ig, 1);
+                               return;
+                       case Action.LeaveOnStack:
+                               // the `e != null' rule.
+                               ig.Emit (OpCodes.Ldnull);
+                               ig.Emit (OpCodes.Ceq);
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               ig.Emit (OpCodes.Ceq);
+                               return;
+                       case Action.Probe:
+                               ig.Emit (OpCodes.Isinst, probe_type);
+                               ig.Emit (OpCodes.Ldnull);
+                               ig.Emit (OpCodes.Cgt_Un);
+                               return;
+                       }
+                       throw new Exception ("never reached");
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expression e = base.DoResolve (ec);
+
+                       if ((e == null) || (expr == null))
+                               return null;
+
+                       Type etype = expr.Type;
+                       bool warning_always_matches = false;
+                       bool warning_never_matches = false;
+
+                       type = TypeManager.bool_type;
+                       eclass = ExprClass.Value;
+
+                       //
+                       // First case, if at compile time, there is an implicit conversion
+                       // then e != null (objects) or true (value types)
+                       //
+                       e = Convert.ImplicitConversionStandard (ec, expr, probe_type, loc);
+                       if (e != null){
+                               expr = e;
+                               if (etype.IsValueType)
+                                       action = Action.AlwaysTrue;
+                               else
+                                       action = Action.LeaveOnStack;
+
+                               warning_always_matches = true;
+                       } else if (Convert.ExplicitReferenceConversionExists (etype, probe_type)){
+                               //
+                               // Second case: explicit reference convresion
+                               //
+                               if (expr is NullLiteral)
+                                       action = Action.AlwaysFalse;
+                               else
+                                       action = Action.Probe;
+                       } else {
+                               action = Action.AlwaysFalse;
+                               warning_never_matches = true;
+                       }
+                       
+                       if (RootContext.WarningLevel >= 1){
+                               if (warning_always_matches)
+                                       Warning (183, "The expression is always of type `" +
+                                                TypeManager.CSharpName (probe_type) + "'");
+                               else if (warning_never_matches){
+                                       if (!(probe_type.IsInterface || expr.Type.IsInterface))
+                                               Warning (184,
+                                                        "The expression is never of type `" +
+                                                        TypeManager.CSharpName (probe_type) + "'");
+                               }
+                       }
+
+                       return this;
+               }                               
+       }
+
+       /// <summary>
+       ///   Implementation of the `as' operator.
+       /// </summary>
+       public class As : Probe {
+               public As (Expression expr, Expression probe_type, Location l)
+                       : base (expr, probe_type, l)
+               {
+               }
+
+               bool do_isinst = false;
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       expr.Emit (ec);
+
+                       if (do_isinst)
+                               ig.Emit (OpCodes.Isinst, probe_type);
+               }
+
+               static void Error_CannotConvertType (Type source, Type target, Location loc)
+               {
+                       Report.Error (
+                               39, loc, "as operator can not convert from `" +
+                               TypeManager.CSharpName (source) + "' to `" +
+                               TypeManager.CSharpName (target) + "'");
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expression e = base.DoResolve (ec);
+
+                       if (e == null)
+                               return null;
+
+                       type = probe_type;
+                       eclass = ExprClass.Value;
+                       Type etype = expr.Type;
+
+                       if (TypeManager.IsValueType (probe_type)){
+                               Report.Error (77, loc, "The as operator should be used with a reference type only (" +
+                                             TypeManager.CSharpName (probe_type) + " is a value type");
+                               return null;
+                       
+                       }
+                       
+                       e = Convert.ImplicitConversion (ec, expr, probe_type, loc);
+                       if (e != null){
+                               expr = e;
+                               do_isinst = false;
+                               return this;
+                       }
+
+                       if (Convert.ExplicitReferenceConversionExists (etype, probe_type)){
+                               do_isinst = true;
+                               return this;
+                       }
+
+                       Error_CannotConvertType (etype, probe_type, loc);
+                       return null;
+               }                               
+       }
+       
+       /// <summary>
+       ///   This represents a typecast in the source language.
+       ///
+       ///   FIXME: Cast expressions have an unusual set of parsing
+       ///   rules, we need to figure those out.
+       /// </summary>
+       public class Cast : Expression {
+               Expression target_type;
+               Expression expr;
+                       
+               public Cast (Expression cast_type, Expression expr, Location loc)
+               {
+                       this.target_type = cast_type;
+                       this.expr = expr;
+                       this.loc = loc;
+               }
+
+               public Expression TargetType {
+                       get {
+                               return target_type;
+                       }
+               }
+
+               public Expression Expr {
+                       get {
+                               return expr;
+                       }
+                       set {
+                               expr = value;
+                       }
+               }
+
+               bool CheckRange (EmitContext ec, long value, Type type, long min, long max)
+               {
+                       if (!ec.ConstantCheckState)
+                               return true;
+
+                       if ((value < min) || (value > max)) {
+                               Error (221, "Constant value `" + value + "' cannot be converted " +
+                                      "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " +
+                                      "syntax to override)");
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               bool CheckRange (EmitContext ec, ulong value, Type type, ulong max)
+               {
+                       if (!ec.ConstantCheckState)
+                               return true;
+
+                       if (value > max) {
+                               Error (221, "Constant value `" + value + "' cannot be converted " +
+                                      "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " +
+                                      "syntax to override)");
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               bool CheckUnsigned (EmitContext ec, long value, Type type)
+               {
+                       if (!ec.ConstantCheckState)
+                               return true;
+
+                       if (value < 0) {
+                               Error (221, "Constant value `" + value + "' cannot be converted " +
+                                      "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " +
+                                      "syntax to override)");
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               /// <summary>
+               ///   Attempts to do a compile-time folding of a constant cast.
+               /// </summary>
+               Expression TryReduce (EmitContext ec, Type target_type)
+               {
+                       Expression real_expr = expr;
+                       if (real_expr is EnumConstant)
+                               real_expr = ((EnumConstant) real_expr).Child;
+                               
+                       if (real_expr is ByteConstant){
+                               byte v = ((ByteConstant) real_expr).Value;
+       
+                               if (target_type == TypeManager.sbyte_type) {
+                                       if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
+                                               return null;
+                                       return new SByteConstant ((sbyte) v);
+                               }
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+                       if (real_expr is SByteConstant){
+                               sbyte v = ((SByteConstant) real_expr).Value;
+       
+                               if (target_type == TypeManager.byte_type) {
+                                       if (!CheckUnsigned (ec, v, target_type))
+                                               return null;
+                                       return new ByteConstant ((byte) v);
+                               }
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type) {
+                                       if (!CheckUnsigned (ec, v, target_type))
+                                               return null;
+                                       return new UShortConstant ((ushort) v);
+                               } if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type) {
+                                       if (!CheckUnsigned (ec, v, target_type))
+                                               return null;
+                                       return new UIntConstant ((uint) v);
+                               } if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type) {
+                                       if (!CheckUnsigned (ec, v, target_type))
+                                               return null;
+                                       return new ULongConstant ((ulong) v);
+                               }
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type) {
+                                       if (!CheckUnsigned (ec, v, target_type))
+                                               return null;
+                                       return new CharConstant ((char) v);
+                               }
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+                       if (real_expr is ShortConstant){
+                               short v = ((ShortConstant) real_expr).Value;
+       
+                               if (target_type == TypeManager.byte_type) {
+                                       if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue))
+                                               return null;
+                                       return new ByteConstant ((byte) v);
+                               }
+                               if (target_type == TypeManager.sbyte_type) {
+                                       if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
+                                               return null;
+                                       return new SByteConstant ((sbyte) v);
+                               }
+                               if (target_type == TypeManager.ushort_type) {
+                                       if (!CheckUnsigned (ec, v, target_type))
+                                               return null;
+                                       return new UShortConstant ((ushort) v);
+                               }
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type) {
+                                       if (!CheckUnsigned (ec, v, target_type))
+                                               return null;
+                                       return new UIntConstant ((uint) v);
+                               }
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type) {
+                                       if (!CheckUnsigned (ec, v, target_type))
+                                               return null;
+                                       return new ULongConstant ((ulong) v);
+                               }
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type) {
+                                       if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
+                                               return null;
+                                       return new CharConstant ((char) v);
+                               }
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+                       if (real_expr is UShortConstant){
+                               ushort v = ((UShortConstant) real_expr).Value;
+       
+                               if (target_type == TypeManager.byte_type) {
+                                       if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue))
+                                               return null;
+                                       return new ByteConstant ((byte) v);
+                               }
+                               if (target_type == TypeManager.sbyte_type) {
+                                       if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
+                                               return null;
+                                       return new SByteConstant ((sbyte) v);
+                               }
+                               if (target_type == TypeManager.short_type) {
+                                       if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue))
+                                               return null;
+                                       return new ShortConstant ((short) v);
+                               }
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type) {
+                                       if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
+                                               return null;
+                                       return new CharConstant ((char) v);
+                               }
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+                       if (real_expr is IntConstant){
+                               int v = ((IntConstant) real_expr).Value;
+       
+                               if (target_type == TypeManager.byte_type) {
+                                       if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue))
+                                               return null;
+                                       return new ByteConstant ((byte) v);
+                               }
+                               if (target_type == TypeManager.sbyte_type) {
+                                       if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
+                                               return null;
+                                       return new SByteConstant ((sbyte) v);
+                               }
+                               if (target_type == TypeManager.short_type) {
+                                       if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue))
+                                               return null;
+                                       return new ShortConstant ((short) v);
+                               }
+                               if (target_type == TypeManager.ushort_type) {
+                                       if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue))
+                                               return null;
+                                       return new UShortConstant ((ushort) v);
+                               }
+                               if (target_type == TypeManager.uint32_type) {
+                                       if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue))
+                                               return null;
+                                       return new UIntConstant ((uint) v);
+                               }
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type) {
+                                       if (!CheckUnsigned (ec, v, target_type))
+                                               return null;
+                                       return new ULongConstant ((ulong) v);
+                               }
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type) {
+                                       if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
+                                               return null;
+                                       return new CharConstant ((char) v);
+                               }
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+                       if (real_expr is UIntConstant){
+                               uint v = ((UIntConstant) real_expr).Value;
+       
+                               if (target_type == TypeManager.byte_type) {
+                                       if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
+                                               return null;
+                                       return new ByteConstant ((byte) v);
+                               }
+                               if (target_type == TypeManager.sbyte_type) {
+                                       if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
+                                               return null;
+                                       return new SByteConstant ((sbyte) v);
+                               }
+                               if (target_type == TypeManager.short_type) {
+                                       if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue))
+                                               return null;
+                                       return new ShortConstant ((short) v);
+                               }
+                               if (target_type == TypeManager.ushort_type) {
+                                       if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue))
+                                               return null;
+                                       return new UShortConstant ((ushort) v);
+                               }
+                               if (target_type == TypeManager.int32_type) {
+                                       if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue))
+                                               return null;
+                                       return new IntConstant ((int) v);
+                               }
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type) {
+                                       if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
+                                               return null;
+                                       return new CharConstant ((char) v);
+                               }
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+                       if (real_expr is LongConstant){
+                               long v = ((LongConstant) real_expr).Value;
+       
+                               if (target_type == TypeManager.byte_type) {
+                                       if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue))
+                                               return null;
+                                       return new ByteConstant ((byte) v);
+                               }
+                               if (target_type == TypeManager.sbyte_type) {
+                                       if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
+                                               return null;
+                                       return new SByteConstant ((sbyte) v);
+                               }
+                               if (target_type == TypeManager.short_type) {
+                                       if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue))
+                                               return null;
+                                       return new ShortConstant ((short) v);
+                               }
+                               if (target_type == TypeManager.ushort_type) {
+                                       if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue))
+                                               return null;
+                                       return new UShortConstant ((ushort) v);
+                               }
+                               if (target_type == TypeManager.int32_type) {
+                                       if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue))
+                                               return null;
+                                       return new IntConstant ((int) v);
+                               }
+                               if (target_type == TypeManager.uint32_type) {
+                                       if (!CheckRange (ec, v, target_type, UInt32.MinValue, UInt32.MaxValue))
+                                               return null;
+                                       return new UIntConstant ((uint) v);
+                               }
+                               if (target_type == TypeManager.uint64_type) {
+                                       if (!CheckUnsigned (ec, v, target_type))
+                                               return null;
+                                       return new ULongConstant ((ulong) v);
+                               }
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type) {
+                                       if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
+                                               return null;
+                                       return new CharConstant ((char) v);
+                               }
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+                       if (real_expr is ULongConstant){
+                               ulong v = ((ULongConstant) real_expr).Value;
+       
+                               if (target_type == TypeManager.byte_type) {
+                                       if (!CheckRange (ec, v, target_type, Byte.MaxValue))
+                                               return null;
+                                       return new ByteConstant ((byte) v);
+                               }
+                               if (target_type == TypeManager.sbyte_type) {
+                                       if (!CheckRange (ec, v, target_type, (ulong) SByte.MaxValue))
+                                               return null;
+                                       return new SByteConstant ((sbyte) v);
+                               }
+                               if (target_type == TypeManager.short_type) {
+                                       if (!CheckRange (ec, v, target_type, (ulong) Int16.MaxValue))
+                                               return null;
+                                       return new ShortConstant ((short) v);
+                               }
+                               if (target_type == TypeManager.ushort_type) {
+                                       if (!CheckRange (ec, v, target_type, UInt16.MaxValue))
+                                               return null;
+                                       return new UShortConstant ((ushort) v);
+                               }
+                               if (target_type == TypeManager.int32_type) {
+                                       if (!CheckRange (ec, v, target_type, Int32.MaxValue))
+                                               return null;
+                                       return new IntConstant ((int) v);
+                               }
+                               if (target_type == TypeManager.uint32_type) {
+                                       if (!CheckRange (ec, v, target_type, UInt32.MaxValue))
+                                               return null;
+                                       return new UIntConstant ((uint) v);
+                               }
+                               if (target_type == TypeManager.int64_type) {
+                                       if (!CheckRange (ec, v, target_type, (ulong) Int64.MaxValue))
+                                               return null;
+                                       return new LongConstant ((long) v);
+                               }
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type) {
+                                       if (!CheckRange (ec, v, target_type, Char.MaxValue))
+                                               return null;
+                                       return new CharConstant ((char) v);
+                               }
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+                       if (real_expr is FloatConstant){
+                               float v = ((FloatConstant) real_expr).Value;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+                       if (real_expr is DoubleConstant){
+                               double v = ((DoubleConstant) real_expr).Value;
+       
+                               if (target_type == TypeManager.byte_type)
+                                       return new ByteConstant ((byte) v);
+                               if (target_type == TypeManager.sbyte_type)
+                                       return new SByteConstant ((sbyte) v);
+                               if (target_type == TypeManager.short_type)
+                                       return new ShortConstant ((short) v);
+                               if (target_type == TypeManager.ushort_type)
+                                       return new UShortConstant ((ushort) v);
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.char_type)
+                                       return new CharConstant ((char) v);
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+
+                       if (real_expr is CharConstant){
+                               char v = ((CharConstant) real_expr).Value;
+                               
+                               if (target_type == TypeManager.byte_type) {
+                                       if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue))
+                                               return null;
+                                       return new ByteConstant ((byte) v);
+                               }
+                               if (target_type == TypeManager.sbyte_type) {
+                                       if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
+                                               return null;
+                                       return new SByteConstant ((sbyte) v);
+                               }
+                               if (target_type == TypeManager.short_type) {
+                                       if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue))
+                                               return null;
+                                       return new ShortConstant ((short) v);
+                               }
+                               if (target_type == TypeManager.int32_type)
+                                       return new IntConstant ((int) v);
+                               if (target_type == TypeManager.uint32_type)
+                                       return new UIntConstant ((uint) v);
+                               if (target_type == TypeManager.int64_type)
+                                       return new LongConstant ((long) v);
+                               if (target_type == TypeManager.uint64_type)
+                                       return new ULongConstant ((ulong) v);
+                               if (target_type == TypeManager.float_type)
+                                       return new FloatConstant ((float) v);
+                               if (target_type == TypeManager.double_type)
+                                       return new DoubleConstant ((double) v);
+                               if (target_type == TypeManager.char_type) {
+                                       if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
+                                               return null;
+                                       return new CharConstant ((char) v);
+                               }
+                               if (target_type == TypeManager.decimal_type)
+                                       return new DecimalConstant ((decimal) v);
+                       }
+
+                       return null;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return null;
+
+                       int errors = Report.Errors;
+
+                       type = ec.DeclSpace.ResolveType (target_type, false, Location);
+                       
+                       if (type == null)
+                               return null;
+
+                       eclass = ExprClass.Value;
+
+                       if (expr is Constant){
+                               Expression e = TryReduce (ec, type);
+
+                               if (e != null)
+                                       return e;
+                       }
+
+                       expr = Convert.ExplicitConversion (ec, expr, type, loc);
+                       return expr;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       //
+                       // This one will never happen
+                       //
+                       throw new Exception ("Should not happen");
+               }
+       }
+
+       /// <summary>
+       ///   Binary operators
+       /// </summary>
+       public class Binary : Expression {
+               public enum Operator : byte {
+                       Multiply, Division, Modulus,
+                       Addition, Subtraction,
+                       LeftShift, RightShift,
+                       LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual, 
+                       Equality, Inequality,
+                       BitwiseAnd,
+                       ExclusiveOr,
+                       BitwiseOr,
+                       LogicalAnd,
+                       LogicalOr,
+                       TOP
+               }
+
+               Operator oper;
+               Expression left, right;
+
+               //
+               // After resolution, method might contain the operator overload
+               // method.
+               //
+               protected MethodBase method;
+               ArrayList  Arguments;
+
+               bool DelegateOperation;
+
+               // This must be kept in sync with Operator!!!
+               public static readonly string [] oper_names;
+               
+               static Binary ()
+               {
+                       oper_names = new string [(int) Operator.TOP];
+
+                       oper_names [(int) Operator.Multiply] = "op_Multiply";
+                       oper_names [(int) Operator.Division] = "op_Division";
+                       oper_names [(int) Operator.Modulus] = "op_Modulus";
+                       oper_names [(int) Operator.Addition] = "op_Addition";
+                       oper_names [(int) Operator.Subtraction] = "op_Subtraction";
+                       oper_names [(int) Operator.LeftShift] = "op_LeftShift";
+                       oper_names [(int) Operator.RightShift] = "op_RightShift";
+                       oper_names [(int) Operator.LessThan] = "op_LessThan";
+                       oper_names [(int) Operator.GreaterThan] = "op_GreaterThan";
+                       oper_names [(int) Operator.LessThanOrEqual] = "op_LessThanOrEqual";
+                       oper_names [(int) Operator.GreaterThanOrEqual] = "op_GreaterThanOrEqual";
+                       oper_names [(int) Operator.Equality] = "op_Equality";
+                       oper_names [(int) Operator.Inequality] = "op_Inequality";
+                       oper_names [(int) Operator.BitwiseAnd] = "op_BitwiseAnd";
+                       oper_names [(int) Operator.BitwiseOr] = "op_BitwiseOr";
+                       oper_names [(int) Operator.ExclusiveOr] = "op_ExclusiveOr";
+                       oper_names [(int) Operator.LogicalOr] = "op_LogicalOr";
+                       oper_names [(int) Operator.LogicalAnd] = "op_LogicalAnd";
+               }
+
+               public Binary (Operator oper, Expression left, Expression right, Location loc)
+               {
+                       this.oper = oper;
+                       this.left = left;
+                       this.right = right;
+                       this.loc = loc;
+               }
+
+               public Operator Oper {
+                       get {
+                               return oper;
+                       }
+                       set {
+                               oper = value;
+                       }
+               }
+               
+               public Expression Left {
+                       get {
+                               return left;
+                       }
+                       set {
+                               left = value;
+                       }
+               }
+
+               public Expression Right {
+                       get {
+                               return right;
+                       }
+                       set {
+                               right = value;
+                       }
+               }
+
+
+               /// <summary>
+               ///   Returns a stringified representation of the Operator
+               /// </summary>
+               static string OperName (Operator oper)
+               {
+                       switch (oper){
+                       case Operator.Multiply:
+                               return "*";
+                       case Operator.Division:
+                               return "/";
+                       case Operator.Modulus:
+                               return "%";
+                       case Operator.Addition:
+                               return "+";
+                       case Operator.Subtraction:
+                               return "-";
+                       case Operator.LeftShift:
+                               return "<<";
+                       case Operator.RightShift:
+                               return ">>";
+                       case Operator.LessThan:
+                               return "<";
+                       case Operator.GreaterThan:
+                               return ">";
+                       case Operator.LessThanOrEqual:
+                               return "<=";
+                       case Operator.GreaterThanOrEqual:
+                               return ">=";
+                       case Operator.Equality:
+                               return "==";
+                       case Operator.Inequality:
+                               return "!=";
+                       case Operator.BitwiseAnd:
+                               return "&";
+                       case Operator.BitwiseOr:
+                               return "|";
+                       case Operator.ExclusiveOr:
+                               return "^";
+                       case Operator.LogicalOr:
+                               return "||";
+                       case Operator.LogicalAnd:
+                               return "&&";
+                       }
+
+                       return oper.ToString ();
+               }
+
+               public override string ToString ()
+               {
+                       return "operator " + OperName (oper) + "(" + left.ToString () + ", " +
+                               right.ToString () + ")";
+               }
+               
+               Expression ForceConversion (EmitContext ec, Expression expr, Type target_type)
+               {
+                       if (expr.Type == target_type)
+                               return expr;
+
+                       return Convert.ImplicitConversion (ec, expr, target_type, loc);
+               }
+
+               public static void Error_OperatorAmbiguous (Location loc, Operator oper, Type l, Type r)
+               {
+                       Report.Error (
+                               34, loc, "Operator `" + OperName (oper) 
+                               + "' is ambiguous on operands of type `"
+                               + TypeManager.CSharpName (l) + "' "
+                               + "and `" + TypeManager.CSharpName (r)
+                               + "'");
+               }
+
+               bool IsOfType (EmitContext ec, Type l, Type r, Type t, bool check_user_conversions)
+               {
+                       if ((l == t) || (r == t))
+                               return true;
+
+                       if (!check_user_conversions)
+                               return false;
+
+                       if (Convert.ImplicitUserConversionExists (ec, l, t))
+                               return true;
+                       else if (Convert.ImplicitUserConversionExists (ec, r, t))
+                               return true;
+                       else
+                               return false;
+               }
+
+               //
+               // Note that handling the case l == Decimal || r == Decimal
+               // is taken care of by the Step 1 Operator Overload resolution.
+               //
+               // If `check_user_conv' is true, we also check whether a user-defined conversion
+               // exists.  Note that we only need to do this if both arguments are of a user-defined
+               // type, otherwise ConvertImplict() already finds the user-defined conversion for us,
+               // so we don't explicitly check for performance reasons.
+               //
+               bool DoNumericPromotions (EmitContext ec, Type l, Type r, bool check_user_conv)
+               {
+                       if (IsOfType (ec, l, r, TypeManager.double_type, check_user_conv)){
+                               //
+                               // If either operand is of type double, the other operand is
+                               // conveted to type double.
+                               //
+                               if (r != TypeManager.double_type)
+                                       right = Convert.ImplicitConversion (ec, right, TypeManager.double_type, loc);
+                               if (l != TypeManager.double_type)
+                                       left = Convert.ImplicitConversion (ec, left, TypeManager.double_type, loc);
+                               
+                               type = TypeManager.double_type;
+                       } else if (IsOfType (ec, l, r, TypeManager.float_type, check_user_conv)){
+                               //
+                               // if either operand is of type float, the other operand is
+                               // converted to type float.
+                               //
+                               if (r != TypeManager.double_type)
+                                       right = Convert.ImplicitConversion (ec, right, TypeManager.float_type, loc);
+                               if (l != TypeManager.double_type)
+                                       left = Convert.ImplicitConversion (ec, left, TypeManager.float_type, loc);
+                               type = TypeManager.float_type;
+                       } else if (IsOfType (ec, l, r, TypeManager.uint64_type, check_user_conv)){
+                               Expression e;
+                               Type other;
+                               //
+                               // If either operand is of type ulong, the other operand is
+                               // converted to type ulong.  or an error ocurrs if the other
+                               // operand is of type sbyte, short, int or long
+                               //
+                               if (l == TypeManager.uint64_type){
+                                       if (r != TypeManager.uint64_type){
+                                               if (right is IntConstant){
+                                                       IntConstant ic = (IntConstant) right;
+                                                       
+                                                       e = Convert.TryImplicitIntConversion (l, ic);
+                                                       if (e != null)
+                                                               right = e;
+                                               } else if (right is LongConstant){
+                                                       long ll = ((LongConstant) right).Value;
+
+                                                       if (ll > 0)
+                                                               right = new ULongConstant ((ulong) ll);
+                                               } else {
+                                                       e = Convert.ImplicitNumericConversion (ec, right, l, loc);
+                                                       if (e != null)
+                                                               right = e;
+                                               }
+                                       }
+                                       other = right.Type;
+                               } else {
+                                       if (left is IntConstant){
+                                               e = Convert.TryImplicitIntConversion (r, (IntConstant) left);
+                                               if (e != null)
+                                                       left = e;
+                                       } else if (left is LongConstant){
+                                               long ll = ((LongConstant) left).Value;
+                                               
+                                               if (ll > 0)
+                                                       left = new ULongConstant ((ulong) ll);
+                                       } else {
+                                               e = Convert.ImplicitNumericConversion (ec, left, r, loc);
+                                               if (e != null)
+                                                       left = e;
+                                       }
+                                       other = left.Type;
+                               }
+
+                               if ((other == TypeManager.sbyte_type) ||
+                                   (other == TypeManager.short_type) ||
+                                   (other == TypeManager.int32_type) ||
+                                   (other == TypeManager.int64_type))
+                                       Error_OperatorAmbiguous (loc, oper, l, r);
+                               type = TypeManager.uint64_type;
+                       } else if (IsOfType (ec, l, r, TypeManager.int64_type, check_user_conv)){
+                               //
+                               // If either operand is of type long, the other operand is converted
+                               // to type long.
+                               //
+                               if (l != TypeManager.int64_type)
+                                       left = Convert.ImplicitConversion (ec, left, TypeManager.int64_type, loc);
+                               if (r != TypeManager.int64_type)
+                                       right = Convert.ImplicitConversion (ec, right, TypeManager.int64_type, loc);
+                               
+                               type = TypeManager.int64_type;
+                       } else if (IsOfType (ec, l, r, TypeManager.uint32_type, check_user_conv)){
+                               //
+                               // If either operand is of type uint, and the other
+                               // operand is of type sbyte, short or int, othe operands are
+                               // converted to type long.
+                               //
+                               Type other = null;
+                               
+                               if (l == TypeManager.uint32_type){
+                                       if (right is IntConstant){
+                                               IntConstant ic = (IntConstant) right;
+                                               int val = ic.Value;
+                                               
+                                               if (val >= 0){
+                                                       right = new UIntConstant ((uint) val);
+                                                       type = l;
+                                                       
+                                                       return true;
+                                               }
+                                       }
+                                       other = r;
+                               } else if (r == TypeManager.uint32_type){
+                                       if (left is IntConstant){
+                                               IntConstant ic = (IntConstant) left;
+                                               int val = ic.Value;
+                                               
+                                               if (val >= 0){
+                                                       left = new UIntConstant ((uint) val);
+                                                       type = r;
+                                                       return true;
+                                               }
+                                       }
+                                       
+                                       other = l;
+                               }
+
+                               if ((other == TypeManager.sbyte_type) ||
+                                   (other == TypeManager.short_type) ||
+                                   (other == TypeManager.int32_type)){
+                                       left = ForceConversion (ec, left, TypeManager.int64_type);
+                                       right = ForceConversion (ec, right, TypeManager.int64_type);
+                                       type = TypeManager.int64_type;
+                               } else {
+                                       //
+                                       // if either operand is of type uint, the other
+                                       // operand is converd to type uint
+                                       //
+                                       left = ForceConversion (ec, left, TypeManager.uint32_type);
+                                       right = ForceConversion (ec, right, TypeManager.uint32_type);
+                                       type = TypeManager.uint32_type;
+                               } 
+                       } else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){
+                               if (l != TypeManager.decimal_type)
+                                       left = Convert.ImplicitConversion (ec, left, TypeManager.decimal_type, loc);
+
+                               if (r != TypeManager.decimal_type)
+                                       right = Convert.ImplicitConversion (ec, right, TypeManager.decimal_type, loc);
+                               type = TypeManager.decimal_type;
+                       } else {
+                               left = ForceConversion (ec, left, TypeManager.int32_type);
+                               right = ForceConversion (ec, right, TypeManager.int32_type);
+
+                               type = TypeManager.int32_type;
+                       }
+
+                       return (left != null) && (right != null);
+               }
+
+               static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
+               {
+                       Report.Error (19, loc,
+                              "Operator " + name + " cannot be applied to operands of type `" +
+                              TypeManager.CSharpName (l) + "' and `" +
+                              TypeManager.CSharpName (r) + "'");
+               }
+               
+               void Error_OperatorCannotBeApplied ()
+               {
+                       Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);
+               }
+
+               static bool is_32_or_64 (Type t)
+               {
+                       return (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
+                               t == TypeManager.int64_type || t == TypeManager.uint64_type);
+               }
+
+               static bool is_unsigned (Type t)
+               {
+                       return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
+                               t == TypeManager.short_type || t == TypeManager.byte_type);
+               }
+
+               static bool is_user_defined (Type t)
+               {
+                       if (t.IsSubclassOf (TypeManager.value_type) &&
+                           (!TypeManager.IsBuiltinType (t) || t == TypeManager.decimal_type))
+                               return true;
+                       else
+                               return false;
+               }
+                                       
+               Expression CheckShiftArguments (EmitContext ec)
+               {
+                       Expression e;
+                       Type l = left.Type;
+                       Type r = right.Type;
+
+                       e = ForceConversion (ec, right, TypeManager.int32_type);
+                       if (e == null){
+                               Error_OperatorCannotBeApplied ();
+                               return null;
+                       }
+                       right = e;
+
+                       if (((e = Convert.ImplicitConversion (ec, left, TypeManager.int32_type, loc)) != null) ||
+                           ((e = Convert.ImplicitConversion (ec, left, TypeManager.uint32_type, loc)) != null) ||
+                           ((e = Convert.ImplicitConversion (ec, left, TypeManager.int64_type, loc)) != null) ||
+                           ((e = Convert.ImplicitConversion (ec, left, TypeManager.uint64_type, loc)) != null)){
+                               left = e;
+                               type = e.Type;
+
+                               return this;
+                       }
+                       Error_OperatorCannotBeApplied ();
+                       return null;
+               }
+
+               Expression ResolveOperator (EmitContext ec)
+               {
+                       Type l = left.Type;
+                       Type r = right.Type;
+
+                       bool overload_failed = false;
+
+                       //
+                       // Special cases: string comapred to null
+                       //
+                       if (oper == Operator.Equality || oper == Operator.Inequality){
+                               if ((l == TypeManager.string_type && (right is NullLiteral)) ||
+                                   (r == TypeManager.string_type && (left is NullLiteral))){
+                                       Type = TypeManager.bool_type;
+                                       
+                                       return this;
+                               }
+                       }
+
+                       //
+                       // Do not perform operator overload resolution when both sides are
+                       // built-in types
+                       //
+                       if (!(TypeManager.IsCLRType (l) && TypeManager.IsCLRType (r))){
+                               //
+                               // Step 1: Perform Operator Overload location
+                               //
+                               Expression left_expr, right_expr;
+                               
+                               string op = oper_names [(int) oper];
+                               
+                               MethodGroupExpr union;
+                               left_expr = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc);
+                               if (r != l){
+                                       right_expr = MemberLookup (
+                                               ec, r, op, MemberTypes.Method, AllBindingFlags, loc);
+                                       union = Invocation.MakeUnionSet (left_expr, right_expr, loc);
+                               } else
+                                       union = (MethodGroupExpr) left_expr;
+                               
+                               if (union != null) {
+                                       Arguments = new ArrayList ();
+                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
+                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                       
+                                       method = Invocation.OverloadResolve (ec, union, Arguments, Location.Null);
+                                       if (method != null) {
+                                               MethodInfo mi = (MethodInfo) method;
+                                               
+                                               type = mi.ReturnType;
+                                               return this;
+                                       } else {
+                                               overload_failed = true;
+                                       }
+                               }
+                       }
+                       
+                       //
+                       // Step 2: Default operations on CLI native types.
+                       //
+
+                       //
+                       // Step 0: String concatenation (because overloading will get this wrong)
+                       //
+                       if (oper == Operator.Addition){
+                               //
+                               // If any of the arguments is a string, cast to string
+                               //
+                               
+                               if (l == TypeManager.string_type){
+                                       
+                                       if (r == TypeManager.void_type) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                                       
+                                       if (r == TypeManager.string_type){
+                                               if (left is Constant && right is Constant){
+                                                       StringConstant ls = (StringConstant) left;
+                                                       StringConstant rs = (StringConstant) right;
+                                                       
+                                                       return new StringConstant (
+                                                               ls.Value + rs.Value);
+                                               }
+
+                                               if (left is Binary){
+                                                       Binary b = (Binary) left;
+
+                                                       //
+                                                       // Call String.Concat (string, string, string) or
+                                                       // String.Concat (string, string, string, string)
+                                                       // if possible.
+                                                       //
+                                                       if (b.oper == Operator.Addition &&
+                                                           (b.method == TypeManager.string_concat_string_string ||
+                                                            b.method == TypeManager.string_concat_string_string_string)){
+                                                               ArrayList bargs = b.Arguments;
+                                                               int count = bargs.Count;
+                                                               
+                                                               if (count == 2){
+                                                                       Arguments = bargs;
+                                                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                                                       type = TypeManager.string_type;
+                                                                       method = TypeManager.string_concat_string_string_string;
+                                                                       
+                                                                       return this;
+                                                               } else if (count == 3){
+                                                                       Arguments = bargs;
+                                                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                                                       type = TypeManager.string_type;
+                                                                       method = TypeManager.string_concat_string_string_string_string;                                                                 
+                                                                       return this;
+                                                               }
+                                                       }
+                                               }
+
+                                               // string + string
+                                               method = TypeManager.string_concat_string_string;
+                                       } else {
+                                               // string + object
+                                               method = TypeManager.string_concat_object_object;
+                                               right = Convert.ImplicitConversion (
+                                                       ec, right, TypeManager.object_type, loc);
+                                               if (right == null){
+                                                       Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                                                       return null;
+                                               }
+                                       }
+                                       type = TypeManager.string_type;
+
+                                       Arguments = new ArrayList ();
+                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
+                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+
+                                       return this;
+                                       
+                               } else if (r == TypeManager.string_type){
+                                       // object + string
+
+                                       if (l == TypeManager.void_type) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                                       
+                                       method = TypeManager.string_concat_object_object;
+                                       left = Convert.ImplicitConversion (ec, left, TypeManager.object_type, loc);
+                                       if (left == null){
+                                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                                               return null;
+                                       }
+                                       Arguments = new ArrayList ();
+                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
+                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+
+                                       type = TypeManager.string_type;
+
+                                       return this;
+                               }
+
+                               //
+                               // Transform a + ( - b) into a - b
+                               //
+                               if (right is Unary){
+                                       Unary right_unary = (Unary) right;
+
+                                       if (right_unary.Oper == Unary.Operator.UnaryNegation){
+                                               oper = Operator.Subtraction;
+                                               right = right_unary.Expr;
+                                               r = right.Type;
+                                       }
+                               }
+                       }
+
+                       if (oper == Operator.Equality || oper == Operator.Inequality){
+                               if (l == TypeManager.bool_type || r == TypeManager.bool_type){
+                                       if (r != TypeManager.bool_type || l != TypeManager.bool_type){
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                                       
+                                       type = TypeManager.bool_type;
+                                       return this;
+                               }
+
+                               //
+                               // operator != (object a, object b)
+                               // operator == (object a, object b)
+                               //
+                               // For this to be used, both arguments have to be reference-types.
+                               // Read the rationale on the spec (14.9.6)
+                               //
+                               // Also, if at compile time we know that the classes do not inherit
+                               // one from the other, then we catch the error there.
+                               //
+                               if (!(l.IsValueType || r.IsValueType)){
+                                       type = TypeManager.bool_type;
+
+                                       if (l == r)
+                                               return this;
+                                       
+                                       if (l.IsSubclassOf (r) || r.IsSubclassOf (l))
+                                               return this;
+
+                                       //
+                                       // Also, a standard conversion must exist from either one
+                                       //
+                                       if (!(Convert.ImplicitStandardConversionExists (left, r) ||
+                                             Convert.ImplicitStandardConversionExists (right, l))){
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                                       //
+                                       // We are going to have to convert to an object to compare
+                                       //
+                                       if (l != TypeManager.object_type)
+                                               left = new EmptyCast (left, TypeManager.object_type);
+                                       if (r != TypeManager.object_type)
+                                               right = new EmptyCast (right, TypeManager.object_type);
+
+                                       //
+                                       // FIXME: CSC here catches errors cs254 and cs252
+                                       //
+                                       return this;
+                               }
+
+                               //
+                               // One of them is a valuetype, but the other one is not.
+                               //
+                               if (!l.IsValueType || !r.IsValueType) {
+                                       Error_OperatorCannotBeApplied ();
+                                       return null;
+                               }
+                       }
+
+                       // Only perform numeric promotions on:
+                       // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
+                       //
+                       if (oper == Operator.Addition || oper == Operator.Subtraction) {
+                               if (l.IsSubclassOf (TypeManager.delegate_type) &&
+                                   r.IsSubclassOf (TypeManager.delegate_type)) {
+                                       
+                                       Arguments = new ArrayList ();
+                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
+                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                                       
+                                       if (oper == Operator.Addition)
+                                               method = TypeManager.delegate_combine_delegate_delegate;
+                                       else
+                                               method = TypeManager.delegate_remove_delegate_delegate;
+
+                                       if (l != r) {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+
+                                       DelegateOperation = true;
+                                       type = l;
+                                       return this;
+                               }
+
+                               //
+                               // Pointer arithmetic:
+                               //
+                               // T* operator + (T* x, int y);
+                               // T* operator + (T* x, uint y);
+                               // T* operator + (T* x, long y);
+                               // T* operator + (T* x, ulong y);
+                               //
+                               // T* operator + (int y,   T* x);
+                               // T* operator + (uint y,  T *x);
+                               // T* operator + (long y,  T *x);
+                               // T* operator + (ulong y, T *x);
+                               //
+                               // T* operator - (T* x, int y);
+                               // T* operator - (T* x, uint y);
+                               // T* operator - (T* x, long y);
+                               // T* operator - (T* x, ulong y);
+                               //
+                               // long operator - (T* x, T *y)
+                               //
+                               if (l.IsPointer){
+                                       if (r.IsPointer && oper == Operator.Subtraction){
+                                               if (r == l)
+                                                       return new PointerArithmetic (
+                                                               false, left, right, TypeManager.int64_type,
+                                                               loc);
+                                       } else if (is_32_or_64 (r))
+                                               return new PointerArithmetic (
+                                                       oper == Operator.Addition, left, right, l, loc);
+                               } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)
+                                       return new PointerArithmetic (
+                                               true, right, left, r, loc);
+                       }
+                       
+                       //
+                       // Enumeration operators
+                       //
+                       bool lie = TypeManager.IsEnumType (l);
+                       bool rie = TypeManager.IsEnumType (r);
+                       if (lie || rie){
+                               Expression temp;
+
+                               // U operator - (E e, E f)
+                               if (lie && rie && oper == Operator.Subtraction){
+                                       if (l == r){
+                                               type = TypeManager.EnumToUnderlying (l);
+                                               return this;
+                                       } 
+                                       Error_OperatorCannotBeApplied ();
+                                       return null;
+                               }
+                                       
+                               //
+                               // operator + (E e, U x)
+                               // operator - (E e, U x)
+                               //
+                               if (oper == Operator.Addition || oper == Operator.Subtraction){
+                                       Type enum_type = lie ? l : r;
+                                       Type other_type = lie ? r : l;
+                                       Type underlying_type = TypeManager.EnumToUnderlying (enum_type);
+;
+                                       
+                                       if (underlying_type != other_type){
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+
+                                       type = enum_type;
+                                       return this;
+                               }
+                               
+                               if (!rie){
+                                       temp = Convert.ImplicitConversion (ec, right, l, loc);
+                                       if (temp != null)
+                                               right = temp;
+                                       else {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                               } if (!lie){
+                                       temp = Convert.ImplicitConversion (ec, left, r, loc);
+                                       if (temp != null){
+                                               left = temp;
+                                               l = r;
+                                       } else {
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                               }
+
+                               if (oper == Operator.Equality || oper == Operator.Inequality ||
+                                   oper == Operator.LessThanOrEqual || oper == Operator.LessThan ||
+                                   oper == Operator.GreaterThanOrEqual || oper == Operator.GreaterThan){
+                                       if (left.Type != right.Type){
+                                               Error_OperatorCannotBeApplied ();
+                                               return null;
+                                       }
+                                       type = TypeManager.bool_type;
+                                       return this;
+                               }
+
+                               if (oper == Operator.BitwiseAnd ||
+                                   oper == Operator.BitwiseOr ||
+                                   oper == Operator.ExclusiveOr){
+                                       type = l;
+                                       return this;
+                               }
+                               Error_OperatorCannotBeApplied ();
+                               return null;
+                       }
+                       
+                       if (oper == Operator.LeftShift || oper == Operator.RightShift)
+                               return CheckShiftArguments (ec);
+
+                       if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
+                               if (l == TypeManager.bool_type && r == TypeManager.bool_type) {
+                                       type = TypeManager.bool_type;
+                                       return this;
+                               }
+
+                               if (l != r) {
+                                       Error_OperatorCannotBeApplied ();
+                                       return null;
+                               }
+
+                               Expression e = new ConditionalLogicalOperator (
+                                       oper == Operator.LogicalAnd, left, right, l, loc);
+                               return e.Resolve (ec);
+                       } 
+
+                       //
+                       // operator & (bool x, bool y)
+                       // operator | (bool x, bool y)
+                       // operator ^ (bool x, bool y)
+                       //
+                       if (l == TypeManager.bool_type && r == TypeManager.bool_type){
+                               if (oper == Operator.BitwiseAnd ||
+                                   oper == Operator.BitwiseOr ||
+                                   oper == Operator.ExclusiveOr){
+                                       type = l;
+                                       return this;
+                               }
+                       }
+                       
+                       //
+                       // Pointer comparison
+                       //
+                       if (l.IsPointer && r.IsPointer){
+                               if (oper == Operator.Equality || oper == Operator.Inequality ||
+                                   oper == Operator.LessThan || oper == Operator.LessThanOrEqual ||
+                                   oper == Operator.GreaterThan || oper == Operator.GreaterThanOrEqual){
+                                       type = TypeManager.bool_type;
+                                       return this;
+                               }
+                       }
+                       
+                       //
+                       // We are dealing with numbers
+                       //
+                       if (overload_failed){
+                               Error_OperatorCannotBeApplied ();
+                               return null;
+                       }
+
+                       //
+                       // This will leave left or right set to null if there is an error
+                       //
+                       bool check_user_conv = is_user_defined (l) && is_user_defined (r);
+                       DoNumericPromotions (ec, l, r, check_user_conv);
+                       if (left == null || right == null){
+                               Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
+                               return null;
+                       }
+
+                       //
+                       // reload our cached types if required
+                       //
+                       l = left.Type;
+                       r = right.Type;
+                       
+                       if (oper == Operator.BitwiseAnd ||
+                           oper == Operator.BitwiseOr ||
+                           oper == Operator.ExclusiveOr){
+                               if (l == r){
+                                       if (!((l == TypeManager.int32_type) ||
+                                             (l == TypeManager.uint32_type) ||
+                                             (l == TypeManager.short_type) ||
+                                             (l == TypeManager.ushort_type) ||
+                                             (l == TypeManager.int64_type) ||
+                                             (l == TypeManager.uint64_type)))
+                                               type = l;
+                               } else {
+                                       Error_OperatorCannotBeApplied ();
+                                       return null;
+                               }
+                       }
+
+                       if (oper == Operator.Equality ||
+                           oper == Operator.Inequality ||
+                           oper == Operator.LessThanOrEqual ||
+                           oper == Operator.LessThan ||
+                           oper == Operator.GreaterThanOrEqual ||
+                           oper == Operator.GreaterThan){
+                               type = TypeManager.bool_type;
+                       }
+
+                       return this;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       left = left.Resolve (ec);
+                       right = right.Resolve (ec);
+
+                       if (left == null || right == null)
+                               return null;
+
+                       eclass = ExprClass.Value;
+
+                       Constant rc = right as Constant;
+                       Constant lc = left as Constant;
+
+                       if (rc != null & lc != null){
+                               Expression e = ConstantFold.BinaryFold (
+                                       ec, oper, lc, rc, loc);
+                                       if (e != null)
+                                               return e;
+                       }
+
+                       return ResolveOperator (ec);
+               }
+
+               /// <remarks>
+               ///   EmitBranchable is called from Statement.EmitBoolExpression in the
+               ///   context of a conditional bool expression.  This function will return
+               ///   false if it is was possible to use EmitBranchable, or true if it was.
+               ///
+               ///   The expression's code is generated, and we will generate a branch to `target'
+               ///   if the resulting expression value is equal to isTrue
+               /// </remarks>
+               public bool EmitBranchable (EmitContext ec, Label target, bool onTrue)
+               {
+                       if (method != null)
+                               return false;
+
+                       ILGenerator ig = ec.ig;
+
+                       //
+                       // This is more complicated than it looks, but its just to avoid
+                       // duplicated tests: basically, we allow ==, !=, >, <, >= and <=
+                       // but on top of that we want for == and != to use a special path
+                       // if we are comparing against null
+                       //
+                       if (oper == Operator.Equality || oper == Operator.Inequality){
+                               bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
+
+                               if (left is NullLiteral){
+                                       right.Emit (ec);
+                                       if (my_on_true)
+                                               ig.Emit (OpCodes.Brtrue, target);
+                                       else
+                                               ig.Emit (OpCodes.Brfalse, target);
+                                       return true;
+                               } else if (right is NullLiteral){
+                                       left.Emit (ec);
+                                       if (my_on_true)
+                                               ig.Emit (OpCodes.Brtrue, target);
+                                       else
+                                               ig.Emit (OpCodes.Brfalse, target);
+                                       return true;
+                               } else if (left is BoolConstant){
+                                       right.Emit (ec);
+                                       if (my_on_true != ((BoolConstant) left).Value)
+                                               ig.Emit (OpCodes.Brtrue, target);
+                                       else
+                                               ig.Emit (OpCodes.Brfalse, target);
+                                       return true;
+                               } else if (right is BoolConstant){
+                                       left.Emit (ec);
+                                       if (my_on_true != ((BoolConstant) right).Value)
+                                               ig.Emit (OpCodes.Brtrue, target);
+                                       else
+                                               ig.Emit (OpCodes.Brfalse, target);
+                                       return true;
+                               }
+
+                       } else if (oper == Operator.LogicalAnd){
+                               if (left is Binary){
+                                       Binary left_binary = (Binary) left;
+
+                                       if (onTrue){
+                                               Label tests_end = ig.DefineLabel ();
+                                               
+                                               if (left_binary.EmitBranchable (ec, tests_end, false)){
+                                                       if (right is Binary){
+                                                               Binary right_binary = (Binary) right;
+
+                                                               if (right_binary.EmitBranchable (ec, target, true)){
+                                                                       ig.MarkLabel (tests_end);
+                                                                       return true;
+                                                               }
+                                                       }
+                                                       right.Emit (ec);
+                                                       ig.Emit (OpCodes.Brtrue, target);
+                                                       ig.MarkLabel (tests_end);
+                                                       return true;
+                                               }
+                                       } else {
+                                               if (left_binary.EmitBranchable (ec, target, false)){
+                                                       if (right is Binary){
+                                                               Binary right_binary = (Binary) right;
+                                                               
+                                                               if (right_binary.EmitBranchable (ec, target, false))
+                                                                       return true;
+                                                       }
+                                                       right.Emit (ec);
+                                                       if (onTrue)
+                                                               ig.Emit (OpCodes.Brtrue, target);
+                                                       else
+                                                               ig.Emit (OpCodes.Brfalse, target);
+                                                       return true;
+                                               }
+                                       }
+                                       //
+                                       // Give up, and let the regular Emit work, but we could
+                                       // also optimize the left-non-Branchable, but-right-Branchable
+                                       //
+                               }
+                               return false;
+                       } else if (oper == Operator.LogicalOr){
+                               if (left is Binary){
+                                       Binary left_binary = (Binary) left;
+
+                                       if (onTrue){
+                                               if (left_binary.EmitBranchable (ec, target, true)){
+                                                       if (right is Binary){
+                                                               Binary right_binary = (Binary) right;
+                                                               
+                                                               if (right_binary.EmitBranchable (ec, target, true))
+                                                                       return true;
+                                                       }
+                                                       right.Emit (ec);
+                                                       ig.Emit (OpCodes.Brtrue, target);
+                                                       return true;
+                                               }
+                                               
+                                               //
+                                               // Give up, and let the regular Emit work, but we could
+                                               // also optimize the left-non-Branchable, but-right-Branchable
+                                               //
+                                       } else {
+                                               Label tests_end = ig.DefineLabel ();
+                                               
+                                               if (left_binary.EmitBranchable (ec, tests_end, true)){
+                                                       if (right is Binary){
+                                                               Binary right_binary = (Binary) right;
+
+                                                               if (right_binary.EmitBranchable (ec, target, false)){
+                                                                       ig.MarkLabel (tests_end);
+                                                                       return true;
+                                                               }
+                                                       }
+                                                       right.Emit (ec);
+                                                       ig.Emit (OpCodes.Brfalse, target);
+                                                       ig.MarkLabel (tests_end);
+                                                       return true;
+                                               }
+                                       }
+                               }
+                               
+                               return false;
+                       } else if (!(oper == Operator.LessThan ||
+                               oper == Operator.GreaterThan ||
+                               oper == Operator.LessThanOrEqual ||
+                               oper == Operator.GreaterThanOrEqual))
+                               return false;
+                       
+                       left.Emit (ec);
+                       right.Emit (ec);
+
+                       Type t = left.Type;
+                       bool isUnsigned = is_unsigned (t);
+
+                       switch (oper){
+                       case Operator.Equality:
+                               if (onTrue)
+                                       ig.Emit (OpCodes.Beq, target);
+                               else
+                                       ig.Emit (OpCodes.Bne_Un, target);
+                               break;
+
+                       case Operator.Inequality:
+                               if (onTrue)
+                                       ig.Emit (OpCodes.Bne_Un, target);
+                               else
+                                       ig.Emit (OpCodes.Beq, target);
+                               break;
+
+                       case Operator.LessThan:
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Blt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Blt, target);
+                               else
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bge_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bge, target);
+                               break;
+
+                       case Operator.GreaterThan:
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bgt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bgt, target);
+                               else
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Ble_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Ble, target);
+                               break;
+
+                       case Operator.LessThanOrEqual:
+                               if (t == TypeManager.double_type || t == TypeManager.float_type)
+                                       isUnsigned = true;
+
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Ble_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Ble, target);
+                               else
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bgt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bgt, target);
+                               break;
+
+
+                       case Operator.GreaterThanOrEqual:
+                               if (t == TypeManager.double_type || t == TypeManager.float_type)
+                                       isUnsigned = true;
+                               if (onTrue)
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Bge_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Bge, target);
+                               else
+                                       if (isUnsigned)
+                                               ig.Emit (OpCodes.Blt_Un, target);
+                                       else
+                                               ig.Emit (OpCodes.Blt, target);
+                               break;
+
+                       default:
+                               return false;
+                       }
+                       
+                       return true;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Type l = left.Type;
+                       Type r = right.Type;
+                       OpCode opcode;
+
+                       if (method != null) {
+
+                               // Note that operators are static anyway
+                               
+                               if (Arguments != null) 
+                                       Invocation.EmitArguments (ec, method, Arguments);
+                               
+                               if (method is MethodInfo)
+                                       ig.Emit (OpCodes.Call, (MethodInfo) method);
+                               else
+                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+
+                               if (DelegateOperation)
+                                       ig.Emit (OpCodes.Castclass, type);
+                                       
+                               return;
+                       }
+
+                       //
+                       // Handle short-circuit operators differently
+                       // than the rest
+                       //
+                       if (oper == Operator.LogicalAnd){
+                               Label load_zero = ig.DefineLabel ();
+                               Label end = ig.DefineLabel ();
+                               bool process = true;
+
+                               if (left is Binary){
+                                       Binary left_binary = (Binary) left;
+
+                                       if (left_binary.EmitBranchable (ec, load_zero, false)){
+                                               right.Emit (ec);
+                                               ig.Emit (OpCodes.Br, end);
+                                               process = false;
+                                       }
+                               }
+
+                               if (process){
+                                       left.Emit (ec);
+                                       ig.Emit (OpCodes.Brfalse, load_zero);
+                                       right.Emit (ec);
+                                       ig.Emit (OpCodes.Br, end);
+                               }
+                               ig.MarkLabel (load_zero);
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               ig.MarkLabel (end);
+                               return;
+                       } else if (oper == Operator.LogicalOr){
+                               Label load_one = ig.DefineLabel ();
+                               Label end = ig.DefineLabel ();
+                               bool process = true;
+                               
+                               if (left is Binary){
+                                       Binary left_binary = (Binary) left;
+
+                                       if (left_binary.EmitBranchable (ec, load_one, true)){
+                                               right.Emit (ec);
+                                               ig.Emit (OpCodes.Br, end);
+                                               process = false;
+                                       } 
+                               }
+
+                               if (process){
+                                       left.Emit (ec);
+                                       ig.Emit (OpCodes.Brtrue, load_one);
+                                       right.Emit (ec);
+                                       ig.Emit (OpCodes.Br, end);
+                               }
+                               ig.MarkLabel (load_one);
+                               ig.Emit (OpCodes.Ldc_I4_1);
+                               ig.MarkLabel (end);
+                               return;
+                       }
+                       
+                       left.Emit (ec);
+                       right.Emit (ec);
+
+                       bool isUnsigned = is_unsigned (left.Type);
+
+                       switch (oper){
+                       case Operator.Multiply:
+                               if (ec.CheckState){
+                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                               opcode = OpCodes.Mul_Ovf;
+                                       else if (isUnsigned)
+                                               opcode = OpCodes.Mul_Ovf_Un;
+                                       else
+                                               opcode = OpCodes.Mul;
+                               } else
+                                       opcode = OpCodes.Mul;
+
+                               break;
+
+                       case Operator.Division:
+                               if (isUnsigned)
+                                       opcode = OpCodes.Div_Un;
+                               else
+                                       opcode = OpCodes.Div;
+                               break;
+
+                       case Operator.Modulus:
+                               if (isUnsigned)
+                                       opcode = OpCodes.Rem_Un;
+                               else
+                                       opcode = OpCodes.Rem;
+                               break;
+
+                       case Operator.Addition:
+                               if (ec.CheckState){
+                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                               opcode = OpCodes.Add_Ovf;
+                                       else if (isUnsigned)
+                                               opcode = OpCodes.Add_Ovf_Un;
+                                       else
+                                               opcode = OpCodes.Add;
+                               } else
+                                       opcode = OpCodes.Add;
+                               break;
+
+                       case Operator.Subtraction:
+                               if (ec.CheckState){
+                                       if (l == TypeManager.int32_type || l == TypeManager.int64_type)
+                                               opcode = OpCodes.Sub_Ovf;
+                                       else if (isUnsigned)
+                                               opcode = OpCodes.Sub_Ovf_Un;
+                                       else
+                                               opcode = OpCodes.Sub;
+                               } else
+                                       opcode = OpCodes.Sub;
+                               break;
+
+                       case Operator.RightShift:
+                               if (isUnsigned)
+                                       opcode = OpCodes.Shr_Un;
+                               else
+                                       opcode = OpCodes.Shr;
+                               break;
+                               
+                       case Operator.LeftShift:
+                               opcode = OpCodes.Shl;
+                               break;
+
+                       case Operator.Equality:
+                               opcode = OpCodes.Ceq;
+                               break;
+
+                       case Operator.Inequality:
+                               ig.Emit (OpCodes.Ceq);
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               
+                               opcode = OpCodes.Ceq;
+                               break;
+
+                       case Operator.LessThan:
+                               if (isUnsigned)
+                                       opcode = OpCodes.Clt_Un;
+                               else
+                                       opcode = OpCodes.Clt;
+                               break;
+
+                       case Operator.GreaterThan:
+                               if (isUnsigned)
+                                       opcode = OpCodes.Cgt_Un;
+                               else
+                                       opcode = OpCodes.Cgt;
+                               break;
+
+                       case Operator.LessThanOrEqual:
+                               Type lt = left.Type;
+                               
+                               if (isUnsigned || (lt == TypeManager.double_type || lt == TypeManager.float_type))
+                                       ig.Emit (OpCodes.Cgt_Un);
+                               else
+                                       ig.Emit (OpCodes.Cgt);
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               
+                               opcode = OpCodes.Ceq;
+                               break;
+
+                       case Operator.GreaterThanOrEqual:
+                               Type le = left.Type;
+                               
+                               if (isUnsigned || (le == TypeManager.double_type || le == TypeManager.float_type))
+                                       ig.Emit (OpCodes.Clt_Un);
+                               else
+                                       ig.Emit (OpCodes.Clt);
+                               
+                               ig.Emit (OpCodes.Ldc_I4_1);
+                               
+                               opcode = OpCodes.Sub;
+                               break;
+
+                       case Operator.BitwiseOr:
+                               opcode = OpCodes.Or;
+                               break;
+
+                       case Operator.BitwiseAnd:
+                               opcode = OpCodes.And;
+                               break;
+
+                       case Operator.ExclusiveOr:
+                               opcode = OpCodes.Xor;
+                               break;
+
+                       default:
+                               throw new Exception ("This should not happen: Operator = "
+                                                    + oper.ToString ());
+                       }
+
+                       ig.Emit (opcode);
+               }
+
+               public bool IsBuiltinOperator {
+                       get {
+                               return method == null;
+                       }
+               }
+       }
+
+       //
+       // User-defined conditional logical operator
+       public class ConditionalLogicalOperator : Expression {
+               Expression left, right;
+               bool is_and;
+
+               public ConditionalLogicalOperator (bool is_and, Expression left, Expression right, Type t, Location loc)
+               {
+                       type = t;
+                       eclass = ExprClass.Value;
+                       this.loc = loc;
+                       this.left = left;
+                       this.right = right;
+                       this.is_and = is_and;
+               }
+
+               protected void Error19 ()
+               {
+                       Binary.Error_OperatorCannotBeApplied (loc, is_and ? "&&" : "||", type, type);
+               }
+
+               protected void Error218 ()
+               {
+                       Error (218, "The type ('" + TypeManager.CSharpName (type) + "') must contain " +
+                              "declarations of operator true and operator false");
+               }
+
+               Expression op_true, op_false, op;
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       MethodInfo method;
+                       Expression operator_group;
+
+                       operator_group = MethodLookup (ec, type, is_and ? "op_BitwiseAnd" : "op_BitwiseOr", loc);
+                       if (operator_group == null) {
+                               Error19 ();
+                               return null;
+                       }
+
+                       ArrayList arguments = new ArrayList ();
+                       arguments.Add (new Argument (left, Argument.AType.Expression));
+                       arguments.Add (new Argument (right, Argument.AType.Expression));
+                       method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc) as MethodInfo;
+                       if ((method == null) || (method.ReturnType != type)) {
+                               Error19 ();
+                               return null;
+                       }
+
+                       op = new StaticCallExpr (method, arguments, loc);
+
+                       op_true = GetOperatorTrue (ec, left, loc);
+                       op_false = GetOperatorFalse (ec, left, loc);
+                       if ((op_true == null) || (op_false == null)) {
+                               Error218 ();
+                               return null;
+                       }
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Label false_target = ig.DefineLabel ();
+                       Label end_target = ig.DefineLabel ();
+
+                       ig.Emit (OpCodes.Nop);
+
+                       Statement.EmitBoolExpression (ec, is_and ? op_false : op_true, 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);
+               }
+       }
+
+       public class PointerArithmetic : Expression {
+               Expression left, right;
+               bool is_add;
+
+               //
+               // We assume that `l' is always a pointer
+               //
+               public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t, Location loc)
+               {
+                       type = t;
+                       eclass = ExprClass.Variable;
+                       this.loc = loc;
+                       left = l;
+                       right = r;
+                       is_add = is_addition;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Type op_type = left.Type;
+                       ILGenerator ig = ec.ig;
+                       int size = GetTypeSize (TypeManager.GetElementType (op_type));
+                       Type rtype = right.Type;
+                       
+                       if (rtype.IsPointer){
+                               //
+                               // handle (pointer - pointer)
+                               //
+                               left.Emit (ec);
+                               right.Emit (ec);
+                               ig.Emit (OpCodes.Sub);
+
+                               if (size != 1){
+                                       if (size == 0)
+                                               ig.Emit (OpCodes.Sizeof, op_type);
+                                       else 
+                                               IntLiteral.EmitInt (ig, size);
+                                       ig.Emit (OpCodes.Div);
+                               }
+                               ig.Emit (OpCodes.Conv_I8);
+                       } else {
+                               //
+                               // handle + and - on (pointer op int)
+                               //
+                               left.Emit (ec);
+                               ig.Emit (OpCodes.Conv_I);
+                               right.Emit (ec);
+                               if (size != 1){
+                                       if (size == 0)
+                                               ig.Emit (OpCodes.Sizeof, op_type);
+                                       else 
+                                               IntLiteral.EmitInt (ig, size);
+                                       if (rtype == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Conv_I8);
+                                       else if (rtype == TypeManager.uint64_type)
+                                               ig.Emit (OpCodes.Conv_U8);
+                                       ig.Emit (OpCodes.Mul);
+                                       ig.Emit (OpCodes.Conv_I);
+                               }
+                               if (is_add)
+                                       ig.Emit (OpCodes.Add);
+                               else
+                                       ig.Emit (OpCodes.Sub);
+                       }
+               }
+       }
+       
+       /// <summary>
+       ///   Implements the ternary conditional operator (?:)
+       /// </summary>
+       public class Conditional : Expression {
+               Expression expr, trueExpr, falseExpr;
+               
+               public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l)
+               {
+                       this.expr = expr;
+                       this.trueExpr = trueExpr;
+                       this.falseExpr = falseExpr;
+                       this.loc = l;
+               }
+
+               public Expression Expr {
+                       get {
+                               return expr;
+                       }
+               }
+
+               public Expression TrueExpr {
+                       get {
+                               return trueExpr;
+                       }
+               }
+
+               public Expression FalseExpr {
+                       get {
+                               return falseExpr;
+                       }
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       expr = expr.Resolve (ec);
+
+                       if (expr == null)
+                               return null;
+                       
+                       if (expr.Type != TypeManager.bool_type){
+                               expr = Expression.ResolveBoolean (
+                                       ec, expr, loc);
+                               
+                               if (expr == null)
+                                       return null;
+                       }
+                       
+                       trueExpr = trueExpr.Resolve (ec);
+                       falseExpr = falseExpr.Resolve (ec);
+
+                       if (trueExpr == null || falseExpr == null)
+                               return null;
+
+                       eclass = ExprClass.Value;
+                       if (trueExpr.Type == falseExpr.Type)
+                               type = trueExpr.Type;
+                       else {
+                               Expression conv;
+                               Type true_type = trueExpr.Type;
+                               Type false_type = falseExpr.Type;
+
+                               if (trueExpr is NullLiteral){
+                                       type = false_type;
+                                       return this;
+                               } else if (falseExpr is NullLiteral){
+                                       type = true_type;
+                                       return this;
+                               }
+                               
+                               //
+                               // First, if an implicit conversion exists from trueExpr
+                               // to falseExpr, then the result type is of type falseExpr.Type
+                               //
+                               conv = Convert.ImplicitConversion (ec, trueExpr, false_type, loc);
+                               if (conv != null){
+                                       //
+                                       // Check if both can convert implicitl to each other's type
+                                       //
+                                       if (Convert.ImplicitConversion (ec, falseExpr, true_type, loc) != null){
+                                               Error (172,
+                                                      "Can not compute type of conditional expression " +
+                                                      "as `" + TypeManager.CSharpName (trueExpr.Type) +
+                                                      "' and `" + TypeManager.CSharpName (falseExpr.Type) +
+                                                      "' convert implicitly to each other");
+                                               return null;
+                                       }
+                                       type = false_type;
+                                       trueExpr = conv;
+                               } else if ((conv = Convert.ImplicitConversion(ec, falseExpr, true_type,loc))!= null){
+                                       type = true_type;
+                                       falseExpr = conv;
+                               } else {
+                                       Error (173, "The type of the conditional expression can " +
+                                              "not be computed because there is no implicit conversion" +
+                                              " from `" + TypeManager.CSharpName (trueExpr.Type) + "'" +
+                                              " and `" + TypeManager.CSharpName (falseExpr.Type) + "'");
+                                       return null;
+                               }
+                       }
+
+                       if (expr is BoolConstant){
+                               BoolConstant bc = (BoolConstant) expr;
+
+                               if (bc.Value)
+                                       return trueExpr;
+                               else
+                                       return falseExpr;
+                       }
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Label false_target = ig.DefineLabel ();
+                       Label end_target = ig.DefineLabel ();
+
+                       Statement.EmitBoolExpression (ec, expr, false_target, false);
+                       trueExpr.Emit (ec);
+                       ig.Emit (OpCodes.Br, end_target);
+                       ig.MarkLabel (false_target);
+                       falseExpr.Emit (ec);
+                       ig.MarkLabel (end_target);
+               }
+
+       }
+
+       /// <summary>
+       ///   Local variables
+       /// </summary>
+       public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
+               public readonly string Name;
+               public readonly Block Block;
+               LocalInfo local_info;
+               VariableInfo variable_info;
+               bool is_readonly;
+               
+               public LocalVariableReference (Block block, string name, Location l)
+               {
+                       Block = block;
+                       Name = name;
+                       loc = l;
+                       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)
+               {
+                       this.local_info = local_info;
+                       this.is_readonly = is_readonly;
+               }
+
+               public VariableInfo VariableInfo {
+                       get { return variable_info; }
+               }
+
+               public bool IsReadOnly {
+                       get {
+                               return is_readonly;
+                       }
+               }
+
+               protected void DoResolveBase (EmitContext ec)
+               {
+                       if (local_info == null) {
+                               local_info = Block.GetLocalInfo (Name);
+                               is_readonly = local_info.ReadOnly;
+                       }
+
+                       variable_info = Block.GetVariableInfo (local_info);
+                       type = local_info.VariableType;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       DoResolveBase (ec);
+
+                       Expression e = Block.GetConstantExpression (Name);
+                       if (e != null) {
+                               local_info.Used = true;
+                               eclass = ExprClass.Value;
+                               return e;
+                       }
+
+                       if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
+                               return null;
+
+                       return this;
+               }
+
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       DoResolveBase (ec);
+
+                       if (variable_info != null)
+                               variable_info.SetAssigned (ec);
+
+                       Expression e = DoResolve (ec);
+
+                       if (e == null)
+                               return null;
+
+                       if (is_readonly){
+                               Error (1604, "cannot assign to `" + Name + "' because it is readonly");
+                               return null;
+                       }
+                       
+                       return this;
+               }
+
+               public bool VerifyFixed (bool is_expression)
+               {
+                       return !is_expression || local_info.IsFixed;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       if (local_info.LocalBuilder == null){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
+                       } else 
+                               ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
+                       
+                       local_info.Used = true;
+               }
+               
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       local_info.Assigned = true;
+
+                       if (local_info.LocalBuilder == null){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               source.Emit (ec);
+                               ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
+                       } else {
+                               source.Emit (ec);
+                               ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
+                       }
+               }
+               
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       if (local_info.LocalBuilder == null){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ig.Emit (OpCodes.Ldflda, local_info.FieldBuilder);
+                       } else
+                               ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("{0} ({1}:{2})", GetType (), Name, loc);
+               }
+       }
+
+       /// <summary>
+       ///   This represents a reference to a parameter in the intermediate
+       ///   representation.
+       /// </summary>
+       public class ParameterReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
+               Parameters pars;
+               String name;
+               int idx;
+               Block block;
+               VariableInfo vi;
+               public Parameter.Modifier mod;
+               public bool is_ref, is_out;
+               
+               public ParameterReference (Parameters pars, Block block, int idx, string name, Location loc)
+               {
+                       this.pars = pars;
+                       this.block = block;
+                       this.idx  = idx;
+                       this.name = name;
+                       this.loc = loc;
+                       eclass = ExprClass.Variable;
+               }
+
+               public VariableInfo VariableInfo {
+                       get { return vi; }
+               }
+
+               public bool VerifyFixed (bool is_expression)
+               {
+                       return !is_expression;
+               }
+
+               public bool IsAssigned (EmitContext ec, Location loc)
+               {
+                       if (!ec.DoFlowAnalysis || !is_out ||
+                           ec.CurrentBranching.IsAssigned (vi))
+                               return true;
+
+                       Report.Error (165, loc,
+                                     "Use of unassigned parameter `" + name + "'");
+                       return false;
+               }
+
+               public bool IsFieldAssigned (EmitContext ec, string field_name, Location loc)
+               {
+                       if (!ec.DoFlowAnalysis || !is_out ||
+                           ec.CurrentBranching.IsFieldAssigned (vi, field_name))
+                               return true;
+
+                       Report.Error (170, loc,
+                                     "Use of possibly unassigned field `" + field_name + "'");
+                       return false;
+               }
+
+               public void SetAssigned (EmitContext ec)
+               {
+                       if (is_out && ec.DoFlowAnalysis)
+                               ec.CurrentBranching.SetAssigned (vi);
+               }
+
+               public void SetFieldAssigned (EmitContext ec, string field_name)
+               {
+                       if (is_out && ec.DoFlowAnalysis)
+                               ec.CurrentBranching.SetFieldAssigned (vi, field_name);
+               }
+
+               protected void DoResolveBase (EmitContext ec)
+               {
+                       type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod);
+                       is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
+                       is_out = (mod & Parameter.Modifier.OUT) != 0;
+                       eclass = ExprClass.Variable;
+
+                       if (is_out)
+                               vi = block.ParameterMap [idx];
+               }
+
+               //
+               // Notice that for ref/out parameters, the type exposed is not the
+               // same type exposed externally.
+               //
+               // for "ref int a":
+               //   externally we expose "int&"
+               //   here we expose       "int".
+               //
+               // We record this in "is_ref".  This means that the type system can treat
+               // the type as it is expected, but when we generate the code, we generate
+               // the alternate kind of code.
+               //
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       DoResolveBase (ec);
+
+                       if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
+                               return null;
+
+                       return this;
+               }
+
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       DoResolveBase (ec);
+
+                       SetAssigned (ec);
+
+                       return this;
+               }
+
+               static public void EmitLdArg (ILGenerator ig, int x)
+               {
+                       if (x <= 255){
+                               switch (x){
+                               case 0: ig.Emit (OpCodes.Ldarg_0); break;
+                               case 1: ig.Emit (OpCodes.Ldarg_1); break;
+                               case 2: ig.Emit (OpCodes.Ldarg_2); break;
+                               case 3: ig.Emit (OpCodes.Ldarg_3); break;
+                               default: ig.Emit (OpCodes.Ldarg_S, (byte) x); break;
+                               }
+                       } else
+                               ig.Emit (OpCodes.Ldarg, x);
+               }
+               
+               //
+               // This method is used by parameters that are references, that are
+               // being passed as references:  we only want to pass the pointer (that
+               // is already stored in the parameter, not the address of the pointer,
+               // and not the value of the variable).
+               //
+               public void EmitLoad (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+
+                       EmitLdArg (ig, arg_idx);
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       if (ec.RemapToProxy){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ec.EmitArgument (idx);
+                               return;
+                       }
+                       
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+
+                       EmitLdArg (ig, arg_idx);
+
+                       if (!is_ref)
+                               return;
+
+                       //
+                       // If we are a reference, we loaded on the stack a pointer
+                       // Now lets load the real value
+                       //
+                       LoadFromPtr (ig, type);
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       if (ec.RemapToProxy){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               source.Emit (ec);
+                               ec.EmitStoreArgument (idx);
+                               return;
+                       }
+                       
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+
+                       if (is_ref)
+                               EmitLdArg (ig, arg_idx);
+                       
+                       source.Emit (ec);
+
+                       if (is_ref)
+                               StoreFromPtr (ig, type);
+                       else {
+                               if (arg_idx <= 255)
+                                       ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
+                               else
+                                       ig.Emit (OpCodes.Starg, arg_idx);
+                       }
+               }
+
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       if (ec.RemapToProxy){
+                               Report.Error (-1, "Report this: Taking the address of a remapped parameter not supported");
+                               return;
+                       }
+                       
+                       int arg_idx = idx;
+
+                       if (!ec.IsStatic)
+                               arg_idx++;
+
+                       if (is_ref){
+                               if (arg_idx <= 255)
+                                       ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
+                               else
+                                       ec.ig.Emit (OpCodes.Ldarg, arg_idx);
+                       } else {
+                               if (arg_idx <= 255)
+                                       ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
+                               else
+                                       ec.ig.Emit (OpCodes.Ldarga, arg_idx);
+                       }
+               }
+
+       }
+       
+       /// <summary>
+       ///   Used for arguments to New(), Invocation()
+       /// </summary>
+       public class Argument {
+               public enum AType : byte {
+                       Expression,
+                       Ref,
+                       Out
+               };
+
+               public readonly AType ArgType;
+               public Expression Expr;
+               
+               public Argument (Expression expr, AType type)
+               {
+                       this.Expr = expr;
+                       this.ArgType = type;
+               }
+
+               public Type Type {
+                       get {
+                               if (ArgType == AType.Ref || ArgType == AType.Out)
+                                       return TypeManager.GetReferenceType (Expr.Type);
+                               else
+                                       return Expr.Type;
+                       }
+               }
+
+               public Parameter.Modifier GetParameterModifier ()
+               {
+                       switch (ArgType) {
+                       case AType.Out:
+                               return Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF;
+
+                       case AType.Ref:
+                               return Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
+
+                       default:
+                               return Parameter.Modifier.NONE;
+                       }
+               }
+
+               public static string FullDesc (Argument a)
+               {
+                       return (a.ArgType == AType.Ref ? "ref " :
+                               (a.ArgType == AType.Out ? "out " : "")) +
+                               TypeManager.CSharpName (a.Expr.Type);
+               }
+
+               public bool ResolveMethodGroup (EmitContext ec, Location loc)
+               {
+                       // FIXME: csc doesn't report any error if you try to use `ref' or
+                       //        `out' in a delegate creation expression.
+                       Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
+                       if (Expr == null)
+                               return false;
+
+                       return true;
+               }
+               
+               public bool Resolve (EmitContext ec, Location loc)
+               {
+                       if (ArgType == AType.Ref) {
+                               Expr = Expr.Resolve (ec);
+                               if (Expr == null)
+                                       return false;
+
+                               Expr = Expr.ResolveLValue (ec, Expr);
+                       } else if (ArgType == AType.Out)
+                               Expr = Expr.ResolveLValue (ec, new EmptyExpression ());
+                       else
+                               Expr = Expr.Resolve (ec);
+
+                       if (Expr == null)
+                               return false;
+
+                       if (ArgType == AType.Expression)
+                               return true;
+
+                       if (Expr.eclass != ExprClass.Variable){
+                               //
+                               // We just probe to match the CSC output
+                               //
+                               if (Expr.eclass == ExprClass.PropertyAccess ||
+                                   Expr.eclass == ExprClass.IndexerAccess){
+                                       Report.Error (
+                                               206, loc,
+                                               "A property or indexer can not be passed as an out or ref " +
+                                               "parameter");
+                               } else {
+                                       Report.Error (
+                                               1510, loc,
+                                               "An lvalue is required as an argument to out or ref");
+                               }
+                               return false;
+                       }
+                               
+                       return true;
+               }
+
+               public void Emit (EmitContext ec)
+               {
+                       //
+                       // Ref and Out parameters need to have their addresses taken.
+                       //
+                       // ParameterReferences might already be references, so we want
+                       // to pass just the value
+                       //
+                       if (ArgType == AType.Ref || ArgType == AType.Out){
+                               AddressOp mode = AddressOp.Store;
+
+                               if (ArgType == AType.Ref)
+                                       mode |= AddressOp.Load;
+                               
+                               if (Expr is ParameterReference){
+                                       ParameterReference pr = (ParameterReference) Expr;
+
+                                       if (pr.is_ref)
+                                               pr.EmitLoad (ec);
+                                       else {
+                                               
+                                               pr.AddressOf (ec, mode);
+                                       }
+                               } else
+                                       ((IMemoryLocation)Expr).AddressOf (ec, mode);
+                       } else
+                               Expr.Emit (ec);
+               }
+       }
+
+       /// <summary>
+       ///   Invocation of methods or delegates.
+       /// </summary>
+       public class Invocation : ExpressionStatement {
+               public readonly ArrayList Arguments;
+
+               Expression expr;
+               MethodBase method = null;
+               bool is_base;
+               
+               static Hashtable method_parameter_cache;
+
+               static Invocation ()
+               {
+                       method_parameter_cache = new PtrHashtable ();
+               }
+                       
+               //
+               // arguments is an ArrayList, but we do not want to typecast,
+               // as it might be null.
+               //
+               // FIXME: only allow expr to be a method invocation or a
+               // delegate invocation (7.5.5)
+               //
+               public Invocation (Expression expr, ArrayList arguments, Location l)
+               {
+                       this.expr = expr;
+                       Arguments = arguments;
+                       loc = l;
+               }
+
+               public Expression Expr {
+                       get {
+                               return expr;
+                       }
+               }
+
+               /// <summary>
+               ///   Returns the Parameters (a ParameterData interface) for the
+               ///   Method `mb'
+               /// </summary>
+               public static ParameterData GetParameterData (MethodBase mb)
+               {
+                       object pd = method_parameter_cache [mb];
+                       object ip;
+                       
+                       if (pd != null)
+                               return (ParameterData) pd;
+
+                       
+                       ip = TypeManager.LookupParametersByBuilder (mb);
+                       if (ip != null){
+                               method_parameter_cache [mb] = ip;
+
+                               return (ParameterData) ip;
+                       } else {
+                               ParameterInfo [] pi = mb.GetParameters ();
+                               ReflectionParameters rp = new ReflectionParameters (pi);
+                               method_parameter_cache [mb] = rp;
+
+                               return (ParameterData) rp;
+                       }
+               }
+
+               /// <summary>
+               ///  Determines "better conversion" as specified in 7.4.2.3
+               ///  Returns : 1 if a->p is better
+               ///            0 if a->q or neither is better 
+               /// </summary>
+               static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
+               {
+                       Type argument_type = a.Type;
+                       Expression argument_expr = a.Expr;
+
+                       if (argument_type == null)
+                               throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
+
+                       //
+                       // This is a special case since csc behaves this way. I can't find
+                       // it anywhere in the spec but oh well ...
+                       //
+                       if (argument_expr is NullLiteral && p == TypeManager.string_type && q == TypeManager.object_type)
+                               return 1;
+                       else if (argument_expr is NullLiteral && p == TypeManager.object_type && q == TypeManager.string_type)
+                               return 0;
+                       
+                       if (p == q)
+                               return 0;
+                       
+                       if (argument_type == p)
+                               return 1;
+
+                       if (argument_type == q)
+                               return 0;
+
+                       //
+                       // Now probe whether an implicit constant expression conversion
+                       // can be used.
+                       //
+                       // An implicit constant expression conversion permits the following
+                       // conversions:
+                       //
+                       //    * A constant-expression of type `int' can be converted to type
+                       //      sbyte, byute, short, ushort, uint, ulong provided the value of
+                       //      of the expression is withing the range of the destination type.
+                       //
+                       //    * A constant-expression of type long can be converted to type
+                       //      ulong, provided the value of the constant expression is not negative
+                       //
+                       // FIXME: Note that this assumes that constant folding has
+                       // taken place.  We dont do constant folding yet.
+                       //
+
+                       if (argument_expr is IntConstant){
+                               IntConstant ei = (IntConstant) argument_expr;
+                               int value = ei.Value;
+
+                               if (p == TypeManager.sbyte_type){
+                                       if (value >= SByte.MinValue && value <= SByte.MaxValue)
+                                               return 1;
+                               } else if (p == TypeManager.byte_type){
+                                       if (q == TypeManager.sbyte_type &&
+                                           value >= SByte.MinValue && value <= SByte.MaxValue)
+                                               return 0;
+                                       else if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
+                                               return 1;
+                               } else if (p == TypeManager.short_type){
+                                       if (value >= Int16.MinValue && value <= Int16.MaxValue)
+                                               return 1;
+                               } else if (p == TypeManager.ushort_type){
+                                       if (q == TypeManager.short_type &&
+                                           value >= Int16.MinValue && value <= Int16.MaxValue)
+                                               return 0;
+                                       else if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
+                                               return 1;
+                               } else if (p == TypeManager.int32_type){
+                                       if (value >= Int32.MinValue && value <= Int32.MaxValue)
+                                               return 1;
+                               } else if (p == TypeManager.uint32_type){
+                                       //
+                                       // we can optimize this case: a positive int32
+                                       // always fits on a uint32
+                                       //
+                                       if (value >= 0)
+                                               return 1;
+                               } else if (p == TypeManager.uint64_type){
+                                       //
+                                       // we can optimize this case: a positive int32
+                                       // always fits on a uint64
+                                       //
+                                       if (q == TypeManager.int64_type)
+                                               return 0;
+                                       else if (value >= 0)
+                                               return 1;
+                               } else if (p == TypeManager.int64_type){
+                                       return 1;
+                               }
+                       } else if (argument_type == TypeManager.int64_type && argument_expr is LongConstant){
+                               LongConstant lc = (LongConstant) argument_expr;
+                               
+                               if (p == TypeManager.uint64_type){
+                                       if (lc.Value > 0)
+                                               return 1;
+                               }
+                       }
+
+                       if (q == null) {
+                               Expression tmp = Convert.ImplicitConversion (ec, argument_expr, p, loc);
+                               
+                               if (tmp != null)
+                                       return 1;
+                               else
+                                       return 0;
+                       }
+
+                       Expression p_tmp = new EmptyExpression (p);
+                       Expression q_tmp = new EmptyExpression (q);
+                       
+                       if (Convert.ImplicitConversionExists (ec, p_tmp, q) == true &&
+                           Convert.ImplicitConversionExists (ec, q_tmp, p) == false)
+                               return 1;
+
+                       if (p == TypeManager.sbyte_type)
+                               if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
+                                   q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+                                       return 1;
+
+                       if (p == TypeManager.short_type)
+                               if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
+                                   q == TypeManager.uint64_type)
+                                       return 1;
+
+                       if (p == TypeManager.int32_type)
+                               if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+                                       return 1;
+
+                       if (p == TypeManager.int64_type)
+                               if (q == TypeManager.uint64_type)
+                                       return 1;
+
+                       return 0;
+               }
+               
+               /// <summary>
+               ///  Determines "Better function"
+               /// </summary>
+               /// <remarks>
+               ///    and returns an integer indicating :
+               ///    0 if candidate ain't better
+               ///    1 if candidate is better than the current best match
+               /// </remarks>
+               static int BetterFunction (EmitContext ec, ArrayList args,
+                                          MethodBase candidate, MethodBase best,
+                                          bool expanded_form, Location loc)
+               {
+                       ParameterData candidate_pd = GetParameterData (candidate);
+                       ParameterData best_pd;
+                       int argument_count;
+               
+                       if (args == null)
+                               argument_count = 0;
+                       else
+                               argument_count = args.Count;
+
+                       int cand_count = candidate_pd.Count;
+
+                       if (cand_count == 0 && argument_count == 0)
+                               return 1;
+
+                       if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
+                               if (cand_count != argument_count)
+                                       return 0;
+                       
+                       if (best == null) {
+                               int x = 0;
+
+                               if (argument_count == 0 && cand_count == 1 &&
+                                   candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
+                                       return 1;
+                               
+                               for (int j = argument_count; j > 0;) {
+                                       j--;
+
+                                       Argument a = (Argument) args [j];
+                                       Type t = candidate_pd.ParameterType (j);
+
+                                       if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
+                                               if (expanded_form)
+                                                       t = TypeManager.GetElementType (t);
+
+                                       x = BetterConversion (ec, a, t, null, loc);
+                                       
+                                       if (x <= 0)
+                                               break;
+                               }
+
+                               if (x > 0)
+                                       return 1;
+                               else
+                                       return 0;
+                       }
+
+                       best_pd = GetParameterData (best);
+
+                       int rating1 = 0, rating2 = 0;
+                       
+                       for (int j = 0; j < argument_count; ++j) {
+                               int x, y;
+                               
+                               Argument a = (Argument) args [j];
+
+                               Type ct = candidate_pd.ParameterType (j);
+                               Type bt = best_pd.ParameterType (j);
+
+                               if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
+                                       if (expanded_form)
+                                               ct = TypeManager.GetElementType (ct);
+
+                               if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
+                                       if (expanded_form)
+                                               bt = TypeManager.GetElementType (bt);
+                               
+                               x = BetterConversion (ec, a, ct, bt, loc);
+                               y = BetterConversion (ec, a, bt, ct, loc);
+
+                               if (x < y)
+                                       return 0;
+                               
+                               rating1 += x;
+                               rating2 += y;
+                       }
+
+                       if (rating1 > rating2)
+                               return 1;
+                       else
+                               return 0;
+               }
+
+               public static string FullMethodDesc (MethodBase mb)
+               {
+                       string ret_type = "";
+
+                       if (mb is MethodInfo)
+                               ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
+                       
+                       StringBuilder sb = new StringBuilder (ret_type);
+                       sb.Append (" ");
+                       sb.Append (mb.ReflectedType.ToString ());
+                       sb.Append (".");
+                       sb.Append (mb.Name);
+                       
+                       ParameterData pd = GetParameterData (mb);
+
+                       int count = pd.Count;
+                       sb.Append (" (");
+                       
+                       for (int i = count; i > 0; ) {
+                               i--;
+
+                               sb.Append (pd.ParameterDesc (count - i - 1));
+                               if (i != 0)
+                                       sb.Append (", ");
+                       }
+                       
+                       sb.Append (")");
+                       return sb.ToString ();
+               }
+
+               public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2, Location loc)
+               {
+                       MemberInfo [] miset;
+                       MethodGroupExpr union;
+
+                       if (mg1 == null){
+                               if (mg2 == null)
+                                       return null;
+                               return (MethodGroupExpr) mg2;
+                       } else {
+                               if (mg2 == null)
+                                       return (MethodGroupExpr) mg1;
+                       }
+                       
+                       MethodGroupExpr left_set = null, right_set = null;
+                       int length1 = 0, length2 = 0;
+                       
+                       left_set = (MethodGroupExpr) mg1;
+                       length1 = left_set.Methods.Length;
+                       
+                       right_set = (MethodGroupExpr) mg2;
+                       length2 = right_set.Methods.Length;
+                       
+                       ArrayList common = new ArrayList ();
+
+                       foreach (MethodBase l in left_set.Methods){
+                               foreach (MethodBase r in right_set.Methods){
+                                       if (l != r)
+                                               continue;
+                                       common.Add (r);
+                                       break;
+                               }
+                       }
+                       
+                       miset = new MemberInfo [length1 + length2 - common.Count];
+                       left_set.Methods.CopyTo (miset, 0);
+                       
+                       int k = length1;
+
+                       foreach (MemberInfo mi in right_set.Methods){
+                               if (!common.Contains (mi))
+                                       miset [k++] = mi;
+                       }
+                       
+                       union = new MethodGroupExpr (miset, loc);
+                       
+                       return union;
+               }
+
+               /// <summary>
+               ///  Determines is the candidate method, if a params method, is applicable
+               ///  in its expanded form to the given set of arguments
+               /// </summary>
+               static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
+               {
+                       int arg_count;
+                       
+                       if (arguments == null)
+                               arg_count = 0;
+                       else
+                               arg_count = arguments.Count;
+                       
+                       ParameterData pd = GetParameterData (candidate);
+                       
+                       int pd_count = pd.Count;
+
+                       if (pd_count == 0)
+                               return false;
+                       
+                       if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
+                               return false;
+                       
+                       if (pd_count - 1 > arg_count)
+                               return false;
+                       
+                       if (pd_count == 1 && arg_count == 0)
+                               return true;
+
+                       //
+                       // If we have come this far, the case which remains is when the number of parameters
+                       // is less than or equal to the argument count.
+                       //
+                       for (int i = 0; i < pd_count - 1; ++i) {
+
+                               Argument a = (Argument) arguments [i];
+
+                               Parameter.Modifier a_mod = a.GetParameterModifier () &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                               Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+
+                               if (a_mod == p_mod) {
+
+                                       if (a_mod == Parameter.Modifier.NONE)
+                                               if (!Convert.ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
+                                                       return false;
+                                                                               
+                                       if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
+                                               Type pt = pd.ParameterType (i);
+
+                                               if (!pt.IsByRef)
+                                                       pt = TypeManager.GetReferenceType (pt);
+                                               
+                                               if (pt != a.Type)
+                                                       return false;
+                                       }
+                               } else
+                                       return false;
+                               
+                       }
+
+                       Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
+
+                       for (int i = pd_count - 1; i < arg_count; i++) {
+                               Argument a = (Argument) arguments [i];
+                               
+                               if (!Convert.ImplicitStandardConversionExists (a.Expr, element_type))
+                                       return false;
+                       }
+                       
+                       return true;
+               }
+
+               /// <summary>
+               ///  Determines if the candidate method is applicable (section 14.4.2.1)
+               ///  to the given set of arguments
+               /// </summary>
+               static bool IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
+               {
+                       int arg_count;
+
+                       if (arguments == null)
+                               arg_count = 0;
+                       else
+                               arg_count = arguments.Count;
+
+
+                       ParameterData pd = GetParameterData (candidate);
+
+                       int pd_count = pd.Count;
+
+                       if (arg_count != pd.Count)
+                               return false;
+
+                       for (int i = arg_count; i > 0; ) {
+                               i--;
+
+                               Argument a = (Argument) arguments [i];
+
+                               Parameter.Modifier a_mod = a.GetParameterModifier () &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                               Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+
+
+                               if (a_mod == p_mod ||
+                                   (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
+                                       if (a_mod == Parameter.Modifier.NONE) {
+                                                 if (!Convert.ImplicitConversionExists (ec,
+                                                                                       a.Expr, pd.ParameterType (i)))
+                                                       return false;
+                                        }
+                                       
+                                       if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
+                                               Type pt = pd.ParameterType (i);
+
+                                               if (!pt.IsByRef)
+                                                       pt = TypeManager.GetReferenceType (pt);
+
+                                               if (pt != a.Type)
+                                                       return false;
+                                       }
+                               } else
+                                       return false;
+                       }
+
+                       return true;
+               }
+               
+               
+
+               /// <summary>
+               ///   Find the Applicable Function Members (7.4.2.1)
+               ///
+               ///   me: Method Group expression with the members to select.
+               ///       it might contain constructors or methods (or anything
+               ///       that maps to a method).
+               ///
+               ///   Arguments: ArrayList containing resolved Argument objects.
+               ///
+               ///   loc: The location if we want an error to be reported, or a Null
+               ///        location for "probing" purposes.
+               ///
+               ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
+               ///            that is the best match of me on Arguments.
+               ///
+               /// </summary>
+               public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
+                                                         ArrayList Arguments, Location loc)
+               {
+                       MethodBase method = null;
+                       Type applicable_type = null;
+                       int argument_count;
+                       ArrayList candidates = new ArrayList ();
+
+                        //
+                        // First we construct the set of applicable methods
+                        //
+
+                        //
+                        // We start at the top of the type hierarchy and
+                        // go down to find applicable methods
+                        //
+                        applicable_type = me.DeclaringType;
+
+                        bool found_applicable = false;
+                       foreach (MethodBase candidate in me.Methods) {
+                                Type decl_type = candidate.DeclaringType;
+
+                                //
+                                // If we have already found an applicable method
+                                // we eliminate all base types (Section 14.5.5.1)
+                                //
+                                if (decl_type != applicable_type &&
+                                    (applicable_type.IsSubclassOf (decl_type) ||
+                                     TypeManager.ImplementsInterface (applicable_type, decl_type)) &&
+                                    found_applicable)
+                                                continue;
+
+
+                               // Check if candidate is applicable (section 14.4.2.1)
+                               if (!IsApplicable (ec, Arguments, candidate))
+                                       continue;
+
+                                
+                               candidates.Add (candidate);
+                                applicable_type = candidate.DeclaringType;
+                                found_applicable = true;
+
+                       }
+
+
+                        //
+                        // Now we actually find the best method
+                        //
+                        foreach (MethodBase candidate in candidates) {
+                                int x = BetterFunction (ec, Arguments, candidate, method, false, loc);
+                                
+                                if (x == 0)
+                                        continue;
+                                
+                                method = candidate;
+                        }
+
+
+                       if (Arguments == null)
+                               argument_count = 0;
+                       else
+                               argument_count = Arguments.Count;
+                       
+                       //
+                       // Now we see if we can find params functions,
+                       // applicable in their expanded form since if
+                       // they were applicable in their normal form,
+                       // they would have been selected above anyways
+                       //
+                       bool chose_params_expanded = false;
+                       
+                       if (method == null) {
+                               candidates = new ArrayList ();
+                               foreach (MethodBase candidate in me.Methods){
+                                       if (!IsParamsMethodApplicable (ec, Arguments, candidate))
+                                               continue;
+
+                                       candidates.Add (candidate);
+
+                                       int x = BetterFunction (ec, Arguments, candidate, method, true, loc);
+                                       if (x == 0)
+                                               continue;
+
+                                       method = candidate; 
+                                       chose_params_expanded = true;
+                               }
+                       }
+
+                       if (method == null) {
+                               //
+                               // Okay so we have failed to find anything so we
+                               // return by providing info about the closest match
+                               //
+                               for (int i = 0; i < me.Methods.Length; ++i) {
+
+                                       MethodBase c = (MethodBase) me.Methods [i];
+                                       ParameterData pd = GetParameterData (c);
+
+                                       if (pd.Count != argument_count)
+                                               continue;
+
+                                       VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
+                                                              null, loc);
+                               }
+
+                                if (!Location.IsNull (loc)) {
+                                        string report_name = me.Name;
+                                        if (report_name == ".ctor")
+                                                report_name = me.DeclaringType.ToString ();
+                                        
+                                        Error_WrongNumArguments (loc, report_name, argument_count);
+                                }
+                                
+                               return null;
+                       }
+
+                       //
+                       // Now check that there are no ambiguities i.e the selected method
+                       // should be better than all the others
+                       //
+
+                       foreach (MethodBase candidate in candidates){
+                               if (candidate == method)
+                                       continue;
+
+                               //
+                               // If a normal method is applicable in
+                               // the sense that it has the same
+                               // number of arguments, then the
+                               // expanded params method is never
+                               // applicable so we debar the params
+                               // method.
+                               //
+
+                                if (IsParamsMethodApplicable (ec, Arguments, candidate) &&
+                                   IsApplicable (ec, Arguments, method))
+                                       continue;
+                                       
+                               int x = BetterFunction (ec, Arguments, method, candidate,
+                                                       chose_params_expanded, loc);
+
+                               if (x != 1) {
+                                       Report.Error (
+                                               121, loc,
+                                               "Ambiguous call when selecting function due to implicit casts");
+                                       return null;
+                               }
+                       }
+
+                       //
+                       // And now check if the arguments are all
+                       // compatible, perform conversions if
+                       // necessary etc. and return if everything is
+                       // all right
+                       //
+
+                       if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
+                                                  chose_params_expanded, null, loc))
+                               return null;
+
+                       return method;
+               }
+
+                static void Error_WrongNumArguments (Location loc, String name, int arg_count)
+                {
+                        Report.Error (1501, loc,
+                                      "No overload for method `" + name + "' takes `" +
+                                      arg_count + "' arguments");
+                }
+
+               static void Error_InvalidArguments (Location loc, int idx, MethodBase method,
+                                                    Type delegate_type, string arg_sig, string par_desc)
+               {
+                       if (delegate_type == null) 
+                               Report.Error (1502, loc,
+                                             "The best overloaded match for method '" +
+                                             FullMethodDesc (method) +
+                                             "' has some invalid arguments");
+                       else
+                               Report.Error (1594, loc,
+                                             "Delegate '" + delegate_type.ToString () +
+                                             "' has some invalid arguments.");
+                       Report.Error (1503, loc,
+                                     String.Format ("Argument {0}: Cannot convert from '{1}' to '{2}'",
+                                                    idx, arg_sig, par_desc));
+               }
+               
+               public static bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments,
+                                                         int argument_count,
+                                                         MethodBase method, 
+                                                         bool chose_params_expanded,
+                                                         Type delegate_type,
+                                                         Location loc)
+               {
+                       ParameterData pd = GetParameterData (method);
+                       int pd_count = pd.Count;
+                       
+                       for (int j = 0; j < argument_count; j++) {
+                               Argument a = (Argument) Arguments [j];
+                               Expression a_expr = a.Expr;
+                               Type parameter_type = pd.ParameterType (j);
+                               Parameter.Modifier pm = pd.ParameterModifier (j);
+                               
+                               if (pm == Parameter.Modifier.PARAMS){
+                                       Parameter.Modifier am = a.GetParameterModifier ();
+
+                                       if ((pm & ~Parameter.Modifier.PARAMS) != a.GetParameterModifier ()) {
+                                               if (!Location.IsNull (loc))
+                                                       Error_InvalidArguments (
+                                                               loc, j, method, delegate_type,
+                                                               Argument.FullDesc (a), pd.ParameterDesc (j));
+                                               return false;
+                                       }
+
+                                       if (chose_params_expanded)
+                                               parameter_type = TypeManager.GetElementType (parameter_type);
+                               } else {
+                                       //
+                                       // Check modifiers
+                                       //
+                                       if (pd.ParameterModifier (j) != a.GetParameterModifier ()){
+                                               if (!Location.IsNull (loc))
+                                                       Error_InvalidArguments (
+                                                               loc, j, method, delegate_type,
+                                                               Argument.FullDesc (a), pd.ParameterDesc (j));
+                                               return false;
+                                       }
+                               }
+
+                               //
+                               // Check Type
+                               //
+                               if (a.Type != parameter_type){
+                                       Expression conv;
+                                       
+                                       conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc);
+
+                                       if (conv == null) {
+                                                Console.WriteLine ("GAA: {0} {1} {2}",
+                                                                   pd.ParameterType (j),
+                                                                   pd.ParameterType (j).Assembly == CodeGen.AssemblyBuilder,
+                                                                   method.DeclaringType.Assembly == CodeGen.AssemblyBuilder);
+
+                                               if (!Location.IsNull (loc)) 
+                                                       Error_InvalidArguments (
+                                                               loc, j, method, delegate_type,
+                                                               Argument.FullDesc (a), pd.ParameterDesc (j));
+                                               return false;
+                                       }
+                                       
+                                       //
+                                       // Update the argument with the implicit conversion
+                                       //
+                                       if (a_expr != conv)
+                                               a.Expr = conv;
+                               }
+
+                               Parameter.Modifier a_mod = a.GetParameterModifier () &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                               Parameter.Modifier p_mod = pd.ParameterModifier (j) &
+                                       ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+                               
+                               if (a_mod != p_mod &&
+                                   pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
+                                       if (!Location.IsNull (loc)) {
+                                               Console.WriteLine ("A:P: " + a.GetParameterModifier ());
+                                               Console.WriteLine ("PP:: " + pd.ParameterModifier (j));
+                                               Console.WriteLine ("PT:  " + parameter_type.IsByRef);
+                                               Report.Error (1502, loc,
+                                                      "The best overloaded match for method '" + FullMethodDesc (method)+
+                                                      "' has some invalid arguments");
+                                               Report.Error (1503, loc,
+                                                      "Argument " + (j+1) +
+                                                      ": Cannot convert from '" + Argument.FullDesc (a) 
+                                                      + "' to '" + pd.ParameterDesc (j) + "'");
+                                       }
+                                       
+                                       return false;
+                               }
+                       }
+
+                       return true;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // First, resolve the expression that is used to
+                       // trigger the invocation
+                       //
+                       if (expr is BaseAccess)
+                               is_base = true;
+
+                       Expression old = expr;
+                       
+                       expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
+                       if (expr == null)
+                               return null;
+
+                       if (!(expr is MethodGroupExpr)) {
+                               Type expr_type = expr.Type;
+
+                               if (expr_type != null){
+                                       bool IsDelegate = TypeManager.IsDelegateType (expr_type);
+                                       if (IsDelegate)
+                                               return (new DelegateInvocation (
+                                                       this.expr, Arguments, loc)).Resolve (ec);
+                               }
+                       }
+
+                       if (!(expr is MethodGroupExpr)){
+                               expr.Error_UnexpectedKind (ResolveFlags.MethodGroup);
+                               return null;
+                       }
+
+                       //
+                       // Next, evaluate all the expressions in the argument list
+                       //
+                       if (Arguments != null){
+                               foreach (Argument a in Arguments){
+                                       if (!a.Resolve (ec, loc))
+                                               return null;
+                               }
+                       }
+
+                       MethodGroupExpr mg = (MethodGroupExpr) expr;
+                       method = OverloadResolve (ec, mg, Arguments, loc);
+
+                       if (method == null){
+                               Error (-6,
+                                      "Could not find any applicable function for this argument list");
+                               return null;
+                       }
+
+                       MethodInfo mi = method as MethodInfo;
+                       if (mi != null) {
+                               type = TypeManager.TypeToCoreType (mi.ReturnType);
+                               if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null))
+                                       SimpleName.Error_ObjectRefRequired (ec, loc, mi.Name);
+                       }
+
+                       if (type.IsPointer){
+                               if (!ec.InUnsafe){
+                                       UnsafeError (loc);
+                                       return null;
+                               }
+                       }
+                       
+                       //
+                       // Only base will allow this invocation to happen.
+                       //
+                       if (is_base && method.IsAbstract){
+                               Report.Error (205, loc, "Cannot call an abstract base member: " +
+                                             FullMethodDesc (method));
+                               return null;
+                       }
+
+                       if ((method.Attributes & MethodAttributes.SpecialName) != 0){
+                               if (TypeManager.IsSpecialMethod (method))
+                                       Report.Error (571, loc, method.Name + ": can not call operator or accessor");
+                       }
+                       
+                       eclass = ExprClass.Value;
+                       return this;
+               }
+
+               // <summary>
+               //   Emits the list of arguments as an array
+               // </summary>
+               static void EmitParams (EmitContext ec, int idx, ArrayList arguments)
+               {
+                       ILGenerator ig = ec.ig;
+                       int count = arguments.Count - idx;
+                       Argument a = (Argument) arguments [idx];
+                       Type t = a.Expr.Type;
+                       string array_type = t.FullName + "[]";
+                       LocalBuilder array;
+
+                       array = ig.DeclareLocal (TypeManager.LookupType (array_type));
+                       IntConstant.EmitInt (ig, count);
+                       ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
+                       ig.Emit (OpCodes.Stloc, array);
+
+                       int top = arguments.Count;
+                       for (int j = idx; j < top; j++){
+                               a = (Argument) arguments [j];
+                               
+                               ig.Emit (OpCodes.Ldloc, array);
+                               IntConstant.EmitInt (ig, j - idx);
+
+                               bool is_stobj;
+                               OpCode op = ArrayAccess.GetStoreOpcode (t, out is_stobj);
+                               if (is_stobj)
+                                       ig.Emit (OpCodes.Ldelema, t);
+
+                               a.Emit (ec);
+
+                               if (is_stobj)
+                                       ig.Emit (OpCodes.Stobj, t);
+                               else
+                                       ig.Emit (op);
+                       }
+                       ig.Emit (OpCodes.Ldloc, array);
+               }
+               
+               /// <summary>
+               ///   Emits a list of resolved Arguments that are in the arguments
+               ///   ArrayList.
+               /// 
+               ///   The MethodBase argument might be null if the
+               ///   emission of the arguments is known not to contain
+               ///   a `params' field (for example in constructors or other routines
+               ///   that keep their arguments in this structure)
+               /// </summary>
+               public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)
+               {
+                       ParameterData pd;
+                       if (mb != null)
+                               pd = GetParameterData (mb);
+                       else
+                               pd = null;
+
+                       //
+                       // If we are calling a params method with no arguments, special case it
+                       //
+                       if (arguments == null){
+                               if (pd != null && pd.Count > 0 &&
+                                   pd.ParameterModifier (0) == Parameter.Modifier.PARAMS){
+                                       ILGenerator ig = ec.ig;
+
+                                       IntConstant.EmitInt (ig, 0);
+                                       ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (0)));
+                               }
+
+                               return;
+                       }
+
+                       int top = arguments.Count;
+
+                       for (int i = 0; i < top; i++){
+                               Argument a = (Argument) arguments [i];
+
+                               if (pd != null){
+                                       if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
+                                               //
+                                               // Special case if we are passing the same data as the
+                                               // params argument, do not put it in an array.
+                                               //
+                                               if (pd.ParameterType (i) == a.Type)
+                                                       a.Emit (ec);
+                                               else
+                                                       EmitParams (ec, i, arguments);
+                                               return;
+                                       }
+                               }
+                                           
+                               a.Emit (ec);
+                       }
+
+                       if (pd != null && pd.Count > top &&
+                           pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){
+                               ILGenerator ig = ec.ig;
+
+                               IntConstant.EmitInt (ig, 0);
+                               ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (top)));
+                       }
+               }
+
+               /// <remarks>
+               ///   is_base tells whether we want to force the use of the `call'
+               ///   opcode instead of using callvirt.  Call is required to call
+               ///   a specific method, while callvirt will always use the most
+               ///   recent method in the vtable.
+               ///
+               ///   is_static tells whether this is an invocation on a static method
+               ///
+               ///   instance_expr is an expression that represents the instance
+               ///   it must be non-null if is_static is false.
+               ///
+               ///   method is the method to invoke.
+               ///
+               ///   Arguments is the list of arguments to pass to the method or constructor.
+               /// </remarks>
+               public static void EmitCall (EmitContext ec, bool is_base,
+                                            bool is_static, Expression instance_expr,
+                                            MethodBase method, ArrayList Arguments, Location loc)
+               {
+                       ILGenerator ig = ec.ig;
+                       bool struct_call = false;
+
+                       Type decl_type = method.DeclaringType;
+
+                       if (!RootContext.StdLib) {
+                               // Replace any calls to the system's System.Array type with calls to
+                               // the newly created one.
+                               if (method == TypeManager.system_int_array_get_length)
+                                       method = TypeManager.int_array_get_length;
+                               else if (method == TypeManager.system_int_array_get_rank)
+                                       method = TypeManager.int_array_get_rank;
+                               else if (method == TypeManager.system_object_array_clone)
+                                       method = TypeManager.object_array_clone;
+                               else if (method == TypeManager.system_int_array_get_length_int)
+                                       method = TypeManager.int_array_get_length_int;
+                               else if (method == TypeManager.system_int_array_get_lower_bound_int)
+                                       method = TypeManager.int_array_get_lower_bound_int;
+                               else if (method == TypeManager.system_int_array_get_upper_bound_int)
+                                       method = TypeManager.int_array_get_upper_bound_int;
+                               else if (method == TypeManager.system_void_array_copyto_array_int)
+                                       method = TypeManager.void_array_copyto_array_int;
+                       }
+
+                       //
+                       // This checks the `ConditionalAttribute' on the method, and the
+                       // ObsoleteAttribute
+                       //
+                       TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method, loc);
+                       if ((flags & TypeManager.MethodFlags.IsObsoleteError) != 0)
+                               return;
+                       if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
+                               return;
+                       
+                       if (!is_static){
+                               if (decl_type.IsValueType)
+                                       struct_call = true;
+                               //
+                               // If this is ourselves, push "this"
+                               //
+                               if (instance_expr == null){
+                                       ig.Emit (OpCodes.Ldarg_0);
+                               } else {
+                                       //
+                                       // Push the instance expression
+                                       //
+                                       if (instance_expr.Type.IsValueType){
+                                               //
+                                               // Special case: calls to a function declared in a 
+                                               // reference-type with a value-type argument need
+                                               // to have their value boxed.  
+
+                                               struct_call = true;
+                                               if (decl_type.IsValueType){
+                                                       //
+                                                       // If the expression implements IMemoryLocation, then
+                                                       // we can optimize and use AddressOf on the
+                                                       // return.
+                                                       //
+                                                       // If not we have to use some temporary storage for
+                                                       // it.
+                                                       if (instance_expr is IMemoryLocation){
+                                                               ((IMemoryLocation)instance_expr).
+                                                                       AddressOf (ec, AddressOp.LoadStore);
+                                                       }
+                                                       else {
+                                                               Type t = instance_expr.Type;
+                                                               
+                                                               instance_expr.Emit (ec);
+                                                               LocalBuilder temp = ig.DeclareLocal (t);
+                                                               ig.Emit (OpCodes.Stloc, temp);
+                                                               ig.Emit (OpCodes.Ldloca, temp);
+                                                       }
+                                               } else {
+                                                       instance_expr.Emit (ec);
+                                                       ig.Emit (OpCodes.Box, instance_expr.Type);
+                                               } 
+                                       } else
+                                               instance_expr.Emit (ec);
+                               }
+                       }
+
+                       EmitArguments (ec, method, Arguments);
+
+                       if (is_static || struct_call || is_base){
+                               if (method is MethodInfo) {
+                                       ig.Emit (OpCodes.Call, (MethodInfo) method);
+                               } else
+                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+                       } else {
+                               if (method is MethodInfo)
+                                       ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
+                               else
+                                       ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
+                       }
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       MethodGroupExpr mg = (MethodGroupExpr) this.expr;
+
+                       EmitCall (ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments, loc);
+               }
+               
+               public override void EmitStatement (EmitContext ec)
+               {
+                       Emit (ec);
+
+                       // 
+                       // Pop the return value if there is one
+                       //
+                       if (method is MethodInfo){
+                               Type ret = ((MethodInfo)method).ReturnType;
+                               if (TypeManager.TypeToCoreType (ret) != TypeManager.void_type)
+                                       ec.ig.Emit (OpCodes.Pop);
+                       }
+               }
+       }
+
+       public class InvocationOrCast : ExpressionStatement
+       {
+               Expression expr;
+               Expression argument;
+
+               public InvocationOrCast (Expression expr, Expression argument, Location loc)
+               {
+                       this.expr = expr;
+                       this.argument = argument;
+                       this.loc = loc;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // First try to resolve it as a cast.
+                       //
+                       type = ec.DeclSpace.ResolveType (expr, true, loc);
+                       if (type != null) {
+                               Cast cast = new Cast (new TypeExpr (type, loc), argument, loc);
+                               return cast.Resolve (ec);
+                       }
+
+                       //
+                       // This can either be a type or a delegate invocation.
+                       // Let's just resolve it and see what we'll get.
+                       //
+                       expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
+                       if (expr == null)
+                               return null;
+
+                       //
+                       // Ok, so it's a Cast.
+                       //
+                       if (expr.eclass == ExprClass.Type) {
+                               Cast cast = new Cast (new TypeExpr (expr.Type, loc), argument, loc);
+                               return cast.Resolve (ec);
+                       }
+
+                       //
+                       // It's a delegate invocation.
+                       //
+                       if (!TypeManager.IsDelegateType (expr.Type)) {
+                               Error (149, "Method name expected");
+                               return null;
+                       }
+
+                       ArrayList args = new ArrayList ();
+                       args.Add (new Argument (argument, Argument.AType.Expression));
+                       DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
+                       return invocation.Resolve (ec);
+               }
+
+               void error201 ()
+               {
+                       Error (201, "Only assignment, call, increment, decrement and new object " +
+                              "expressions can be used as a statement");
+               }
+
+               public override ExpressionStatement ResolveStatement (EmitContext ec)
+               {
+                       //
+                       // First try to resolve it as a cast.
+                       //
+                       type = ec.DeclSpace.ResolveType (expr, true, loc);
+                       if (type != null) {
+                               error201 ();
+                               return null;
+                       }
+
+                       //
+                       // This can either be a type or a delegate invocation.
+                       // Let's just resolve it and see what we'll get.
+                       //
+                       expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
+                       if ((expr == null) || (expr.eclass == ExprClass.Type)) {
+                               error201 ();
+                               return null;
+                       }
+
+                       //
+                       // It's a delegate invocation.
+                       //
+                       if (!TypeManager.IsDelegateType (expr.Type)) {
+                               Error (149, "Method name expected");
+                               return null;
+                       }
+
+                       ArrayList args = new ArrayList ();
+                       args.Add (new Argument (argument, Argument.AType.Expression));
+                       DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
+                       return invocation.ResolveStatement (ec);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Cannot happen");
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       throw new Exception ("Cannot happen");
+               }
+       }
+
+       //
+       // This class is used to "disable" the code generation for the
+       // temporary variable when initializing value types.
+       //
+       class EmptyAddressOf : EmptyExpression, IMemoryLocation {
+               public void AddressOf (EmitContext ec, AddressOp Mode)
+               {
+                       // nothing
+               }
+       }
+       
+       /// <summary>
+       ///    Implements the new expression 
+       /// </summary>
+       public class New : ExpressionStatement, IMemoryLocation {
+               public readonly ArrayList Arguments;
+               public readonly Expression RequestedType;
+
+               MethodBase method = null;
+
+               //
+               // If set, the new expression is for a value_target, and
+               // we will not leave anything on the stack.
+               //
+               Expression value_target;
+               bool value_target_set = false;
+               
+               public New (Expression requested_type, ArrayList arguments, Location l)
+               {
+                       RequestedType = requested_type;
+                       Arguments = arguments;
+                       loc = l;
+               }
+
+               public bool SetValueTypeVariable (Expression value)
+               {
+                       value_target = value;
+                       value_target_set = true;
+                       if (!(value_target is IMemoryLocation)){
+                               Error_UnexpectedKind ("variable");
+                               return false;
+                       }
+                       return true;
+               }
+
+               //
+               // This function is used to disable the following code sequence for
+               // value type initialization:
+               //
+               // AddressOf (temporary)
+               // Construct/Init
+               // LoadTemporary
+               //
+               // Instead the provide will have provided us with the address on the
+               // stack to store the results.
+               //
+               static Expression MyEmptyExpression;
+               
+               public void DisableTemporaryValueType ()
+               {
+                       if (MyEmptyExpression == null)
+                               MyEmptyExpression = new EmptyAddressOf ();
+
+                       //
+                       // To enable this, look into:
+                       // test-34 and test-89 and self bootstrapping.
+                       //
+                       // For instance, we can avoid a copy by using `newobj'
+                       // instead of Call + Push-temp on value types.
+//                     value_target = MyEmptyExpression;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // The New DoResolve might be called twice when initializing field
+                       // expressions (see EmitFieldInitializers, the call to
+                       // GetInitializerExpression will perform a resolve on the expression,
+                       // and later the assign will trigger another resolution
+                       //
+                       // This leads to bugs (#37014)
+                       //
+                       if (type != null)
+                               return this;
+                       
+                       type = ec.DeclSpace.ResolveType (RequestedType, false, loc);
+                       
+                       if (type == null)
+                               return null;
+                       
+                       bool IsDelegate = TypeManager.IsDelegateType (type);
+                       
+                       if (IsDelegate)
+                               return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+
+                       if (type.IsInterface || type.IsAbstract){
+                               Error (144, "It is not possible to create instances of interfaces or abstract classes");
+                               return null;
+                       }
+                       
+                       bool is_struct = type.IsValueType;
+                       eclass = ExprClass.Value;
+
+                       //
+                       // SRE returns a match for .ctor () on structs (the object constructor), 
+                       // so we have to manually ignore it.
+                       //
+                       if (is_struct && Arguments == null)
+                               return this;
+                       
+                       Expression ml;
+                       ml = MemberLookupFinal (ec, null, type, ".ctor",
+                                               MemberTypes.Constructor,
+                                               AllBindingFlags | BindingFlags.DeclaredOnly, loc);
+
+                       if (ml == null)
+                               return null;
+                       
+                       if (! (ml is MethodGroupExpr)){
+                               if (!is_struct){
+                                       ml.Error_UnexpectedKind ("method group");
+                                       return null;
+                               }
+                       }
+
+                       if (ml != null) {
+                               if (Arguments != null){
+                                       foreach (Argument a in Arguments){
+                                               if (!a.Resolve (ec, loc))
+                                                       return null;
+                                       }
+                               }
+
+                               method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
+                               
+                       }
+
+                       if (method == null) { 
+                                if (!is_struct || Arguments.Count > 0) {
+                                       Error (1501, String.Format (
+                                           "New invocation: Can not find a constructor in `{0}' for this argument list",
+                                           TypeManager.CSharpName (type)));
+                                       return null;
+                                }
+                       }
+
+                       return this;
+               }
+
+               //
+               // This DoEmit can be invoked in two contexts:
+               //    * As a mechanism that will leave a value on the stack (new object)
+               //    * As one that wont (init struct)
+               //
+               // You can control whether a value is required on the stack by passing
+               // need_value_on_stack.  The code *might* leave a value on the stack
+               // so it must be popped manually
+               //
+               // If we are dealing with a ValueType, we have a few
+               // situations to deal with:
+               //
+               //    * The target is a ValueType, and we have been provided
+               //      the instance (this is easy, we are being assigned).
+               //
+               //    * The target of New is being passed as an argument,
+               //      to a boxing operation or a function that takes a
+               //      ValueType.
+               //
+               //      In this case, we need to create a temporary variable
+               //      that is the argument of New.
+               //
+               // Returns whether a value is left on the stack
+               //
+               bool DoEmit (EmitContext ec, bool need_value_on_stack)
+               {
+                       bool is_value_type = type.IsValueType;
+                       ILGenerator ig = ec.ig;
+
+                       if (is_value_type){
+                               IMemoryLocation ml;
+
+                               // Allow DoEmit() to be called multiple times.
+                               // We need to create a new LocalTemporary each time since
+                               // you can't share LocalBuilders among ILGeneators.
+                               if (!value_target_set)
+                                       value_target = new LocalTemporary (ec, type);
+
+                               ml = (IMemoryLocation) value_target;
+                               ml.AddressOf (ec, AddressOp.Store);
+                       }
+
+                       if (method != null)
+                               Invocation.EmitArguments (ec, method, Arguments);
+
+                       if (is_value_type){
+                               if (method == null)
+                                       ig.Emit (OpCodes.Initobj, type);
+                               else 
+                                       ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+                                if (need_value_on_stack){
+                                        value_target.Emit (ec);
+                                        return true;
+                                }
+                                return false;
+                       } else {
+                               ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
+                               return true;
+                       }
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       DoEmit (ec, true);
+               }
+               
+               public override void EmitStatement (EmitContext ec)
+               {
+                       if (DoEmit (ec, false))
+                               ec.ig.Emit (OpCodes.Pop);
+               }
+
+               public void AddressOf (EmitContext ec, AddressOp Mode)
+               {
+                       if (!type.IsValueType){
+                               //
+                               // We throw an exception.  So far, I believe we only need to support
+                               // value types:
+                               // foreach (int j in new StructType ())
+                               // see bug 42390
+                               //
+                               throw new Exception ("AddressOf should not be used for classes");
+                       }
+
+                       if (!value_target_set)
+                               value_target = new LocalTemporary (ec, type);
+                                       
+                       IMemoryLocation ml = (IMemoryLocation) value_target;
+                       ml.AddressOf (ec, AddressOp.Store);
+                       if (method != null)
+                               Invocation.EmitArguments (ec, method, Arguments);
+
+                       if (method == null)
+                               ec.ig.Emit (OpCodes.Initobj, type);
+                       else 
+                               ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+                       
+                       ((IMemoryLocation) value_target).AddressOf (ec, Mode);
+               }
+       }
+
+       /// <summary>
+       ///   14.5.10.2: Represents an array creation expression.
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   There are two possible scenarios here: one is an array creation
+       ///   expression that specifies the dimensions and optionally the
+       ///   initialization data and the other which does not need dimensions
+       ///   specified but where initialization data is mandatory.
+       /// </remarks>
+       public class ArrayCreation : ExpressionStatement {
+               Expression requested_base_type;
+               ArrayList initializers;
+
+               //
+               // The list of Argument types.
+               // This is used to construct the `newarray' or constructor signature
+               //
+               ArrayList arguments;
+
+               //
+               // Method used to create the array object.
+               //
+               MethodBase new_method = null;
+               
+               Type array_element_type;
+               Type underlying_type;
+               bool is_one_dimensional = false;
+               bool is_builtin_type = false;
+               bool expect_initializers = false;
+               int num_arguments = 0;
+               int dimensions = 0;
+               string rank;
+
+               ArrayList array_data;
+
+               Hashtable bounds;
+
+               //
+               // The number of array initializers that we can handle
+               // via the InitializeArray method - through EmitStaticInitializers
+               //
+               int num_automatic_initializers;
+
+               const int max_automatic_initializers = 6;
+               
+               public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
+               {
+                       this.requested_base_type = requested_base_type;
+                       this.initializers = initializers;
+                       this.rank = rank;
+                       loc = l;
+
+                       arguments = new ArrayList ();
+
+                       foreach (Expression e in exprs) {
+                               arguments.Add (new Argument (e, Argument.AType.Expression));
+                               num_arguments++;
+                       }
+               }
+
+               public ArrayCreation (Expression requested_base_type, string rank, ArrayList initializers, Location l)
+               {
+                       this.requested_base_type = requested_base_type;
+                       this.initializers = initializers;
+                       this.rank = rank;
+                       loc = l;
+
+                       //this.rank = rank.Substring (0, rank.LastIndexOf ("["));
+                       //
+                       //string tmp = rank.Substring (rank.LastIndexOf ("["));
+                       //
+                       //dimensions = tmp.Length - 1;
+                       expect_initializers = true;
+               }
+
+               public Expression FormArrayType (Expression base_type, int idx_count, string rank)
+               {
+                       StringBuilder sb = new StringBuilder (rank);
+                       
+                       sb.Append ("[");
+                       for (int i = 1; i < idx_count; i++)
+                               sb.Append (",");
+                       
+                       sb.Append ("]");
+
+                       return new ComposedCast (base_type, sb.ToString (), loc);
+               }
+
+               void Error_IncorrectArrayInitializer ()
+               {
+                       Error (178, "Incorrectly structured array initializer");
+               }
+               
+               public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims)
+               {
+                       if (specified_dims) { 
+                               Argument a = (Argument) arguments [idx];
+                               
+                               if (!a.Resolve (ec, loc))
+                                       return false;
+                               
+                               if (!(a.Expr is Constant)) {
+                                       Error (150, "A constant value is expected");
+                                       return false;
+                               }
+                               
+                               int value = (int) ((Constant) a.Expr).GetValue ();
+                               
+                               if (value != probe.Count) {
+                                       Error_IncorrectArrayInitializer ();
+                                       return false;
+                               }
+                               
+                               bounds [idx] = value;
+                       }
+
+                       int child_bounds = -1;
+                       foreach (object o in probe) {
+                               if (o is ArrayList) {
+                                       int current_bounds = ((ArrayList) o).Count;
+                                       
+                                       if (child_bounds == -1) 
+                                               child_bounds = current_bounds;
+
+                                       else if (child_bounds != current_bounds){
+                                               Error_IncorrectArrayInitializer ();
+                                               return false;
+                                       }
+                                       if (specified_dims && (idx + 1 >= arguments.Count)){
+                                               Error (623, "Array initializers can only be used in a variable or field initializer, try using the new expression");
+                                               return false;
+                                       }
+                                       
+                                       bool ret = CheckIndices (ec, (ArrayList) o, idx + 1, specified_dims);
+                                       if (!ret)
+                                               return false;
+                               } else {
+                                       if (child_bounds != -1){
+                                               Error_IncorrectArrayInitializer ();
+                                               return false;
+                                       }
+                                       
+                                       Expression tmp = (Expression) o;
+                                       tmp = tmp.Resolve (ec);
+                                       if (tmp == null)
+                                               continue;
+
+                                       // Console.WriteLine ("I got: " + tmp);
+                                       // Handle initialization from vars, fields etc.
+
+                                       Expression conv = Convert.ImplicitConversionRequired (
+                                               ec, tmp, underlying_type, loc);
+                                       
+                                       if (conv == null) 
+                                               return false;
+
+                                       if (conv is StringConstant)
+                                               array_data.Add (conv);
+                                       else if (conv is Constant) {
+                                               array_data.Add (conv);
+                                               num_automatic_initializers++;
+                                       } else
+                                               array_data.Add (conv);
+                               }
+                       }
+
+                       return true;
+               }
+               
+               public void UpdateIndices (EmitContext ec)
+               {
+                       int i = 0;
+                       for (ArrayList probe = initializers; probe != null;) {
+                               if (probe.Count > 0 && probe [0] is ArrayList) {
+                                       Expression e = new IntConstant (probe.Count);
+                                       arguments.Add (new Argument (e, Argument.AType.Expression));
+
+                                       bounds [i++] =  probe.Count;
+                                       
+                                       probe = (ArrayList) probe [0];
+                                       
+                               } else {
+                                       Expression e = new IntConstant (probe.Count);
+                                       arguments.Add (new Argument (e, Argument.AType.Expression));
+
+                                       bounds [i++] = probe.Count;
+                                       probe = null;
+                               }
+                       }
+
+               }
+               
+               public bool ValidateInitializers (EmitContext ec, Type array_type)
+               {
+                       if (initializers == null) {
+                               if (expect_initializers)
+                                       return false;
+                               else
+                                       return true;
+                       }
+                       
+                       if (underlying_type == null)
+                               return false;
+                       
+                       //
+                       // We use this to store all the date values in the order in which we
+                       // will need to store them in the byte blob later
+                       //
+                       array_data = new ArrayList ();
+                       bounds = new Hashtable ();
+                       
+                       bool ret;
+
+                       if (arguments != null) {
+                               ret = CheckIndices (ec, initializers, 0, true);
+                               return ret;
+                       } else {
+                               arguments = new ArrayList ();
+
+                               ret = CheckIndices (ec, initializers, 0, false);
+                               
+                               if (!ret)
+                                       return false;
+                               
+                               UpdateIndices (ec);
+                               
+                               if (arguments.Count != dimensions) {
+                                       Error_IncorrectArrayInitializer ();
+                                       return false;
+                               }
+
+                               return ret;
+                       }
+               }
+
+               void Error_NegativeArrayIndex ()
+               {
+                       Error (284, "Can not create array with a negative size");
+               }
+               
+               //
+               // Converts `source' to an int, uint, long or ulong.
+               //
+               Expression ExpressionToArrayArgument (EmitContext ec, Expression source)
+               {
+                       Expression target;
+                       
+                       bool old_checked = ec.CheckState;
+                       ec.CheckState = true;
+                       
+                       target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
+                       if (target == null){
+                               target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
+                               if (target == null){
+                                       target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
+                                       if (target == null){
+                                               target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
+                                               if (target == null)
+                                                       Convert.Error_CannotImplicitConversion (loc, source.Type, TypeManager.int32_type);
+                                       }
+                               }
+                       } 
+                       ec.CheckState = old_checked;
+
+                       //
+                       // Only positive constants are allowed at compile time
+                       //
+                       if (target is Constant){
+                               if (target is IntConstant){
+                                       if (((IntConstant) target).Value < 0){
+                                               Error_NegativeArrayIndex ();
+                                               return null;
+                                       }
+                               }
+
+                               if (target is LongConstant){
+                                       if (((LongConstant) target).Value < 0){
+                                               Error_NegativeArrayIndex ();
+                                               return null;
+                                       }
+                               }
+                               
+                       }
+
+                       return target;
+               }
+
+               //
+               // Creates the type of the array
+               //
+               bool LookupType (EmitContext ec)
+               {
+                       StringBuilder array_qualifier = new StringBuilder (rank);
+
+                       //
+                       // `In the first form allocates an array instace of the type that results
+                       // from deleting each of the individual expression from the expression list'
+                       //
+                       if (num_arguments > 0) {
+                               array_qualifier.Append ("[");
+                               for (int i = num_arguments-1; i > 0; i--)
+                                       array_qualifier.Append (",");
+                               array_qualifier.Append ("]");                           
+                       }
+
+                       //
+                       // Lookup the type
+                       //
+                       Expression array_type_expr;
+                       array_type_expr = new ComposedCast (requested_base_type, array_qualifier.ToString (), loc);
+                       type = ec.DeclSpace.ResolveType (array_type_expr, false, loc);
+
+                       if (type == null)
+                               return false;
+
+                       underlying_type = type;
+                       if (underlying_type.IsArray)
+                               underlying_type = TypeManager.GetElementType (underlying_type);
+                       dimensions = type.GetArrayRank ();
+
+                       return true;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       int arg_count;
+
+                       if (!LookupType (ec))
+                               return null;
+                       
+                       //
+                       // First step is to validate the initializers and fill
+                       // in any missing bits
+                       //
+                       if (!ValidateInitializers (ec, type))
+                               return null;
+
+                       if (arguments == null)
+                               arg_count = 0;
+                       else {
+                               arg_count = arguments.Count;
+                               foreach (Argument a in arguments){
+                                       if (!a.Resolve (ec, loc))
+                                               return null;
+
+                                       Expression real_arg = ExpressionToArrayArgument (ec, a.Expr, loc);
+                                       if (real_arg == null)
+                                               return null;
+
+                                       a.Expr = real_arg;
+                               }
+                       }
+                       
+                       array_element_type = TypeManager.GetElementType (type);
+
+                       if (arg_count == 1) {
+                               is_one_dimensional = true;
+                               eclass = ExprClass.Value;
+                               return this;
+                       }
+
+                       is_builtin_type = TypeManager.IsBuiltinType (type);
+
+                       if (is_builtin_type) {
+                               Expression ml;
+                               
+                               ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor,
+                                                  AllBindingFlags, loc);
+                               
+                               if (!(ml is MethodGroupExpr)) {
+                                       ml.Error_UnexpectedKind ("method group");
+                                       return null;
+                               }
+                               
+                               if (ml == null) {
+                                       Error (-6, "New invocation: Can not find a constructor for " +
+                                                     "this argument list");
+                                       return null;
+                               }
+                               
+                               new_method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, arguments, loc);
+
+                               if (new_method == null) {
+                                       Error (-6, "New invocation: Can not find a constructor for " +
+                                                     "this argument list");
+                                       return null;
+                               }
+                               
+                               eclass = ExprClass.Value;
+                               return this;
+                       } else {
+                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               ArrayList args = new ArrayList ();
+                               
+                               if (arguments != null) {
+                                       for (int i = 0; i < arg_count; i++)
+                                               args.Add (TypeManager.int32_type);
+                               }
+                               
+                               Type [] arg_types = null;
+
+                               if (args.Count > 0)
+                                       arg_types = new Type [args.Count];
+                               
+                               args.CopyTo (arg_types, 0);
+                               
+                               new_method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
+                                                           arg_types);
+
+                               if (new_method == null) {
+                                       Error (-6, "New invocation: Can not find a constructor for " +
+                                                     "this argument list");
+                                       return null;
+                               }
+                               
+                               eclass = ExprClass.Value;
+                               return this;
+                       }
+               }
+
+               public static byte [] MakeByteBlob (ArrayList array_data, Type underlying_type, Location loc)
+               {
+                       int factor;
+                       byte [] data;
+                       byte [] element;
+                       int count = array_data.Count;
+
+                       if (underlying_type.IsEnum)
+                               underlying_type = TypeManager.EnumToUnderlying (underlying_type);
+                       
+                       factor = GetTypeSize (underlying_type);
+                       if (factor == 0)
+                               throw new Exception ("unrecognized type in MakeByteBlob: " + underlying_type);
+
+                       data = new byte [(count * factor + 4) & ~3];
+                       int idx = 0;
+                       
+                       for (int i = 0; i < count; ++i) {
+                               object v = array_data [i];
+
+                               if (v is EnumConstant)
+                                       v = ((EnumConstant) v).Child;
+                               
+                               if (v is Constant && !(v is StringConstant))
+                                       v = ((Constant) v).GetValue ();
+                               else {
+                                       idx += factor;
+                                       continue;
+                               }
+                               
+                               if (underlying_type == TypeManager.int64_type){
+                                       if (!(v is Expression)){
+                                               long val = (long) v;
+                                               
+                                               for (int j = 0; j < factor; ++j) {
+                                                       data [idx + j] = (byte) (val & 0xFF);
+                                                       val = (val >> 8);
+                                               }
+                                       }
+                               } else if (underlying_type == TypeManager.uint64_type){
+                                       if (!(v is Expression)){
+                                               ulong val = (ulong) v;
+
+                                               for (int j = 0; j < factor; ++j) {
+                                                       data [idx + j] = (byte) (val & 0xFF);
+                                                       val = (val >> 8);
+                                               }
+                                       }
+                               } else if (underlying_type == TypeManager.float_type) {
+                                       if (!(v is Expression)){
+                                               element = BitConverter.GetBytes ((float) v);
+                                                       
+                                               for (int j = 0; j < factor; ++j)
+                                                       data [idx + j] = element [j];
+                                       }
+                               } else if (underlying_type == TypeManager.double_type) {
+                                       if (!(v is Expression)){
+                                               element = BitConverter.GetBytes ((double) v);
+
+                                               for (int j = 0; j < factor; ++j)
+                                                       data [idx + j] = element [j];
+                                       }
+                               } else if (underlying_type == TypeManager.char_type){
+                                       if (!(v is Expression)){
+                                               int val = (int) ((char) v);
+                                               
+                                               data [idx] = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) (val >> 8);
+                                       }
+                               } else if (underlying_type == TypeManager.short_type){
+                                       if (!(v is Expression)){
+                                               int val = (int) ((short) v);
+                                       
+                                               data [idx] = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) (val >> 8);
+                                       }
+                               } else if (underlying_type == TypeManager.ushort_type){
+                                       if (!(v is Expression)){
+                                               int val = (int) ((ushort) v);
+                                       
+                                               data [idx] = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) (val >> 8);
+                                       }
+                               } else if (underlying_type == TypeManager.int32_type) {
+                                       if (!(v is Expression)){
+                                               int val = (int) v;
+                                       
+                                               data [idx]   = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) ((val >> 8) & 0xff);
+                                               data [idx+2] = (byte) ((val >> 16) & 0xff);
+                                               data [idx+3] = (byte) (val >> 24);
+                                       }
+                               } else if (underlying_type == TypeManager.uint32_type) {
+                                       if (!(v is Expression)){
+                                               uint val = (uint) v;
+                                       
+                                               data [idx]   = (byte) (val & 0xff);
+                                               data [idx+1] = (byte) ((val >> 8) & 0xff);
+                                               data [idx+2] = (byte) ((val >> 16) & 0xff);
+                                               data [idx+3] = (byte) (val >> 24);
+                                       }
+                               } else if (underlying_type == TypeManager.sbyte_type) {
+                                       if (!(v is Expression)){
+                                               sbyte val = (sbyte) v;
+                                               data [idx] = (byte) val;
+                                       }
+                               } else if (underlying_type == TypeManager.byte_type) {
+                                       if (!(v is Expression)){
+                                               byte val = (byte) v;
+                                               data [idx] = (byte) val;
+                                       }
+                               } else if (underlying_type == TypeManager.bool_type) {
+                                       if (!(v is Expression)){
+                                               bool val = (bool) v;
+                                               data [idx] = (byte) (val ? 1 : 0);
+                                       }
+                               } else if (underlying_type == TypeManager.decimal_type){
+                                       if (!(v is Expression)){
+                                               int [] bits = Decimal.GetBits ((decimal) v);
+                                               int p = idx;
+
+                                               // FIXME: For some reason, this doesn't work on the MS runtime.
+                                               int [] nbits = new int [4];
+                                               nbits [0] = bits [3];
+                                               nbits [1] = bits [2];
+                                               nbits [2] = bits [0];
+                                               nbits [3] = bits [1];
+                                               
+                                               for (int j = 0; j < 4; j++){
+                                                       data [p++] = (byte) (nbits [j] & 0xff);
+                                                       data [p++] = (byte) ((nbits [j] >> 8) & 0xff);
+                                                       data [p++] = (byte) ((nbits [j] >> 16) & 0xff);
+                                                       data [p++] = (byte) (nbits [j] >> 24);
+                                               }
+                                       }
+                               } else
+                                       throw new Exception ("Unrecognized type in MakeByteBlob: " + underlying_type);
+
+                                idx += factor;
+                       }
+
+                       return data;
+               }
+
+               //
+               // Emits the initializers for the array
+               //
+               void EmitStaticInitializers (EmitContext ec, bool is_expression)
+               {
+                       //
+                       // First, the static data
+                       //
+                       FieldBuilder fb;
+                       ILGenerator ig = ec.ig;
+                       
+                       byte [] data = MakeByteBlob (array_data, underlying_type, loc);
+
+                       fb = RootContext.MakeStaticData (data);
+
+                       if (is_expression)
+                               ig.Emit (OpCodes.Dup);
+                       ig.Emit (OpCodes.Ldtoken, fb);
+                       ig.Emit (OpCodes.Call,
+                                TypeManager.void_initializearray_array_fieldhandle);
+               }
+               
+               //
+               // Emits pieces of the array that can not be computed at compile
+               // time (variables and string locations).
+               //
+               // This always expect the top value on the stack to be the array
+               //
+               void EmitDynamicInitializers (EmitContext ec, bool is_expression)
+               {
+                       ILGenerator ig = ec.ig;
+                       int dims = bounds.Count;
+                       int [] current_pos = new int [dims];
+                       int top = array_data.Count;
+                       LocalBuilder temp = ig.DeclareLocal (type);
+
+                       ig.Emit (OpCodes.Stloc, temp);
+
+                       MethodInfo set = null;
+
+                       if (dims != 1){
+                               Type [] args;
+                               ModuleBuilder mb = null;
+                               mb = CodeGen.ModuleBuilder;
+                               args = new Type [dims + 1];
+
+                               int j;
+                               for (j = 0; j < dims; j++)
+                                       args [j] = TypeManager.int32_type;
+
+                               args [j] = array_element_type;
+                               
+                               set = mb.GetArrayMethod (
+                                       type, "Set",
+                                       CallingConventions.HasThis | CallingConventions.Standard,
+                                       TypeManager.void_type, args);
+                       }
+                       
+                       for (int i = 0; i < top; i++){
+
+                               Expression e = null;
+
+                               if (array_data [i] is Expression)
+                                       e = (Expression) array_data [i];
+
+                               if (e != null) {
+                                       //
+                                       // Basically we do this for string literals and
+                                       // other non-literal expressions
+                                       //
+                                       if (e is EnumConstant){
+                                               e = ((EnumConstant) e).Child;
+                                       }
+                                       
+                                       if (e is StringConstant || e is DecimalConstant || !(e is Constant) ||
+                                           num_automatic_initializers <= max_automatic_initializers) {
+                                               Type etype = e.Type;
+                                               
+                                               ig.Emit (OpCodes.Ldloc, temp);
+
+                                               for (int idx = 0; idx < dims; idx++) 
+                                                       IntConstant.EmitInt (ig, current_pos [idx]);
+
+                                               //
+                                               // If we are dealing with a struct, get the
+                                               // address of it, so we can store it.
+                                               //
+                                               if ((dims == 1) &&
+                                                   etype.IsSubclassOf (TypeManager.value_type) &&
+                                                   (!TypeManager.IsBuiltinType (etype) ||
+                                                    etype == TypeManager.decimal_type)) {
+                                                       if (e is New){
+                                                               New n = (New) e;
+
+                                                               //
+                                                               // Let new know that we are providing
+                                                               // the address where to store the results
+                                                               //
+                                                               n.DisableTemporaryValueType ();
+                                                       }
+
+                                                       ig.Emit (OpCodes.Ldelema, etype);
+                                               }
+
+                                               e.Emit (ec);
+
+                                                if (dims == 1)
+                                                        ArrayAccess.EmitStoreOpcode (ig, array_element_type);
+                                                else 
+                                                        ig.Emit (OpCodes.Call, set);
+                                                
+                                        }
+                               }
+                               
+                               //
+                               // Advance counter
+                               //
+                               for (int j = dims - 1; j >= 0; j--){
+                                       current_pos [j]++;
+                                       if (current_pos [j] < (int) bounds [j])
+                                               break;
+                                       current_pos [j] = 0;
+                               }
+                       }
+
+                       if (is_expression)
+                               ig.Emit (OpCodes.Ldloc, temp);
+               }
+
+               void EmitArrayArguments (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       foreach (Argument a in arguments) {
+                               Type atype = a.Type;
+                               a.Emit (ec);
+
+                               if (atype == TypeManager.uint64_type)
+                                       ig.Emit (OpCodes.Conv_Ovf_U4);
+                               else if (atype == TypeManager.int64_type)
+                                       ig.Emit (OpCodes.Conv_Ovf_I4);
+                       }
+               }
+               
+               void DoEmit (EmitContext ec, bool is_statement)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       EmitArrayArguments (ec);
+                       if (is_one_dimensional)
+                               ig.Emit (OpCodes.Newarr, array_element_type);
+                       else {
+                               if (is_builtin_type) 
+                                       ig.Emit (OpCodes.Newobj, (ConstructorInfo) new_method);
+                               else 
+                                       ig.Emit (OpCodes.Newobj, (MethodInfo) new_method);
+                       }
+                       
+                       if (initializers != null){
+                               //
+                               // FIXME: Set this variable correctly.
+                               // 
+                               bool dynamic_initializers = true;
+
+                               if (underlying_type != TypeManager.string_type &&
+                                   underlying_type != TypeManager.decimal_type &&
+                                   underlying_type != TypeManager.object_type) {
+                                       if (num_automatic_initializers > max_automatic_initializers)
+                                               EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
+                               }
+                               
+                               if (dynamic_initializers)
+                                       EmitDynamicInitializers (ec, !is_statement);
+                       }
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       DoEmit (ec, false);
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       DoEmit (ec, true);
+               }
+
+               public object EncodeAsAttribute ()
+               {
+                       if (!is_one_dimensional){
+                               Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
+                               return null;
+                       }
+
+                       if (array_data == null){
+                               Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
+                               return null;
+                       }
+                       
+                       object [] ret = new object [array_data.Count];
+                       int i = 0;
+                       foreach (Expression e in array_data){
+                               object v;
+                               
+                               if (e is NullLiteral)
+                                       v = null;
+                               else {
+                                       if (!Attribute.GetAttributeArgumentExpression (e, Location, out v))
+                                               return null;
+                               }
+                               ret [i++] = v;
+                       }
+                       return ret;
+               }
+       }
+       
+       /// <summary>
+       ///   Represents the `this' construct
+       /// </summary>
+       public class This : Expression, IAssignMethod, IMemoryLocation, IVariable {
+
+               Block block;
+               VariableInfo variable_info;
+               
+               public This (Block block, Location loc)
+               {
+                       this.loc = loc;
+                       this.block = block;
+               }
+
+               public This (Location loc)
+               {
+                       this.loc = loc;
+               }
+
+               public VariableInfo VariableInfo {
+                       get { return variable_info; }
+               }
+
+               public bool VerifyFixed (bool is_expression)
+               {
+                       return variable_info.LocalInfo.IsFixed;
+               }
+
+               public bool ResolveBase (EmitContext ec)
+               {
+                       eclass = ExprClass.Variable;
+                       type = ec.ContainerType;
+
+                       if (ec.IsStatic) {
+                               Error (26, "Keyword this not valid in static code");
+                               return false;
+                       }
+
+                       if ((block != null) && (block.ThisVariable != null))
+                               variable_info = block.GetVariableInfo (block.ThisVariable);
+
+                       return true;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (!ResolveBase (ec))
+                               return null;
+
+                       if ((variable_info != null) && !variable_info.IsAssigned (ec)) {
+                               Error (188, "The this object cannot be used before all " +
+                                      "of its fields are assigned to");
+                               variable_info.SetAssigned (ec);
+                               return this;
+                       }
+
+                       if (ec.IsFieldInitializer) {
+                               Error (27, "Keyword `this' can't be used outside a constructor, " +
+                                      "a method or a property.");
+                               return null;
+                       }
+
+                       return this;
+               }
+
+               override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       if (!ResolveBase (ec))
+                               return null;
+
+                       if (variable_info != null)
+                               variable_info.SetAssigned (ec);
+                       
+                       if (ec.TypeContainer is Class){
+                               Error (1604, "Cannot assign to `this'");
+                               return null;
+                       }
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       ig.Emit (OpCodes.Ldarg_0);
+                       if (ec.TypeContainer is Struct)
+                               ig.Emit (OpCodes.Ldobj, type);
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       if (ec.TypeContainer is Struct){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               source.Emit (ec);
+                               ig.Emit (OpCodes.Stobj, type);
+                       } else {
+                               source.Emit (ec);
+                               ig.Emit (OpCodes.Starg, 0);
+                       }
+               }
+
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       ec.ig.Emit (OpCodes.Ldarg_0);
+
+                       // FIMXE
+                       // FIGURE OUT WHY LDARG_S does not work
+                       //
+                       // consider: struct X { int val; int P { set { val = value; }}}
+                       //
+                       // Yes, this looks very bad. Look at `NOTAS' for
+                       // an explanation.
+                       // ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
+               }
+       }
+
+       /// <summary>
+       ///   Implements the typeof operator
+       /// </summary>
+       public class TypeOf : Expression {
+               public readonly Expression QueriedType;
+               Type typearg;
+               
+               public TypeOf (Expression queried_type, Location l)
+               {
+                       QueriedType = queried_type;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       typearg = ec.DeclSpace.ResolveType (QueriedType, false, loc);
+
+                       if (typearg == null)
+                               return null;
+
+                       if (typearg == TypeManager.void_type) {
+                               Error (673, "System.Void cannot be used from C# - " +
+                                      "use typeof (void) to get the void type object");
+                               return null;
+                       }
+
+                       type = TypeManager.type_type;
+                       eclass = ExprClass.Type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldtoken, typearg);
+                       ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
+               }
+
+               public Type TypeArg { 
+                       get { return typearg; }
+               }
+       }
+
+       /// <summary>
+       ///   Implements the `typeof (void)' operator
+       /// </summary>
+       public class TypeOfVoid : Expression {
+               public TypeOfVoid (Location l)
+               {
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.type_type;
+                       eclass = ExprClass.Type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldtoken, TypeManager.void_type);
+                       ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
+               }
+
+               public Type TypeArg { 
+                       get { return TypeManager.void_type; }
+               }
+       }
+
+       /// <summary>
+       ///   Implements the sizeof expression
+       /// </summary>
+       public class SizeOf : Expression {
+               public readonly Expression QueriedType;
+               Type type_queried;
+               
+               public SizeOf (Expression queried_type, Location l)
+               {
+                       this.QueriedType = queried_type;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (!ec.InUnsafe) {
+                               Report.Error (
+                                       233, loc, "Sizeof may only be used in an unsafe context " +
+                                       "(consider using System.Runtime.InteropServices.Marshal.Sizeof");
+                               return null;
+                       }
+                               
+                       type_queried = ec.DeclSpace.ResolveType (QueriedType, false, loc);
+                       if (type_queried == null)
+                               return null;
+
+                       if (!TypeManager.IsUnmanagedType (type_queried)){
+                               Report.Error (208, loc, "Cannot take the size of an unmanaged type (" + TypeManager.CSharpName (type_queried) + ")");
+                               return null;
+                       }
+                       
+                       type = TypeManager.int32_type;
+                       eclass = ExprClass.Value;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       int size = GetTypeSize (type_queried);
+
+                       if (size == 0)
+                               ec.ig.Emit (OpCodes.Sizeof, type_queried);
+                       else
+                               IntConstant.EmitInt (ec.ig, size);
+               }
+       }
+
+       /// <summary>
+       ///   Implements the member access expression
+       /// </summary>
+       public class MemberAccess : Expression {
+               public readonly string Identifier;
+               Expression expr;
+               
+               public MemberAccess (Expression expr, string id, Location l)
+               {
+                       this.expr = expr;
+                       Identifier = id;
+                       loc = l;
+               }
+
+               public Expression Expr {
+                       get {
+                               return expr;
+                       }
+               }
+
+               static void error176 (Location loc, string name)
+               {
+                       Report.Error (176, loc, "Static member `" +
+                                     name + "' cannot be accessed " +
+                                     "with an instance reference, qualify with a " +
+                                     "type name instead");
+               }
+
+               static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc)
+               {
+                       if (left_original == null)
+                               return false;
+
+                       if (!(left_original is SimpleName))
+                               return false;
+
+                       SimpleName sn = (SimpleName) left_original;
+
+                       Type t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
+                       if (t != null)
+                               return true;
+
+                       return false;
+               }
+               
+               public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
+                                                             Expression left, Location loc,
+                                                             Expression left_original)
+               {
+                       bool left_is_type, left_is_explicit;
+
+                       // If `left' is null, then we're called from SimpleNameResolve and this is
+                       // a member in the currently defining class.
+                       if (left == null) {
+                               left_is_type = ec.IsStatic || ec.IsFieldInitializer;
+                               left_is_explicit = false;
+
+                               // Implicitly default to `this' unless we're static.
+                               if (!ec.IsStatic && !ec.IsFieldInitializer && !ec.InEnumContext)
+                                       left = ec.GetThis (loc);
+                       } else {
+                               left_is_type = left is TypeExpr;
+                               left_is_explicit = true;
+                       }
+
+                       if (member_lookup is FieldExpr){
+                               FieldExpr fe = (FieldExpr) member_lookup;
+                               FieldInfo fi = fe.FieldInfo;
+                               Type decl_type = fi.DeclaringType;
+
+                               if (fi is FieldBuilder) {
+                                       Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
+                                       
+                                       if (c != null) {
+                                               object o = c.LookupConstantValue ();
+                                               if (o == null)
+                                                       return null;
+                                               
+                                               object real_value = ((Constant) c.Expr).GetValue ();
+
+                                               return Constantify (real_value, fi.FieldType);
+                                       }
+                               }
+
+                               if (fi.IsLiteral) {
+                                       Type t = fi.FieldType;
+                                       
+                                       object o;
+
+                                       if (fi is FieldBuilder)
+                                               o = TypeManager.GetValue ((FieldBuilder) fi);
+                                       else
+                                               o = fi.GetValue (fi);
+                                       
+                                       if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
+                                               if (left_is_explicit && !left_is_type &&
+                                                   !IdenticalNameAndTypeName (ec, left_original, loc)) {
+                                                       error176 (loc, fe.FieldInfo.Name);
+                                                       return null;
+                                               }                                       
+                                               
+                                               Expression enum_member = MemberLookup (
+                                                       ec, decl_type, "value__", MemberTypes.Field,
+                                                       AllBindingFlags, loc); 
+
+                                               Enum en = TypeManager.LookupEnum (decl_type);
+
+                                               Constant c;
+                                               if (en != null)
+                                                       c = Constantify (o, en.UnderlyingType);
+                                               else 
+                                                       c = Constantify (o, enum_member.Type);
+                                               
+                                               return new EnumConstant (c, decl_type);
+                                       }
+                                       
+                                       Expression exp = Constantify (o, t);
+
+                                       if (left_is_explicit && !left_is_type) {
+                                               error176 (loc, fe.FieldInfo.Name);
+                                               return null;
+                                       }
+                                       
+                                       return exp;
+                               }
+
+                               if (fi.FieldType.IsPointer && !ec.InUnsafe){
+                                       UnsafeError (loc);
+                                       return null;
+                               }
+                       }
+
+                       if (member_lookup is EventExpr) {
+                               EventExpr ee = (EventExpr) member_lookup;
+                               
+                               //
+                               // If the event is local to this class, we transform ourselves into
+                               // a FieldExpr
+                               //
+
+                               if (ee.EventInfo.DeclaringType == ec.ContainerType) {
+                                       MemberInfo mi = GetFieldFromEvent (ee);
+
+                                       if (mi == null) {
+                                               //
+                                               // If this happens, then we have an event with its own
+                                               // accessors and private field etc so there's no need
+                                               // to transform ourselves.
+                                               //
+                                               return ee;
+                                       }
+
+                                       Expression ml = ExprClassFromMemberInfo (ec, mi, loc);
+                                       
+                                       if (ml == null) {
+                                               Report.Error (-200, loc, "Internal error!!");
+                                               return null;
+                                       }
+
+                                       if (!left_is_explicit)
+                                               left = null;
+                                       
+                                       return ResolveMemberAccess (ec, ml, left, loc, left_original);
+                               }
+                       }
+
+                       if (member_lookup is IMemberExpr) {
+                               IMemberExpr me = (IMemberExpr) member_lookup;
+
+                               if (left_is_type){
+                                       MethodGroupExpr mg = me as MethodGroupExpr;
+                                       if ((mg != null) && left_is_explicit && left.Type.IsInterface)
+                                               mg.IsExplicitImpl = left_is_explicit;
+
+                                       if (!me.IsStatic){
+                                               if ((ec.IsFieldInitializer || ec.IsStatic) &&
+                                                   IdenticalNameAndTypeName (ec, left_original, loc))
+                                                       return member_lookup;
+
+                                               SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
+                                               return null;
+                                       }
+
+                               } else {
+                                       if (!me.IsInstance){
+                                               if (IdenticalNameAndTypeName (ec, left_original, loc))
+                                                       return member_lookup;
+
+                                               if (left_is_explicit) {
+                                                       error176 (loc, me.Name);
+                                                       return null;
+                                               }
+                                       }
+
+                                       //
+                                       // Since we can not check for instance objects in SimpleName,
+                                       // becaue of the rule that allows types and variables to share
+                                       // the name (as long as they can be de-ambiguated later, see 
+                                       // IdenticalNameAndTypeName), we have to check whether left 
+                                       // is an instance variable in a static context
+                                       //
+                                       // However, if the left-hand value is explicitly given, then
+                                       // it is already our instance expression, so we aren't in
+                                       // static context.
+                                       //
+
+                                       if (ec.IsStatic && !left_is_explicit && left is IMemberExpr){
+                                               IMemberExpr mexp = (IMemberExpr) left;
+
+                                               if (!mexp.IsStatic){
+                                                       SimpleName.Error_ObjectRefRequired (ec, loc, mexp.Name);
+                                                       return null;
+                                               }
+                                       }
+
+                                       me.InstanceExpression = left;
+                               }
+
+                               return member_lookup;
+                       }
+
+                       Console.WriteLine ("Left is: " + left);
+                       Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
+                       Environment.Exit (0);
+                       return null;
+               }
+               
+               public Expression DoResolve (EmitContext ec, Expression right_side, ResolveFlags flags)
+               {
+                       if (type != null)
+                               throw new Exception ();
+
+                       //
+                       // Resolve the expression with flow analysis turned off, we'll do the definite
+                       // assignment checks later.  This is because we don't know yet what the expression
+                       // will resolve to - it may resolve to a FieldExpr and in this case we must do the
+                       // definite assignment check on the actual field and not on the whole struct.
+                       //
+
+                       Expression original = expr;
+                       expr = expr.Resolve (ec, flags | ResolveFlags.DisableFlowAnalysis);
+                       if (expr == null)
+                               return null;
+
+                       if (expr is SimpleName){
+                               SimpleName child_expr = (SimpleName) expr;
+
+                               Expression new_expr = new SimpleName (child_expr.Name, Identifier, loc);
+
+                               return new_expr.Resolve (ec, flags);
+                       }
+                                       
+                       //
+                       // TODO: I mailed Ravi about this, and apparently we can get rid
+                       // of this and put it in the right place.
+                       // 
+                       // Handle enums here when they are in transit.
+                       // Note that we cannot afford to hit MemberLookup in this case because
+                       // it will fail to find any members at all
+                       //
+
+                       int errors = Report.Errors;
+                       
+                       Type expr_type = expr.Type;
+                       if (expr is TypeExpr){
+                               if (!ec.DeclSpace.CheckAccessLevel (expr_type)){
+                                       Error (122, "`" + expr_type + "' " +
+                                              "is inaccessible because of its protection level");
+                                       return null;
+                               }
+
+                               if (expr_type == TypeManager.enum_type || expr_type.IsSubclassOf (TypeManager.enum_type)){
+                                       Enum en = TypeManager.LookupEnum (expr_type);
+
+                                       if (en != null) {
+                                               object value = en.LookupEnumValue (ec, Identifier, loc);
+                                               
+                                               if (value != null){
+                                                       Constant c = Constantify (value, en.UnderlyingType);
+                                                       return new EnumConstant (c, expr_type);
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       if (expr_type.IsPointer){
+                               Error (23, "The `.' operator can not be applied to pointer operands (" +
+                                      TypeManager.CSharpName (expr_type) + ")");
+                               return null;
+                       }
+
+                       Expression member_lookup;
+                       member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc);
+                       if (member_lookup == null)
+                               return null;
+
+                       if (member_lookup is TypeExpr) {
+                               if (!(expr is TypeExpr) && !(expr is SimpleName)) {
+                                       Error (572, "Can't reference type `" + Identifier + "' through an expression; try `" +
+                                              member_lookup.Type + "' instead");
+                                       return null;
+                               }
+
+                               return member_lookup;
+                       }
+                       
+                       member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original);
+                       if (member_lookup == null)
+                               return null;
+
+                       // The following DoResolve/DoResolveLValue will do the definite assignment
+                       // check.
+
+                       if (right_side != null)
+                               member_lookup = member_lookup.DoResolveLValue (ec, right_side);
+                       else
+                               member_lookup = member_lookup.DoResolve (ec);
+
+                       return member_lookup;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return DoResolve (ec, null, ResolveFlags.VariableOrValue |
+                                         ResolveFlags.SimpleName | ResolveFlags.Type);
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       return DoResolve (ec, right_side, ResolveFlags.VariableOrValue |
+                                         ResolveFlags.SimpleName | ResolveFlags.Type);
+               }
+
+               public override Expression ResolveAsTypeStep (EmitContext ec)
+               {
+                       string fname = null;
+                       MemberAccess full_expr = this;
+                       while (full_expr != null) {
+                               if (fname != null)
+                                       fname = String.Concat (full_expr.Identifier, ".", fname);
+                               else
+                                       fname = full_expr.Identifier;
+
+                               if (full_expr.Expr is SimpleName) {
+                                       string full_name = String.Concat (((SimpleName) full_expr.Expr).Name, ".", fname);
+                                       Type fully_qualified = ec.DeclSpace.FindType (loc, full_name);
+                                       if (fully_qualified != null)
+                                               return new TypeExpr (fully_qualified, loc);
+                               }
+
+                               full_expr = full_expr.Expr as MemberAccess;
+                       }
+
+                       Expression new_expr = expr.ResolveAsTypeStep (ec);
+
+                       if (new_expr == null)
+                               return null;
+
+                       if (new_expr is SimpleName){
+                               SimpleName child_expr = (SimpleName) new_expr;
+                               
+                               new_expr = new SimpleName (child_expr.Name, Identifier, loc);
+
+                               return new_expr.ResolveAsTypeStep (ec);
+                       }
+
+                       Type expr_type = new_expr.Type;
+                     
+                       if (expr_type.IsPointer){
+                               Error (23, "The `.' operator can not be applied to pointer operands (" +
+                                      TypeManager.CSharpName (expr_type) + ")");
+                               return null;
+                       }
+                       
+                       Expression member_lookup;
+                       member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc);
+                       if (member_lookup == null)
+                               return null;
+
+                       if (member_lookup is TypeExpr){
+                               member_lookup.Resolve (ec, ResolveFlags.Type);
+                               return member_lookup;
+                       } 
+
+                       return null;                    
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should not happen");
+               }
+
+               public override string ToString ()
+               {
+                       return expr + "." + Identifier;
+               }
+       }
+
+       /// <summary>
+       ///   Implements checked expressions
+       /// </summary>
+       public class CheckedExpr : Expression {
+
+               public Expression Expr;
+
+               public CheckedExpr (Expression e, Location l)
+               {
+                       Expr = e;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       bool last_check = ec.CheckState;
+                       bool last_const_check = ec.ConstantCheckState;
+
+                       ec.CheckState = true;
+                       ec.ConstantCheckState = true;
+                       Expr = Expr.Resolve (ec);
+                       ec.CheckState = last_check;
+                       ec.ConstantCheckState = last_const_check;
+                       
+                       if (Expr == null)
+                               return null;
+
+                       if (Expr is Constant)
+                               return Expr;
+                       
+                       eclass = Expr.eclass;
+                       type = Expr.Type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       bool last_check = ec.CheckState;
+                       bool last_const_check = ec.ConstantCheckState;
+                       
+                       ec.CheckState = true;
+                       ec.ConstantCheckState = true;
+                       Expr.Emit (ec);
+                       ec.CheckState = last_check;
+                       ec.ConstantCheckState = last_const_check;
+               }
+               
+       }
+
+       /// <summary>
+       ///   Implements the unchecked expression
+       /// </summary>
+       public class UnCheckedExpr : Expression {
+
+               public Expression Expr;
+
+               public UnCheckedExpr (Expression e, Location l)
+               {
+                       Expr = e;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       bool last_check = ec.CheckState;
+                       bool last_const_check = ec.ConstantCheckState;
+
+                       ec.CheckState = false;
+                       ec.ConstantCheckState = false;
+                       Expr = Expr.Resolve (ec);
+                       ec.CheckState = last_check;
+                       ec.ConstantCheckState = last_const_check;
+
+                       if (Expr == null)
+                               return null;
+
+                       if (Expr is Constant)
+                               return Expr;
+                       
+                       eclass = Expr.eclass;
+                       type = Expr.Type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       bool last_check = ec.CheckState;
+                       bool last_const_check = ec.ConstantCheckState;
+                       
+                       ec.CheckState = false;
+                       ec.ConstantCheckState = false;
+                       Expr.Emit (ec);
+                       ec.CheckState = last_check;
+                       ec.ConstantCheckState = last_const_check;
+               }
+               
+       }
+
+       /// <summary>
+       ///   An Element Access expression.
+       ///
+       ///   During semantic analysis these are transformed into 
+       ///   IndexerAccess, ArrayAccess or a PointerArithmetic.
+       /// </summary>
+       public class ElementAccess : Expression {
+               public ArrayList  Arguments;
+               public Expression Expr;
+               
+               public ElementAccess (Expression e, ArrayList e_list, Location l)
+               {
+                       Expr = e;
+
+                       loc  = l;
+                       
+                       if (e_list == null)
+                               return;
+                       
+                       Arguments = new ArrayList ();
+                       foreach (Expression tmp in e_list)
+                               Arguments.Add (new Argument (tmp, Argument.AType.Expression));
+                       
+               }
+
+               bool CommonResolve (EmitContext ec)
+               {
+                       Expr = Expr.Resolve (ec);
+
+                       if (Expr == null) 
+                               return false;
+
+                       if (Arguments == null)
+                               return false;
+
+                       foreach (Argument a in Arguments){
+                               if (!a.Resolve (ec, loc))
+                                       return false;
+                       }
+
+                       return true;
+               }
+
+               Expression MakePointerAccess ()
+               {
+                       Type t = Expr.Type;
+
+                       if (t == TypeManager.void_ptr_type){
+                               Error (242, "The array index operation is not valid for void pointers");
+                               return null;
+                       }
+                       if (Arguments.Count != 1){
+                               Error (196, "A pointer must be indexed by a single value");
+                               return null;
+                       }
+                       Expression p;
+
+                       p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, t, loc);
+                       return new Indirection (p, loc);
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (!CommonResolve (ec))
+                               return null;
+
+                       //
+                       // We perform some simple tests, and then to "split" the emit and store
+                       // code we create an instance of a different class, and return that.
+                       //
+                       // I am experimenting with this pattern.
+                       //
+                       Type t = Expr.Type;
+
+                       if (t == TypeManager.array_type){
+                               Report.Error (21, loc, "Cannot use indexer on System.Array");
+                               return null;
+                       }
+                       
+                       if (t.IsArray)
+                               return (new ArrayAccess (this, loc)).Resolve (ec);
+                       else if (t.IsPointer)
+                               return MakePointerAccess ();
+                       else
+                               return (new IndexerAccess (this, loc)).Resolve (ec);
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       if (!CommonResolve (ec))
+                               return null;
+
+                       Type t = Expr.Type;
+                       if (t.IsArray)
+                               return (new ArrayAccess (this, loc)).ResolveLValue (ec, right_side);
+                       else if (t.IsPointer)
+                               return MakePointerAccess ();
+                       else
+                               return (new IndexerAccess (this, loc)).ResolveLValue (ec, right_side);
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should never be reached");
+               }
+       }
+
+       /// <summary>
+       ///   Implements array access 
+       /// </summary>
+       public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation {
+               //
+               // Points to our "data" repository
+               //
+               ElementAccess ea;
+
+               LocalTemporary [] cached_locations;
+               
+               public ArrayAccess (ElementAccess ea_data, Location l)
+               {
+                       ea = ea_data;
+                       eclass = ExprClass.Variable;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       ExprClass eclass = ea.Expr.eclass;
+
+#if false
+                       // As long as the type is valid
+                       if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
+                             eclass == ExprClass.Value)) {
+                               ea.Expr.Error_UnexpectedKind ("variable or value");
+                               return null;
+                       }
+#endif
+
+                       Type t = ea.Expr.Type;
+                       if (t.GetArrayRank () != ea.Arguments.Count){
+                               ea.Error (22,
+                                         "Incorrect number of indexes for array " +
+                                         " expected: " + t.GetArrayRank () + " got: " +
+                                         ea.Arguments.Count);
+                               return null;
+                       }
+
+                        type = TypeManager.GetElementType (t);
+                        if (type.IsPointer && !ec.InUnsafe){
+                               UnsafeError (ea.Location);
+                               return null;
+                       }
+
+                       foreach (Argument a in ea.Arguments){
+                               Type argtype = a.Type;
+
+                               if (argtype == TypeManager.int32_type ||
+                                   argtype == TypeManager.uint32_type ||
+                                   argtype == TypeManager.int64_type ||
+                                   argtype == TypeManager.uint64_type)
+                                       continue;
+
+                               //
+                               // Mhm.  This is strage, because the Argument.Type is not the same as
+                               // Argument.Expr.Type: the value changes depending on the ref/out setting.
+                               //
+                               // Wonder if I will run into trouble for this.
+                               //
+                               a.Expr = ExpressionToArrayArgument (ec, a.Expr, ea.Location);
+                               if (a.Expr == null)
+                                       return null;
+                       }
+                       
+                       eclass = ExprClass.Variable;
+
+                       return this;
+               }
+
+               /// <summary>
+               ///    Emits the right opcode to load an object of Type `t'
+               ///    from an array of T
+               /// </summary>
+               static public void EmitLoadOpcode (ILGenerator ig, Type type)
+               {
+                       if (type == TypeManager.byte_type || type == TypeManager.bool_type)
+                               ig.Emit (OpCodes.Ldelem_U1);
+                       else if (type == TypeManager.sbyte_type)
+                               ig.Emit (OpCodes.Ldelem_I1);
+                       else if (type == TypeManager.short_type)
+                               ig.Emit (OpCodes.Ldelem_I2);
+                       else if (type == TypeManager.ushort_type || type == TypeManager.char_type)
+                               ig.Emit (OpCodes.Ldelem_U2);
+                       else if (type == TypeManager.int32_type)
+                               ig.Emit (OpCodes.Ldelem_I4);
+                       else if (type == TypeManager.uint32_type)
+                               ig.Emit (OpCodes.Ldelem_U4);
+                       else if (type == TypeManager.uint64_type)
+                               ig.Emit (OpCodes.Ldelem_I8);
+                       else if (type == TypeManager.int64_type)
+                               ig.Emit (OpCodes.Ldelem_I8);
+                       else if (type == TypeManager.float_type)
+                               ig.Emit (OpCodes.Ldelem_R4);
+                       else if (type == TypeManager.double_type)
+                               ig.Emit (OpCodes.Ldelem_R8);
+                       else if (type == TypeManager.intptr_type)
+                               ig.Emit (OpCodes.Ldelem_I);
+                       else if (type.IsValueType){
+                               ig.Emit (OpCodes.Ldelema, type);
+                               ig.Emit (OpCodes.Ldobj, type);
+                       } else 
+                               ig.Emit (OpCodes.Ldelem_Ref);
+               }
+
+               /// <summary>
+               ///    Emits the right opcode to store an object of Type `t'
+               ///    from an array of T.  
+               /// </summary>
+               static public void EmitStoreOpcode (ILGenerator ig, Type t)
+               {
+                       bool is_stobj;
+                       OpCode op = GetStoreOpcode (t, out is_stobj);
+                       if (is_stobj)
+                               ig.Emit (OpCodes.Stobj, t);
+                       else
+                               ig.Emit (op);
+               }
+
+               /// <summary>
+               ///    Returns the right opcode to store an object of Type `t'
+               ///    from an array of T.  
+               /// </summary>
+               static public OpCode GetStoreOpcode (Type t, out bool is_stobj)
+               {
+                       //Console.WriteLine (new System.Diagnostics.StackTrace ());
+                       is_stobj = false;
+                       t = TypeManager.TypeToCoreType (t);
+                       if (TypeManager.IsEnumType (t) && t != TypeManager.enum_type)
+                               t = TypeManager.EnumToUnderlying (t);
+                       if (t == TypeManager.byte_type || t == TypeManager.sbyte_type ||
+                           t == TypeManager.bool_type)
+                               return OpCodes.Stelem_I1;
+                       else if (t == TypeManager.short_type || t == TypeManager.ushort_type ||
+                                t == TypeManager.char_type)
+                               return OpCodes.Stelem_I2;
+                       else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
+                               return OpCodes.Stelem_I4;
+                       else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
+                               return OpCodes.Stelem_I8;
+                       else if (t == TypeManager.float_type)
+                               return OpCodes.Stelem_R4;
+                       else if (t == TypeManager.double_type)
+                               return OpCodes.Stelem_R8;
+                       else if (t == TypeManager.intptr_type) {
+                                is_stobj = true;
+                                return OpCodes.Stobj;
+                       } else if (t.IsValueType) {
+                               is_stobj = true;
+                               return OpCodes.Stobj;
+                       } else
+                               return OpCodes.Stelem_Ref;
+               }
+
+               MethodInfo FetchGetMethod ()
+               {
+                       ModuleBuilder mb = CodeGen.ModuleBuilder;
+                       int arg_count = ea.Arguments.Count;
+                       Type [] args = new Type [arg_count];
+                       MethodInfo get;
+                       
+                       for (int i = 0; i < arg_count; i++){
+                               //args [i++] = a.Type;
+                               args [i] = TypeManager.int32_type;
+                       }
+                       
+                       get = mb.GetArrayMethod (
+                               ea.Expr.Type, "Get",
+                               CallingConventions.HasThis |
+                               CallingConventions.Standard,
+                               type, args);
+                       return get;
+               }
+                               
+
+               MethodInfo FetchAddressMethod ()
+               {
+                       ModuleBuilder mb = CodeGen.ModuleBuilder;
+                       int arg_count = ea.Arguments.Count;
+                       Type [] args = new Type [arg_count];
+                       MethodInfo address;
+                       Type ret_type;
+                       
+                       ret_type = TypeManager.GetReferenceType (type);
+                       
+                       for (int i = 0; i < arg_count; i++){
+                               //args [i++] = a.Type;
+                               args [i] = TypeManager.int32_type;
+                       }
+                       
+                       address = mb.GetArrayMethod (
+                               ea.Expr.Type, "Address",
+                               CallingConventions.HasThis |
+                               CallingConventions.Standard,
+                               ret_type, args);
+
+                       return address;
+               }
+
+               //
+               // Load the array arguments into the stack.
+               //
+               // If we have been requested to cache the values (cached_locations array
+               // initialized), then load the arguments the first time and store them
+               // in locals.  otherwise load from local variables.
+               //
+               void LoadArrayAndArguments (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       if (cached_locations == null){
+                               ea.Expr.Emit (ec);
+                               foreach (Argument a in ea.Arguments){
+                                       Type argtype = a.Expr.Type;
+                                       
+                                       a.Expr.Emit (ec);
+                                       
+                                       if (argtype == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Conv_Ovf_I);
+                                       else if (argtype == TypeManager.uint64_type)
+                                               ig.Emit (OpCodes.Conv_Ovf_I_Un);
+                               }
+                               return;
+                       }
+
+                       if (cached_locations [0] == null){
+                               cached_locations [0] = new LocalTemporary (ec, ea.Expr.Type);
+                               ea.Expr.Emit (ec);
+                               ig.Emit (OpCodes.Dup);
+                               cached_locations [0].Store (ec);
+                               
+                               int j = 1;
+                               
+                               foreach (Argument a in ea.Arguments){
+                                       Type argtype = a.Expr.Type;
+                                       
+                                       cached_locations [j] = new LocalTemporary (ec, TypeManager.intptr_type /* a.Expr.Type */);
+                                       a.Expr.Emit (ec);
+                                       if (argtype == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Conv_Ovf_I);
+                                       else if (argtype == TypeManager.uint64_type)
+                                               ig.Emit (OpCodes.Conv_Ovf_I_Un);
+
+                                       ig.Emit (OpCodes.Dup);
+                                       cached_locations [j].Store (ec);
+                                       j++;
+                               }
+                               return;
+                       }
+
+                       foreach (LocalTemporary lt in cached_locations)
+                               lt.Emit (ec);
+               }
+
+               public new void CacheTemporaries (EmitContext ec)
+               {
+                       cached_locations = new LocalTemporary [ea.Arguments.Count + 1];
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       int rank = ea.Expr.Type.GetArrayRank ();
+                       ILGenerator ig = ec.ig;
+
+                       LoadArrayAndArguments (ec);
+                       
+                       if (rank == 1)
+                               EmitLoadOpcode (ig, type);
+                       else {
+                               MethodInfo method;
+                               
+                               method = FetchGetMethod ();
+                               ig.Emit (OpCodes.Call, method);
+                       }
+               }
+
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       int rank = ea.Expr.Type.GetArrayRank ();
+                       ILGenerator ig = ec.ig;
+                       Type t = source.Type;
+
+                       LoadArrayAndArguments (ec);
+
+                       //
+                       // The stobj opcode used by value types will need
+                       // an address on the stack, not really an array/array
+                       // pair
+                       //
+                       if (rank == 1){
+                               if (t == TypeManager.enum_type || t == TypeManager.decimal_type ||
+                                   (t.IsSubclassOf (TypeManager.value_type) && !TypeManager.IsEnumType (t) && !TypeManager.IsBuiltinType (t)))
+                                       ig.Emit (OpCodes.Ldelema, t);
+                       }
+                       
+                       source.Emit (ec);
+
+                       if (rank == 1)
+                               EmitStoreOpcode (ig, t);
+                       else {
+                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               int arg_count = ea.Arguments.Count;
+                               Type [] args = new Type [arg_count + 1];
+                               MethodInfo set;
+                               
+                               for (int i = 0; i < arg_count; i++){
+                                       //args [i++] = a.Type;
+                                       args [i] = TypeManager.int32_type;
+                               }
+
+                               args [arg_count] = type;
+                               
+                               set = mb.GetArrayMethod (
+                                       ea.Expr.Type, "Set",
+                                       CallingConventions.HasThis |
+                                       CallingConventions.Standard,
+                                       TypeManager.void_type, args);
+                               
+                               ig.Emit (OpCodes.Call, set);
+                       }
+               }
+
+               public void AddressOf (EmitContext ec, AddressOp mode)
+               {
+                       int rank = ea.Expr.Type.GetArrayRank ();
+                       ILGenerator ig = ec.ig;
+
+                       LoadArrayAndArguments (ec);
+
+                       if (rank == 1){
+                               ig.Emit (OpCodes.Ldelema, type);
+                       } else {
+                               MethodInfo address = FetchAddressMethod ();
+                               ig.Emit (OpCodes.Call, address);
+                       }
+               }
+       }
+
+       
+       class Indexers {
+               public ArrayList properties;
+               static Hashtable map;
+
+               static Indexers ()
+               {
+                       map = new Hashtable ();
+               }
+
+               Indexers ()
+               {
+                       properties = new ArrayList ();
+               }
+                               
+               void Append (MemberInfo [] mi)
+               {
+                       foreach (PropertyInfo property in mi){
+                               MethodInfo get, set;
+                               
+                               get = property.GetGetMethod (true);
+                               set = property.GetSetMethod (true);
+                               properties.Add (new Pair (get, set));
+                       }
+               }
+
+               static private MemberInfo [] GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type)
+               {
+                       string p_name = TypeManager.IndexerPropertyName (lookup_type);
+
+                       MemberInfo [] mi = TypeManager.MemberLookup (
+                               caller_type, caller_type, lookup_type, MemberTypes.Property,
+                               BindingFlags.Public | BindingFlags.Instance |
+                               BindingFlags.DeclaredOnly, p_name);
+
+                       if (mi == null || mi.Length == 0)
+                               return null;
+
+                       return mi;
+               }
+               
+               static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc) 
+               {
+                       Indexers ix = (Indexers) map [lookup_type];
+                       
+                       if (ix != null)
+                               return ix;
+
+                       Type copy = lookup_type;
+                       while (copy != TypeManager.object_type && copy != null){
+                               MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, copy);
+
+                               if (mi != null){
+                                       if (ix == null)
+                                               ix = new Indexers ();
+
+                                       ix.Append (mi);
+                               }
+                                       
+                               copy = copy.BaseType;
+                       }
+
+                       return ix;
+               }
+       }
+
+       /// <summary>
+       ///   Expressions that represent an indexer call.
+       /// </summary>
+       public class IndexerAccess : Expression, IAssignMethod {
+               //
+               // Points to our "data" repository
+               //
+               MethodInfo get, set;
+               ArrayList set_arguments;
+               bool is_base_indexer;
+
+               protected Type indexer_type;
+               protected Type current_type;
+               protected Expression instance_expr;
+               protected ArrayList arguments;
+               
+               public IndexerAccess (ElementAccess ea, Location loc)
+                       : this (ea.Expr, false, loc)
+               {
+                       this.arguments = ea.Arguments;
+               }
+
+               protected IndexerAccess (Expression instance_expr, bool is_base_indexer,
+                                        Location loc)
+               {
+                       this.instance_expr = instance_expr;
+                       this.is_base_indexer = is_base_indexer;
+                       this.eclass = ExprClass.Value;
+                       this.loc = loc;
+               }
+
+               protected virtual bool CommonResolve (EmitContext ec)
+               {
+                       indexer_type = instance_expr.Type;
+                       current_type = ec.ContainerType;
+
+                       return true;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       ArrayList AllGetters = new ArrayList();
+                       if (!CommonResolve (ec))
+                               return null;
+
+                       //
+                       // Step 1: Query for all `Item' *properties*.  Notice
+                       // that the actual methods are pointed from here.
+                       //
+                       // This is a group of properties, piles of them.  
+
+                       bool found_any = false, found_any_getters = false;
+                       Type lookup_type = indexer_type;
+
+                       Indexers ilist;
+                       ilist = Indexers.GetIndexersForType (current_type, lookup_type, loc);
+                       if (ilist != null) {
+                               found_any = true;
+                               if (ilist.properties != null) {
+                                       foreach (Pair o in ilist.properties) {
+                                               if (o.First != null)
+                                                       AllGetters.Add(o.First);
+                                       }
+                               }
+                       }
+
+                       if (AllGetters.Count > 0) {
+                               found_any_getters = true;
+                               get = (MethodInfo) Invocation.OverloadResolve (
+                                       ec, new MethodGroupExpr (AllGetters, loc), arguments, loc);
+                       }
+
+                       if (!found_any) {
+                               Report.Error (21, loc,
+                                             "Type `" + TypeManager.CSharpName (indexer_type) +
+                                             "' does not have any indexers defined");
+                               return null;
+                       }
+
+                       if (!found_any_getters) {
+                               Error (154, "indexer can not be used in this context, because " +
+                                      "it lacks a `get' accessor");
+                               return null;
+                       }
+
+                       if (get == null) {
+                               Error (1501, "No Overload for method `this' takes `" +
+                                      arguments.Count + "' arguments");
+                               return null;
+                       }
+
+                       //
+                       // Only base will allow this invocation to happen.
+                       //
+                       if (get.IsAbstract && this is BaseIndexerAccess){
+                               Report.Error (205, loc, "Cannot call an abstract base indexer: " + Invocation.FullMethodDesc (get));
+                               return null;
+                       }
+
+                       type = get.ReturnType;
+                       if (type.IsPointer && !ec.InUnsafe){
+                               UnsafeError (loc);
+                               return null;
+                       }
+                       
+                       eclass = ExprClass.IndexerAccess;
+                       return this;
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       ArrayList AllSetters = new ArrayList();
+                       if (!CommonResolve (ec))
+                               return null;
+
+                       Type right_type = right_side.Type;
+
+                       bool found_any = false, found_any_setters = false;
+
+                       Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type, loc);
+                       if (ilist != null) {
+                               found_any = true;
+                               if (ilist.properties != null) {
+                                       foreach (Pair o in ilist.properties) {
+                                               if (o.Second != null)
+                                                       AllSetters.Add(o.Second);
+                                       }
+                               }
+                       }
+                       if (AllSetters.Count > 0) {
+                               found_any_setters = true;
+                               set_arguments = (ArrayList) arguments.Clone ();
+                               set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
+                               set = (MethodInfo) Invocation.OverloadResolve (
+                                       ec, new MethodGroupExpr (AllSetters, loc),
+                                       set_arguments, loc);
+                       }
+
+                       if (!found_any) {
+                               Report.Error (21, loc,
+                                             "Type `" + TypeManager.CSharpName (indexer_type) +
+                                             "' does not have any indexers defined");
+                               return null;
+                       }
+
+                       if (!found_any_setters) {
+                               Error (154, "indexer can not be used in this context, because " +
+                                      "it lacks a `set' accessor");
+                               return null;
+                       }
+
+                       if (set == null) {
+                               Error (1501, "No Overload for method `this' takes `" +
+                                      arguments.Count + "' arguments");
+                               return null;
+                       }
+
+                       //
+                       // Only base will allow this invocation to happen.
+                       //
+                       if (set.IsAbstract && this is BaseIndexerAccess){
+                               Report.Error (205, loc, "Cannot call an abstract base indexer: " + Invocation.FullMethodDesc (set));
+                               return null;
+                       }
+
+                       //
+                       // Now look for the actual match in the list of indexers to set our "return" type
+                       //
+                       type = TypeManager.void_type;   // default value
+                       foreach (Pair t in ilist.properties){
+                               if (t.Second == set){
+                                       if (t.First != null)
+                                               type = ((MethodInfo) t.First).ReturnType;
+                                       break;
+                               }
+                       }
+                       
+                       eclass = ExprClass.IndexerAccess;
+                       return this;
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, get, arguments, loc);
+               }
+
+               //
+               // source is ignored, because we already have a copy of it from the
+               // LValue resolution and we have already constructed a pre-cached
+               // version of the arguments (ea.set_arguments);
+               //
+               public void EmitAssign (EmitContext ec, Expression source)
+               {
+                       Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, set, set_arguments, loc);
+               }
+       }
+
+       /// <summary>
+       ///   The base operator for method names
+       /// </summary>
+       public class BaseAccess : Expression {
+               string member;
+               
+               public BaseAccess (string member, Location l)
+               {
+                       this.member = member;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Expression c = CommonResolve (ec);
+
+                       if (c == null)
+                               return null;
+
+                       //
+                       // MethodGroups use this opportunity to flag an error on lacking ()
+                       //
+                       if (!(c is MethodGroupExpr))
+                               return c.Resolve (ec);
+                       return c;
+               }
+
+               public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+               {
+                       Expression c = CommonResolve (ec);
+
+                       if (c == null)
+                               return null;
+
+                       //
+                       // MethodGroups use this opportunity to flag an error on lacking ()
+                       //
+                       if (! (c is MethodGroupExpr))
+                               return c.DoResolveLValue (ec, right_side);
+
+                       return c;
+               }
+
+               Expression CommonResolve (EmitContext ec)
+               {
+                       Expression member_lookup;
+                       Type current_type = ec.ContainerType;
+                       Type base_type = current_type.BaseType;
+                       Expression e;
+
+                       if (ec.IsStatic){
+                               Error (1511, "Keyword base is not allowed in static method");
+                               return null;
+                       }
+                       
+                       member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type, member,
+                                                     AllMemberTypes, AllBindingFlags, loc);
+                       if (member_lookup == null) {
+                               MemberLookupFailed (ec, base_type, base_type, member, null, loc);
+                               return null;
+                       }
+
+                       Expression left;
+                       
+                       if (ec.IsStatic)
+                               left = new TypeExpr (base_type, loc);
+                       else
+                               left = ec.GetThis (loc);
+                       
+                       e = MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null);
+
+                       if (e is PropertyExpr){
+                               PropertyExpr pe = (PropertyExpr) e;
+
+                               pe.IsBase = true;
+                       }
+
+                       return e;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("Should never be called"); 
+               }
+       }
+
+       /// <summary>
+       ///   The base indexer operator
+       /// </summary>
+       public class BaseIndexerAccess : IndexerAccess {
+               public BaseIndexerAccess (ArrayList args, Location loc)
+                       : base (null, true, loc)
+               {
+                       arguments = new ArrayList ();
+                       foreach (Expression tmp in args)
+                               arguments.Add (new Argument (tmp, Argument.AType.Expression));
+               }
+
+               protected override bool CommonResolve (EmitContext ec)
+               {
+                       instance_expr = ec.GetThis (loc);
+
+                       current_type = ec.ContainerType.BaseType;
+                       indexer_type = current_type;
+
+                       foreach (Argument a in arguments){
+                               if (!a.Resolve (ec, loc))
+                                       return false;
+                       }
+
+                       return true;
+               }
+       }
+       
+       /// <summary>
+       ///   This class exists solely to pass the Type around and to be a dummy
+       ///   that can be passed to the conversion functions (this is used by
+       ///   foreach implementation to typecast the object return value from
+       ///   get_Current into the proper type.  All code has been generated and
+       ///   we only care about the side effect conversions to be performed
+       ///
+       ///   This is also now used as a placeholder where a no-action expression
+       ///   is needed (the `New' class).
+       /// </summary>
+       public class EmptyExpression : Expression {
+               public EmptyExpression ()
+               {
+                       type = TypeManager.object_type;
+                       eclass = ExprClass.Value;
+                       loc = Location.Null;
+               }
+
+               public EmptyExpression (Type t)
+               {
+                       type = t;
+                       eclass = ExprClass.Value;
+                       loc = Location.Null;
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       // nothing, as we only exist to not do anything.
+               }
+
+               //
+               // This is just because we might want to reuse this bad boy
+               // instead of creating gazillions of EmptyExpressions.
+               // (CanImplicitConversion uses it)
+               //
+               public void SetType (Type t)
+               {
+                       type = t;
+               }
+       }
+
+       public class UserCast : Expression {
+               MethodBase method;
+               Expression source;
+               
+               public UserCast (MethodInfo method, Expression source, Location l)
+               {
+                       this.method = method;
+                       this.source = source;
+                       type = method.ReturnType;
+                       eclass = ExprClass.Value;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       source.Emit (ec);
+                       
+                       if (method is MethodInfo)
+                               ig.Emit (OpCodes.Call, (MethodInfo) method);
+                       else
+                               ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+
+               }
+       }
+
+       // <summary>
+       //   This class is used to "construct" the type during a typecast
+       //   operation.  Since the Type.GetType class in .NET can parse
+       //   the type specification, we just use this to construct the type
+       //   one bit at a time.
+       // </summary>
+       public class ComposedCast : Expression {
+               Expression left;
+               string dim;
+               
+               public ComposedCast (Expression left, string dim, Location l)
+               {
+                       this.left = left;
+                       this.dim = dim;
+                       loc = l;
+               }
+
+               public override Expression ResolveAsTypeStep (EmitContext ec)
+               {
+                       Type ltype = ec.DeclSpace.ResolveType (left, false, loc);
+                       if (ltype == null)
+                               return null;
+
+                       //
+                       // ltype.Fullname is already fully qualified, so we can skip
+                       // a lot of probes, and go directly to TypeManager.LookupType
+                       //
+                       string cname = ltype.FullName + dim;
+                       type = TypeManager.LookupTypeDirect (cname);
+                       if (type == null){
+                               //
+                               // For arrays of enumerations we are having a problem
+                               // with the direct lookup.  Need to investigate.
+                               //
+                               // For now, fall back to the full lookup in that case.
+                               //
+                               type = RootContext.LookupType (
+                                       ec.DeclSpace, cname, false, loc);
+
+                               if (type == null)
+                                       return null;
+                       }
+
+                       if (!ec.ResolvingTypeTree){
+                               //
+                               // If the above flag is set, this is being invoked from the ResolveType function.
+                               // Upper layers take care of the type validity in this context.
+                               //
+                       if (!ec.InUnsafe && type.IsPointer){
+                               UnsafeError (loc);
+                               return null;
+                       }
+                       }
+                       
+                       eclass = ExprClass.Type;
+                       return this;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return ResolveAsTypeStep (ec);
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       throw new Exception ("This should never be called");
+               }
+
+               public override string ToString ()
+               {
+                       return left + dim;
+               }
+       }
+
+       //
+       // This class is used to represent the address of an array, used
+       // only by the Fixed statement, this is like the C "&a [0]" construct.
+       //
+       public class ArrayPtr : Expression {
+               Expression array;
+               
+               public ArrayPtr (Expression array, Location l)
+               {
+                       Type array_type = TypeManager.GetElementType (array.Type);
+
+                       this.array = array;
+
+                       type = TypeManager.GetPointerType (array_type);
+                       eclass = ExprClass.Value;
+                       loc = l;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       array.Emit (ec);
+                       IntLiteral.EmitInt (ig, 0);
+                       ig.Emit (OpCodes.Ldelema, TypeManager.GetElementType (array.Type));
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are born fully resolved
+                       //
+                       return this;
+               }
+       }
+
+       //
+       // Used by the fixed statement
+       //
+       public class StringPtr : Expression {
+               LocalBuilder b;
+               
+               public StringPtr (LocalBuilder b, Location l)
+               {
+                       this.b = b;
+                       eclass = ExprClass.Value;
+                       type = TypeManager.char_ptr_type;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       ig.Emit (OpCodes.Ldloc, b);
+                       ig.Emit (OpCodes.Conv_I);
+                       ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
+                       ig.Emit (OpCodes.Add);
+               }
+       }
+       
+       //
+       // Implements the `stackalloc' keyword
+       //
+       public class StackAlloc : Expression {
+               Type otype;
+               Expression t;
+               Expression count;
+               
+               public StackAlloc (Expression type, Expression count, Location l)
+               {
+                       t = type;
+                       this.count = count;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       count = count.Resolve (ec);
+                       if (count == null)
+                               return null;
+                       
+                       if (count.Type != TypeManager.int32_type){
+                               count = Convert.ImplicitConversionRequired (ec, count, TypeManager.int32_type, loc);
+                               if (count == null)
+                                       return null;
+                       }
+
+                       if (ec.InCatch || ec.InFinally){
+                               Error (255,
+                                             "stackalloc can not be used in a catch or finally block");
+                               return null;
+                       }
+
+                       otype = ec.DeclSpace.ResolveType (t, false, loc);
+
+                       if (otype == null)
+                               return null;
+
+                       if (!TypeManager.VerifyUnManaged (otype, loc))
+                               return null;
+
+                       type = TypeManager.GetPointerType (otype);
+                       eclass = ExprClass.Value;
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       int size = GetTypeSize (otype);
+                       ILGenerator ig = ec.ig;
+                               
+                       if (size == 0)
+                               ig.Emit (OpCodes.Sizeof, otype);
+                       else
+                               IntConstant.EmitInt (ig, size);
+                       count.Emit (ec);
+                       ig.Emit (OpCodes.Mul);
+                       ig.Emit (OpCodes.Localloc);
+               }
+       }
+}
diff --git a/mcs/gmcs/gen-il.cs b/mcs/gmcs/gen-il.cs
new file mode 100755 (executable)
index 0000000..2dfeecc
--- /dev/null
@@ -0,0 +1,100 @@
+// gen-il.cs: Generates MSIL code from the CIR.Tree
+//
+// Author: Miguel de Icaza (miguel@ximian.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc. (http://www.ximian.com)
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using CIR;
+
+namespace MSIL {
+
+       public class Generator : CIR.ITreeDump {
+               StreamWriter o;
+               int indent = 0;
+               
+               void output (string s)
+               {
+                       Console.Write (s);
+                       o.Write (s);
+               }
+
+               void space ()
+               {
+                       output (new String (' ', indent * 2));
+               }
+
+               void ioutput (string s)
+               {
+                       space ();
+                       output (s);
+               }
+
+               void ioutputl (string s)
+               {
+                       ioutput (s + "\n");
+               }
+
+               string ClassAttributes (Class c)
+               {
+                       // FIXME
+                       return "";
+               }
+
+               string ILName (string name)
+               {
+                       return name;
+               }
+
+               string ClassExtends (Class c)
+               {
+                       return "";
+               }
+               
+               void GenerateFromClass (Class c)
+               {
+                       ioutputl (".class " + ClassAttributes (c) + " " + ILName (c.Name));
+                       ioutputl (ClassExtends (c));
+                       ioutputl ("{");
+                       indent++;
+
+                       
+
+                       indent--;
+                       ioutputl ("}");
+               }
+               
+               void GenerateFromTypes (TypeContainer types)
+               {
+                       if (types.Types == null)
+                               return;
+                       
+                       foreach (DictionaryEntry de in types.Types){
+                               TypeContainer type = (TypeContainer) de.Value;
+                               
+                               if (type is Class)
+                                       GenerateFromClass ((Class) type);
+                       }
+                       
+               }
+               
+               public int GenerateFromTree (Tree tree, StreamWriter os)
+               {
+                       this.o = os;
+
+                       ioutputl (".assembly test.exe { }");
+                       GenerateFromTypes (tree.Types);
+                       return 0;
+               }
+
+               public void ParseOptions (string options)
+               {
+               }
+               
+       }
+}
diff --git a/mcs/gmcs/gen-treedump.cs b/mcs/gmcs/gen-treedump.cs
new file mode 100755 (executable)
index 0000000..8ad20e8
--- /dev/null
@@ -0,0 +1,988 @@
+// cs-treedump.cs: Dumps the parsed tree to standard output
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc. (http://www.ximian.com)
+//
+// TODO:
+//     Variable declarations
+//      Fix precedence rules to lower the number of parenthesis.
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using CIR;
+
+namespace Generator {
+       
+       public class TreeDump : CIR.ITreeDump {
+               StreamWriter o;
+               int indent;
+               bool indented;
+               bool tag_values;
+               
+               void space ()
+               {
+                       if (!indented)
+                               output (new String (' ', indent * 8));
+                       indented = true;
+               }
+
+               void output (string s)
+               {
+                       Console.Write (s);
+                       //o.Write (s);
+               }
+
+               void newline ()
+               {
+                       output ("\n");
+                       indented = false;
+               }
+
+               void output_newline (string s)
+               {
+                       output (s);
+                       newline ();
+               }
+               
+               void ioutput (string s)
+               {
+                       space ();
+                       output (s);
+               }
+
+               string GetParameter (Parameter par)
+               {
+                       Parameter.Modifier f = par.ModFlags;
+                       string mod = "";
+                       
+                       switch (f){
+                       case Parameter.Modifier.REF:
+                               mod = "ref "; break;
+                       case Parameter.Modifier.OUT:
+                               mod = "out "; break;
+                       case Parameter.Modifier.PARAMS:
+                               mod = "params "; break;
+                       case Parameter.Modifier.NONE:
+                               mod = ""; break;
+                       }
+                       return mod + par.Type + " " + par.Name;
+               }
+
+               string GetUnary (Unary u, int paren_level)
+               {
+                       string e;
+                       bool left = true;
+                       string s = "0_ERROR>";
+                       int prec = 0;
+                       
+                       switch (u.Oper){
+                       case Unary.Operator.UnaryPlus:
+                               prec = 10;
+                               s = "+";
+                               break;
+                               
+                       case Unary.Operator.UnaryNegation:
+                               prec = 10;
+                               s = "-";
+                               break;
+                               
+                       case Unary.Operator.LogicalNot:
+                               s = "!";
+                               prec = 10;
+                               break;
+                               
+                       case Unary.Operator.OnesComplement:
+                               prec = 10;
+                               s = "~";
+                               break;
+                               
+                       case Unary.Operator.Indirection:
+                               prec = 10;
+                               s = "*";
+                               break;
+                               
+                       case Unary.Operator.AddressOf:
+                               prec = 10;
+                               s = "&";
+                               break;
+                               
+                       case Unary.Operator.PreIncrement:
+                               prec = 11;
+                               s = "++";
+                               break;
+                               
+                       case Unary.Operator.PreDecrement:
+                               prec = 11;
+                               s = "--";
+                               break;
+                               
+                       case Unary.Operator.PostDecrement:
+                               left = false;
+                               prec = 12;
+                               s = "--";
+                               break;
+                               
+                       case Unary.Operator.PostIncrement:
+                               s = "++";
+                               prec = 12;
+                               left = false;
+                               break;
+                       }
+
+                       e = GetExpression (u.Expr, prec);
+                       if (left)
+                               e = s + e;
+                       else
+                               e = e + s;
+                       
+                       if (prec < paren_level)
+                               return "(" + e + ")";
+                       else
+                               return e;
+               }
+
+               string GetBinary (Binary b, int paren_level)
+               {
+                       string l, r;
+                       string op = null;
+                       bool assoc_left = true;
+                       int prec = 0;
+                       
+                       switch (b.Oper){
+                               case Binary.Operator.Multiply:
+                                       prec = 9;
+                                       op = "*"; break;
+
+                               case Binary.Operator.Division:
+                                       prec = 9;
+                                       op = "/"; break;
+                               
+                               case Binary.Operator.Modulus:
+                                       prec = 9;
+                                       op = "%"; break;
+                               
+                               case Binary.Operator.Addition:
+                                       prec = 8;
+                                       op = "+"; break;
+                               
+                               case Binary.Operator.Subtraction:
+                                       prec = 8;
+                                       op = "-"; break;
+                               
+                               case Binary.Operator.LeftShift:
+                                       prec = 7;
+                                       op = "<<"; break;
+                               
+                               case Binary.Operator.RightShift:
+                                       prec = 7;
+                                       op = ">>"; break;
+                               
+                               case Binary.Operator.LessThan:
+                                       prec = 6;
+                                       op = "<"; break;
+                               
+                               case Binary.Operator.GreaterThan:
+                                       prec = 6;
+                                       op = ">"; break;
+                               
+                               case Binary.Operator.LessThanOrEqual:
+                                       prec = 6;
+                                       op = "<="; break;
+                               
+                               case Binary.Operator.GreaterThanOrEqual:
+                                       prec = 6;
+                                       op = ">="; break;
+                               
+                               case Binary.Operator.Equality:
+                                       prec = 5;
+                                       op = "=="; break;
+                               
+                               case Binary.Operator.Inequality:
+                                       prec = 5;
+                                       op = "!="; break;
+                               
+                               case Binary.Operator.BitwiseAnd:
+                                       prec = 4;
+                                       op = "&"; break;
+                               
+                               case Binary.Operator.BitwiseOr:
+                                       prec = 2;
+                                       op = "|"; break;
+                               
+                               case Binary.Operator.LogicalAnd:
+                                       prec = 1;
+                                       op = "&&"; break;
+                               
+                               case Binary.Operator.LogicalOr:
+                                       prec = 0;
+                                       op = "||"; break;
+                               
+                               case Binary.Operator.ExclusiveOr:
+                                       prec = 3;
+                                       op = "^"; break;
+                       }
+
+                       l = GetExpression (b.Left, prec - (assoc_left ? 0 : 1));
+                       r = GetExpression (b.Right, prec - (assoc_left ? 0 : 1));
+                       
+                       if (prec <= paren_level)
+                               return "(" + l + " " + op + " " + r + ")";
+                       else
+                               return l + " " + op + " " + r;
+               }
+
+               string GetCast (Cast c)
+               {
+                       return "(" + c.TargetType + ") (" + GetExpression (c.Expr, 0) + ")";
+               }
+
+               string GetConditional (Conditional c)
+               {
+                       return "(" + GetExpression (c.Expr, 0) + ") ? (" +
+                               GetExpression (c.TrueExpr, 0) + ") : (" +
+                               GetExpression (c.FalseExpr, 0) + ")";
+               }
+
+               string GetAssign (Assign a)
+               {
+                       return GetExpression (a.Target, 0) + " = " + GetExpression (a.Source, 0);
+               }
+
+               string GetArguments (ArrayList args)
+               {
+                       string r = "";
+                       
+                       if (args != null){
+                               int top = args.Count;
+                               
+                               for (int i = 0; i < top; i++){
+                                       Argument arg = (Argument) args [i];
+                                               
+                                       switch (arg.ArgType){
+                                               case Argument.AType.Ref:
+                                                       r += "ref "; break;
+                                               case Argument.AType.Out:
+                                                       r += "out "; break;
+                                       }
+                                       r += GetExpression (arg.Expr, 0);
+
+                                       if (i+1 != top)
+                                               r += ", ";
+                               }
+                       }
+
+                       return "(" + r + ")";
+               }
+               
+               string GetInvocation (Invocation i)
+               {
+                       return GetExpression (i.Expr, 0) + " " + GetArguments (i.Arguments);
+               }
+
+               string GetNew (New n)
+               {
+                       return "new " + n.RequestedType + GetArguments (n.Arguments);
+               }
+
+               string GetTypeOf (TypeOf t)
+               {
+                       return "typeof (" + t.QueriedType + ")";
+               }
+
+               string GetSizeOf (SizeOf t)
+               {
+                       return "sizeof (" + t.QueriedType + ")";
+               }
+
+               string GetMemberAccess (MemberAccess m)
+               {
+                       return GetExpression (m.Expr, 0) +
+                               (tag_values ? "/* member access */ . " : ".") +
+                               m.Identifier;
+               }
+
+               string GetSimpleName (SimpleName n)
+               {
+                       string s = n.Name;
+                       
+                       if (s.StartsWith ("0_"))
+                               return "id_" + s;
+                       else
+                               return s;
+               }
+
+               string GetProbe (Probe p)
+               {
+                       string s = GetExpression (p.Expr, 6);
+
+                       if (p.Oper == CIR.Probe.Operator.Is)
+                               s += " is ";
+                       else if (p.Oper == CIR.Probe.Operator.As)
+                               s += " as ";
+                       else
+                               s += "UNHANDLED";
+
+                       s += p.ProbeType;
+
+                       return s;
+               }
+
+               string GetLocalVariableReference (LocalVariableReference l)
+               {
+                       if (tag_values)
+                               return "/* local var: */" + l.Name;
+                       else
+                               return l.Name;
+               }
+
+               string GetParameterReference (ParameterReference r)
+               {
+                       if (tag_values)
+                               return "/* par: */ " + r.Name;
+                       else
+                               return r.Name;
+               }
+               
+               string GetExpression (Expression e, int paren_level)
+               {
+                       if (e == null){
+                               return "<NULL EXPRESSION>";
+                       }
+                       
+                       if (e is Unary)
+                               return GetUnary ((Unary) e, paren_level);
+                       else if (e is Binary)
+                               return GetBinary ((Binary) e, paren_level);
+                       else if (e is Cast)
+                               return GetCast ((Cast) e);
+                       else if (e is Conditional)
+                               return GetConditional ((Conditional) e);
+                       else if (e is SimpleName)
+                               return GetSimpleName ((SimpleName)e);
+                       else if (e is LocalVariableReference)
+                               return GetLocalVariableReference ((LocalVariableReference) e);
+                       else if (e is ParameterReference)
+                               return GetParameterReference ((ParameterReference) e);
+                       else if (e is Assign)
+                               return GetAssign ((Assign) e);
+                       else if (e is Literal)
+                               return e.ToString ();
+                       else if (e is Invocation)
+                               return GetInvocation ((Invocation) e);
+                       else if (e is New)
+                               return GetNew ((New) e);
+                       else if (e is This)
+                               return "this";
+                       else if (e is TypeOf)
+                               return GetTypeOf ((TypeOf) e);
+                       else if (e is SizeOf)
+                               return GetSizeOf ((SizeOf) e);
+                       else if (e is MemberAccess)
+                               return GetMemberAccess ((MemberAccess) e);
+                       else if (e is Probe)
+                               return GetProbe ((Probe) e);
+                       else
+                               return "WARNING {" + e.ToString () + "} WARNING";
+               }
+               
+               void GenerateParameters (Parameters pars)
+               {
+                       Parameter [] pfixed;
+                       Parameter parray;
+
+                       pfixed = pars.FixedParameters;
+
+                       if (pfixed != null){
+                               for (int i = 0; i < pfixed.Length; i++){
+                                       output (GetParameter (pfixed [i]));
+                                       if (i+1 != pfixed.Length)
+                                               output (", ");
+                               }
+                       }
+
+                       parray = pars.ArrayParameter;
+                       if (parray != null){
+                               output (GetParameter (parray));
+                       }
+               }
+
+               void GenerateIf (If s)
+               {
+                       bool do_indent;
+                       
+                       output ("if (" + GetExpression (s.Expr, 0) + ") ");
+                       do_indent = !(s.TrueStatement is Block);
+                       if (do_indent)
+                               indent++;
+                       GenerateStatement (s.TrueStatement, true, false, false);
+                       if (do_indent)
+                               indent--;
+                       if (s.FalseStatement != null){
+                               ioutput ("else");
+                               newline ();
+                               GenerateStatement (s.FalseStatement, false, true, false);
+                       }
+               }
+
+               void GenerateDo (Do s)
+               {
+                       output ("do"); newline ();
+                       indent++;
+                       GenerateStatement (s.EmbeddedStatement, false, false, false);
+                       indent--;
+                       output (" while (" + GetExpression (s.Expr, 0) + ");");
+                       newline ();
+               }
+
+               void GenerateWhile (While s)
+               {
+                       output ("while (" + GetExpression (s.Expr, 0) + ")");
+                       GenerateStatement (s.Statement, true, true, false);
+               }
+
+               void GenerateFor (For s)
+               {
+                       output ("for (");
+                       if (! (s.InitStatement is EmptyStatement))
+                               GenerateStatement (s.InitStatement, true, true, true);
+                       output ("; ");
+                       output (GetExpression (s.Test, 0));
+                       output ("; ");
+                       if (! (s.Increment is EmptyStatement))
+                               GenerateStatement (s.Increment, true, true, true);
+                       output (") ");
+                       GenerateStatement (s.Statement, true, true, false);
+               }
+
+               void GenerateReturn (Return s)
+               {
+                       output ("return " +
+                               (s.Expr != null ?
+                                GetExpression (s.Expr, 0) : "" + ";") +
+                               ";");
+                       newline ();
+               }
+
+               void GenerateGoto (Goto s)
+               {
+                       output ("goto " + s.Target + ";");
+                       newline ();
+               }
+
+               void GenerateThrow (Throw s)
+               {
+               }
+
+               void GenerateStatementExpression (StatementExpression s)
+               {
+                       output (GetExpression (s.Expr, 0) + ";");
+                       newline ();
+               }
+
+               void GenerateSwitchLabels (ArrayList labels)
+               {
+                       foreach (SwitchLabel sl in labels){
+                               Expression lab = sl.Label;
+                               
+                               if (lab == null){
+                                       ioutput ("default:");
+                                       newline ();
+                               } else {
+                                       ioutput ("case " + GetExpression (lab, 0) + ":");
+                                       newline ();
+                               }
+                       }
+               }
+               
+               void GenerateSwitch (Switch s)
+               {
+                       output_newline ("switch (" + GetExpression (s.Expr, 0) + ")");
+                       foreach (SwitchSection ss in s.Sections){
+                               GenerateSwitchLabels (ss.Labels);
+                               GenerateBlock (ss.Block, false, false);
+                       }
+               }
+               
+               void GenerateChecked (Checked c)
+               {
+                       output ("checked ");
+                       GenerateBlock (c.Block, false, false);
+               }
+
+               void GenerateUnchecked (Unchecked c)
+               {
+                       output ("unchecked ");
+                       GenerateBlock (c.Block, false, false);
+               }
+
+               void GenerateCatchClauses (ArrayList list)
+               {
+                       foreach (Catch c in list){
+                               space ();
+                               output ("catch ");
+                               
+                               if (c.Type != null){
+                                       output ("(" + c.Type +
+                                               (c.Name != null ? " " + c.Name : "") + ")");
+                               } 
+                               GenerateBlock (c.Block, false, false);
+                       }
+               }
+
+               void GenerateTry (Try t)
+               {
+                       output ("try");
+                       GenerateBlock (t.Block, false, false);
+
+                       if (t.Specific != null){
+                               GenerateCatchClauses (t.Specific);
+                       }
+
+                       if (t.General != null){
+                               space ();
+                               output ("catch");
+                               GenerateBlock (t.Block, false, false);
+                       }
+
+                       if (t.Fini != null){
+                               GenerateBlock (t.Fini, false, false);
+                       }
+               }
+               
+               void GenerateStatement (Statement s, bool doPlacement, bool blockFlushesLine, bool embedded)
+               {
+                       if (s == null){
+                               output ("WARNING: got a null Statement");
+                               newline ();
+                               return;
+                       }
+
+                       if (doPlacement){
+                               if (s is Block){
+                                       GenerateBlock ((Block) s, doPlacement, embedded);
+                                       return;
+                               } else 
+                                       newline ();
+                       } 
+                               
+                       space ();
+                       if (s is If)
+                               GenerateIf ((If) s);
+                       else if (s is Do)
+                               GenerateDo ((Do) s);
+                       else if (s is While)
+                               GenerateWhile ((While) s);
+                       else if (s is For)
+                               GenerateFor ((For) s);
+                       else if (s is Return)
+                               GenerateReturn ((Return) s);
+                       else if (s is Goto)
+                               GenerateGoto ((Goto) s);
+                       else if (s is Throw)
+                               GenerateThrow ((Throw) s);
+                       else if (s is Break)
+                               output_newline ("break;");
+                       else if (s is Continue)
+                               output_newline ("continue;");
+                       else if (s is EmptyStatement)
+                               output_newline ("/* empty statement */;");
+                       else if (s is Block)
+                               GenerateBlock ((Block) s, doPlacement, embedded);
+                       else if (s is StatementExpression)
+                               GenerateStatementExpression ((StatementExpression) s);
+                       else if (s is Switch)
+                               GenerateSwitch ((Switch) s);
+                       else if (s is Checked)
+                               GenerateChecked ((Checked) s);
+                       else if (s is Unchecked)
+                               GenerateUnchecked ((Unchecked) s);
+                       else if (s is Try)
+                               GenerateTry ((Try) s);
+                       else {
+                               System.Type t = s.GetType ();
+
+                               output ("\n*****UNKNOWN Statement:" + t.ToString ());
+                       }
+               }
+
+               //
+               // embedded is used only for things like the For thing
+               // that has blocks but for display purposes we want to keep
+               // without newlines.
+               void GenerateBlock (Block b, bool doPlacement, bool embedded)
+               {
+                       if (b.Label != null)
+                               output (b.Label + ":");
+
+                       if (!b.Implicit){
+                               if (!doPlacement)
+                                       space ();
+                       
+                               output ("{");
+                               if (!embedded)
+                                       newline ();
+                               indent++;
+                       }
+
+                       if (b.Variables != null){
+                               foreach (DictionaryEntry entry in b.Variables){
+                                       VariableInfo vi = (VariableInfo) entry.Value;
+                                       
+                                       space ();
+                                       output_newline (
+                                               vi.Type + " " +
+                                               (string) entry.Key + ";");
+                               }
+                               newline ();
+                       }
+                       
+                       foreach (Statement s in b.Statements){
+                               GenerateStatement (s, false, true, false);
+                       }
+                       
+                       if (!b.Implicit){
+                               indent--;
+                               ioutput ("}");
+                               if (!embedded)
+                                       newline ();
+                       }
+               }
+               
+               void GenerateMethod (Method m)
+               {
+                       ioutput (GetModifiers (m.ModFlags) +
+                                m.ReturnType + " " +
+                                m.Name + " (");
+                       GenerateParameters (m.Parameters);
+                       output_newline (")");
+                       
+
+                       GenerateBlock (m.Block, false, false);
+                       newline ();
+               }
+
+               void GenerateInterfaceMethod (InterfaceMethod imethod)
+               {
+                       space ();
+                       output (imethod.IsNew ? "new " : "");
+                       output (imethod.ReturnType + " " + imethod.Name + " (");
+                       GenerateParameters (imethod.Parameters);
+                       output (");");
+                       newline ();
+               }
+
+               void GenerateInterfaceProperty (InterfaceProperty iprop)
+               {
+                       space ();
+                       output (iprop.IsNew ? "new " : "");
+                       output (iprop.Type + " " + iprop.Name + " { ");
+                       if (iprop.HasGet) output ("get; ");
+                       if (iprop.HasSet) output ("set; ");
+                       output ("}");
+                       newline ();
+               }
+               
+               void GenerateInterfaceEvent (InterfaceEvent ievent)
+               {
+                       space ();
+                       output ((ievent.IsNew ? "new " : "") + "event ");
+                       output (ievent.Type + " " + ievent.Name + ";");
+                       newline ();
+               }
+               
+               void GenerateInterfaceIndexer (InterfaceIndexer iindexer)
+               {
+                       space ();
+                       output (iindexer.IsNew ? "new " : "");
+                       output (iindexer.Type + " this [");
+                       output (iindexer.Parameters + "] {");
+                       if (iindexer.HasGet) output ("get; ");
+                       if (iindexer.HasSet) output ("set; ");
+                       output ("}");
+                       newline ();
+               }
+
+               string GenIfaceBases (Interface iface)
+               {
+                       return GenBases (iface.Bases);
+               }
+               
+               void GenerateInterface (Interface iface)
+               {
+                       ioutput (GetModifiers (iface.ModFlags) + "interface " +
+                                ClassName (iface.Name) + GenIfaceBases (iface) + " {");
+                       newline ();
+                       indent++;
+                       
+                       if (iface.InterfaceMethods != null){
+                               foreach (DictionaryEntry de in iface.InterfaceMethods){
+                                       InterfaceMethod method = (InterfaceMethod) de.Value;
+                                       GenerateInterfaceMethod (method);
+                               }
+                       }
+
+                       if (iface.InterfaceProperties != null){
+                               foreach (DictionaryEntry de in iface.InterfaceProperties){
+                                       InterfaceProperty iprop = (InterfaceProperty) de.Value;
+                                       GenerateInterfaceProperty (iprop);
+                               }
+                       }
+
+                       if (iface.InterfaceEvents != null){
+                               foreach (DictionaryEntry de in iface.InterfaceEvents){
+                                       InterfaceEvent ievent = (InterfaceEvent) de.Value;
+                                       GenerateInterfaceEvent (ievent);
+                               }
+                       }
+
+                       if (iface.InterfaceIndexers != null){
+                               foreach (DictionaryEntry de in iface.InterfaceIndexers){
+                                       InterfaceIndexer iindexer = (InterfaceIndexer) de.Value;
+                                       GenerateInterfaceIndexer (iindexer);
+                               }
+                       }
+                       indent--;
+                       ioutput ("}");
+                       newline ();
+                       newline ();
+               }
+
+               void GenerateField (Field f)
+               {
+                       space ();
+                       output (GetModifiers (f.ModFlags) + 
+                               f.Type + " " + f.Name);
+                       if (f.Initializer != null){
+                               if (f.Initializer is Expression)
+                                       output (" = " + GetExpression ((Expression) f.Initializer, 0));
+                               else
+                                       output ("ADD SUPPORT FOR ARRAYS");
+                       }
+                       output (";");
+                       newline ();
+               }
+
+               void GenerateConstructor (Constructor c)
+               {
+                       ConstructorInitializer init = c.Initializer;
+
+                       space ();
+                       output (GetModifiers (c.ModFlags) + c.Name + " (");
+                       GenerateParameters (c.Parameters);
+                       output (")");
+
+                       if (init != null){
+                               if (init is ConstructorThisInitializer)
+                                       output (": this (");
+                               else
+                                       output (": base (");
+                               output (GetArguments (init.Arguments));
+                               output (")");
+                       }
+                       newline ();
+                       GenerateBlock (c.Block, false, false);
+               }
+
+               void GenerateProperty (Property prop)
+               {
+                       space ();
+                       output (GetModifiers (prop.ModFlags) + prop.Type +
+                               " " + prop.Name + " {");
+                       newline ();
+                       indent++;
+                       if (prop.Get != null){
+                               space ();
+                               output ("get ");
+                               GenerateBlock (prop.Get, false, false);
+                               newline (); 
+                       }
+
+                       if (prop.Set != null){
+                               space ();
+                               output ("set ");
+                               GenerateBlock (prop.Set, false, false);
+                       }
+                       indent--;
+                       space ();
+                       output ("}");
+                       newline ();
+               }
+
+               void GenerateEnum (CIR.Enum e)
+               {
+                       space ();
+                       output ("enum " + e.Name + " {");
+                       newline ();
+
+                       indent++;
+                       foreach (string name in e.ValueNames){
+                               Expression expr = e [name];
+
+                               space ();
+
+                               output (name);
+                               if (expr != null)
+                                       output (" = " + GetExpression (expr, 0));
+
+                               output (",");
+                               newline ();
+                       }
+                       indent--;
+                       space ();
+                       output_newline ("}");
+               }
+               
+               void GenerateTypeContainerData (TypeContainer tc)
+               {
+                       if (tc.Constants != null){
+                               foreach (Constant c in tc.Constants){
+                                       space ();
+
+                                       output ("const " + c.ConstantType + " " + c.Name + " = " +
+                                               GetExpression (c.Expr, 0) + ";");
+                                       newline ();
+                               }
+                               newline ();
+                       }
+
+                       if (tc.Enums != null){
+                               foreach (CIR.Enum e in tc.Enums)
+                                       GenerateEnum (e);
+                       }
+
+                       if (tc.Fields != null){
+                               foreach (Field f in tc.Fields)
+                                       GenerateField (f);
+                               newline ();
+                       }
+
+                       if (tc.Constructors != null){
+                               foreach (Constructor c in tc.Constructors)
+                                       GenerateConstructor (c);
+
+                               newline ();
+                                       
+                       }
+
+                       if (tc.Properties != null){
+                               foreach (Property prop in tc.Properties)
+                                       GenerateProperty (prop);
+                       }
+                       
+                       GenerateFromTypes (tc);
+                       
+                       if (tc.Methods != null){
+                               foreach (Method m in tc.Methods){
+                                       GenerateMethod (m);
+                               }
+                       }
+               }
+
+               string GetModifiers (int mod_flags)
+               {
+                       string s = "";
+
+                       for (int i = 1; i <= (int) CIR.Modifiers.TOP; i <<= 1){
+                               if ((mod_flags & i) != 0)
+                                       s += Modifiers.Name (i) + " ";
+                       }
+
+                       return s;
+               }
+
+               string ClassName (string name)
+               {
+                       return name;
+                       //return name.Substring (1 + name.LastIndexOf ("."));
+               }
+
+               string GenBases (ArrayList bases)
+               {
+                       if (bases == null)
+                               return "";
+
+                       string res = ": ";
+                       int top = bases.Count;
+                       for (int i = 0; i < bases.Count; i++){
+                               Type t = (Type) bases [i];
+
+                               res += t.Name;
+                               if (i + 1 != top)
+                                       res += ", ";
+                       }
+                       return res;
+               }
+               
+               string GenClassBases (Class c)
+               {
+                       return GenBases (c.Bases);
+               }
+               
+               void GenerateFromClass (Class c)
+               {
+                       ioutput (GetModifiers (c.ModFlags) + "class " + ClassName (c.Name) +
+                                " " + GenClassBases (c) + " {");
+                       newline ();
+                       indent++;
+                       
+                       GenerateTypeContainerData (c);
+
+                       indent--;
+                       ioutput ("}");
+                       newline ();
+                       newline ();
+               }
+
+               void GenerateFromStruct (Struct s)
+               {
+                       GenerateTypeContainerData (s);
+               }
+               
+               void GenerateFromTypes (TypeContainer types)
+               {
+                       if (types.Types == null)
+                               return;
+                       
+                       foreach (DictionaryEntry de in types.Types){
+                               TypeContainer type = (TypeContainer) de.Value;
+                               
+                               if (type is Class)
+                                       GenerateFromClass ((Class) type);
+                               if (type is Struct)
+                                       GenerateFromStruct ((Struct) type);
+                                       
+                       }
+
+                       if (types.Interfaces != null){
+                               foreach (DictionaryEntry de in types.Interfaces){
+                                       Interface iface = (Interface) de.Value;
+
+                                       GenerateInterface (iface);
+                               }
+                       }
+               }
+               
+               public int Dump (Tree tree, StreamWriter output)
+               {
+                       this.o = output;
+
+                       indent = 0;
+                       GenerateFromTypes (tree.Types);
+
+                       return 0;
+               }
+
+               public void ParseOptions (string options)
+               {
+                       if (options == "tag")
+                               tag_values = true;
+               }
+       }
+}
+
+
diff --git a/mcs/gmcs/generic.cs b/mcs/gmcs/generic.cs
new file mode 100644 (file)
index 0000000..4e66eb6
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// generic.cs: Support classes for generics
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2003 Ximian, Inc.
+//
+using System;
+using System.Collections;
+
+namespace Mono.CSharp {
+
+       //
+       // Tracks the constraints for a type parameter
+       //
+       class Constraints {
+               string type_parameter;
+               ArrayList constraints;
+               
+               //
+               // type_parameter is the identifier, constraints is an arraylist of
+               // Expressions (with types) or `true' for the constructor constraint.
+               // 
+               public Constraints (string type_parameter, ArrayList constraints)
+               {
+                       this.type_parameter = type_parameter;
+                       this.constraints = constraints;
+               }
+       }
+
+       //
+       // This type represents a generic type parameter reference.
+       //
+       // These expressions are born in a fully resolved state.
+       //
+       public class TypeParameterExpr : TypeExpr {
+               string type_parameter;
+               
+               public TypeParameterExpr (string type_parameter, Location l)
+                       : base (typeof (object), l)
+               {
+                       this.type_parameter = type_parameter;
+               }
+
+               public override string ToString ()
+               {
+                       return "TypeParameter[" + type_parameter + "]";
+               }
+
+               public void Error_CannotUseAsUnmanagedType (Location loc)
+               {
+                       Report.Error (-203, loc, "Can not use type parameter as unamanged type");
+               }
+       }
+}
diff --git a/mcs/gmcs/genericparser.cs b/mcs/gmcs/genericparser.cs
new file mode 100644 (file)
index 0000000..522987d
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// GenericParser.cs: The Base Parser for the Mono compilers
+//
+// Author: A Rafael D Teixeira (rafaelteixeirabr@hotmail.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// Copyright (C) 2001 Ximian, Inc.
+//
+using System;
+using System.Text;
+
+namespace Mono.Languages
+{
+       using System.Collections;
+
+       /// <summary>
+       /// Base class to support multiple Jay generated parsers
+       /// </summary>
+       public abstract class GenericParser
+       {
+               // Name of the file we are parsing
+               public string name;
+
+               // Input stream to parse from.
+               public System.IO.Stream input;
+
+               public abstract void parse ();
+
+               public virtual string[] extensions()
+               {
+                       string [] list = { ".cs" };
+                       return list;
+               }
+
+               public GenericParser()
+               {
+                       //
+                       // DO NOTHING: Derived classes should do their iniatilization here duties
+                       //
+               }
+
+               protected bool yacc_verbose_flag = false;
+
+               public bool yacc_verbose
+               {
+                       set
+                       {
+                               yacc_verbose_flag = value;
+                       }
+
+                       get
+                       {
+                               return yacc_verbose_flag;
+                       }
+               }
+       }
+}
+
+
+
diff --git a/mcs/gmcs/interface.cs b/mcs/gmcs/interface.cs
new file mode 100755 (executable)
index 0000000..7466e92
--- /dev/null
@@ -0,0 +1,1091 @@
+//
+// interface.cs: Interface handler
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+#define CACHE
+using System.Collections;
+using System;
+using System.IO;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///   Interfaces
+       /// </summary>
+       public class Interface : DeclSpace, IMemberContainer {
+               const MethodAttributes interface_method_attributes =
+                       MethodAttributes.Public |
+                       MethodAttributes.Abstract |
+                       MethodAttributes.HideBySig |
+                       MethodAttributes.NewSlot |
+                       MethodAttributes.Virtual;
+
+               const MethodAttributes property_attributes =
+                       MethodAttributes.Public |
+                       MethodAttributes.Abstract |
+                       MethodAttributes.HideBySig |
+                       MethodAttributes.NewSlot |
+                       MethodAttributes.SpecialName |
+                       MethodAttributes.Virtual;
+               
+               ArrayList bases;
+               
+               ArrayList defined_method;
+               ArrayList defined_indexer;
+               ArrayList defined_events;
+               ArrayList defined_properties;
+
+               ArrayList method_builders;
+               ArrayList property_builders;
+               ArrayList event_builders;
+               
+               Attributes OptAttributes;
+
+               public string IndexerName;
+
+               IMemberContainer parent_container;
+               MemberCache member_cache;
+
+               bool members_defined;
+
+               // These will happen after the semantic analysis
+               
+               // Hashtable defined_indexers;
+               // Hashtable defined_methods;
+               
+               /// <summary>
+               ///   Modifiers allowed in a class declaration
+               /// </summary>
+               public const int AllowedModifiers =
+                       Modifiers.NEW       |
+                       Modifiers.PUBLIC    |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL  |
+                       Modifiers.UNSAFE    |
+                       Modifiers.PRIVATE;
+
+               public Interface (TypeContainer parent, string name, int mod, Attributes attrs, Location l)
+                       : base (parent, name, l)
+               {
+                       ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
+                       OptAttributes = attrs;
+                       
+                       method_builders = new ArrayList ();
+                       property_builders = new ArrayList ();
+                       event_builders = new ArrayList ();
+               }
+
+               public AdditionResult AddMethod (InterfaceMethod imethod)
+               {
+                       string name = imethod.Name;
+                       Object value = defined_names [name];
+
+                       if (value != null){
+                               if (!(value is InterfaceMethod))
+                                       return AdditionResult.NameExists;
+                       } 
+
+                       if (defined_method == null)
+                               defined_method = new ArrayList ();
+
+                       defined_method.Add (imethod);
+                       if (value == null)
+                               DefineName (name, imethod);
+                       
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddProperty (InterfaceProperty iprop)
+               {
+                       AdditionResult res;
+                       string name = iprop.Name;
+
+                       if ((res = IsValid (name, name)) != AdditionResult.Success)
+                               return res;
+
+                       DefineName (name, iprop);
+
+                       if (defined_properties == null)
+                               defined_properties = new ArrayList ();
+
+                       defined_properties.Add (iprop);
+                       return AdditionResult.Success;
+               }
+
+               public AdditionResult AddEvent (InterfaceEvent ievent)
+               {
+                       string name = ievent.Name;
+                       AdditionResult res;
+                       
+                       if ((res = IsValid (name, name)) != AdditionResult.Success)
+                               return res;
+
+                       DefineName (name, ievent);
+
+                       if (defined_events == null)
+                               defined_events = new ArrayList ();
+
+                       defined_events.Add (ievent);
+                       return AdditionResult.Success;
+               }
+
+               public bool AddIndexer (InterfaceIndexer iindexer)
+               {
+                       if (defined_indexer == null)
+                               defined_indexer = new ArrayList ();
+                       
+                       defined_indexer.Add (iindexer);
+                       return true;
+               }
+               
+               public ArrayList InterfaceMethods {
+                       get {
+                               return defined_method;
+                       }
+               }
+
+               public ArrayList InterfaceProperties {
+                       get {
+                               return defined_properties;
+                       }
+               }
+
+               public ArrayList InterfaceEvents {
+                       get {
+                               return defined_events;
+                       }
+               }
+
+               public ArrayList InterfaceIndexers {
+                       get {
+                               return defined_indexer;
+                       }
+               }
+
+               public ArrayList Bases {
+                       get {
+                               return bases;
+                       }
+
+                       set {
+                               bases = value;
+                       }
+               }
+
+               public virtual TypeAttributes InterfaceAttr {
+                       get {
+                               TypeAttributes x = TypeAttributes.Interface | TypeAttributes.Abstract;
+
+                               if (IsTopLevel == false) {
+                                       
+                                       if ((ModFlags & Modifiers.PROTECTED) != 0
+                                           && (ModFlags & Modifiers.INTERNAL) != 0)
+                                               x |= TypeAttributes.NestedFamORAssem;
+                                       else if ((ModFlags & Modifiers.PROTECTED) != 0)
+                                               x |= TypeAttributes.NestedFamily;
+                                       else if ((ModFlags & Modifiers.INTERNAL) != 0)
+                                               x |= TypeAttributes.NestedAssembly;
+                                       else if ((ModFlags & Modifiers.PUBLIC) != 0)
+                                               x |= TypeAttributes.NestedPublic;
+                                       else
+                                               x |= TypeAttributes.NestedPrivate;
+                               } else {
+                                       if ((ModFlags & Modifiers.PUBLIC) != 0)
+                                               x |= TypeAttributes.Public;
+                                       else if ((ModFlags & Modifiers.PRIVATE) != 0)
+                                               x |= TypeAttributes.NotPublic;
+                               }
+                               
+                               if ((ModFlags & Modifiers.ABSTRACT) != 0)
+                                       x |= TypeAttributes.Abstract;
+                               
+                               if ((ModFlags & Modifiers.SEALED) != 0)
+                                       x |= TypeAttributes.Sealed;
+
+                               return x;
+                       }
+               }
+               
+               void Error111 (InterfaceMemberBase ib)
+               {
+                       Report.Error (
+                               111,
+                               "Interface `" + Name + "' already contains a definition with the " +
+                               "same return value and parameter types for member `" + ib.Name + "'");
+               }
+
+               bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] types)
+               {
+                       if (!TypeManager.RegisterMethod (mb, ip, types))
+                               return false;
+
+                       method_builders.Add (mb);
+                       return true;
+               }
+
+               //
+               // This might trigger a definition of the methods.  This happens only
+               // with Attributes, as Attribute classes are processed before interfaces.
+               // Ideally, we should make everything just define recursively in terms
+               // of its dependencies.
+               //
+               public MethodInfo [] GetMethods (TypeContainer container)
+               {
+                       int n = 0;
+                       
+                       if (!members_defined){
+                               if (DefineMembers (container))
+                                       n = method_builders.Count;
+                       } else
+                               n = method_builders.Count;
+                       
+                       MethodInfo [] mi = new MethodInfo [n];
+                       
+                       method_builders.CopyTo (mi, 0);
+
+                       return mi;
+               }
+
+               // Hack around System.Reflection as found everywhere else
+               public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                                       MemberFilter filter, object criteria)
+               {
+                       ArrayList members = new ArrayList ();
+
+                       if ((mt & MemberTypes.Method) != 0) {
+                               foreach (MethodBuilder mb in method_builders)
+                                       if (filter (mb, criteria))
+                                               members.Add (mb);
+                       }
+
+                       if ((mt & MemberTypes.Property) != 0) {
+                               foreach (PropertyBuilder pb in property_builders)
+                                       if (filter (pb, criteria))
+                                               members.Add (pb);
+                       }
+
+                       if ((mt & MemberTypes.Event) != 0) {
+                               foreach (MyEventBuilder eb in event_builders)
+                                       if (filter (eb, criteria))
+                                               members.Add (eb);
+                       }
+
+                       if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
+                               MemberList parent_mi;
+                               
+                               parent_mi = TypeContainer.FindMembers (
+                                       TypeBuilder.BaseType, mt, bf, filter, criteria);
+
+                               members.AddRange (parent_mi);
+                       }
+
+                       return new MemberList (members);
+               }
+
+               public override MemberCache MemberCache {
+                       get {
+                               return member_cache;
+                       }
+               }
+
+               //
+               // Populates the methods in the interface
+               //
+               void PopulateMethod (TypeContainer parent, DeclSpace decl_space, InterfaceMethod im)
+               {
+                       Type return_type = im.ReturnType.Type;
+                       if (return_type == null)
+                               return_type = this.ResolveType (im.ReturnType, false, im.Location);
+                       
+                       Type [] arg_types = im.ParameterTypes (this);
+                       MethodBuilder mb;
+                       Parameter [] p;
+                       int i;
+
+                       if (return_type == null)
+                               return;
+
+                       if (return_type.IsPointer && !UnsafeOK (this))
+                               return;
+
+                       if (arg_types == null)
+                               return;
+
+                       foreach (Type t in arg_types){
+
+                               if (t == null)
+                                       return;
+                               
+                               if (t.IsPointer && !UnsafeOK (this))
+                                       return;
+                       }
+                       
+                       //
+                       // Create the method
+                       //
+                       mb = TypeBuilder.DefineMethod (
+                               im.Name, interface_method_attributes,
+                               return_type, arg_types);
+
+                       InternalParameters ip = new InternalParameters (arg_types, im.Parameters);
+
+                       if (!RegisterMethod (mb, ip, arg_types)) {
+                               Error111 (im);
+                               return;
+                       }
+
+                       //
+                       // Define each type attribute (in/out/ref) and
+                       // the argument names.
+                       //
+                       p = im.Parameters.FixedParameters;
+                       if (p != null){
+                               for (i = 0; i < p.Length; i++)
+                                       mb.DefineParameter (i + 1, p [i].Attributes, p [i].Name);
+
+                               if (i != arg_types.Length)
+                                       Console.WriteLine ("Implement the type definition for params");
+                       }
+
+                       EmitContext ec = new EmitContext (parent, decl_space, Location, null,
+                                                         return_type, ModFlags, false);
+
+                       if (im.OptAttributes != null)
+                               Attribute.ApplyAttributes (ec, mb, im, im.OptAttributes);
+               }
+
+               //
+               // Populates the properties in the interface
+               //
+               void PopulateProperty (TypeContainer parent, DeclSpace decl_space, InterfaceProperty ip)
+               {
+                       PropertyBuilder pb;
+                       MethodBuilder get = null, set = null;
+                       ip.Type = this.ResolveTypeExpr (ip.Type, false, ip.Location);
+                       if (ip.Type == null)
+                               return;
+                       
+                       Type prop_type = ip.Type.Type;
+                       Type [] setter_args = new Type [1];
+
+                       if (prop_type == null)
+                               return;
+
+                       if (prop_type.IsPointer && !UnsafeOK (this))
+                               return;
+                       
+                       setter_args [0] = prop_type;
+
+                       //
+                       // FIXME: properties are missing the following
+                       // flags: hidebysig newslot specialname
+                       //
+                       pb = TypeBuilder.DefineProperty (
+                               ip.Name, PropertyAttributes.None,
+                               prop_type, null);
+
+                       if (ip.HasGet){
+                               get = TypeBuilder.DefineMethod (
+                                       "get_" + ip.Name, property_attributes ,
+                                       prop_type, null);
+
+                               //
+                               // HACK because System.Reflection.Emit is lame
+                               //
+                               Type [] null_types = null;
+                               InternalParameters inp = new InternalParameters
+                                       (null_types, Parameters.EmptyReadOnlyParameters);
+                               
+                               if (!RegisterMethod (get, inp, null)) {
+                                       Error111 (ip);
+                                       return;
+                               }
+                               
+                               pb.SetGetMethod (get);
+                       }
+
+                       if (ip.HasSet){
+                               setter_args [0] = prop_type;
+
+                               set = TypeBuilder.DefineMethod (
+                                       "set_" + ip.Name, property_attributes,
+                                       TypeManager.void_type, setter_args);
+
+                               set.DefineParameter (1, ParameterAttributes.None, "value");
+                               pb.SetSetMethod (set);
+
+                               //
+                               // HACK because System.Reflection.Emit is lame
+                               //
+                               Parameter [] parms = new Parameter [1];
+                               parms [0] = new Parameter (ip.Type, "value", Parameter.Modifier.NONE, null);
+                               InternalParameters ipp = new InternalParameters (
+                                       this, new Parameters (parms, null, Location.Null));
+                                       
+                               if (!RegisterMethod (set, ipp, setter_args)) {
+                                       Error111 (ip);
+                                       return;
+                               }
+                       }
+
+                       EmitContext ec = new EmitContext (parent, decl_space, Location, null,
+                                                         null, ModFlags, false);
+
+                       if (ip.OptAttributes != null)
+                               Attribute.ApplyAttributes (ec, pb, ip, ip.OptAttributes);
+
+                       TypeManager.RegisterProperty (pb, get, set);
+                       property_builders.Add (pb);
+               }
+
+               //
+               // Populates the events in the interface
+               //
+               void PopulateEvent (TypeContainer parent, DeclSpace decl_space, InterfaceEvent ie)
+               {
+                       //
+                       // FIXME: We need to do this after delegates have been
+                       // declared or we declare them recursively.
+                       //
+                       MyEventBuilder eb;
+                       MethodBuilder add = null, remove = null;
+                       ie.Type = this.ResolveTypeExpr (ie.Type, false, ie.Location);
+                       if (ie.Type == null)
+                               return;
+                       
+                       Type event_type = ie.Type.Type;
+
+                       if (event_type == null)
+                               return;
+
+                       if (event_type.IsPointer && !UnsafeOK (this))
+                               return;
+
+                       Type [] parameters = new Type [1];
+                       parameters [0] = event_type;
+
+                       eb = new MyEventBuilder (null, TypeBuilder, ie.Name,
+                                                EventAttributes.None, event_type);
+
+                       //
+                       // Now define the accessors
+                       //
+                       string add_name = "add_" + ie.Name;
+                       
+                       add = TypeBuilder.DefineMethod (
+                               add_name, property_attributes, null, parameters);
+                       add.DefineParameter (1, ParameterAttributes.None, "value");
+                       eb.SetAddOnMethod (add);
+
+                       string remove_name = "remove_" + ie.Name;
+                       remove = TypeBuilder.DefineMethod (
+                               remove_name, property_attributes, null, parameters);
+                       remove.DefineParameter (1, ParameterAttributes.None, "value");
+                       eb.SetRemoveOnMethod (remove);
+
+                       Parameter [] parms = new Parameter [1];
+                       parms [0] = new Parameter (ie.Type, "value", Parameter.Modifier.NONE, null);
+                       InternalParameters ip = new InternalParameters (
+                               this, new Parameters (parms, null, Location.Null));
+
+                       if (!RegisterMethod (add, ip, parameters)) {
+                               Error111 (ie);
+                               return;
+                       }
+                       
+                       if (!RegisterMethod (remove, ip, parameters)) {
+                               Error111 (ie);
+                               return;
+                       }
+
+                       EmitContext ec = new EmitContext (parent, decl_space, Location, null,
+                                                         null, ModFlags, false);
+
+
+                       if (ie.OptAttributes != null)
+                               Attribute.ApplyAttributes (ec, eb, ie, ie.OptAttributes);
+
+                       TypeManager.RegisterEvent (eb, add, remove);
+                       event_builders.Add (eb);
+               }
+
+               //
+               // Populates the indexers in the interface
+               //
+               void PopulateIndexer (TypeContainer parent, DeclSpace decl_space, InterfaceIndexer ii)
+               {
+                       PropertyBuilder pb;
+                       ii.Type = this.ResolveTypeExpr (ii.Type, false, ii.Location);
+                       if (ii.Type == null)
+                               return;
+                       
+                       Type prop_type = ii.Type.Type;
+                       Type [] arg_types = ii.ParameterTypes (this);
+                       Type [] value_arg_types;
+
+                       if (prop_type == null)
+                               return;
+
+                       if (prop_type.IsPointer && !UnsafeOK (this))
+                               return;
+                       
+                       //
+                       // Sets up the extra invisible `value' argument for setters.
+                       // 
+                       if (arg_types != null){
+                               int count = arg_types.Length;
+                               value_arg_types = new Type [count + 1];
+
+                               arg_types.CopyTo (value_arg_types, 0);
+                               value_arg_types [count] = prop_type;
+
+                               foreach (Type t in arg_types){
+                                       if (t.IsPointer && !UnsafeOK (this))
+                                               return;
+                               }
+                       } else {
+                               value_arg_types = new Type [1];
+
+                               value_arg_types [1] = prop_type;
+                       }
+
+                       EmitContext ec = new EmitContext (parent, decl_space, Location, null,
+                                                         null, ModFlags, false);
+
+                       IndexerName = Attribute.ScanForIndexerName (ec, ii.OptAttributes);
+                       if (IndexerName == null)
+                               IndexerName = "Item";
+                       
+                       pb = TypeBuilder.DefineProperty (
+                               IndexerName, PropertyAttributes.None,
+                               prop_type, arg_types);
+                       
+                       MethodBuilder set_item = null, get_item = null;
+                       if (ii.HasGet){
+                               Parameter [] p = ii.Parameters.FixedParameters;
+                               
+                               get_item = TypeBuilder.DefineMethod (
+                                       "get_" + IndexerName, property_attributes,
+                                       prop_type, arg_types);
+                               pb.SetGetMethod (get_item);
+                               //
+                               // HACK because System.Reflection.Emit is lame
+                               //
+                               InternalParameters ip = new InternalParameters (
+                                       arg_types, ii.Parameters);
+                               
+                               if (!RegisterMethod (get_item, ip, arg_types)) {
+                                       Error111 (ii);
+                                       return;
+                               }
+
+                               if (p != null){
+                                       for (int i = 0; i < p.Length; i++)
+                                               get_item.DefineParameter (
+                                                       i + 1,
+                                                       p [i].Attributes, p [i].Name);
+                               }
+                       }
+
+                       if (ii.HasSet){
+                               Parameter [] p = ii.Parameters.FixedParameters;
+                               Parameter [] pv;
+                               int i = 0;
+                               
+                               pv = new Parameter [p.Length + 1];
+                               p.CopyTo (pv, 0);
+                               pv [p.Length] = new Parameter (ii.Type, "value", Parameter.Modifier.NONE, null);
+                               Parameters value_params = new Parameters (pv, null, Location.Null);
+                               value_params.GetParameterInfo (decl_space);
+                               
+                               set_item = TypeBuilder.DefineMethod (
+                                       "set_" + IndexerName, property_attributes,
+                                       TypeManager.void_type, value_arg_types);
+                               pb.SetSetMethod (set_item);
+                               //
+                               // HACK because System.Reflection.Emit is lame
+                               //
+                               InternalParameters ip = new InternalParameters (
+                                       value_arg_types, value_params);
+                               if (!RegisterMethod (set_item, ip, value_arg_types)) {
+                                       Error111 (ii);
+                                       return;
+                               }
+
+                               if (p != null){
+                                       for (; i < p.Length; i++)
+                                               set_item.DefineParameter (
+                                                       i + 1,
+                                                       p [i].Attributes, p [i].Name);
+                               }
+                               
+                               set_item.DefineParameter (i + 1, ParameterAttributes.None, "value");
+                       }
+
+                       if (ii.OptAttributes != null)
+                               Attribute.ApplyAttributes (ec, pb, ii, ii.OptAttributes);
+
+                       property_builders.Add (pb);
+               }
+
+               /// <summary>
+               ///   Performs the semantic analysis for all the interface members
+               ///   that were declared
+               /// </summary>
+               bool SemanticAnalysis ()
+               {
+                       Hashtable methods = new Hashtable ();
+
+                       
+                       if (defined_method != null){
+                               foreach (InterfaceMethod im in defined_method){
+                                       string sig = im.GetSignature (this);
+                                       
+                                       //
+                                       // If there was an undefined Type on the signatures
+                                       // 
+                                       if (sig == null)
+                                               continue;
+                                       
+                                       if (methods [sig] != null){
+                                               Error111 (im);
+                                               return false;
+                                       }
+                               }
+                       }
+
+                       //
+                       // FIXME: Here I should check i
+                       // 
+                       return true;
+               }
+
+               Type GetInterfaceTypeByName (string name)
+               {
+                       Type t = FindType (Location, name);
+
+                       if (t == null) {
+                               Report.Error (246, Location, "The type or namespace `" + name +
+                                             "' could not be found");
+                               return null;
+                       }
+                       
+                       if (t.IsInterface)
+                               return t;
+                               
+                       string cause;
+                       
+                       if (t.IsValueType)
+                               cause = "is a struct";
+                       else if (t.IsClass) 
+                               cause = "is a class";
+                       else
+                               cause = "Should not happen.";
+                       
+                       Report.Error (527, Location, "`"+name+"' " + cause +
+                                     ", need an interface instead");
+                       
+                       return null;
+               }
+               
+               //
+               // Returns the list of interfaces that this interface implements
+               // Or null if it does not implement any interface.
+               //
+               // Sets the error boolean accoringly.
+               //
+               Type [] GetInterfaceBases (out bool error)
+               {
+                       Type [] tbases;
+                       int i;
+
+                       error = false;
+                       if (Bases == null)
+                               return null;
+                       
+                       tbases = new Type [Bases.Count];
+                       i = 0;
+
+                       foreach (string name in Bases){
+                               Type t;
+
+                               t = GetInterfaceTypeByName (name);
+                               if (t == null){
+                                       error = true;
+                                       return null;
+                               }
+
+                               if (!Parent.AsAccessible (t, ModFlags))
+                                       Report.Error (61, Location,
+                                                     "Inconsistent accessibility: base interface `" +
+                                                     TypeManager.CSharpName (t) + "' is less " +
+                                                     "accessible than interface `" +
+                                                     Name + "'");
+
+                               tbases [i++] = t;
+                       }
+                       
+                       return TypeManager.ExpandInterfaces (tbases);
+               }
+               
+               //
+               // <summary>
+               //  Defines the Interface in the appropriate ModuleBuilder or TypeBuilder
+               // </summary>
+               //
+               // TODO:
+               //   Rework the way we recurse, because for recursive
+               //   definitions of interfaces (A:B and B:A) we report the
+               //   error twice, rather than once.  
+               
+               public override TypeBuilder DefineType ()
+               {
+                       Type [] ifaces;
+                       bool error;
+
+                       if (TypeBuilder != null)
+                               return TypeBuilder;
+                       
+                       if (InTransit)
+                               return null;
+                       
+                       InTransit = true;
+                       
+                       ifaces = GetInterfaceBases (out error);
+
+                       if (error)
+                               return null;
+
+                       if (IsTopLevel) {
+                               if (TypeManager.NamespaceClash (Name, Location))
+                                       return null;
+                               
+                               ModuleBuilder builder = CodeGen.ModuleBuilder;
+
+                               TypeBuilder = builder.DefineType (
+                                       Name,
+                                       InterfaceAttr,
+                                       (Type)null,   // Parent Type
+                                       ifaces);
+                               RootContext.RegisterOrder (this);
+                       } else {
+                               TypeBuilder builder = Parent.TypeBuilder;
+
+                               TypeBuilder = builder.DefineNestedType (
+                                       Basename,
+                                       InterfaceAttr,
+                                       (Type) null, //parent type
+                                       ifaces);
+
+                               TypeContainer tc = TypeManager.LookupTypeContainer (builder);
+                               tc.RegisterOrder (this);
+                       }
+
+                       TypeManager.AddUserInterface (Name, TypeBuilder, this, ifaces);
+                       InTransit = false;
+
+                       return TypeBuilder;
+               }
+
+               //
+               // Defines the indexers, and also verifies that the IndexerNameAttribute in the
+               // interface is consistent.  Either it is `Item' or it is the name defined by all the
+               // indexers with the `IndexerName' attribute.
+               //
+               // Turns out that the IndexerNameAttribute is applied to each indexer,
+               // but it is never emitted, instead a DefaultName attribute is attached
+               // to the interface
+               //
+               void DefineIndexers (TypeContainer parent)
+               {
+                       string interface_indexer_name = null;
+
+                       foreach (InterfaceIndexer ii in defined_indexer){
+
+                               PopulateIndexer (parent, this, ii);
+
+                               if (interface_indexer_name == null){
+                                       interface_indexer_name = IndexerName;
+                                       continue;
+                               }
+                               
+                               if (IndexerName == interface_indexer_name)
+                                       continue;
+                               
+                               Report.Error (
+                                       668, "Two indexers have different names, " +
+                                       " you should use the same name for all your indexers");
+                       }
+                       if (interface_indexer_name == null)
+                               interface_indexer_name = "Item";
+                       IndexerName = interface_indexer_name;
+               }
+               
+               /// <summary>
+               ///   Performs semantic analysis, and then generates the IL interfaces
+               /// </summary>
+               public override bool DefineMembers (TypeContainer parent)
+               {
+                       if (members_defined)
+                               return true;
+                       
+                       if (!SemanticAnalysis ())
+                               return false;
+
+                       
+                       if (defined_method != null){
+                               foreach (InterfaceMethod im in defined_method)
+                                       PopulateMethod (parent, this, im);
+                       }
+
+                       if (defined_properties != null){
+                               foreach (InterfaceProperty ip in defined_properties)
+                                       PopulateProperty (parent, this, ip);
+                       }
+
+                       if (defined_events != null)
+                               foreach (InterfaceEvent ie in defined_events)
+                                       PopulateEvent (parent, this, ie);
+
+                       if (defined_indexer != null) {
+                               DefineIndexers (parent);
+
+                               CustomAttributeBuilder cb = EmitDefaultMemberAttr (
+                                       parent, IndexerName, ModFlags, Location);
+                               if (cb != null)
+                                       TypeBuilder.SetCustomAttribute (cb);
+                       }
+
+#if CACHE
+                       if (TypeBuilder.BaseType != null)
+                               parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
+
+                       member_cache = new MemberCache (this);
+#endif
+                       members_defined = true;
+                       return true;
+               }
+
+
+                //
+                // In the case of Interfaces, there is nothing to do here
+                //
+               public override bool Define (TypeContainer parent)
+               {
+                       return true;
+               }
+
+                /// <summary>
+               ///   Applies all the attributes.
+               /// </summary>
+                public void Emit (TypeContainer tc)
+                {
+                        if (OptAttributes != null) {
+                               EmitContext ec = new EmitContext (tc, this, Location, null, null,
+                                                                 ModFlags, false);
+                               Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
+                       }
+                }
+
+               public static CustomAttributeBuilder EmitDefaultMemberAttr (TypeContainer parent,
+                                                                           string name,
+                                                                           int flags,
+                                                                           Location loc)
+               {
+                       EmitContext ec = new EmitContext (parent, loc, null, null, flags);
+
+                       Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
+                                                                ".ctor", MemberTypes.Constructor,
+                                                                BindingFlags.Public | BindingFlags.Instance,
+                                                                Location.Null);
+                       
+                       if (!(ml is MethodGroupExpr)) {
+                               Console.WriteLine ("Internal error !!!!");
+                               return null;
+                       }
+                       
+                       MethodGroupExpr mg = (MethodGroupExpr) ml;
+
+                       MethodBase constructor = mg.Methods [0];
+
+                       string [] vals = { name };
+
+                       CustomAttributeBuilder cb = null;
+                       try {
+                               cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
+                       } catch {
+                               Report.Warning (-100, "Can not set the indexer default member attribute");
+                       }
+
+                       return cb;
+               }
+
+               //
+               // IMemberContainer
+               //
+
+               string IMemberContainer.Name {
+                       get {
+                               return Name;
+                       }
+               }
+
+               Type IMemberContainer.Type {
+                       get {
+                               return TypeBuilder;
+                       }
+               }
+
+               IMemberContainer IMemberContainer.Parent {
+                       get {
+                               return parent_container;
+                       }
+               }
+
+               MemberCache IMemberContainer.MemberCache {
+                       get {
+                               return member_cache;
+                       }
+               }
+
+               bool IMemberContainer.IsInterface {
+                       get {
+                               return true;
+                       }
+               }
+
+               MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
+               {
+                       // Interfaces only contain instance members.
+                       if ((bf & BindingFlags.Instance) == 0)
+                               return MemberList.Empty;
+                       if ((bf & BindingFlags.Public) == 0)
+                               return MemberList.Empty;
+
+                       ArrayList members = new ArrayList ();
+
+                       if ((mt & MemberTypes.Method) != 0)
+                               members.AddRange (method_builders);
+
+                       if ((mt & MemberTypes.Property) != 0)
+                               members.AddRange (property_builders);
+
+                       if ((mt & MemberTypes.Event) != 0)
+                               members.AddRange (event_builders);
+
+                       return new MemberList (members);
+               }
+       }
+
+       public class InterfaceMemberBase {
+               public readonly string Name;
+               public readonly bool IsNew;
+               public Attributes OptAttributes;
+               
+               public InterfaceMemberBase (string name, bool is_new, Attributes attrs)
+               {
+                       Name = name;
+                       IsNew = is_new;
+                       OptAttributes = attrs;
+               }
+       }
+       
+       public class InterfaceProperty : InterfaceMemberBase {
+               public readonly bool HasSet;
+               public readonly bool HasGet;
+               public readonly Location Location;
+               public Expression Type;
+               
+               public InterfaceProperty (Expression type, string name,
+                                         bool is_new, bool has_get, bool has_set,
+                                         Attributes attrs, Location loc)
+                       : base (name, is_new, attrs)
+               {
+                       Type = type;
+                       HasGet = has_get;
+                       HasSet = has_set;
+                       Location = loc;
+               }
+       }
+
+       public class InterfaceEvent : InterfaceMemberBase {
+               public readonly Location Location;
+               public Expression Type;
+               
+               public InterfaceEvent (Expression type, string name, bool is_new, Attributes attrs,
+                                      Location loc)
+                       : base (name, is_new, attrs)
+               {
+                       Type = type;
+                       Location = loc;
+               }
+       }
+       
+       public class InterfaceMethod : InterfaceMemberBase {
+               public Expression ReturnType;
+               public readonly Parameters Parameters;
+               public readonly Location Location;
+               
+               public InterfaceMethod (Expression return_type, string name, bool is_new, Parameters args,
+                                       Attributes attrs, Location l)
+                       : base (name, is_new, attrs)
+               {
+                       this.ReturnType = return_type;
+                       this.Parameters = args;
+                       Location = l;
+               }
+
+               /// <summary>
+               ///   Returns the signature for this interface method
+               /// </summary>
+               public string GetSignature (DeclSpace ds)
+               {
+                       ReturnType = ds.ResolveTypeExpr (ReturnType, false, Location);
+                       if (ReturnType == null)
+                               return null;
+                       
+                       Type ret = ReturnType.Type;
+                       string args = Parameters.GetSignature (ds);
+
+                       if ((ret == null) || (args == null))
+                               return null;
+                       
+                       return (IsNew ? "new-" : "") + ret.FullName + "(" + args + ")";
+               }
+
+               public Type [] ParameterTypes (DeclSpace ds)
+               {
+                       return Parameters.GetParameterInfo (ds);
+               }
+       }
+
+       public class InterfaceIndexer : InterfaceMemberBase {
+               public readonly bool HasGet, HasSet;
+               public readonly Parameters Parameters;
+               public readonly Location Location;
+               public Expression Type;
+               
+               public InterfaceIndexer (Expression type, Parameters args, bool do_get, bool do_set,
+                                        bool is_new, Attributes attrs, Location loc)
+                       : base ("", is_new, attrs)
+               {
+                       Type = type;
+                       Parameters = args;
+                       HasGet = do_get;
+                       HasSet = do_set;
+                       Location = loc;
+               }
+
+               public Type [] ParameterTypes (DeclSpace ds)
+               {
+                       return Parameters.GetParameterInfo (ds);
+               }
+       }
+}
diff --git a/mcs/gmcs/iterators.cs b/mcs/gmcs/iterators.cs
new file mode 100644 (file)
index 0000000..bed8852
--- /dev/null
@@ -0,0 +1,692 @@
+//
+// iterators.cs: Support for implementing iterators
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2003 Ximian, Inc.
+//
+// TODO:
+//    Flow analysis for Yield.
+//    Emit calls to parent object constructor.
+//
+// Generics note:
+//    Current should be defined to return T, and IEnumerator.Current returns object
+//
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Mono.CSharp {
+
+       public interface IIteratorContainer {
+
+               //
+               // Invoked if a yield statement is found in the body
+               //
+               void SetYields ();
+       }
+       
+       public class Yield : Statement {
+               public Expression expr;
+
+               public Yield (Expression expr, Location l)
+               {
+                       this.expr = expr;
+                       loc = l;
+               }
+
+               public static bool CheckContext (EmitContext ec, Location loc)
+               {
+                       if (ec.InFinally){
+                               Report.Error (-208, loc, "yield statement can not appear in finally clause");
+                               return false;
+                       }
+                       if (ec.InCatch){
+                               Report.Error (-209, loc, "yield statement can not appear in the catch clause");
+                               return false;
+                       }
+                       if (ec.InAnonymousMethod){
+                               Report.Error (-209, loc, "yield statement can not appear inside an anonymoud method");
+                               return false;
+                       }
+
+                       //
+                       // FIXME: Missing check for Yield inside try block that contains catch clauses
+                       //
+                       return true;
+               }
+               
+               public override bool Resolve (EmitContext ec)
+               {
+                       expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return false;
+                       if (!CheckContext (ec, loc))
+                               return false;
+                       
+                       Type iterator_type = IteratorHandler.Current.IteratorType;
+                       if (expr.Type != iterator_type){
+                               expr = Convert.ImplicitConversionRequired (ec, expr, iterator_type, loc);
+                               if (expr == null)
+                                       return false;
+                       }
+                       return true;
+               }
+
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       IteratorHandler.Current.MarkYield (ec, expr);
+                       
+                       return false;
+               }
+       }
+
+       public class YieldBreak : Statement {
+
+               public YieldBreak (Location l)
+               {
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       if (!Yield.CheckContext (ec, loc))
+                               return false;
+
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+                       return true;
+               }
+
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       IteratorHandler.Current.EmitYieldBreak (ec.ig, true);
+                       return false;
+               }
+       }
+
+       public class IteratorHandler {
+               //
+               // Points to the current iterator handler, will be probed by
+               // Yield and YieldBreak to get their context information
+               //
+               public static IteratorHandler Current;
+               
+               //
+               // The typebuilder to the proxy class we create
+               //
+               TypeBuilder enumerator_proxy_class;
+               TypeBuilder enumerable_proxy_class;
+
+               //
+               // The type of this iterator, object by default.
+               //
+               public Type IteratorType;
+               
+               //
+               // The members we create on the proxy class
+               //
+               MethodBuilder move_next_method;
+               MethodBuilder reset_method;
+               MethodBuilder get_current_method;
+               MethodBuilder dispose_method;
+               MethodBuilder getenumerator_method;
+               PropertyBuilder current_property;
+               ConstructorBuilder enumerator_proxy_constructor;
+               ConstructorBuilder enumerable_proxy_constructor;
+
+               //
+               // The PC for the state machine.
+               //
+               FieldBuilder pc_field;
+
+               //
+               // The value computed for Current
+               //
+               FieldBuilder current_field;
+
+               //
+               // Used to reference fields on the container class (instance methods)
+               //
+               public FieldBuilder this_field;
+               public FieldBuilder enumerable_this_field;
+
+               //
+               // References the parameters
+               //
+
+               public FieldBuilder [] parameter_fields;
+               FieldBuilder [] enumerable_parameter_fields;
+               
+               //
+               // The state as we generate the iterator
+               //
+               ArrayList resume_labels = new ArrayList ();
+               int pc;
+               
+               //
+               // Context from the original method
+               //
+               string name;
+               TypeContainer container;
+               Type return_type;
+               Type [] param_types;
+               InternalParameters parameters;
+               Block original_block;
+               Location loc;
+               int modifiers;
+
+               static int proxy_count;
+               string MakeProxyName ()
+               {
+                       return String.Format ("__Proxy_{0}", proxy_count++);
+               }
+
+               public void EmitYieldBreak (ILGenerator ig, bool add_return)
+               {
+                       ig.Emit (OpCodes.Ldarg_0);
+                       IntConstant.EmitInt (ig, -1);
+                       ig.Emit (OpCodes.Stfld, pc_field);
+                       if (add_return){
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               ig.Emit (OpCodes.Ret);
+                       }
+               }
+
+               void EmitThrowInvalidOp (ILGenerator ig)
+               {
+                       ig.Emit (OpCodes.Newobj, TypeManager.invalid_operation_ctor);
+                       ig.Emit (OpCodes.Throw);
+               }
+               
+               void Create_MoveNext ()
+               {
+                       move_next_method = enumerator_proxy_class.DefineMethod (
+                               "System.IEnumerator.MoveNext",
+                               MethodAttributes.HideBySig | MethodAttributes.NewSlot |
+                               MethodAttributes.Virtual,
+                               CallingConventions.HasThis, TypeManager.bool_type, TypeManager.NoTypes);
+                       enumerator_proxy_class.DefineMethodOverride (move_next_method, TypeManager.bool_movenext_void);
+
+                       ILGenerator ig = move_next_method.GetILGenerator ();
+                       EmitContext ec = new EmitContext (
+                               container, loc, ig,
+                               TypeManager.void_type, modifiers);
+
+                       Label dispatcher = ig.DefineLabel ();
+                       ig.Emit (OpCodes.Br, dispatcher);
+                       Label entry_point = ig.DefineLabel ();
+                       ig.MarkLabel (entry_point);
+                       resume_labels.Add (entry_point);
+                       
+                       Current = this;
+                       SymbolWriter sw = CodeGen.SymbolWriter;
+                       if ((sw != null) && !Location.IsNull (loc) && !Location.IsNull (original_block.EndLocation)) {
+                               sw.OpenMethod (container, move_next_method, loc, original_block.EndLocation);
+
+                               ec.EmitTopBlock (original_block, parameters, loc);
+
+                               sw.CloseMethod ();
+                       } else {
+                               ec.EmitTopBlock (original_block, parameters, loc);
+                       }
+                       Current = null;
+
+                       EmitYieldBreak (ig, true);
+
+                       //
+                       // FIXME: Split the switch in blocks that can be consumed by switch.
+                       //
+                       ig.MarkLabel (dispatcher);
+                       
+                       Label [] labels = new Label [resume_labels.Count];
+                       resume_labels.CopyTo (labels);
+                       ig.Emit (OpCodes.Ldarg_0);
+                       ig.Emit (OpCodes.Ldfld, pc_field);
+                       ig.Emit (OpCodes.Switch, labels);
+                       ig.Emit (OpCodes.Ldc_I4_0); 
+                       ig.Emit (OpCodes.Ret); 
+               }
+
+               // 
+               // Invoked when a local variable declaration needs to be mapped to
+               // a field in our proxy class
+               //
+               public FieldBuilder MapVariable (string name, Type t)
+               {
+                       return enumerator_proxy_class.DefineField ("v" + name, t, FieldAttributes.Public);
+               }
+               
+               void Create_Reset ()
+               {
+                       reset_method = enumerator_proxy_class.DefineMethod (
+                               "System.IEnumerator.Reset",
+                               MethodAttributes.HideBySig | MethodAttributes.NewSlot |
+                               MethodAttributes.Virtual,
+                               CallingConventions.HasThis, TypeManager.void_type, TypeManager.NoTypes);
+                       enumerator_proxy_class.DefineMethodOverride (reset_method, TypeManager.void_reset_void);
+                       ILGenerator ig = reset_method.GetILGenerator ();
+                       EmitThrowInvalidOp (ig);
+               }
+
+               void Create_Current ()
+               {
+                       get_current_method = enumerator_proxy_class.DefineMethod (
+                               "System.IEnumerator.get_Current",
+                               MethodAttributes.HideBySig | MethodAttributes.SpecialName |
+                               MethodAttributes.NewSlot | MethodAttributes.Virtual,
+                               CallingConventions.HasThis, TypeManager.object_type, TypeManager.NoTypes);
+                       enumerator_proxy_class.DefineMethodOverride (get_current_method, TypeManager.object_getcurrent_void);
+
+                       current_property = enumerator_proxy_class.DefineProperty (
+                               "Current",
+                               PropertyAttributes.RTSpecialName | PropertyAttributes.SpecialName,
+                               TypeManager.object_type, null);
+
+                       current_property.SetGetMethod (get_current_method);
+                       
+                       ILGenerator ig = get_current_method.GetILGenerator ();
+
+                       ig.Emit (OpCodes.Ldarg_0);
+                       ig.Emit (OpCodes.Ldfld, pc_field);
+                       ig.Emit (OpCodes.Ldc_I4_0);
+                       Label return_current = ig.DefineLabel ();
+                       ig.Emit (OpCodes.Bgt, return_current);
+                       EmitThrowInvalidOp (ig);
+                       
+                       ig.MarkLabel (return_current);
+                       ig.Emit (OpCodes.Ldarg_0);
+                       ig.Emit (OpCodes.Ldfld, current_field);
+                       ig.Emit (OpCodes.Ret);
+               }
+
+               void Create_Dispose ()
+               {
+                       dispose_method = enumerator_proxy_class.DefineMethod (
+                               "System.IDisposable.Dispose",
+                               MethodAttributes.HideBySig | MethodAttributes.SpecialName |
+                               MethodAttributes.NewSlot | MethodAttributes.Virtual,
+                               CallingConventions.HasThis, TypeManager.void_type, TypeManager.NoTypes);
+                       enumerator_proxy_class.DefineMethodOverride (dispose_method, TypeManager.void_dispose_void);
+                       ILGenerator ig = dispose_method.GetILGenerator (); 
+
+                       EmitYieldBreak (ig, false);
+                       ig.Emit (OpCodes.Ret);
+               }
+               
+               void Create_GetEnumerator ()
+               {
+                       getenumerator_method = enumerable_proxy_class.DefineMethod (
+                               "IEnumerable.GetEnumerator",
+                               MethodAttributes.HideBySig | MethodAttributes.SpecialName |
+                               MethodAttributes.NewSlot | MethodAttributes.Virtual,
+                               CallingConventions.HasThis, TypeManager.ienumerator_type, TypeManager.NoTypes);
+
+                       enumerable_proxy_class.DefineMethodOverride  (getenumerator_method, TypeManager.ienumerable_getenumerator_void);
+                       ILGenerator ig = getenumerator_method.GetILGenerator ();
+
+                       if (enumerable_this_field != null){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ig.Emit (OpCodes.Ldfld, enumerable_this_field);
+                       }
+                       for (int i = 0; i < parameters.Count; i++){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ig.Emit (OpCodes.Ldfld, enumerable_parameter_fields [i]);
+                       }
+                       ig.Emit (OpCodes.Newobj, (ConstructorInfo) enumerator_proxy_constructor);
+                       ig.Emit (OpCodes.Ret);
+               }
+
+               void LoadArgs (ILGenerator ig)
+               {
+                       int count = parameters.Count;
+                       if ((modifiers & Modifiers.STATIC) == 0)
+                               count++;
+
+                       for (int i = 0; i < count; i++)
+                               ParameterReference.EmitLdArg (ig, i);
+               }
+               
+               //
+               // Called back from Yield
+               //
+               public void MarkYield (EmitContext ec, Expression expr)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       // Store the new current
+                       ig.Emit (OpCodes.Ldarg_0);
+                       expr.Emit (ec);
+                       ig.Emit (OpCodes.Stfld, current_field);
+
+                       // increment pc
+                       pc++;
+                       ig.Emit (OpCodes.Ldarg_0);
+                       IntConstant.EmitInt (ig, pc);
+                       ig.Emit (OpCodes.Stfld, pc_field);
+                       
+                       // Return ok.
+                       ig.Emit (OpCodes.Ldc_I4_1);
+                       ig.Emit (OpCodes.Ret);
+                       
+                       Label resume_point = ig.DefineLabel ();
+                       ig.MarkLabel (resume_point);
+                       resume_labels.Add (resume_point);
+               }
+
+               void ComputeConstructorTypes (out Type [] constructor_types, out Parameters constructor_parameters)
+               {
+                       bool is_static =  (modifiers & Modifiers.STATIC) != 0;
+                       
+                       if (is_static && parameters.Count == 0){
+                               constructor_types = TypeManager.NoTypes;
+                               constructor_parameters = Parameters.EmptyReadOnlyParameters;
+                               return;
+                       }
+
+                       int count = (is_static ? 0 : 1) + parameters.Count;
+                       constructor_types = new Type [count];
+                       Parameter [] pars = new Parameter [count];
+                       constructor_parameters = new Parameters (pars, null, loc);
+                       
+                       int i = 0;
+                       if (!is_static){
+                               constructor_types [0] = container.TypeBuilder;
+
+                               Parameter THIS = new Parameter (
+                                       new TypeExpr (container.TypeBuilder, loc), "this", Parameter.Modifier.NONE, null);
+                               pars [0] = THIS;
+                               i++;
+                       }
+
+                       for (int j = 0; j < parameters.Count; j++, i++){
+                               Type partype = parameters.ParameterType (j);
+                               
+                               pars [i] = new Parameter (new TypeExpr (partype, loc),
+                                                         parameters.ParameterName (j),
+                                                         Parameter.Modifier.NONE, null);
+                               constructor_types [i] = partype;
+                       }
+               }
+               
+               //
+               // Creates the IEnumerator Proxy class
+               //
+               void MakeEnumeratorProxy ()
+               {
+                       Type [] proxy_base_interfaces = new Type [2];
+                       proxy_base_interfaces [0] = TypeManager.ienumerator_type;
+                       proxy_base_interfaces [1] = TypeManager.idisposable_type;
+                       TypeBuilder container_builder = container.TypeBuilder;
+
+                       //
+                       // Create the class
+                       //
+                       enumerator_proxy_class = container_builder.DefineNestedType (
+                               MakeProxyName (), TypeAttributes.AutoLayout | TypeAttributes.Class |TypeAttributes.NestedPublic,
+                               TypeManager.object_type, proxy_base_interfaces);
+
+                       TypeManager.RegisterBuilder (enumerator_proxy_class, proxy_base_interfaces);
+
+                       //
+                       // Define our fields
+                       //
+                       pc_field = enumerator_proxy_class.DefineField ("PC", TypeManager.int32_type, FieldAttributes.Private);
+                       current_field = enumerator_proxy_class.DefineField ("current", IteratorType, FieldAttributes.Private);
+                       if ((modifiers & Modifiers.STATIC) == 0)
+                               this_field = enumerator_proxy_class.DefineField ("THIS", container.TypeBuilder, FieldAttributes.Private);
+
+                       parameter_fields = new FieldBuilder [parameters.Count];
+                       for (int i = 0; i < parameters.Count; i++){
+                               parameter_fields [i] = enumerator_proxy_class.DefineField (
+                                       String.Format ("p{0}_{1}", i, parameters.ParameterName (i)),
+                                       parameters.ParameterType (i), FieldAttributes.Private);
+                       }
+                       
+                       //
+                       // Define a constructor 
+                       //
+                       // FIXME: currently its parameterless
+                       Type [] constructor_types;
+                       Parameters constructor_parameters;
+
+                       ComputeConstructorTypes (out constructor_types, out constructor_parameters);
+                       
+                       enumerator_proxy_constructor = enumerator_proxy_class.DefineConstructor (
+                               MethodAttributes.Public | MethodAttributes.HideBySig |
+                               MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
+                               CallingConventions.HasThis, constructor_types);
+                       InternalParameters parameter_info = new InternalParameters (constructor_types, constructor_parameters);
+                       TypeManager.RegisterMethod (enumerator_proxy_constructor, parameter_info, constructor_types);
+
+                       //
+                       // Our constructor
+                       //
+                       ILGenerator ig = enumerator_proxy_constructor.GetILGenerator ();
+                       ig.Emit (OpCodes.Ldarg_0);
+                       ig.Emit (OpCodes.Call, TypeManager.object_ctor);
+
+                       int arg_start;
+                       if (this_field != null){
+                               arg_start = 2;
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ig.Emit (OpCodes.Ldarg_1);
+                               ig.Emit (OpCodes.Stfld, this_field);
+                       } else {
+                               arg_start = 1;
+                       }
+                       for (int i = 0; i < parameters.Count; i++){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ParameterReference.EmitLdArg (ig, i + arg_start);
+                               ig.Emit (OpCodes.Stfld, parameter_fields [i]);
+                       }
+                       ig.Emit (OpCodes.Ret);
+               }
+
+               //
+               // Creates the IEnumerable proxy class
+               //
+               void MakeEnumerableProxy ()
+               {
+                       TypeBuilder container_builder = container.TypeBuilder;
+                       Type [] proxy_base_interfaces = new Type [1];
+                       proxy_base_interfaces [0] = TypeManager.ienumerable_type;
+
+                       //
+                       // Creates the Enumerable proxy class.
+                       //
+                       enumerable_proxy_class = container_builder.DefineNestedType (
+                               MakeProxyName (), TypeAttributes.AutoLayout | TypeAttributes.Class |TypeAttributes.NestedPublic,
+                               TypeManager.object_type, proxy_base_interfaces);
+
+                       //
+                       // Constructor
+                       //
+                       Type [] constructor_types;
+                       Parameters constructor_parameters;
+
+                       ComputeConstructorTypes (out constructor_types, out constructor_parameters);
+                       if ((modifiers & Modifiers.STATIC) == 0){
+                               enumerable_this_field = enumerable_proxy_class.DefineField (
+                                       "THIS", container.TypeBuilder, FieldAttributes.Private);
+                       }
+                       enumerable_parameter_fields = new FieldBuilder [parameters.Count];
+                       for (int i = 0; i < parameters.Count; i++){
+                               enumerable_parameter_fields [i] = enumerable_proxy_class.DefineField (
+                                       String.Format ("p{0}_{1}", i, parameters.ParameterName (i)),
+                                       parameters.ParameterType (i), FieldAttributes.Private);
+                       }
+                       
+                       enumerable_proxy_constructor = enumerable_proxy_class.DefineConstructor (
+                               MethodAttributes.Public | MethodAttributes.HideBySig |
+                               MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
+                               CallingConventions.HasThis, constructor_types);
+                       InternalParameters parameter_info = new InternalParameters (constructor_types, constructor_parameters);
+                       TypeManager.RegisterMethod (enumerable_proxy_constructor, parameter_info, constructor_types);
+                       
+                       ILGenerator ig = enumerable_proxy_constructor.GetILGenerator ();
+                       ig.Emit (OpCodes.Ldarg_0);
+                       ig.Emit (OpCodes.Call, TypeManager.object_ctor);
+
+                       int first_arg;
+                       if (enumerable_this_field != null){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ig.Emit (OpCodes.Ldarg_1);
+                               ig.Emit (OpCodes.Stfld, enumerable_this_field);
+                               first_arg = 2;
+                       } else
+                               first_arg = 1;
+                       
+                       for (int i = 0; i < parameters.Count; i++){
+                               ig.Emit (OpCodes.Ldarg_0);
+                               ParameterReference.EmitLdArg (ig, i + first_arg);
+                               ig.Emit (OpCodes.Stfld, enumerable_parameter_fields [i]);
+                       }
+                       ig.Emit (OpCodes.Ret);
+               }
+
+               //
+               // Populates the Enumerator Proxy class
+               //
+               void PopulateProxy ()
+               {
+                       RootContext.RegisterHelperClass (enumerator_proxy_class);
+                       
+                       Create_MoveNext ();
+                       Create_Reset ();
+                       Create_Current ();
+                       Create_Dispose ();
+
+                       if (return_type == TypeManager.ienumerable_type){
+                               Create_GetEnumerator ();
+                               RootContext.RegisterHelperClass (enumerable_proxy_class);
+                       }
+               }
+               
+
+               //
+               // This is invoked by the EmitCode hook
+               //
+               void SetupIterator ()
+               {
+                       PopulateProxy ();
+               }
+
+               //
+               // Our constructor
+               //
+               public IteratorHandler (string name, TypeContainer container, Type return_type, Type [] param_types,
+                                       InternalParameters parameters, int modifiers, Location loc)
+               {
+                       this.name = name;
+                       this.container = container;
+                       this.return_type = return_type;
+                       this.param_types = param_types;
+                       this.parameters = parameters;
+                       this.modifiers = modifiers;
+                       this.loc = loc;
+
+                       IteratorType = TypeManager.object_type;
+                       
+                       RootContext.EmitCodeHook += new RootContext.Hook (SetupIterator);
+               }
+
+               //
+               // This class is just an expression that evaluates to a type, and the
+               // type is our internal proxy class.  Used in the generated new body
+               // of the original method
+               //
+               class NewInnerType : Expression {
+                       IteratorHandler handler;
+                       
+                       public NewInnerType (IteratorHandler handler, Location l) 
+                       {
+                               this.handler = handler;
+                               eclass = ExprClass.Value;
+                               loc = l;
+                       }
+
+                       public override Expression DoResolve (EmitContext ec)
+                       {
+                               // Create the proxy class type.
+                               handler.MakeEnumeratorProxy ();
+
+                               if (handler.return_type == TypeManager.ienumerable_type)
+                                       handler.MakeEnumerableProxy ();
+
+                               type = handler.return_type;
+                               return this;
+                       }
+
+                       public override Expression ResolveAsTypeStep (EmitContext ec)
+                       {
+                               return DoResolve (ec);
+                       }
+
+                       public override void Emit (EmitContext ec)
+                       {
+                               handler.LoadArgs (ec.ig);
+                               
+                               if (handler.return_type == TypeManager.ienumerable_type)
+                                       ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) handler.enumerable_proxy_constructor);
+                               else 
+                                       ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) handler.enumerator_proxy_constructor);
+                       }
+               }
+
+               //
+               // This return statement tricks return into not flagging an error for being
+               // used in a Yields method
+               //
+               class NoCheckReturn : Return {
+                       public NoCheckReturn (Expression expr, Location loc) : base (expr, loc)
+                       {
+                       }
+                       
+                       public override bool Resolve (EmitContext ec)
+                       {
+                               ec.InIterator = false;
+                               bool ret_val = base.Resolve (ec);
+                               ec.InIterator = true;
+
+                               return ret_val;
+                       }
+               }
+               
+               //
+               // Returns the new block for the method, or null on failure
+               //
+               public Block Setup (Block block)
+               {
+                       if (return_type != TypeManager.ienumerator_type &&
+                           return_type != TypeManager.ienumerable_type){
+                               Report.Error (
+                                       -205, loc, String.Format (
+                                               "The method `{0}' contains a yield statement, but has an invalid return type for an iterator",
+                                               name));
+                               return null;
+                       }
+
+                       for (int i = 0; i < parameters.Count; i++){
+                               Parameter.Modifier mod = parameters.ParameterModifier (i);
+                               if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){
+                                       Report.Error (-207, loc, String.Format (
+                                                             "Parameter {0} of `{1}' is {2} and not allowed for an iterator method",
+                                                             i+1, name, parameters.ParameterDesc (i)));
+                                       return null;
+                               }
+                       }
+
+                       original_block = block;
+                       Block b = new Block (null);
+
+                       // return new InnerClass ()
+                       b.AddStatement (new NoCheckReturn (new NewInnerType (this, loc), loc));
+                       return b;
+               }
+       }
+}
+
diff --git a/mcs/gmcs/literal.cs b/mcs/gmcs/literal.cs
new file mode 100755 (executable)
index 0000000..051f902
--- /dev/null
@@ -0,0 +1,205 @@
+//
+// literal.cs: Literal representation for the IL tree.
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc.
+//
+//
+// Notice that during parsing we create objects of type Literal, but the
+// types are not loaded (thats why the Resolve method has to assign the
+// type at that point).
+//
+// Literals differ from the constants in that we know we encountered them
+// as a literal in the source code (and some extra rules apply there) and
+// they have to be resolved (since during parsing we have not loaded the
+// types yet) while constants are created only after types have been loaded
+// and are fully resolved when born.
+//
+
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Mono.CSharp {
+
+       public class NullLiteral : Constant {
+               public static readonly NullLiteral Null;
+
+               static NullLiteral ()
+               {
+                       Null = new NullLiteral ();
+               }
+                       
+               public NullLiteral ()
+               {
+                       eclass = ExprClass.Value;
+               }
+               
+               override public string AsString ()
+               {
+                       return "null";
+               }
+
+               public override object GetValue ()
+               {
+                       return null;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.object_type;
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldnull);
+               }
+       }
+
+       //
+       // A null literal in a pointer context
+       //
+       public class NullPointer : NullLiteral {
+               public new static readonly NullLiteral Null;
+
+               static NullPointer ()
+               {
+                       Null = new NullPointer ();
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                               
+                       ig.Emit (OpCodes.Ldc_I4_0);
+                       ig.Emit (OpCodes.Conv_U);
+               }
+       }
+
+       public class BoolLiteral : BoolConstant {
+               public BoolLiteral (bool val) : base (val)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.bool_type;
+                       return this;
+               }
+       }
+
+       public class CharLiteral : CharConstant {
+               public CharLiteral (char c) : base (c)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.char_type;
+                       return this;
+               }
+       }
+
+       public class IntLiteral : IntConstant {
+               public IntLiteral (int l) : base (l)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.int32_type;
+                       return this;
+               }
+       }
+
+       public class UIntLiteral : UIntConstant {
+               public UIntLiteral (uint l) : base (l)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.uint32_type;
+                       return this;
+               }
+       }
+       
+       public class LongLiteral : LongConstant {
+               public LongLiteral (long l) : base (l)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.int64_type;
+
+                       return this;
+               }
+       }
+
+       public class ULongLiteral : ULongConstant {
+               public ULongLiteral (ulong l) : base (l)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.uint64_type;
+                       return this;
+               }
+       }
+       
+       public class FloatLiteral : FloatConstant {
+               
+               public FloatLiteral (float f) : base (f)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.float_type;
+                       return this;
+               }
+       }
+
+       public class DoubleLiteral : DoubleConstant {
+               public DoubleLiteral (double d) : base (d)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.double_type;
+
+                       return this;
+               }
+       }
+
+       public class DecimalLiteral : DecimalConstant {
+               public DecimalLiteral (decimal d) : base (d)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.decimal_type;
+                       return this;
+               }
+       }
+
+       public class StringLiteral : StringConstant {
+               public StringLiteral (string s) : base (s)
+               {
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       type = TypeManager.string_type;
+
+                       return this;
+               }
+       }
+}
diff --git a/mcs/gmcs/location.cs b/mcs/gmcs/location.cs
new file mode 100644 (file)
index 0000000..aeffec1
--- /dev/null
@@ -0,0 +1,225 @@
+//
+// location.cs: Keeps track of the location of source code entity
+//
+// Author:
+//   Miguel de Icaza
+//
+// (C) 2001 Ximian, Inc.
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Diagnostics.SymbolStore;
+
+namespace Mono.CSharp {
+       /// <summary>
+       ///   This is one single source file.
+       /// </summary>
+       /// <remarks>
+       ///   This is intentionally a class and not a struct since we need
+       ///   to pass this by reference.
+       /// </remarks>
+       public sealed class SourceFile {
+               public readonly string Name;
+               public readonly string Path;
+               public readonly int Index;
+               public ISymbolDocumentWriter SymbolDocument;
+
+               public SourceFile (string name, string path, int index)
+               {
+                       this.Index = index;
+                       this.Name = name;
+                       this.Path = path;
+               }
+       }
+
+       /// <summary>
+       ///   Keeps track of the location in the program
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   This uses a compact representation and a couple of auxiliary
+       ///   structures to keep track of tokens to (file,line) mappings.
+       ///
+       ///   We could probably also keep track of columns by storing those
+       ///   in 8 bits (and say, map anything after char 255 to be `255+').
+       /// </remarks>
+       public struct Location {
+               public int token; 
+
+               static ArrayList source_list;
+               static Hashtable source_files;
+               static int source_bits;
+               static int source_mask;
+               static int source_count;
+               static int module_base;
+               static int current_source;
+
+               public readonly static Location Null;
+               
+               static Location ()
+               {
+                       source_files = new Hashtable ();
+                       source_list = new ArrayList ();
+                       current_source = 0;
+                       module_base = 0;
+                       Null.token = 0;
+               }
+
+               // <summary>
+               //   This must be called before parsing/tokenizing any files.
+               // </summary>
+               static public void AddFile (string name)
+               {
+                       string path = Path.GetFullPath (name);
+
+                       if (source_files.Contains (path)){
+                               Report.Error (
+                                       1516,
+                                       "Source file `" + name + "' specified multiple times");
+                               Environment.Exit (1);
+                       }
+
+                       source_files.Add (path, ++source_count);
+                       source_list.Add (new SourceFile (name, path, source_count));
+               }
+
+               static public SourceFile[] SourceFiles {
+                       get {
+                               SourceFile[] retval = new SourceFile [source_list.Count];
+                               source_list.CopyTo (retval, 0);
+                               return retval;
+                       }
+               }
+
+               static int log2 (int number)
+               {
+                       int bits = 0;
+                       while (number > 0) {
+                               bits++;
+                               number /= 2;
+                       }
+
+                       return bits;
+               }
+
+               // <summary>
+               //   After adding all source files we want to compile with AddFile(), this method
+               //   must be called to `reserve' an appropriate number of bits in the token for the
+               //   source file.  We reserve some extra space for files we encounter via #line
+               //   directives while parsing.
+               // </summary>
+               static public void Initialize ()
+               {
+                       source_bits = log2 (source_list.Count) + 2;
+                       source_mask = (1 << source_bits) - 1;
+               }
+
+               // <remarks>
+               //   This is used when we encounter a #line preprocessing directive.
+               // </remarks>
+               static public SourceFile LookupFile (string name)
+               {
+                       string path = Path.GetFullPath (name);
+
+                       if (!source_files.Contains (path)) {
+                               if (source_count >= (1 << source_bits))
+                                       return new SourceFile (name, path, 0);
+
+                               source_files.Add (path, ++source_count);
+                               SourceFile retval = new SourceFile (name, path, source_count);
+                               source_list.Add (retval);
+                               return retval;
+                       }
+
+                       int index = (int) source_files [path];
+                       return (SourceFile) source_list [index - 1];
+               }
+
+               static public void Push (SourceFile file)
+               {
+                       current_source = file.Index;
+                       module_base = current_source << source_bits;
+               }
+
+               // <remarks>
+               //   If we're compiling with debugging support, this is called between parsing and
+               //   code generation to register all the source files with the symbol writer.           //
+               // </remarks>
+               static public void DefineSymbolDocuments (SymbolWriter symwriter)
+               {
+                       foreach (SourceFile file in source_list)
+                               file.SymbolDocument = symwriter.DefineDocument (file.Path);
+               }
+               
+               public Location (int row)
+               {
+                       if (row < 0)
+                               token = 0;
+                       else
+                               token = current_source + (row << source_bits);
+               }
+
+               public override string ToString ()
+               {
+                       return Name + ": (" + Row + ")";
+               }
+               
+               /// <summary>
+               ///   Whether the Location is Null
+               /// </summary>
+               static public bool IsNull (Location l)
+               {
+                       return l.token == 0;
+               }
+
+               public string Name {
+                       get {
+                               int index = token & source_mask;
+                               if ((token == 0) || (index == 0))
+                                       return "Internal";
+
+                               SourceFile file = (SourceFile) source_list [index - 1];
+                               return file.Name;
+                       }
+               }
+
+               public int Row {
+                       get {
+                               if (token == 0)
+                                       return 1;
+
+                               return token >> source_bits;
+                       }
+               }
+
+               public int File {
+                       get {
+                               return token & source_mask;
+                       }
+               }
+
+               // The ISymbolDocumentWriter interface is used by the symbol writer to
+               // describe a single source file - for each source file there's exactly
+               // one corresponding ISymbolDocumentWriter instance.
+               //
+               // This class has an internal hash table mapping source document names
+               // to such ISymbolDocumentWriter instances - so there's exactly one
+               // instance per document.
+               //
+               // This property returns the ISymbolDocumentWriter instance which belongs
+               // to the location's source file.
+               //
+               // If we don't have a symbol writer, this property is always null.
+               public ISymbolDocumentWriter SymbolDocument {
+                       get {
+                               int index = token & source_mask;
+                               if (index == 0)
+                                       return null;
+                               SourceFile file = (SourceFile) source_list [index - 1];
+                               return file.SymbolDocument;
+                       }
+               }
+       }
+}
diff --git a/mcs/gmcs/mcs.exe.config b/mcs/gmcs/mcs.exe.config
new file mode 100644 (file)
index 0000000..cf61d4b
--- /dev/null
@@ -0,0 +1,11 @@
+<configuration>\r
+  <system.diagnostics>\r
+    <trace autoflush="true" indentsize="4">\r
+      <listeners>\r
+        <add name="compilerLogListener" type="System.Diagnostics.TextWriterTraceListener,System"\r
+             initializeData="mcs.log" />\r
+        <remove type="System.Diagnostics.DefaultTraceListener,System"/>\r
+      </listeners>\r
+    </trace>\r
+  </system.diagnostics>\r
+</configuration>\r
diff --git a/mcs/gmcs/modifiers.cs b/mcs/gmcs/modifiers.cs
new file mode 100755 (executable)
index 0000000..edbc6d1
--- /dev/null
@@ -0,0 +1,246 @@
+//
+// modifiers.cs: Modifier handling.
+// 
+using System;
+using System.Reflection;
+
+namespace Mono.CSharp {
+       public class Modifiers {
+
+               //
+               // The ordering of the following 4 constants
+               // has been carefully done.
+               //
+               public const int PROTECTED = 0x0001;
+               public const int PUBLIC    = 0x0002;
+               public const int PRIVATE   = 0x0004;
+               public const int INTERNAL  = 0x0008;
+               public const int NEW       = 0x0010;
+               public const int ABSTRACT  = 0x0020;
+               public const int SEALED    = 0x0040;
+               public const int STATIC    = 0x0080;
+               public const int READONLY  = 0x0100;
+               public const int VIRTUAL   = 0x0200;
+               public const int OVERRIDE  = 0x0400;
+               public const int EXTERN    = 0x0800;
+               public const int VOLATILE  = 0x1000;
+               public const int UNSAFE    = 0x2000;
+               public const int TOP       = 0x2000;
+
+               //
+               // We use this internally to flag that the method contains an iterator
+               //
+               public const int METHOD_YIELDS = 0x8000;
+
+               public const int Accessibility =
+                       PUBLIC | PROTECTED | INTERNAL | PRIVATE;
+               
+               static public string Name (int i)
+               {
+                       string s = "";
+                       
+                       switch (i) {
+                       case Modifiers.NEW:
+                               s = "new"; break;
+                       case Modifiers.PUBLIC:
+                               s = "public"; break;
+                       case Modifiers.PROTECTED:
+                               s = "protected"; break;
+                       case Modifiers.INTERNAL:
+                               s = "internal"; break;
+                       case Modifiers.PRIVATE:
+                               s = "private"; break;
+                       case Modifiers.ABSTRACT:
+                               s = "abstract"; break;
+                       case Modifiers.SEALED:
+                               s = "sealed"; break;
+                       case Modifiers.STATIC:
+                               s = "static"; break;
+                       case Modifiers.READONLY:
+                               s = "readonly"; break;
+                       case Modifiers.VIRTUAL:
+                               s = "virtual"; break;
+                       case Modifiers.OVERRIDE:
+                               s = "override"; break;
+                       case Modifiers.EXTERN:
+                               s = "extern"; break;
+                       case Modifiers.VOLATILE:
+                               s = "volatile"; break;
+                       }
+
+                       return s;
+               }
+
+               public static TypeAttributes TypeAttr (int mod_flags, bool is_toplevel)
+               {
+                       TypeAttributes t = 0;
+
+                       if (is_toplevel){
+                               if ((mod_flags & PUBLIC) != 0)
+                                       t |= TypeAttributes.Public;
+                               if ((mod_flags & PRIVATE) != 0)
+                                       t |= TypeAttributes.NotPublic;
+                       } else {
+                               if ((mod_flags & PUBLIC) != 0)
+                                       t |= TypeAttributes.NestedPublic;
+                               if ((mod_flags & PRIVATE) != 0)
+                                       t |= TypeAttributes.NestedPrivate;
+                               if ((mod_flags & PROTECTED) != 0 && (mod_flags & INTERNAL) != 0)
+                                       t |= TypeAttributes.NestedFamORAssem;
+                               if ((mod_flags & PROTECTED) != 0)
+                                       t |= TypeAttributes.NestedFamily;
+                               if ((mod_flags & INTERNAL) != 0)
+                                       t |= TypeAttributes.NestedAssembly;
+                       }
+                       
+                       if ((mod_flags & SEALED) != 0)
+                               t |= TypeAttributes.Sealed;
+                       if ((mod_flags & ABSTRACT) != 0)
+                               t |= TypeAttributes.Abstract;
+
+                       return t;
+               }
+               
+               public static TypeAttributes TypeAttr (int mod_flags, TypeContainer caller)
+               {
+                       TypeAttributes t = TypeAttr (mod_flags, caller.IsTopLevel);
+
+                       // If we do not have static constructors, static methods
+                       // can be invoked without initializing the type.
+                       if (!caller.HaveStaticConstructor)
+                               t |= TypeAttributes.BeforeFieldInit;
+                               
+                       return t;
+               }
+
+               public static FieldAttributes FieldAttr (int mod_flags)
+               {
+                       FieldAttributes fa = 0;
+
+                       if ((mod_flags & PUBLIC) != 0)
+                               fa |= FieldAttributes.Public;
+                       if ((mod_flags & PRIVATE) != 0)
+                               fa |= FieldAttributes.Private;
+                       if ((mod_flags & PROTECTED) != 0){
+                               if ((mod_flags & INTERNAL) != 0)
+                                       fa |= FieldAttributes.FamORAssem;
+                               else 
+                                       fa |= FieldAttributes.Family;
+                       } else {
+                               if ((mod_flags & INTERNAL) != 0)
+                                       fa |= FieldAttributes.Assembly;
+                       }
+                       
+                       if ((mod_flags & STATIC) != 0)
+                               fa |= FieldAttributes.Static;
+                       if ((mod_flags & READONLY) != 0)
+                               fa |= FieldAttributes.InitOnly;
+
+                       return fa;
+               }
+
+               public static MethodAttributes MethodAttr (int mod_flags)
+               {
+                       MethodAttributes ma = 0;
+
+                       if ((mod_flags & PUBLIC) != 0)
+                               ma |= MethodAttributes.Public;
+                       if ((mod_flags & PRIVATE) != 0)
+                               ma |= MethodAttributes.Private;
+                       if ((mod_flags & PROTECTED) != 0){
+                               if ((mod_flags & INTERNAL) != 0)
+                                       ma |= MethodAttributes.FamORAssem;
+                               else 
+                                       ma |= MethodAttributes.Family;
+                       } else {
+                               if ((mod_flags & INTERNAL) != 0)
+                                       ma |= MethodAttributes.Assembly;
+                       }
+
+                       if ((mod_flags & STATIC) != 0)
+                               ma |= MethodAttributes.Static;
+                       if ((mod_flags & ABSTRACT) != 0){
+                               ma |= MethodAttributes.Abstract | MethodAttributes.Virtual |
+                                       MethodAttributes.HideBySig;
+                       }
+                       if ((mod_flags & SEALED) != 0)
+                               ma |= MethodAttributes.Final;
+
+                       if ((mod_flags & VIRTUAL) != 0)
+                               ma |= MethodAttributes.Virtual;
+
+                       if ((mod_flags & OVERRIDE) != 0)
+                               ma |= MethodAttributes.Virtual | MethodAttributes.HideBySig;
+                       else {
+                               if ((ma & MethodAttributes.Virtual) != 0)
+                                       ma |= MethodAttributes.NewSlot;
+                       }
+                       
+                       if ((mod_flags & NEW) != 0)
+                               ma |= MethodAttributes.HideBySig;
+                       
+                       return ma;
+               }
+
+               // <summary>
+               //   Checks the object @mod modifiers to be in @allowed.
+               //   Returns the new mask.  Side effect: reports any
+               //   incorrect attributes. 
+               // </summary>
+               public static int Check (int allowed, int mod, int def_access, Location l)
+               {
+                       int invalid_flags  = (~allowed) & mod;
+                       int i;
+
+                       if (invalid_flags == 0){
+                               int a = mod;
+
+                               if ((mod & Modifiers.UNSAFE) != 0){
+                                       if (!RootContext.Unsafe){
+                                               Report.Error (227, l,
+                                                             "Unsafe code requires the --unsafe command " +
+                                                             "line option to be specified");
+                                       }
+                               }
+                               
+                               //
+                               // If no accessibility bits provided
+                               // then provide the defaults.
+                               //
+                               if ((mod & Accessibility) == 0){
+                                       mod |= def_access;
+                                       return mod;
+                               }
+
+                               //
+                               // Make sure that no conflicting accessibility
+                               // bits have been set.  Protected+Internal is
+                               // allowed, that is why they are placed on bits
+                               // 1 and 4 (so the shift 3 basically merges them)
+                               //
+                               a &= 15;
+                               a |= (a >> 3);
+                               a = ((a & 2) >> 1) + (a & 5);
+                               a = ((a & 4) >> 2) + (a & 3);
+                               if (a > 1)
+                                       Report.Error (107, l, "More than one protection modifier specified");
+                               
+                               return mod;
+                       }
+                       
+                       for (i = 1; i < TOP; i <<= 1){
+                               if ((i & invalid_flags) == 0)
+                                       continue;
+
+                               Error_InvalidModifier (l, Name (i));
+                       }
+
+                       return allowed & mod;
+               }
+
+               public static void Error_InvalidModifier (Location l, string name)
+               {
+                       Report.Error (106, l, "the modifier " + name + " is not valid for this item");
+               }
+       }
+}
diff --git a/mcs/gmcs/namespace.cs b/mcs/gmcs/namespace.cs
new file mode 100755 (executable)
index 0000000..e517d62
--- /dev/null
@@ -0,0 +1,511 @@
+//
+// namespace.cs: Tracks namespaces
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc.
+//
+using System;
+using System.Collections;
+using Mono.Languages;
+
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///   Keeps track of the namespaces defined in the C# code.
+       /// </summary>
+       public class Namespace {
+               static ArrayList all_namespaces = new ArrayList ();
+               
+               Namespace parent;
+               string name, fullname;
+               ArrayList entries;
+               Hashtable namespaces;
+
+               /// <summary>
+               ///   Constructor Takes the current namespace and the
+               ///   name.  This is bootstrapped with parent == null
+               ///   and name = ""
+               /// </summary>
+               public Namespace (Namespace parent, string name)
+               {
+                       this.name = name;
+                       this.parent = parent;
+
+                       string pname = parent != null ? parent.Name : "";
+                               
+                       if (pname == "")
+                               fullname = name;
+                       else
+                               fullname = parent.Name + "." + name;
+
+                       entries = new ArrayList ();
+                       namespaces = new Hashtable ();
+
+                       all_namespaces.Add (this);
+               }
+
+               public static Namespace Root = new Namespace (null, "");
+
+               public Namespace GetNamespace (string name, bool create)
+               {
+                       int pos = name.IndexOf ('.');
+
+                       Namespace ns;
+                       string first;
+                       if (pos >= 0)
+                               first = name.Substring (0, pos);
+                       else
+                               first = name;
+
+                       ns = (Namespace) namespaces [first];
+                       if (ns == null) {
+                               if (!create)
+                                       return null;
+
+                               ns = new Namespace (this, first);
+                               namespaces.Add (first, ns);
+                       }
+
+                       if (pos >= 0)
+                               ns = ns.GetNamespace (name.Substring (pos + 1), create);
+
+                       return ns;
+               }
+
+               public static Namespace LookupNamespace (string name, bool create)
+               {
+                       return Root.GetNamespace (name, create);
+               }
+
+               public void AddNamespaceEntry (NamespaceEntry entry)
+               {
+                       entries.Add (entry);
+               }
+
+               static public ArrayList UserDefinedNamespaces {
+                       get {
+                               return all_namespaces;
+                       }
+               }
+
+               /// <summary>
+               ///   The qualified name of the current namespace
+               /// </summary>
+               public string Name {
+                       get {
+                               return fullname;
+                       }
+               }
+
+               /// <summary>
+               ///   The parent of this namespace, used by the parser to "Pop"
+               ///   the current namespace declaration
+               /// </summary>
+               public Namespace Parent {
+                       get {
+                               return parent;
+                       }
+               }
+
+               public static void DefineNamespaces (SymbolWriter symwriter)
+               {
+                       foreach (Namespace ns in all_namespaces) {
+                               foreach (NamespaceEntry entry in ns.entries)
+                                       entry.DefineNamespace (symwriter);
+                       }
+               }
+
+               /// <summary>
+               ///   Used to validate that all the using clauses are correct
+               ///   after we are finished parsing all the files.  
+               /// </summary>
+               public static void VerifyUsing ()
+               {
+                       foreach (Namespace ns in all_namespaces) {
+                               foreach (NamespaceEntry entry in ns.entries)
+                                       entry.VerifyUsing ();
+                       }
+               }
+
+               public override string ToString ()
+               {
+                       if (this == Root)
+                               return "Namespace (<root>)";
+                       else
+                               return String.Format ("Namespace ({0})", Name);
+               }
+       }
+
+       public class NamespaceEntry
+       {
+               Namespace ns;
+               NamespaceEntry parent, implicit_parent;
+               SourceFile file;
+               int symfile_id;
+               Hashtable aliases;
+               ArrayList using_clauses;
+               public bool DeclarationFound = false;
+
+               //
+               // This class holds the location where a using definition is
+               // done, and whether it has been used by the program or not.
+               //
+               // We use this to flag using clauses for namespaces that do not
+               // exist.
+               //
+               public class UsingEntry {
+                       public readonly string Name;
+                       public readonly NamespaceEntry NamespaceEntry;
+                       public readonly Location Location;
+                       
+                       public UsingEntry (NamespaceEntry entry, string name, Location loc)
+                       {
+                               Name = name;
+                               NamespaceEntry = entry;
+                               Location = loc;
+                       }
+
+                       Namespace resolved_ns;
+
+                       public Namespace Resolve ()
+                       {
+                               if (resolved_ns != null)
+                                       return resolved_ns;
+
+                               Namespace curr_ns = NamespaceEntry.NS;
+                               while ((curr_ns != null) && (resolved_ns == null)) {
+                                       string full_name = DeclSpace.MakeFQN (curr_ns.Name, Name);
+                                       resolved_ns = curr_ns.GetNamespace (Name, false);
+
+                                       if (resolved_ns == null)
+                                               curr_ns = curr_ns.Parent;
+                               }
+
+                               return resolved_ns;
+                       }
+               }
+
+               public class AliasEntry {
+                       public readonly string Name;
+                       public readonly string Alias;
+                       public readonly NamespaceEntry NamespaceEntry;
+                       public readonly Location Location;
+                       
+                       public AliasEntry (NamespaceEntry entry, string name, string alias, Location loc)
+                       {
+                               Name = name;
+                               Alias = alias;
+                               NamespaceEntry = entry;
+                               Location = loc;
+                       }
+
+                       object resolved;
+
+                       public object Resolve ()
+                       {
+                               if (resolved != null)
+                                       return resolved;
+
+                               int pos = Alias.IndexOf ('.');
+                               if (pos >= 0) {
+                                       string first = Alias.Substring (0, pos);
+                               }
+
+                               NamespaceEntry curr_ns = NamespaceEntry;
+                               while ((curr_ns != null) && (resolved == null)) {
+                                       string full_name = DeclSpace.MakeFQN (curr_ns.Name, Alias);
+                                       resolved = curr_ns.LookupName (Alias);
+
+                                       if (resolved == null)
+                                               curr_ns = curr_ns.Parent;
+                               }
+
+                               return resolved;
+                       }
+               }
+
+               public NamespaceEntry (NamespaceEntry parent, SourceFile file, string name)
+                       : this (parent, file, name, false)
+               { }
+
+               protected NamespaceEntry (NamespaceEntry parent, SourceFile file, string name, bool is_implicit)
+               {
+                       this.parent = parent;
+                       this.file = file;
+                       this.IsImplicit = is_implicit;
+                       this.ID = ++next_id;
+
+                       if (!is_implicit && (parent != null))
+                               ns = parent.NS.GetNamespace (name, true);
+                       else if (name != null)
+                               ns = Namespace.LookupNamespace (name, true);
+                       else
+                               ns = Namespace.Root;
+                       ns.AddNamespaceEntry (this);
+
+                       if ((parent != null) && (parent.NS != ns.Parent))
+                               implicit_parent = new NamespaceEntry (parent, file, ns.Parent.Name, true);
+                       else
+                               implicit_parent = parent;
+               }
+
+               static int next_id = 0;
+               public readonly int ID;
+               public readonly bool IsImplicit;
+
+               public string Name {
+                       get {
+                               return ns.Name;
+                       }
+               }
+
+               public Namespace NS {
+                       get {
+                               return ns;
+                       }
+               }
+
+               public NamespaceEntry Parent {
+                       get {
+                               return parent;
+                       }
+               }
+
+               public NamespaceEntry ImplicitParent {
+                       get {
+                               return implicit_parent;
+                       }
+               }
+
+               /// <summary>
+               ///   Records a new namespace for resolving name references
+               /// </summary>
+               public void Using (string ns, Location loc)
+               {
+                       if (DeclarationFound){
+                               Report.Error (1529, loc, "A using clause must precede all other namespace elements");
+                               return;
+                       }
+
+                       if (ns == Name)
+                               return;
+                       
+                       if (using_clauses == null)
+                               using_clauses = new ArrayList ();
+
+                       foreach (UsingEntry old_entry in using_clauses){
+                               if (old_entry.Name == ns){
+                                       Report.Warning (105, loc, "The using directive for '" + ns +
+                                                       "' appeared previously in this namespace");
+                                       return;
+                               }
+                       }
+                       
+                       UsingEntry ue = new UsingEntry (this, ns, loc);
+                       using_clauses.Add (ue);
+               }
+
+               public void UsingAlias (string alias, string namespace_or_type, Location loc)
+               {
+                       if (aliases == null)
+                               aliases = new Hashtable ();
+                       
+                       if (aliases.Contains (alias)){
+                               Report.Error (1537, loc, "The using alias `" + alias +
+                                             "' appeared previously in this namespace");
+                               return;
+                       }
+
+                       aliases [alias] = new AliasEntry (this, alias, namespace_or_type, loc);
+               }
+
+               protected AliasEntry GetAliasEntry (string alias)
+               {
+                       AliasEntry entry = null;
+
+                       if (aliases != null)
+                               entry = (AliasEntry) aliases [alias];
+                       if (entry == null && Parent != null)
+                               entry = Parent.GetAliasEntry (alias);
+
+                       return entry;
+               }
+
+               public string LookupAlias (string alias)
+               {
+                       AliasEntry entry = GetAliasEntry (alias);
+
+                       if (entry == null)
+                               return null;
+
+                       object resolved = entry.Resolve ();
+                       if (resolved == null)
+                               return null;
+                       else if (resolved is Namespace)
+                               return ((Namespace) resolved).Name;
+                       else
+                               return ((Type) resolved).FullName;
+               }
+
+               public object LookupName (string name)
+               {
+                       Namespace ns = Namespace.LookupNamespace (name, false);
+                       if (ns != null)
+                               return ns;
+
+                       int pos = name.IndexOf ('.');
+                       AliasEntry alias = null;
+                       if (pos >= 0) {
+                               string first = name.Substring (0, pos);
+                               string last = name.Substring (pos + 1);
+
+                               alias = GetAliasEntry (first);
+                               if (alias != null)
+                                       return LookupName (DeclSpace.MakeFQN (alias.Alias, last));
+                       }
+
+                       Type t = TypeManager.LookupType (name);
+                       if (t != null)
+                               return t;
+
+                       alias = GetAliasEntry (name);
+                       if (alias != null)
+                               return LookupName (alias.Alias);
+
+                       return null;
+               }
+               
+               public Namespace[] GetUsingTable ()
+               {
+                       ArrayList list = new ArrayList ();
+
+                       if (using_clauses == null)
+                               return new Namespace [0];
+
+                       foreach (UsingEntry ue in using_clauses) {
+                               Namespace using_ns = ue.Resolve ();
+                               if (using_ns == null)
+                                       continue;
+
+                               list.Add (using_ns);
+                       }
+
+                       Namespace[] retval = new Namespace [list.Count];
+                       list.CopyTo (retval, 0);
+                       return retval;
+               }
+
+               public void DefineNamespace (SymbolWriter symwriter)
+               {
+                       if (symfile_id != 0)
+                               return;
+                       if (parent != null)
+                               parent.DefineNamespace (symwriter);
+
+                       string[] using_list;
+                       if (using_clauses != null) {
+                               using_list = new string [using_clauses.Count];
+                               for (int i = 0; i < using_clauses.Count; i++)
+                                       using_list [i] = ((UsingEntry) using_clauses [i]).Name;
+                       } else {
+                               using_list = new string [0];
+                       }
+
+                       int parent_id = parent != null ? parent.symfile_id : 0;
+                       symfile_id = symwriter.DefineNamespace (ns.Name, file, using_list, parent_id);
+               }
+
+               public int SymbolFileID {
+                       get {
+                               return symfile_id;
+                       }
+               }
+
+               static void Msgtry (string s)
+               {
+                       Console.WriteLine ("    Try using -r:" + s);
+               }
+
+               protected void error246 (Location loc, string name)
+               {
+                       if (TypeManager.LookupType (name) != null)
+                               Report.Error (138, loc, "The using keyword only lets you specify a namespace, " +
+                                             "`" + name + "' is a class not a namespace.");
+                       else {
+                               Report.Error (246, loc, "The namespace `" + name +
+                                             "' can not be found (missing assembly reference?)");
+
+                               switch (name){
+                               case "Gtk": case "GtkSharp":
+                                       Msgtry ("gtk-sharp");
+                                       break;
+
+                               case "Gdk": case "GdkSharp":
+                                       Msgtry ("gdk-sharp");
+                                       break;
+
+                               case "Glade": case "GladeSharp":
+                                       Msgtry ("glade-sharp");
+                                       break;
+                                                       
+                               case "System.Drawing":
+                                       Msgtry ("System.Drawing");
+                                       break;
+                                                       
+                               case "System.Web.Services":
+                                       Msgtry ("System.Web.Services");
+                                       break;
+
+                               case "System.Web":
+                                       Msgtry ("System.Web");
+                                       break;
+                                                       
+                               case "System.Data":
+                                       Msgtry ("System.Data");
+                                       break;
+
+                               case "System.Windows.Forms":
+                                       Msgtry ("System.Windows.Forms");
+                                       break;
+                               }
+                       }
+               }
+
+               /// <summary>
+               ///   Used to validate that all the using clauses are correct
+               ///   after we are finished parsing all the files.  
+               /// </summary>
+               public void VerifyUsing ()
+               {
+                       if (using_clauses != null){
+                               foreach (UsingEntry ue in using_clauses){
+                                       if (ue.Resolve () != null)
+                                               continue;
+
+                                       error246 (ue.Location, ue.Name);
+                               }
+                       }
+
+                       if (aliases != null){
+                               foreach (DictionaryEntry de in aliases){
+                                       AliasEntry alias = (AliasEntry) de.Value;
+
+                                       if (alias.Resolve () != null)
+                                               continue;
+
+                                       error246 (alias.Location, alias.Alias);
+                               }
+                       }
+               }
+
+               public override string ToString ()
+               {
+                       if (NS == Namespace.Root)
+                               return "NamespaceEntry (<root>)";
+                       else
+                               return String.Format ("NamespaceEntry ({0},{1},{2})", Name, IsImplicit, ID);
+               }
+       }
+}
diff --git a/mcs/gmcs/old-code.cs b/mcs/gmcs/old-code.cs
new file mode 100755 (executable)
index 0000000..cb7c31a
--- /dev/null
@@ -0,0 +1,217 @@
+#else
+
+               bla bla bla
+               //
+               // This code is more conformant to the spec (it follows it step by step),
+               // but it has not been tested yet, and there is nothing here that is not
+               // caught by the above code.  But it might be a better foundation to improve
+               // on in the future
+               //
+               public ResolveTypeMemberAccess (EmitContext ec, Expression member_lookup,
+                                               Expression left, Location loc)
+               {
+                       if (member_lookup is TypeExpr){
+                               member_lookup.Resolve (ec);
+                               return member_lookup;
+                       }
+                       
+                       if (member_lookup is MethodGroupExpr){
+                               if (!mg.RemoveStaticMethods ()){
+                                       SimpleName.Error120 (loc, mg.Methods [0].Name); 
+                                       return null;
+                               }
+                               
+                               return member_lookup;
+                       }
+                       
+                       if (member_lookup is PropertyExpr){
+                               PropertyExpr pe = (PropertyExpr) member_lookup;
+                                       
+                                       if (!pe.IsStatic){
+                                               SimpleName.Error120 (loc, pe.PropertyInfo.Name);
+                                               return null;
+                                       }
+                                       return pe;
+                       }
+                       
+                       if (member_lookup is FieldExpr){
+                               FieldExpr fe = (FieldExpr) member_lookup;
+                               FieldInfo fi = fe.FieldInfo;
+                               
+                               if (fi is FieldBuilder) {
+                                       Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
+                                       
+                                       if (c != null) {
+                                               object o = c.LookupConstantValue (ec);
+                                               return Constantify (o, fi.FieldType);
+                                       }
+                               }
+                               
+                               if (fi.IsLiteral) {
+                                       Type t = fi.FieldType;
+                                       Type decl_type = fi.DeclaringType;
+                                       object o;
+                                       
+                                       if (fi is FieldBuilder)
+                                               o = TypeManager.GetValue ((FieldBuilder) fi);
+                                       else
+                                               o = fi.GetValue (fi);
+                                       
+                                       if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
+                                               Expression enum_member = MemberLookup (
+                                                       ec, decl_type, "value__", loc); 
+                                               
+                                               Enum en = TypeManager.LookupEnum (decl_type);
+                                               
+                                               Constant c;
+                                               if (en != null)
+                                                       c = Constantify (o, en.UnderlyingType);
+                                               else 
+                                                       c = Constantify (o, enum_member.Type);
+                                               
+                                               return new EnumConstant (c, decl_type);
+                                       }
+                                       
+                                       Expression exp = Constantify (o, t);
+                                       
+                                       return exp;
+                               }
+
+                               if (!fe.FieldInfo.IsStatic){
+                                       error176 (loc, fe.FieldInfo.Name);
+                                       return null;
+                               }
+                               return member_lookup;
+                       }
+
+                       if (member_lookup is EventExpr){
+
+                               EventExpr ee = (EventExpr) member_lookup;
+                               
+                               //
+                               // If the event is local to this class, we transform ourselves into
+                               // a FieldExpr
+                               //
+
+                               Expression ml = MemberLookup (
+                                       ec, ec.TypeContainer.TypeBuilder, ee.EventInfo.Name,
+                                       MemberTypes.Event, AllBindingFlags, loc);
+
+                               if (ml != null) {
+                                       MemberInfo mi = ec.TypeContainer.GetFieldFromEvent ((EventExpr) ml);
+
+                                       ml = ExprClassFromMemberInfo (ec, mi, loc);
+                                       
+                                       if (ml == null) {
+                                               Report.Error (-200, loc, "Internal error!!");
+                                               return null;
+                                       }
+
+                                       return ResolveMemberAccess (ec, ml, left, loc);
+                               }
+
+                               if (!ee.IsStatic) {
+                                       SimpleName.Error120 (loc, ee.EventInfo.Name);
+                                       return null;
+                               }
+                               
+                               return ee;
+                       }
+
+                       Console.WriteLine ("Left is: " + left);
+                       Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
+                       Environment.Exit (0);
+
+                       return null;
+               }
+               
+               public ResolveInstanceMemberAccess (EmitContext ec, Expression member_lookup,
+                                                   Expression left, Location loc)
+               {
+                       if (member_lookup is MethodGroupExpr){
+                               //
+                               // Instance.MethodGroup
+                               //
+                               if (!mg.RemoveStaticMethods ()){
+                                       error176 (loc, mg.Methods [0].Name);
+                                       return null;
+                               }
+                               
+                               mg.InstanceExpression = left;
+                                       
+                               return member_lookup;
+                       }
+
+                       if (member_lookup is PropertyExpr){
+                               PropertyExpr pe = (PropertyExpr) member_lookup;
+
+                               if (pe.IsStatic){
+                                       error176 (loc, pe.PropertyInfo.Name);
+                                       return null;
+                               }
+                               Console.WriteLine ("HERE *************");
+                               pe.InstanceExpression = left;
+                               
+                               return pe;
+                       }
+
+                       Type left_type = left.type;
+
+                       if (left_type.IsValueType){
+                       } else {
+                               
+                       }
+               }
+               
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       //
+                       // We are the sole users of ResolveWithSimpleName (ie, the only
+                       // ones that can cope with it
+                       //
+                       expr = expr.ResolveWithSimpleName (ec);
+
+                       if (expr == null)
+                               return null;
+
+                       if (expr is SimpleName){
+                               SimpleName child_expr = (SimpleName) expr;
+                               
+                               expr = new SimpleName (child_expr.Name + "." + Identifier, loc);
+
+                               return expr.ResolveWithSimpleName (ec);
+                       }
+
+                       //
+                       // Handle enums here when they are in transit.
+                       // Note that we cannot afford to hit MemberLookup in this case because
+                       // it will fail to find any members at all (Why?)
+                       //
+
+                       Type expr_type = expr.Type;
+                       if (expr_type.IsSubclassOf (TypeManager.enum_type)) {
+                               
+                               Enum en = TypeManager.LookupEnum (expr_type);
+                               
+                               if (en != null) {
+                                       object value = en.LookupEnumValue (ec, Identifier, loc);
+
+                                       if (value == null)
+                                               return null;
+                                       
+                                       Constant c = Constantify (value, en.UnderlyingType);
+                                       return new EnumConstant (c, expr_type);
+                               }
+                       }
+
+                       member_lookup = MemberLookup (ec, expr.Type, Identifier, loc);
+
+                       if (member_lookup == null)
+                               return null;
+
+                       if (expr is TypeExpr)
+                               return ResolveTypeMemberAccess (ec, member_lookup, expr, loc);
+                       else
+                               return ResolveInstanceMemberAccess (ec, member_lookup, expr, loc);
+               }
+#endif
diff --git a/mcs/gmcs/parameter.cs b/mcs/gmcs/parameter.cs
new file mode 100755 (executable)
index 0000000..2eaeb02
--- /dev/null
@@ -0,0 +1,415 @@
+//
+// parameter.cs: Parameter definition.
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+//
+//
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Collections;
+
+namespace Mono.CSharp {
+
+
+       /// <summary>
+       ///   Represents a single method parameter
+       /// </summary>
+       public class Parameter {
+               [Flags]
+               public enum Modifier : byte {
+                       NONE    = 0,
+                       REF     = 1,
+                       OUT     = 2,
+                       PARAMS  = 4,
+                       // This is a flag which says that it's either REF or OUT.
+                       ISBYREF = 8
+               }
+
+               public readonly Expression TypeName;
+               public readonly Modifier ModFlags;
+               public Attributes OptAttributes;
+               public readonly string Name;
+               public Type parameter_type;
+               
+               public Parameter (Expression type, string name, Modifier mod, Attributes attrs)
+               {
+                       Name = name;
+                       ModFlags = mod;
+                       TypeName = type;
+                       OptAttributes = attrs;
+               }
+
+               // <summary>
+               //   Resolve is used in method definitions
+               // </summary>
+               public bool Resolve (DeclSpace ds, Location l)
+               {
+                       parameter_type = ds.ResolveType (TypeName, false, l);
+
+                       if (parameter_type == TypeManager.void_type){
+                               Report.Error (1536, l, "`void' parameter is not permitted");
+                               return false;
+                       }
+
+                       return parameter_type != null;
+               }
+
+               public Type ExternalType ()
+               {
+                       if ((ModFlags & Parameter.Modifier.ISBYREF) != 0)
+                               return TypeManager.GetReferenceType (parameter_type);
+                       
+                       return parameter_type;
+               }
+
+               public Type ParameterType {
+                       get {
+                               return parameter_type;
+                       }
+               }
+               
+               public ParameterAttributes Attributes {
+                       get {
+                               int flags = ((int) ModFlags) & ~((int) Parameter.Modifier.ISBYREF);
+                               switch ((Modifier) flags) {
+                               case Modifier.NONE:
+                                       return ParameterAttributes.None;
+                               case Modifier.REF:
+                                       return ParameterAttributes.None;
+                               case Modifier.OUT:
+                                       return ParameterAttributes.Out;
+                               case Modifier.PARAMS:
+                                       return 0;
+                               }
+                               
+                               return ParameterAttributes.None;
+                       }
+               }
+               
+               /// <summary>
+               ///   Returns the signature for this parameter evaluating it on the
+               ///   @tc context
+               /// </summary>
+               public string GetSignature (DeclSpace ds, Location loc)
+               {
+                       if (parameter_type == null){
+                               if (!Resolve (ds, loc))
+                                       return null;
+                       }
+
+                       return ExternalType ().FullName;
+               }
+       }
+
+       /// <summary>
+       ///   Represents the methods parameters
+       /// </summary>
+       public class Parameters {
+               public Parameter [] FixedParameters;
+               public readonly Parameter ArrayParameter;
+               string signature;
+               Type [] types;
+               Location loc;
+               
+               static Parameters empty_parameters;
+               
+               public Parameters (Parameter [] fixed_parameters, Parameter array_parameter, Location l)
+               {
+                       FixedParameters = fixed_parameters;
+                       ArrayParameter  = array_parameter;
+                       loc = l;
+               }
+
+               /// <summary>
+               ///   This is used to reuse a set of empty parameters, because they
+               ///   are common
+               /// </summary>
+               public static Parameters EmptyReadOnlyParameters {
+                       get {
+                               if (empty_parameters == null)
+                                       empty_parameters = new Parameters (null, null, Location.Null);
+                       
+                               return empty_parameters;
+                       }
+               }
+               
+               public bool Empty {
+                       get {
+                               return (FixedParameters == null) && (ArrayParameter == null);
+                       }
+               }
+               
+               public void ComputeSignature (DeclSpace ds)
+               {
+                       signature = "";
+                       if (FixedParameters != null){
+                               for (int i = 0; i < FixedParameters.Length; i++){
+                                       Parameter par = FixedParameters [i];
+                                       
+                                       signature += par.GetSignature (ds, loc);
+                               }
+                       }
+                       //
+                       // Note: as per the spec, the `params' arguments (ArrayParameter)
+                       // are not used in the signature computation for a method
+                       //
+               }
+
+               static void Error_DuplicateParameterName (string name)
+               {
+                       Report.Error (
+                               100, "The parameter name `" + name + "' is a duplicate");
+               }
+               
+               public bool VerifyArgs ()
+               {
+                       int count;
+                       int i, j;
+
+                       if (FixedParameters == null)
+                               return true;
+                       
+                       count = FixedParameters.Length;
+                       string array_par_name = ArrayParameter != null ? ArrayParameter.Name : null;
+                       for (i = 0; i < count; i++){
+                               string base_name = FixedParameters [i].Name;
+                               
+                               for (j = i + 1; j < count; j++){
+                                       if (base_name != FixedParameters [j].Name)
+                                               continue;
+                                       Error_DuplicateParameterName (base_name);
+                                       return false;
+                               }
+
+                               if (base_name == array_par_name){
+                                       Error_DuplicateParameterName (base_name);
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+               
+               /// <summary>
+               ///    Returns the signature of the Parameters evaluated in
+               ///    the @tc environment
+               /// </summary>
+               public string GetSignature (DeclSpace ds)
+               {
+                       if (signature == null){
+                               VerifyArgs ();
+                               ComputeSignature (ds);
+                       }
+                       
+                       return signature;
+               }
+               
+               /// <summary>
+               ///    Returns the paramenter information based on the name
+               /// </summary>
+               public Parameter GetParameterByName (string name, out int idx)
+               {
+                       idx = 0;
+                       int i = 0;
+
+                       if (FixedParameters != null){
+                               foreach (Parameter par in FixedParameters){
+                                       if (par.Name == name){
+                                               idx = i;
+                                               return par;
+                                       }
+                                       i++;
+                               }
+                       }
+
+                       if (ArrayParameter != null){
+                               if (name == ArrayParameter.Name){
+                                       idx = i;
+                                       return ArrayParameter;
+                               }
+                       }
+                       
+                       return null;
+               }
+
+               bool ComputeParameterTypes (DeclSpace ds)
+               {
+                       int extra = (ArrayParameter != null) ? 1 : 0;
+                       int i = 0;
+                       int pc;
+
+                       if (FixedParameters == null)
+                               pc = extra;
+                       else
+                               pc = extra + FixedParameters.Length;
+
+                       types = new Type [pc];
+                       
+                       if (!VerifyArgs ()){
+                               FixedParameters = null;
+                               return false;
+                       }
+
+                       bool failed = false;
+                       if (FixedParameters != null){
+                               foreach (Parameter p in FixedParameters){
+                                       Type t = null;
+                                       
+                                       if (p.Resolve (ds, loc))
+                                               t = p.ExternalType ();
+                                       else
+                                               failed = true;
+
+                                       types [i] = t;
+                                       i++;
+                               }
+                       }
+                       
+                       if (extra > 0){
+                               if (ArrayParameter.Resolve (ds, loc))
+                                       types [i] = ArrayParameter.ExternalType ();
+                               else 
+                                       failed = true;
+                       }
+
+                       if (failed){
+                               types = null;
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               //
+               // This variant is used by Delegates, because they need to
+               // resolve/define names, instead of the plain LookupType
+               //
+               public bool ComputeAndDefineParameterTypes (DeclSpace ds)
+               {
+                       int extra = (ArrayParameter != null) ? 1 : 0;
+                       int i = 0;
+                       int pc;
+
+                       if (FixedParameters == null)
+                               pc = extra;
+                       else
+                               pc = extra + FixedParameters.Length;
+                       
+                       types = new Type [pc];
+                       
+                       if (!VerifyArgs ()){
+                               FixedParameters = null;
+                               return false;
+                       }
+
+                       bool ok_flag = true;
+                       
+                       if (FixedParameters != null){
+                               foreach (Parameter p in FixedParameters){
+                                       Type t = null;
+                                       
+                                       if (p.Resolve (ds, loc))
+                                               t = p.ExternalType ();
+                                       else
+                                               ok_flag = false;
+                                       
+                                       types [i] = t;
+                                       i++;
+                               }
+                       }
+                       
+                       if (extra > 0){
+                               if (ArrayParameter.Resolve (ds, loc))
+                                       types [i] = ArrayParameter.ExternalType ();
+                               else
+                                       ok_flag = false;
+                       }
+
+                       //
+                       // invalidate the cached types
+                       //
+                       if (!ok_flag){
+                               types = null;
+                       }
+                       
+                       return ok_flag;
+               }
+               
+               /// <summary>
+               ///   Returns the argument types as an array
+               /// </summary>
+               static Type [] no_types = new Type [0];
+               
+               public Type [] GetParameterInfo (DeclSpace ds)
+               {
+                       if (types != null)
+                               return types;
+                       
+                       if (FixedParameters == null && ArrayParameter == null)
+                               return no_types;
+
+                       if (ComputeParameterTypes (ds) == false){
+                               types = null;
+                               return null;
+                       }
+
+                       return types;
+               }
+
+               /// <summary>
+               ///   Returns the type of a given parameter, and stores in the `is_out'
+               ///   boolean whether this is an out or ref parameter.
+               ///
+               ///   Note that the returned type will not contain any dereference in this
+               ///   case (ie, you get "int" for a ref int instead of "int&"
+               /// </summary>
+               public Type GetParameterInfo (DeclSpace ds, int idx, out Parameter.Modifier mod)
+               {
+                       mod = Parameter.Modifier.NONE;
+                       
+                       if (!VerifyArgs ()){
+                               FixedParameters = null;
+                               return null;
+                       }
+
+                       if (FixedParameters == null && ArrayParameter == null)
+                               return null;
+                       
+                       if (types == null)
+                               if (ComputeParameterTypes (ds) == false)
+                                       return null;
+
+                       //
+                       // If this is a request for the variable lenght arg.
+                       //
+                       int array_idx = (FixedParameters != null ? FixedParameters.Length : 0);
+                       if (idx == array_idx)
+                               return types [idx];
+
+                       //
+                       // Otherwise, it is a fixed parameter
+                       //
+                       Parameter p = FixedParameters [idx];
+                       mod = p.ModFlags;
+
+                       if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
+                               mod |= Parameter.Modifier.ISBYREF;
+
+                       return p.ParameterType;
+               }
+
+               public CallingConventions GetCallingConvention ()
+               {
+                       // For now this is the only correc thing to do
+                       return CallingConventions.Standard;
+               }
+       }
+}
+               
+       
+
diff --git a/mcs/gmcs/parameterCollection.cs b/mcs/gmcs/parameterCollection.cs
new file mode 100755 (executable)
index 0000000..2227425
--- /dev/null
@@ -0,0 +1,166 @@
+//
+// System.CodeDOM CodeParameterCollection Class implementation
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc.
+//
+
+namespace Mono.CSharp {
+
+       using System.Collections;
+       using System;
+       
+       public class ParameterCollection : IList, ICollection, IEnumerable {
+
+               ArrayList parameters;
+               
+               //
+               // Constructors
+               //
+               public ParameterCollection ()
+               {
+                       parameters = new ArrayList ();
+               }
+
+               //
+               // Properties
+               //
+               public int Count {
+                       get {
+                               return parameters.Count;
+                       }
+               }
+
+               //
+               // Methods
+               //
+               public void Add (Parameter value)
+               {
+                       parameters.Add (value);
+               }
+
+               public void AddRange (Parameter [] values)
+               {
+                       foreach (Parameter ca in values) 
+                               parameters.Add (ca);
+
+               }
+
+               public void Clear ()
+               {
+                       parameters.Clear ();
+               }
+
+               private class Enumerator : IEnumerator {
+                       private ParameterCollection collection;
+                       private int currentIndex = -1;
+
+                       internal Enumerator (ParameterCollection collection)
+                       {
+                               this.collection = collection;
+                       }
+
+                       public object Current {
+                               get {
+                                       if (currentIndex == collection.Count)
+                                               throw new InvalidOperationException ();
+                                       return collection [currentIndex];
+                               }
+                       }
+
+                       public bool MoveNext ()
+                       {
+                               if (currentIndex > collection.Count)
+                                       throw new InvalidOperationException ();
+                               return ++currentIndex < collection.Count;
+                       }
+
+                       public void Reset ()
+                       {
+                               currentIndex = -1;
+                       }
+               }
+               
+               public IEnumerator GetEnumerator ()
+               {
+                       return new ParameterCollection.Enumerator (this);
+               }
+
+               //
+               // IList method implementations
+               //
+               public int Add (object value)
+               {
+                       return parameters.Add (value);
+               }
+
+               public bool Contains (Object value)
+               {
+                       return parameters.Contains (value);
+               }
+
+               public int IndexOf (Object value)
+               {
+                       return parameters.IndexOf (value);
+               }
+
+               public void Insert (int index, Object value)
+               {
+                       parameters [index] = value;
+               }
+
+               public object this[int index] {
+                       get {
+                               return parameters [index];
+                       }
+
+                       set {
+                               parameters [index] = value;
+                       }
+               }
+
+               public void Remove (object value)
+               {
+                       parameters.Remove (value);
+               }
+
+               public void RemoveAt (int index)
+               {
+                       parameters.RemoveAt (index);
+               }
+
+               //
+               // ICollection method implementations
+               //
+               public void CopyTo (Array array, int index)
+               {
+                       parameters.CopyTo (array, index);
+               }
+
+               public object SyncRoot {
+                       get {
+                               return parameters.SyncRoot;
+                       }
+               }
+
+               public bool IsReadOnly {
+                       get {
+                               return false;
+                       }
+               }
+
+               public bool IsSynchronized {
+                       get {
+                               return parameters.IsSynchronized;
+                       }
+               }
+
+               public bool IsFixedSize {
+                       get {
+                               return false;
+                       }
+               }
+       }
+}
diff --git a/mcs/gmcs/parser.cs b/mcs/gmcs/parser.cs
new file mode 100755 (executable)
index 0000000..c30a354
--- /dev/null
@@ -0,0 +1,23 @@
+\r
+namespace Compiler {\r
+\r
+       using System;\r
+\r
+       abstract public class Parser {\r
+               public string name;\r
+               public System.IO.Stream input;\r
+               \r
+               public Parser (Mono.CSharp.Tree tree, string name, System.IO.Stream stream) \r
+               {\r
+                       this.tree = tree;\r
+                       this.name = name;\r
+                       this.input = stream;\r
+               }\r
+\r
+               public string getName (){\r
+                       return name;\r
+               }\r
+\r
+               abstract public int parse ();\r
+       }\r
+}\r
diff --git a/mcs/gmcs/pending.cs b/mcs/gmcs/pending.cs
new file mode 100755 (executable)
index 0000000..9e10ab3
--- /dev/null
@@ -0,0 +1,554 @@
+//
+// pending.cs: Pending method implementation
+//
+// Author:
+//   Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
+//
+//
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Mono.CSharp {
+
+       struct TypeAndMethods {
+               public Type          type;
+               public MethodInfo [] methods;
+
+               // 
+               // Whether it is optional, this is used to allow the explicit/implicit
+               // implementation when a parent class already implements an interface. 
+               //
+               // For example:
+               //
+               // class X : IA { }  class Y : X, IA { IA.Explicit (); }
+               //
+               public bool          optional;
+               
+               // Far from ideal, but we want to avoid creating a copy
+               // of methods above.
+               public Type [][]     args;
+               
+               //
+               // This flag on the method says `We found a match, but
+               // because it was private, we could not use the match
+               //
+               public bool []       found;
+
+               // If a method is defined here, then we always need to
+               // create a proxy for it.  This is used when implementing
+               // an interface's indexer with a different IndexerName.
+               public MethodInfo [] need_proxy;
+       }
+
+       public class PendingImplementation {
+               /// <summary>
+               ///   The container for this PendingImplementation
+               /// </summary>
+               TypeContainer container;
+               
+               /// <summary>
+               ///   This filter is used by FindMembers, and it is used to
+               ///   extract only virtual/abstract fields
+               /// </summary>
+               static MemberFilter virtual_method_filter;
+
+               /// <summary>
+               ///   This is the array of TypeAndMethods that describes the pending implementations
+               ///   (both interfaces and abstract methods in parent class)
+               /// </summary>
+               TypeAndMethods [] pending_implementations;
+
+               static bool IsVirtualFilter (MemberInfo m, object filterCriteria)
+               {
+                       if (!(m is MethodInfo))
+                               return false;
+
+                       return ((MethodInfo) m).IsVirtual;
+               }
+
+               /// <summary>
+               ///   Inits the virtual_method_filter
+               /// </summary>
+               static PendingImplementation ()
+               {
+                       virtual_method_filter = new MemberFilter (IsVirtualFilter);
+               }
+
+               // <remarks>
+               //   Returns a list of the abstract methods that are exposed by all of our
+               //   parents that we must implement.  Notice that this `flattens' the
+               //   method search space, and takes into account overrides.  
+               // </remarks>
+               static ArrayList GetAbstractMethods (Type t)
+               {
+                       ArrayList list = null;
+                       bool searching = true;
+                       Type current_type = t;
+                       
+                       do {
+                               MemberList mi;
+                               
+                               mi = TypeContainer.FindMembers (
+                                       current_type, MemberTypes.Method,
+                                       BindingFlags.Public | BindingFlags.Instance |
+                                       BindingFlags.DeclaredOnly,
+                                       virtual_method_filter, null);
+
+                               if (current_type == TypeManager.object_type)
+                                       searching = false;
+                               else {
+                                       current_type = current_type.BaseType;
+                                       if (!current_type.IsAbstract)
+                                               searching = false;
+                               }
+
+                               if (mi.Count == 0)
+                                       continue;
+
+                               if (mi.Count == 1 && !(mi [0] is MethodBase))
+                                       searching = false;
+                               else 
+                                       list = TypeManager.CopyNewMethods (list, mi);
+                       } while (searching);
+
+                       if (list == null)
+                               return null;
+                       
+                       for (int i = 0; i < list.Count; i++){
+                               while (list.Count > i && !((MethodInfo) list [i]).IsAbstract)
+                                       list.RemoveAt (i);
+                       }
+
+                       if (list.Count == 0)
+                               return null;
+
+                       return list;
+               }
+
+               PendingImplementation (TypeContainer container, MissingInterfacesInfo [] missing_ifaces, ArrayList abstract_methods, int total)
+               {
+                       TypeBuilder type_builder = container.TypeBuilder;
+                       
+                       this.container = container;
+                       pending_implementations = new TypeAndMethods [total];
+
+                       int i = 0;
+                       foreach (MissingInterfacesInfo missing in missing_ifaces){
+                               MethodInfo [] mi;
+                               Type t = missing.Type;
+                               
+                               if (t is TypeBuilder){
+                                       Interface iface;
+
+                                       iface = TypeManager.LookupInterface (t);
+                                       
+                                       mi = iface.GetMethods (container);
+                               } else 
+                                       mi = t.GetMethods ();
+                               
+                               int count = mi.Length;
+                               pending_implementations [i].type = missing.Type;
+                               pending_implementations [i].optional = missing.Optional;
+                               pending_implementations [i].methods = mi;
+                               pending_implementations [i].args = new Type [count][];
+                               pending_implementations [i].found = new bool [count];
+                               pending_implementations [i].need_proxy = new MethodInfo [count];
+                               
+                               int j = 0;
+                               foreach (MethodInfo m in mi){
+                                       Type [] types = TypeManager.GetArgumentTypes (m);
+                                       
+                                       pending_implementations [i].args [j] = types;
+                                       j++;
+                               }
+                               i++;
+                       }
+
+                       if (abstract_methods != null){
+                               int count = abstract_methods.Count;
+                               pending_implementations [i].methods = new MethodInfo [count];
+                               pending_implementations [i].need_proxy = new MethodInfo [count];
+                               
+                               abstract_methods.CopyTo (pending_implementations [i].methods, 0);
+                               pending_implementations [i].found = new bool [count];
+                               pending_implementations [i].args = new Type [count][];
+                               pending_implementations [i].type = type_builder;
+                               
+                               int j = 0;
+                               foreach (MemberInfo m in abstract_methods){
+                                       MethodInfo mi = (MethodInfo) m;
+                                       
+                                       Type [] types = TypeManager.GetArgumentTypes (mi);
+                                       
+                                       pending_implementations [i].args [j] = types;
+                                       j++;
+                               }
+                       }
+               }
+
+               struct MissingInterfacesInfo {
+                       public Type Type;
+                       public bool Optional;
+
+                       public MissingInterfacesInfo (Type t)
+                       {
+                               Type = t;
+                               Optional = false;
+                       }
+               }
+
+               static MissingInterfacesInfo [] EmptyMissingInterfacesInfo = new MissingInterfacesInfo [0];
+               
+               static MissingInterfacesInfo [] GetMissingInterfaces (TypeBuilder type_builder)
+               {
+                       //
+                       // Notice that TypeBuilders will only return the interfaces that the Type
+                       // is supposed to implement, not all the interfaces that the type implements.
+                       //
+                       // Completely broken.  Anyways, we take advantage of this, so we only register
+                       // the implementations that we need, as they are those that are listed by the
+                       // TypeBuilder.
+                       //
+                       Type [] implementing_ifaces = type_builder.GetInterfaces ();
+                       int count = implementing_ifaces.Length;
+
+                       if (implementing_ifaces.Length == 0)
+                               return EmptyMissingInterfacesInfo;
+
+                       MissingInterfacesInfo [] missing_info = new MissingInterfacesInfo [count];
+
+                       for (int i = 0; i < count; i++)
+                               missing_info [i] = new MissingInterfacesInfo (implementing_ifaces [i]);
+                       
+                       
+                       //
+                       // Now, we have to extract the interfaces implements by our parents, and
+                       // remove them from the implementing_ifaces array.
+                       //
+                       for (Type t = type_builder.BaseType; t != null; t = t.BaseType){
+                               Type [] base_ifaces = t.GetInterfaces ();
+                                       
+                               foreach (Type base_iface in base_ifaces){
+                                       for (int i = 0; i < count; i++){
+                                               if (implementing_ifaces [i] == base_iface)
+                                                       missing_info [i].Optional = true;
+                                       }
+                               }
+
+                               //
+                               // When we reach a `Type' instead of `TypeBuilder', the GetInterfaces
+                               // call would have returned all of the parent implementations, so we can end.
+                               //
+                               if (!(t is TypeBuilder))
+                                       break;
+                       }
+
+                       return missing_info;
+               }
+               
+               //
+               // Factory method: if there are pending implementation methods, we return a PendingImplementation
+               // object, otherwise we return null.
+               //
+               // Register method implementations are either abstract methods
+               // flagged as such on the base class or interface methods
+               //
+               static public PendingImplementation GetPendingImplementations (TypeContainer container)
+               {
+                       TypeBuilder type_builder = container.TypeBuilder;
+                       MissingInterfacesInfo [] missing_interfaces;
+                       Type b = type_builder.BaseType;
+
+                       missing_interfaces = GetMissingInterfaces (type_builder);
+
+                       //
+                       // If we are implementing an abstract class, and we are not
+                       // ourselves abstract, and there are abstract methods (C# allows
+                       // abstract classes that have no abstract methods), then allocate
+                       // one slot.
+                       //
+                       // We also pre-compute the methods.
+                       //
+                       bool implementing_abstract = ((b != null) && b.IsAbstract && !type_builder.IsAbstract);
+                       ArrayList abstract_methods = null;
+
+                       if (implementing_abstract){
+                               abstract_methods = GetAbstractMethods (b);
+                               
+                               if (abstract_methods == null)
+                                       implementing_abstract = false;
+                       }
+                       
+                       int total = missing_interfaces.Length +  (implementing_abstract ? 1 : 0);
+                       if (total == 0)
+                               return null;
+
+                       return new PendingImplementation (container, missing_interfaces, abstract_methods, total);
+               }
+
+               public enum Operation {
+                       //
+                       // If you change this, review the whole InterfaceMethod routine as there
+                       // are a couple of assumptions on these three states
+                       //
+                       Lookup, ClearOne, ClearAll
+               }
+
+               /// <summary>
+               ///   Whether the specified method is an interface method implementation
+               /// </summary>
+               public MethodInfo IsInterfaceMethod (Type t, string name, Type ret_type, Type [] args)
+               {
+                       return InterfaceMethod (t, name, ret_type, args, Operation.Lookup, null);
+               }
+
+               public MethodInfo IsInterfaceIndexer (Type t, Type ret_type, Type [] args)
+               {
+                       return InterfaceMethod (t, null, ret_type, args, Operation.Lookup, null);
+               }
+
+               public void ImplementMethod (Type t, string name, Type ret_type, Type [] args, bool clear_one) 
+               {
+                       InterfaceMethod (t, name, ret_type, args,
+                                        clear_one ? Operation.ClearOne : Operation.ClearAll, null);
+               }
+
+               public void ImplementIndexer (Type t, MethodInfo mi, Type ret_type, Type [] args, bool clear_one) 
+               {
+                       InterfaceMethod (t, mi.Name, ret_type, args,
+                                        clear_one ? Operation.ClearOne : Operation.ClearAll, mi);
+               }
+               
+               /// <remarks>
+               ///   If a method in Type `t' (or null to look in all interfaces
+               ///   and the base abstract class) with name `Name', return type `ret_type' and
+               ///   arguments `args' implements an interface, this method will
+               ///   return the MethodInfo that this method implements.
+               ///
+               ///   If `name' is null, we operate solely on the method's signature.  This is for
+               ///   instance used when implementing indexers.
+               ///
+               ///   The `Operation op' controls whether to lookup, clear the pending bit, or clear
+               ///   all the methods with the given signature.
+               ///
+               ///   The `MethodInfo need_proxy' is used when we're implementing an interface's
+               ///   indexer in a class.  If the new indexer's IndexerName does not match the one
+               ///   that was used in the interface, then we always need to create a proxy for it.
+               ///
+               /// </remarks>
+               public MethodInfo InterfaceMethod (Type t, string name, Type ret_type, Type [] args,
+                                                  Operation op, MethodInfo need_proxy)
+               {
+                       int arg_len = args.Length;
+
+                       if (pending_implementations == null)
+                               return null;
+
+                       foreach (TypeAndMethods tm in pending_implementations){
+                               if (!(t == null || tm.type == t))
+                                       continue;
+
+                               int method_count = tm.methods.Length;
+                               MethodInfo m;
+                               for (int i = 0; i < method_count; i++){
+                                       m = tm.methods [i];
+
+                                       if (m == null)
+                                               continue;
+
+                                       // `need_proxy' is not null when we're implementing an
+                                       // interface indexer and this is Clear(One/All) operation.
+                                       // If `name' is null, then we do a match solely based on the
+                                       // signature and not on the name (this is done in the Lookup
+                                       // for an interface indexer).
+                                       if ((name != null) && (need_proxy == null) && (name != m.Name))
+                                               continue;
+
+                                       if (ret_type != m.ReturnType){
+                                               if (!((ret_type == null && m.ReturnType == TypeManager.void_type) ||
+                                                     (m.ReturnType == null && ret_type == TypeManager.void_type)))
+                                                       continue;
+                                       }
+
+                                       //
+                                       // Check if we have the same parameters
+                                       //
+                                       if (tm.args [i].Length != arg_len)
+                                               continue;
+
+                                       int j, top = args.Length;
+                                       bool fail = false;
+                                       
+                                       for (j = 0; j < top; j++){
+                                               if (tm.args [i][j] != args[j]){
+                                                       fail = true;
+                                                       break;
+                                               }
+                                       }
+                                       if (fail)
+                                               continue;
+
+                                       if (op != Operation.Lookup){
+                                               // If `t != null', then this is an explicitly interface
+                                               // implementation and we can always clear the method.
+                                               // `need_proxy' is not null if we're implementing an
+                                               // interface indexer.  In this case, we need to create
+                                               // a proxy if the implementation's IndexerName doesn't
+                                               // match the IndexerName in the interface.
+                                               if ((t == null) && (need_proxy != null) && (name != m.Name))
+                                                       tm.need_proxy [i] = need_proxy;
+                                               else 
+                                                       tm.methods [i] = null;
+                                       }
+                                       tm.found [i] = true;
+
+                                       //
+                                       // Lookups and ClearOne return
+                                       //
+                                       if (op != Operation.ClearAll)
+                                               return m;
+                               }
+
+                               // If a specific type was requested, we can stop now.
+                               if (tm.type == t)
+                                       return null;
+                       }
+                       return null;
+               }
+
+               /// <summary>
+               ///   C# allows this kind of scenarios:
+               ///   interface I { void M (); }
+               ///   class X { public void M (); }
+               ///   class Y : X, I { }
+               ///
+               ///   For that case, we create an explicit implementation function
+               ///   I.M in Y.
+               /// </summary>
+               void DefineProxy (Type iface, MethodInfo parent_method, MethodInfo iface_method,
+                                 Type [] args)
+               {
+                       MethodBuilder proxy;
+
+                       string proxy_name = iface.Name + "." + iface_method.Name;
+
+                       proxy = container.TypeBuilder.DefineMethod (
+                               proxy_name,
+                               MethodAttributes.HideBySig |
+                               MethodAttributes.NewSlot |
+                               MethodAttributes.Virtual,
+                               CallingConventions.Standard | CallingConventions.HasThis,
+                               parent_method.ReturnType, args);
+
+                       int top = args.Length;
+                       ILGenerator ig = proxy.GetILGenerator ();
+
+                       ig.Emit (OpCodes.Ldarg_0);
+                       for (int i = 0; i < top; i++){
+                               switch (i){
+                               case 0:
+                                       ig.Emit (OpCodes.Ldarg_1); break;
+                               case 1:
+                                       ig.Emit (OpCodes.Ldarg_2); break;
+                               case 2:
+                                       ig.Emit (OpCodes.Ldarg_3); break;
+                               default:
+                                       ig.Emit (OpCodes.Ldarg, i - 1); break;
+                               }
+                       }
+                       ig.Emit (OpCodes.Call, parent_method);
+                       ig.Emit (OpCodes.Ret);
+
+                       container.TypeBuilder.DefineMethodOverride (proxy, iface_method);
+               }
+               
+               /// <summary>
+               ///   This function tells whether one of our parent classes implements
+               ///   the given method (which turns out, it is valid to have an interface
+               ///   implementation in a parent
+               /// </summary>
+               bool ParentImplements (Type iface_type, MethodInfo mi)
+               {
+                       MethodSignature ms;
+                       
+                       Type [] args = TypeManager.GetArgumentTypes (mi);
+                       ms = new MethodSignature (mi.Name, mi.ReturnType, args);
+                       MemberList list = TypeContainer.FindMembers (
+                               container.TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property,
+                               BindingFlags.Public | BindingFlags.Instance,
+                               MethodSignature.method_signature_filter, ms);
+
+                       if (list.Count == 0)
+                               return false;
+
+                       MethodInfo parent = (MethodInfo) list [0];
+                       if (!parent.IsAbstract)
+                               DefineProxy (iface_type, parent, mi, args);
+                       return true;
+               }
+
+               /// <summary>
+               ///   Verifies that any pending abstract methods or interface methods
+               ///   were implemented.
+               /// </summary>
+               public bool VerifyPendingMethods ()
+               {
+                       int top = pending_implementations.Length;
+                       bool errors = false;
+                       int i;
+                       
+                       for (i = 0; i < top; i++){
+                               Type type = pending_implementations [i].type;
+                               int j = 0;
+                               
+                               foreach (MethodInfo mi in pending_implementations [i].methods){
+                                       if (mi == null)
+                                               continue;
+
+                                       if (type.IsInterface){
+                                               MethodInfo need_proxy =
+                                                       pending_implementations [i].need_proxy [j];
+
+                                               if (need_proxy != null) {
+                                                       Type [] args = TypeManager.GetArgumentTypes (mi);
+                                                       DefineProxy (type, need_proxy, mi, args);
+                                                       continue;
+                                               }
+
+                                               if (ParentImplements (type, mi))
+                                                       continue;
+
+                                               if (pending_implementations [i].optional)
+                                                       continue;
+                                               
+                                               string extra = "";
+                                               
+                                               if (pending_implementations [i].found [j])
+                                                       extra = ".  (method might be non-public or static)";
+                                               Report.Error (
+                                                       536, container.Location,
+                                                       "`" + container.Name + "' does not implement " +
+                                                       "interface member `" +
+                                                       type.FullName + "." + mi.Name + "'" + extra);
+                                       } else {
+                                               Report.Error (
+                                                       534, container.Location,
+                                                       "`" + container.Name + "' does not implement " +
+                                                       "inherited abstract member `" +
+                                                       type.FullName + "." + mi.Name + "'");
+                                       }
+                                       errors = true;
+                                       j++;
+                               }
+                       }
+                       return errors;
+               }
+       } /* end of class */
+}
diff --git a/mcs/gmcs/report.cs b/mcs/gmcs/report.cs
new file mode 100644 (file)
index 0000000..f5c90e4
--- /dev/null
@@ -0,0 +1,368 @@
+//
+// report.cs: report errors and warnings.
+//
+// Author: Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc. (http://www.ximian.com)
+//
+
+//
+// FIXME: currently our class library does not support custom number format strings
+//
+using System;
+using System.Text;
+using System.Collections;
+using System.Diagnostics;
+
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///   This class is used to report errors and warnings t te user.
+       /// </summary>
+       public class Report {
+               /// <summary>  
+               ///   Errors encountered so far
+               /// </summary>
+               static public int Errors;
+
+               /// <summary>  
+               ///   Warnings encountered so far
+               /// </summary>
+               static public int Warnings;
+
+               /// <summary>  
+               ///   Whether errors should be throw an exception
+               /// </summary>
+               static public bool Fatal;
+               
+               /// <summary>  
+               ///   Whether warnings should be considered errors
+               /// </summary>
+               static public bool WarningsAreErrors;
+
+               /// <summary>  
+               ///   Whether to dump a stack trace on errors. 
+               /// </summary>
+               static public bool Stacktrace;
+               
+               //
+               // If the 'expected' error code is reported then the
+                // compilation succeeds.
+               //
+               // Used for the test suite to excercise the error codes
+               //
+               static int expected_error = 0;
+
+               //
+               // Keeps track of the warnings that we are ignoring
+               //
+               static Hashtable warning_ignore_table;
+               
+               static void Check (int code)
+               {
+                       if (code == expected_error){
+                               if (Fatal)
+                                       throw new Exception ();
+                               
+                               Environment.Exit (0);
+                       }
+               }
+               
+               static public void RealError (string msg)
+               {
+                       Errors++;
+                       Console.WriteLine (msg);
+
+                       if (Stacktrace)
+                               Console.WriteLine (new StackTrace ().ToString ());
+                       if (Fatal)
+                               throw new Exception (msg);
+               }
+
+               static public void Error (int code, Location l, string text)
+               {
+                       if (code < 0)
+                               code = 8000-code;
+                       
+                       string msg = String.Format (
+                               "{0}({1}) error CS{2:0000}: {3}", l.Name, l.Row, code, text);
+//                             "{0}({1}) error CS{2}: {3}", l.Name, l.Row, code, text);
+                       
+                       RealError (msg);
+                       Check (code);
+               }
+
+               static public void Warning (int code, Location l, string text)
+               {
+                       if (code < 0)
+                               code = 8000-code;
+                       
+                       if (warning_ignore_table != null){
+                               if (warning_ignore_table.Contains (code))
+                                       return;
+                       }
+                       
+                       if (WarningsAreErrors)
+                               Error (code, l, text);
+                       else {
+                               string row;
+                               
+                               if (Location.IsNull (l))
+                                       row = "";
+                               else
+                                       row = l.Row.ToString ();
+                               
+                               Console.WriteLine (String.Format (
+                                       "{0}({1}) warning CS{2:0000}: {3}",
+//                                     "{0}({1}) warning CS{2}: {3}",
+                                       l.Name,  row, code, text));
+                               Warnings++;
+                               Check (code);
+
+                               if (Stacktrace)
+                                       Console.WriteLine (new StackTrace ().ToString ());
+                       }
+               }
+               
+               static public void Warning (int code, string text)
+               {
+                       Warning (code, Location.Null, text);
+               }
+
+               static public void Warning (int code, int level, string text)
+               {
+                       if (RootContext.WarningLevel >= level)
+                               Warning (code, Location.Null, text);
+               }
+
+               static public void Warning (int code, int level, Location l, string text)
+               {
+                       if (RootContext.WarningLevel >= level)
+                               Warning (code, l, text);
+               }
+
+               static public void Error (int code, string text)
+               {
+                       if (code < 0)
+                               code = 8000-code;
+                       
+                       string msg = String.Format ("error CS{0:0000}: {1}", code, text);
+//                     string msg = String.Format ("error CS{0}: {1}", code, text);
+                       
+                       RealError (msg);
+                       Check (code);
+               }
+
+               static public void Message (Message m)
+               {
+                       if (m is ErrorMessage)
+                               Error (m.code, m.text);
+                       else
+                               Warning (m.code, m.text);
+               }
+
+               static public void SetIgnoreWarning (int code)
+               {
+                       if (warning_ignore_table == null)
+                               warning_ignore_table = new Hashtable ();
+
+                       warning_ignore_table [code] = true;
+               }
+               
+                static public int ExpectedError {
+                        set {
+                                expected_error = value;
+                        }
+                        get {
+                                return expected_error;
+                        }
+                }
+
+               public static int DebugFlags = 0;
+
+               [Conditional ("MCS_DEBUG")]
+               static public void Debug (string message, params object[] args)
+               {
+                       Debug (4, message, args);
+               }
+                       
+               [Conditional ("MCS_DEBUG")]
+               static public void Debug (int category, string message, params object[] args)
+               {
+                       if ((category & DebugFlags) == 0)
+                               return;
+
+                       StringBuilder sb = new StringBuilder (message);
+
+                       if ((args != null) && (args.Length > 0)) {
+                               sb.Append (": ");
+
+                               bool first = true;
+                               foreach (object arg in args) {
+                                       if (first)
+                                               first = false;
+                                       else
+                                               sb.Append (", ");
+                                       if (arg == null)
+                                               sb.Append ("null");
+                                       else if (arg is ICollection)
+                                               sb.Append (PrintCollection ((ICollection) arg));
+                                       else
+                                               sb.Append (arg);
+                               }
+                       }
+
+                       Console.WriteLine (sb.ToString ());
+               }
+
+               static public string PrintCollection (ICollection collection)
+               {
+                       StringBuilder sb = new StringBuilder ();
+
+                       sb.Append (collection.GetType ());
+                       sb.Append ("(");
+
+                       bool first = true;
+                       foreach (object o in collection) {
+                               if (first)
+                                       first = false;
+                               else
+                                       sb.Append (", ");
+                               sb.Append (o);
+                       }
+
+                       sb.Append (")");
+                       return sb.ToString ();
+               }
+       }
+
+       public class Message {
+               public int code;
+               public string text;
+               
+               public Message (int code, string text)
+               {
+                       this.code = code;
+                       this.text = text;
+               }
+       }
+
+       public class WarningMessage : Message {
+               public WarningMessage (int code, string text) : base (code, text)
+               {
+               }
+       }
+
+       public class ErrorMessage : Message {
+               public ErrorMessage (int code, string text) : base (code, text)
+               {
+               }
+
+               //
+               // For compatibility reasons with old code.
+               //
+               public static void report_error (string error)
+               {
+                       Console.Write ("ERROR: ");
+                       Console.WriteLine (error);
+               }
+       }
+
+       public enum TimerType {
+               FindMembers     = 0,
+               TcFindMembers   = 1,
+               MemberLookup    = 2,
+               CachedLookup    = 3,
+               CacheInit       = 4,
+               MiscTimer       = 5,
+               CountTimers     = 6
+       }
+
+       public enum CounterType {
+               FindMembers     = 0,
+               MemberCache     = 1,
+               MiscCounter     = 2,
+               CountCounters   = 3
+       }
+
+       public class Timer
+       {
+               static DateTime[] timer_start;
+               static TimeSpan[] timers;
+               static long[] timer_counters;
+               static long[] counters;
+
+               static Timer ()
+               {
+                       timer_start = new DateTime [(int) TimerType.CountTimers];
+                       timers = new TimeSpan [(int) TimerType.CountTimers];
+                       timer_counters = new long [(int) TimerType.CountTimers];
+                       counters = new long [(int) CounterType.CountCounters];
+
+                       for (int i = 0; i < (int) TimerType.CountTimers; i++) {
+                               timer_start [i] = DateTime.Now;
+                               timers [i] = TimeSpan.Zero;
+                       }
+               }
+
+               [Conditional("TIMER")]
+               static public void IncrementCounter (CounterType which)
+               {
+                       ++counters [(int) which];
+               }
+
+               [Conditional("TIMER")]
+               static public void StartTimer (TimerType which)
+               {
+                       timer_start [(int) which] = DateTime.Now;
+               }
+
+               [Conditional("TIMER")]
+               static public void StopTimer (TimerType which)
+               {
+                       timers [(int) which] += DateTime.Now - timer_start [(int) which];
+                       ++timer_counters [(int) which];
+               }
+
+               [Conditional("TIMER")]
+               static public void ShowTimers ()
+               {
+                       ShowTimer (TimerType.FindMembers, "- FindMembers timer");
+                       ShowTimer (TimerType.TcFindMembers, "- TypeContainer.FindMembers timer");
+                       ShowTimer (TimerType.MemberLookup, "- MemberLookup timer");
+                       ShowTimer (TimerType.CachedLookup, "- CachedLookup timer");
+                       ShowTimer (TimerType.CacheInit, "- Cache init");
+                       ShowTimer (TimerType.MiscTimer, "- Misc timer");
+
+                       ShowCounter (CounterType.FindMembers, "- Find members");
+                       ShowCounter (CounterType.MemberCache, "- Member cache");
+                       ShowCounter (CounterType.MiscCounter, "- Misc counter");
+               }
+
+               static public void ShowCounter (CounterType which, string msg)
+               {
+                       Console.WriteLine ("{0} {1}", counters [(int) which], msg);
+               }
+
+               static public void ShowTimer (TimerType which, string msg)
+               {
+                       Console.WriteLine (
+                               "[{0:00}:{1:000}] {2} (used {3} times)",
+                               (int) timers [(int) which].TotalSeconds,
+                               timers [(int) which].Milliseconds, msg,
+                               timer_counters [(int) which]);
+               }
+       }
+
+       public class InternalErrorException : Exception {
+               public InternalErrorException ()
+                       : base ("Internal error")
+               {
+               }
+
+               public InternalErrorException (string message)
+                       : base (message)
+               {
+               }
+       }
+}
diff --git a/mcs/gmcs/rootcontext.cs b/mcs/gmcs/rootcontext.cs
new file mode 100755 (executable)
index 0000000..74e39fd
--- /dev/null
@@ -0,0 +1,900 @@
+//
+// rootcontext.cs: keeps track of our tree representation, and assemblies loaded.
+//
+// Author: Miguel de Icaza (miguel@ximian.com)
+//         Ravi Pratap     (ravi@ximian.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+
+namespace Mono.CSharp {
+
+       public class RootContext {
+
+               //
+               // Contains the parsed tree
+               //
+               static Tree tree;
+
+               //
+               // This hashtable contains all of the #definitions across the source code
+               // it is used by the ConditionalAttribute handler.
+               //
+               public static Hashtable AllDefines = new Hashtable ();
+               
+               //
+               // The list of global attributes (those that target the assembly)
+               //
+               static Hashtable global_attributes = new Hashtable ();
+               
+               //
+               // Whether we are being linked against the standard libraries.
+               // This is only used to tell whether `System.Object' should
+               // have a parent or not.
+               //
+               public static bool StdLib = true;
+
+               //
+               // This keeps track of the order in which classes were defined
+               // so that we can poulate them in that order.
+               //
+               // Order is important, because we need to be able to tell by
+               // examining the parent's list of methods which ones are virtual
+               // or abstract as well as the parent names (to implement new, 
+               // override).
+               //
+               static ArrayList type_container_resolve_order;
+               static ArrayList interface_resolve_order;
+               static ArrayList attribute_types;
+
+               //
+               // Holds a reference to the Private Implementation Details
+               // class.
+               //
+               static ArrayList helper_classes;
+               
+               static TypeBuilder impl_details_class;
+
+               public static int WarningLevel = 2;
+
+               //
+               // If set, enable C# version 2 features
+               //
+               public static bool V2;
+               //
+               // Constructor
+               //
+               static RootContext ()
+               {
+                       tree = new Tree ();
+                       interface_resolve_order = new ArrayList ();
+                       type_container_resolve_order = new ArrayList ();
+               }
+
+               static public Tree Tree {
+                       get {
+                               return tree;
+                       }
+               }
+
+               static public string MainClass;
+               
+               public static void RegisterOrder (Interface iface)
+               {
+                       interface_resolve_order.Add (iface);
+               }
+               
+               public static void RegisterOrder (TypeContainer tc)
+               {
+                       type_container_resolve_order.Add (tc);
+               }
+
+               public static void RegisterAttribute (TypeContainer tc)
+               {
+                       if (attribute_types == null)
+                               attribute_types = new ArrayList ();
+                       
+                       attribute_types.Add (tc);
+               }
+               
+               // 
+               // The default compiler checked state
+               //
+               static public bool Checked = false;
+
+               //
+               // Whether to allow Unsafe code
+               //
+               static public bool Unsafe = false;
+               
+               static string MakeFQN (string nsn, string name)
+               {
+                       if (nsn == "")
+                               return name;
+                       return String.Concat (nsn, ".", name);
+               }
+
+               // <remarks>
+               //   This function is used to resolve the hierarchy tree.
+               //   It processes interfaces, structs and classes in that order.
+               //
+               //   It creates the TypeBuilder's as it processes the user defined
+               //   types.  
+               // </remarks>
+               static public void ResolveTree ()
+               {
+                       //
+                       // Process the attribute types separately and before anything else
+                       //
+                       if (attribute_types != null)
+                               foreach (TypeContainer tc in attribute_types)
+                                       tc.DefineType ();
+                       
+                       //
+                       // Interfaces are processed next, as classes and
+                       // structs might inherit from an object or implement
+                       // a set of interfaces, we need to be able to tell
+                       // them appart by just using the TypeManager.
+                       //
+                       TypeContainer root = Tree.Types;
+
+                       ArrayList ifaces = root.Interfaces;
+                       if (ifaces != null){
+                               foreach (Interface i in ifaces) 
+                                       i.DefineType ();
+                       }
+
+                       foreach (TypeContainer tc in root.Types)
+                               tc.DefineType ();
+
+                       if (root.Delegates != null)
+                               foreach (Delegate d in root.Delegates) 
+                                       d.DefineType ();
+
+                       if (root.Enums != null)
+                               foreach (Enum e in root.Enums)
+                                       e.DefineType ();
+               }
+
+               static void Error_TypeConflict (string name, Location loc)
+               {
+                       Report.Error (
+                               520, loc, "`" + name + "' conflicts with a predefined type");
+               }
+
+               static void Error_TypeConflict (string name)
+               {
+                       Report.Error (
+                               520, "`" + name + "' conflicts with a predefined type");
+               }
+
+               //
+               // Resolves a single class during the corlib bootstrap process
+               //
+               static TypeBuilder BootstrapCorlib_ResolveClass (TypeContainer root, string name)
+               {
+                       object o = root.GetDefinition (name);
+                       if (o == null){
+                               Report.Error (518, "The predefined type `" + name + "' is not defined");
+                               return null;
+                       }
+
+                       if (!(o is Class)){
+                               if (o is DeclSpace){
+                                       DeclSpace d = (DeclSpace) o;
+
+                                       Error_TypeConflict (name, d.Location);
+                               } else
+                                       Error_TypeConflict (name);
+
+                               return null;
+                       }
+
+                       return ((DeclSpace) o).DefineType ();
+               }
+
+               //
+               // Resolves a struct during the corlib bootstrap process
+               //
+               static void BootstrapCorlib_ResolveStruct (TypeContainer root, string name)
+               {
+                       object o = root.GetDefinition (name);
+                       if (o == null){
+                               Report.Error (518, "The predefined type `" + name + "' is not defined");
+                               return;
+                       }
+
+                       if (!(o is Struct)){
+                               if (o is DeclSpace){
+                                       DeclSpace d = (DeclSpace) o;
+
+                                       Error_TypeConflict (name, d.Location);
+                               } else
+                                       Error_TypeConflict (name);
+
+                               return;
+                       }
+
+                       ((DeclSpace) o).DefineType ();
+               }
+
+               //
+               // Resolves a struct during the corlib bootstrap process
+               //
+               static void BootstrapCorlib_ResolveInterface (TypeContainer root, string name)
+               {
+                       object o = root.GetDefinition (name);
+                       if (o == null){
+                               Report.Error (518, "The predefined type `" + name + "' is not defined");
+                               return;
+                       }
+
+                       if (!(o is Interface)){
+                               if (o is DeclSpace){
+                                       DeclSpace d = (DeclSpace) o;
+
+                                       Error_TypeConflict (name, d.Location);
+                               } else
+                                       Error_TypeConflict (name);
+
+                               return;
+                       }
+
+                       ((DeclSpace) o).DefineType ();
+               }
+
+               //
+               // Resolves a delegate during the corlib bootstrap process
+               //
+               static void BootstrapCorlib_ResolveDelegate (TypeContainer root, string name)
+               {
+                       object o = root.GetDefinition (name);
+                       if (o == null){
+                               Report.Error (518, "The predefined type `" + name + "' is not defined");
+                               Environment.Exit (0);
+                       }
+
+                       if (!(o is Delegate)){
+                               Error_TypeConflict (name);
+                               return;
+                       }
+
+                       ((DeclSpace) o).DefineType ();
+               }
+               
+
+               /// <summary>
+               ///    Resolves the core types in the compiler when compiling with --nostdlib
+               /// </summary>
+               static public void ResolveCore ()
+               {
+                       TypeContainer root = Tree.Types;
+
+                       TypeManager.object_type = BootstrapCorlib_ResolveClass (root, "System.Object");
+                       TypeManager.value_type = BootstrapCorlib_ResolveClass (root, "System.ValueType");
+                       TypeManager.attribute_type = BootstrapCorlib_ResolveClass (root, "System.Attribute");
+                       
+                       string [] interfaces_first_stage = {
+                               "System.IComparable", "System.ICloneable",
+                               "System.IConvertible",
+                               
+                               "System.Collections.IEnumerable",
+                               "System.Collections.ICollection",
+                               "System.Collections.IEnumerator",
+                               "System.Collections.IList", 
+                               "System.IAsyncResult",
+                               "System.IDisposable",
+                               
+                               "System.Runtime.Serialization.ISerializable",
+
+                               "System.Reflection.IReflect",
+                               "System.Reflection.ICustomAttributeProvider"
+                       };
+
+                       foreach (string iname in interfaces_first_stage)
+                               BootstrapCorlib_ResolveInterface (root, iname);
+
+                       //
+                       // These are the base value types
+                       //
+                       string [] structs_first_stage = {
+                               "System.Byte",    "System.SByte",
+                               "System.Int16",   "System.UInt16",
+                               "System.Int32",   "System.UInt32",
+                               "System.Int64",   "System.UInt64",
+                       };
+
+                       foreach (string cname in structs_first_stage)
+                               BootstrapCorlib_ResolveStruct (root, cname);
+
+                       //
+                       // Now, we can load the enumerations, after this point,
+                       // we can use enums.
+                       //
+                       TypeManager.InitEnumUnderlyingTypes ();
+
+                       string [] structs_second_stage = {
+                               "System.Single",  "System.Double",
+                               "System.Char",    "System.Boolean",
+                               "System.Decimal", "System.Void",
+                               "System.RuntimeFieldHandle",
+                               "System.RuntimeTypeHandle",
+                               "System.IntPtr"
+                       };
+                       
+                       foreach (string cname in structs_second_stage)
+                               BootstrapCorlib_ResolveStruct (root, cname);
+                       
+                       //
+                       // These are classes that depends on the core interfaces
+                       //
+                       string [] classes_second_stage = {
+                               "System.Reflection.MemberInfo",
+                               "System.Type",
+                               "System.Exception",
+
+                               //
+                               // These are not really important in the order, but they
+                               // are used by the compiler later on (typemanager/CoreLookupType-d)
+                               //
+                               "System.Runtime.CompilerServices.RuntimeHelpers",
+                               "System.Reflection.DefaultMemberAttribute",
+                               "System.Threading.Monitor",
+                               
+                               "System.AttributeUsageAttribute",
+                               "System.Runtime.InteropServices.DllImportAttribute",
+                               "System.Runtime.CompilerServices.MethodImplAttribute",
+                               "System.Runtime.InteropServices.MarshalAsAttribute",
+                               "System.Diagnostics.ConditionalAttribute",
+                               "System.ObsoleteAttribute",
+                               "System.ParamArrayAttribute",
+                               "System.Security.UnverifiableCodeAttribute",
+                               "System.Runtime.CompilerServices.IndexerNameAttribute",
+                               "System.Runtime.InteropServices.InAttribute",
+                               "System.InvalidOperationException"
+
+                       };
+
+                       // We must store them here before calling BootstrapCorlib_ResolveDelegate.
+                       TypeManager.string_type = BootstrapCorlib_ResolveClass (root, "System.String");
+                       TypeManager.enum_type = BootstrapCorlib_ResolveClass (root, "System.Enum");
+                       TypeManager.array_type = BootstrapCorlib_ResolveClass (root, "System.Array");
+                       TypeManager.multicast_delegate_type = BootstrapCorlib_ResolveClass (root, "System.MulticastDelegate");
+                       TypeManager.delegate_type = BootstrapCorlib_ResolveClass (root, "System.Delegate");
+                       
+                       foreach (string cname in classes_second_stage)
+                               BootstrapCorlib_ResolveClass (root, cname);
+
+                       BootstrapCorlib_ResolveDelegate (root, "System.AsyncCallback");
+               }
+                       
+               // <summary>
+               //   Closes all open types
+               // </summary>
+               //
+               // <remarks>
+               //   We usually use TypeBuilder types.  When we are done
+               //   creating the type (which will happen after we have added
+               //   methods, fields, etc) we need to "Define" them before we
+               //   can save the Assembly
+               // </remarks>
+               static public void CloseTypes ()
+               {
+                       TypeContainer root = Tree.Types;
+                       
+                       ArrayList ifaces = root.Interfaces;
+
+                       if (root.Enums != null)
+                               foreach (Enum en in root.Enums)
+                                       en.CloseType ();
+
+                       if (attribute_types != null)
+                               foreach (TypeContainer tc in attribute_types)
+                                       tc.CloseType ();
+                       
+                       foreach (Interface iface in interface_resolve_order)
+                               iface.CloseType ();
+
+                       //
+                       // We do this in two passes, first we close the structs,
+                       // then the classes, because it seems the code needs it this
+                       // way.  If this is really what is going on, we should probably
+                       // make sure that we define the structs in order as well.
+                       //
+                       foreach (TypeContainer tc in type_container_resolve_order){
+                               if (tc is Struct && tc.Parent == tree.Types){
+                                       tc.CloseType ();
+                               }
+                       }
+
+                       foreach (TypeContainer tc in type_container_resolve_order){
+                               if (!(tc is Struct && tc.Parent == tree.Types))
+                                       tc.CloseType ();                                        
+                       }
+                       
+                       if (root.Delegates != null)
+                               foreach (Delegate d in root.Delegates)
+                                       d.CloseType ();
+
+
+                       //
+                       // If we have a <PrivateImplementationDetails> class, close it
+                       //
+                       if (helper_classes != null){
+                               foreach (TypeBuilder type_builder in helper_classes)
+                                       type_builder.CreateType ();
+                       }
+               }
+
+               /// <summary>
+               ///   Used to register classes that need to be closed after all the
+               ///   user defined classes
+               /// </summary>
+               public static void RegisterHelperClass (TypeBuilder helper_class)
+               {
+                       if (helper_classes == null)
+                               helper_classes = new ArrayList ();
+                       helper_classes.Add (helper_class);
+               }
+               
+               //
+               // This idea is from Felix Arrese-Igor
+               //
+               // Returns : the implicit parent of a composite namespace string
+               //   eg. Implicit parent of A.B is A
+               //
+               static public string ImplicitParent (string ns)
+               {
+                       int i = ns.LastIndexOf (".");
+                       if (i < 0)
+                               return null;
+                       
+                       return ns.Substring (0, i);
+               }
+
+               static Type NamespaceLookup (DeclSpace ds, string name, Location loc)
+               {
+                       Type t;
+
+                       //
+                       // Try in the current namespace and all its implicit parents
+                       //
+                       for (NamespaceEntry ns = ds.Namespace; ns != null; ns = ns.ImplicitParent) {
+                               t = TypeManager.LookupType (MakeFQN (ns.Name, name));
+                               if (t != null) {
+                                       if (!ds.CheckAccessLevel (t))
+                                               t = null;
+                               }
+                               if (t != null)
+                                       return t;
+                       }
+                       
+                       //
+                       // It's possible that name already is fully qualified. So we do
+                       // a simple direct lookup without adding any namespace names
+                       //
+                       t = TypeManager.LookupType (name); 
+                       if (t != null)
+                               return t;
+
+                       //
+                       // Try the aliases in the current namespace
+                       //
+                       string alias = ds.Namespace.LookupAlias (name);
+
+                       if (alias != null) {
+                               t = TypeManager.LookupType (alias);
+                               if (t != null)
+                                       return t;
+
+                               t = TypeManager.LookupType (MakeFQN (alias, name));
+                               if (t != null)
+                                       return t;
+                       }
+                       
+                       for (NamespaceEntry ns = ds.Namespace; ns != null; ns = ns.Parent) {
+                               //
+                               // Look in the namespace ns
+                               //
+                               t = TypeManager.LookupType (MakeFQN (ns.Name, name));
+                               if (t != null) {
+                                       if (!ds.CheckAccessLevel (t))
+                                               t = null;
+                               }
+                               if (t != null)
+                                       return t;
+                               
+                               //
+                               // Then try with the using clauses
+                               //
+                               Type match = null;
+                               foreach (Namespace using_ns in ns.GetUsingTable ()) {
+                                       string full_name = DeclSpace.MakeFQN (using_ns.Name, name);
+                                       match = TypeManager.LookupType (full_name);
+                                       if (match != null){
+                                               if (t != null) {
+                                                       if (ds.CheckAccessLevel (match)) {
+                                                               DeclSpace.Error_AmbiguousTypeReference (loc, name, t, match);
+                                                               return null;
+                                                       }
+                                                       continue;
+                                               } else {
+                                                       if (ds.CheckAccessLevel (match))
+                                                               t = match;
+                                               }
+                                       }
+                               }
+
+                               if (t != null)
+                                       return t;
+
+                               //
+                               // Try with aliases
+                               //
+                               string a = ns.LookupAlias (name);
+                               if (a != null) {
+                                       t = TypeManager.LookupType (a);
+                                       if (t != null)
+                                               return t;
+
+                                       t = TypeManager.LookupType (MakeFQN (a, name));
+                                       if (t != null)
+                                               return t;
+                               }
+                       }
+
+                       return null;
+               }
+               
+               //
+               // Public function used to locate types, this can only
+               // be used after the ResolveTree function has been invoked.
+               //
+               // Returns: Type or null if they type can not be found.
+               //
+               // Come to think of it, this should be a DeclSpace
+               //
+               static public Type LookupType (DeclSpace ds, string name, bool silent, Location loc)
+               {
+                       Type t;
+
+                       if (ds.Cache.Contains (name)){
+                               t = (Type) ds.Cache [name];
+                               if (t != null)
+                                       return t;
+                       } else {
+                               //
+                               // For the case the type we are looking for is nested within this one
+                               // or is in any base class
+                               //
+                               DeclSpace containing_ds = ds;
+                               while (containing_ds != null){
+                                       Type current_type = containing_ds.TypeBuilder;
+                                       
+                                       while (current_type != null) {
+                                               //
+                                               // nested class
+                                               //
+                                               t = TypeManager.LookupType (current_type.FullName + "." + name);
+                                               if (t != null){
+                                                       ds.Cache [name] = t;
+                                                       return t;
+                                               }
+                                               
+                                               current_type = current_type.BaseType;
+                                       }
+                                       
+                                       containing_ds = containing_ds.Parent;
+                               }
+                               
+                               t = NamespaceLookup (ds, name, loc);
+                               if (t != null){
+                                       ds.Cache [name] = t;
+                                       return t;
+                               }
+                       }
+
+                       if (!silent)
+                               Report.Error (246, loc, "Cannot find type `"+name+"'");
+                       
+                       return null;
+               }
+
+               // <summary>
+               //   This is the silent version of LookupType, you can use this
+               //   to `probe' for a type
+               // </summary>
+               static public Type LookupType (TypeContainer tc, string name, Location loc)
+               {
+                       return LookupType (tc, name, true, loc);
+               }
+
+               static public bool IsNamespace (string name)
+               {
+                       Namespace ns;
+
+                       if (tree.Namespaces != null){
+                               ns = (Namespace) tree.Namespaces [name];
+
+                               if (ns != null)
+                                       return true;
+                       }
+
+                       return false;
+               }
+
+               static void Report1530 (Location loc)
+               {
+                       Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
+               }
+               
+               static public void PopulateCoreType (TypeContainer root, string name)
+               {
+                       DeclSpace ds = (DeclSpace) root.GetDefinition (name);
+
+                       ds.DefineMembers (root);
+                       ds.Define (root);
+               }
+               
+               static public void BootCorlib_PopulateCoreTypes ()
+               {
+                       TypeContainer root = tree.Types;
+
+                       PopulateCoreType (root, "System.Object");
+                       PopulateCoreType (root, "System.ValueType");
+                       PopulateCoreType (root, "System.Attribute");
+               }
+               
+               // <summary>
+               //   Populates the structs and classes with fields and methods
+               // </summary>
+               //
+               // This is invoked after all interfaces, structs and classes
+               // have been defined through `ResolveTree' 
+               static public void PopulateTypes ()
+               {
+                       TypeContainer root = Tree.Types;
+
+                       if (attribute_types != null)
+                               foreach (TypeContainer tc in attribute_types)
+                                       tc.DefineMembers (root);
+                       
+                       if (interface_resolve_order != null){
+                               foreach (Interface iface in interface_resolve_order)
+                                       if ((iface.ModFlags & Modifiers.NEW) == 0)
+                                               iface.DefineMembers (root);
+                                       else
+                                               Report1530 (iface.Location);
+                       }
+
+
+                       if (type_container_resolve_order != null){
+                               if (RootContext.StdLib){
+                                       foreach (TypeContainer tc in type_container_resolve_order)
+                                               tc.DefineMembers (root);
+                               } else {
+                                       foreach (TypeContainer tc in type_container_resolve_order) {
+                                               // When compiling corlib, these types have already been
+                                               // populated from BootCorlib_PopulateCoreTypes ().
+                                               if (((tc.Name == "System.Object") ||
+                                                    (tc.Name == "System.Attribute") ||
+                                                    (tc.Name == "System.ValueType")))
+                                               continue;
+
+                                               tc.DefineMembers (root);
+                                       }
+                               } 
+                       }
+
+                       ArrayList delegates = root.Delegates;
+                       if (delegates != null){
+                               foreach (Delegate d in delegates)
+                                       if ((d.ModFlags & Modifiers.NEW) == 0)
+                                               d.DefineMembers (root);
+                                       else
+                                               Report1530 (d.Location);
+                       }
+
+                       ArrayList enums = root.Enums;
+                       if (enums != null){
+                               foreach (Enum en in enums)
+                                       if ((en.ModFlags & Modifiers.NEW) == 0)
+                                               en.DefineMembers (root);
+                                       else
+                                               Report1530 (en.Location);
+                       }
+               }
+
+               //
+               // A generic hook delegate
+               //
+               public delegate void Hook ();
+
+               //
+               // A hook invoked when the code has been generated.
+               //
+               public static event Hook EmitCodeHook;
+
+               //
+               // DefineTypes is used to fill in the members of each type.
+               //
+               static public void DefineTypes ()
+               {
+                       TypeContainer root = Tree.Types;
+
+                       if (attribute_types != null)
+                               foreach (TypeContainer tc in attribute_types)
+                                       tc.Define (root);
+                       
+                       if (interface_resolve_order != null){
+                               foreach (Interface iface in interface_resolve_order)
+                                       if ((iface.ModFlags & Modifiers.NEW) == 0)
+                                               iface.Define (root);
+                       }
+
+
+                       if (type_container_resolve_order != null){
+                               foreach (TypeContainer tc in type_container_resolve_order) {
+                                       // When compiling corlib, these types have already been
+                                       // populated from BootCorlib_PopulateCoreTypes ().
+                                       if (!RootContext.StdLib &&
+                                           ((tc.Name == "System.Object") ||
+                                            (tc.Name == "System.Attribute") ||
+                                            (tc.Name == "System.ValueType")))
+                                               continue;
+
+                                       if ((tc.ModFlags & Modifiers.NEW) == 0)
+                                               tc.Define (root);
+                               }
+                       }
+
+                       ArrayList delegates = root.Delegates;
+                       if (delegates != null){
+                               foreach (Delegate d in delegates)
+                                       if ((d.ModFlags & Modifiers.NEW) == 0)
+                                               d.Define (root);
+                       }
+
+                       ArrayList enums = root.Enums;
+                       if (enums != null){
+                               foreach (Enum en in enums)
+                                       if ((en.ModFlags & Modifiers.NEW) == 0)
+                                               en.Define (root);
+                       }
+               }
+
+               static public void EmitCode ()
+               {
+                       //
+                       // Because of the strange way in which we do things, global
+                       // attributes must be processed first.
+                       //
+                       if (global_attributes.Count > 0){
+                               AssemblyBuilder ab = CodeGen.AssemblyBuilder;
+                               TypeContainer dummy = new TypeContainer (null, "", new Location (-1));
+                               EmitContext temp_ec = new EmitContext (
+                                       dummy, Mono.CSharp.Location.Null, null, null, 0, false);
+                       
+                               foreach (DictionaryEntry de in global_attributes){
+                                       NamespaceEntry ns = (NamespaceEntry) de.Key;
+                                       Attributes attrs = (Attributes) de.Value;
+                                       
+                                       dummy.Namespace = ns;
+                                       Attribute.ApplyAttributes (temp_ec, ab, ab, attrs);
+                               }
+                       }
+                        
+                       if (attribute_types != null)
+                               foreach (TypeContainer tc in attribute_types)
+                                       tc.Emit ();
+
+                        if (interface_resolve_order != null){
+                               foreach (Interface iface in interface_resolve_order)
+                                        iface.Emit (Tree.Types);
+                       }                        
+                       
+                       if (type_container_resolve_order != null) {
+                               foreach (TypeContainer tc in type_container_resolve_order)
+                                       tc.EmitConstants ();
+                               
+                               foreach (TypeContainer tc in type_container_resolve_order)
+                                       tc.Emit ();
+                       }
+                       
+                       //
+                       // Run any hooks after all the types have been defined.
+                       // This is used to create nested auxiliary classes for example
+                       //
+
+                       if (EmitCodeHook != null)
+                               EmitCodeHook ();
+
+                       
+                       if (Unsafe) {
+                               if (TypeManager.unverifiable_code_ctor == null) {
+                                       Console.WriteLine ("Internal error ! Cannot set unverifiable code attribute.");
+                                       return;
+                               }
+                               
+                               CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.unverifiable_code_ctor,
+                                                                                       new object [0]);
+                               CodeGen.ModuleBuilder.SetCustomAttribute (cb);
+                       }
+               }
+               
+               //
+               // Public Field, used to track which method is the public entry
+               // point.
+               //
+               static public MethodInfo EntryPoint;
+
+                //
+                // Track the location of the entry point.
+                //
+                static public Location EntryPointLocation;
+
+               //
+               // These are used to generate unique names on the structs and fields.
+               //
+               static int field_count;
+               
+               //
+               // Makes an initialized struct, returns the field builder that
+               // references the data.  Thanks go to Sergey Chaban for researching
+               // how to do this.  And coming up with a shorter mechanism than I
+               // was able to figure out.
+               //
+               // This works but makes an implicit public struct $ArrayType$SIZE and
+               // makes the fields point to it.  We could get more control if we did
+               // use instead:
+               //
+               // 1. DefineNestedType on the impl_details_class with our struct.
+               //
+               // 2. Define the field on the impl_details_class
+               //
+               static public FieldBuilder MakeStaticData (byte [] data)
+               {
+                       FieldBuilder fb;
+                       int size = data.Length;
+                       
+                       if (impl_details_class == null){
+                               impl_details_class = CodeGen.ModuleBuilder.DefineType (
+                                       "<PrivateImplementationDetails>",
+                                        TypeAttributes.NotPublic,
+                                        TypeManager.object_type);
+                                
+                               RegisterHelperClass (impl_details_class);
+                       }
+
+                       fb = impl_details_class.DefineInitializedData (
+                               "$$field-" + (field_count++), data,
+                               FieldAttributes.Static | FieldAttributes.Assembly);
+                       
+                       return fb;
+               }
+
+               //
+               // Adds a global attribute that was declared in `container', 
+               // the attribute is in `attr', and it was defined at `loc'
+               //
+               static public void AddGlobalAttributeSection (TypeContainer container, AttributeSection attr)
+               {
+                       NamespaceEntry ns = container.Namespace;
+                       Attributes a = (Attributes) global_attributes [ns];
+
+                       if (a == null)
+                               global_attributes [ns] = new Attributes (attr);
+                       else
+                               a.AddAttributeSection (attr);
+               }
+       }
+}
+             
+
diff --git a/mcs/gmcs/statement.cs b/mcs/gmcs/statement.cs
new file mode 100755 (executable)
index 0000000..9f021bb
--- /dev/null
@@ -0,0 +1,5768 @@
+//
+// statement.cs: Statement representation for the IL tree.
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//   Martin Baulig (martin@gnome.org)
+//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+//
+
+using System;
+using System.Text;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+
+namespace Mono.CSharp {
+
+       using System.Collections;
+       
+       public abstract class Statement {
+               public Location loc;
+               
+               ///
+               /// Resolves the statement, true means that all sub-statements
+               /// did resolve ok.
+               //
+               public virtual bool Resolve (EmitContext ec)
+               {
+                       return true;
+               }
+               
+               /// <summary>
+               ///   Return value indicates whether all code paths emitted return.
+               /// </summary>
+               protected abstract bool DoEmit (EmitContext ec);
+
+               /// <summary>
+               ///   Return value indicates whether all code paths emitted return.
+               /// </summary>
+               public virtual bool Emit (EmitContext ec)
+               {
+                       ec.Mark (loc, true);
+                       return DoEmit (ec);
+               }
+               
+               /// <remarks>
+               ///    Encapsulates the emission of a boolean test and jumping to a
+               ///    destination.
+               ///
+               ///    This will emit the bool expression in `bool_expr' and if
+               ///    `target_is_for_true' is true, then the code will generate a 
+               ///    brtrue to the target.   Otherwise a brfalse. 
+               /// </remarks>
+               public static void EmitBoolExpression (EmitContext ec, Expression bool_expr,
+                                                      Label target, bool target_is_for_true)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       bool invert = false;
+                       if (bool_expr is Unary){
+                               Unary u = (Unary) bool_expr;
+                               
+                               if (u.Oper == Unary.Operator.LogicalNot){
+                                       invert = true;
+
+                                       u.EmitLogicalNot (ec);
+                               }
+                       } else if (bool_expr is Binary){
+                               Binary b = (Binary) bool_expr;
+
+                               if (b.EmitBranchable (ec, target, target_is_for_true))
+                                       return;
+                       }
+
+                       if (!invert)
+                               bool_expr.Emit (ec);
+
+                       if (target_is_for_true){
+                               if (invert)
+                                       ig.Emit (OpCodes.Brfalse, target);
+                               else
+                                       ig.Emit (OpCodes.Brtrue, target);
+                       } else {
+                               if (invert)
+                                       ig.Emit (OpCodes.Brtrue, target);
+                               else
+                                       ig.Emit (OpCodes.Brfalse, target);
+                       }
+               }
+
+               public static void Warning_DeadCodeFound (Location loc)
+               {
+                       Report.Warning (162, loc, "Unreachable code detected");
+               }
+       }
+
+       public class EmptyStatement : Statement {
+               public override bool Resolve (EmitContext ec)
+               {
+                       return true;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       return false;
+               }
+       }
+       
+       public class If : Statement {
+               Expression expr;
+               public Statement TrueStatement;
+               public Statement FalseStatement;
+               
+               public If (Expression expr, Statement trueStatement, Location l)
+               {
+                       this.expr = expr;
+                       TrueStatement = trueStatement;
+                       loc = l;
+               }
+
+               public If (Expression expr,
+                          Statement trueStatement,
+                          Statement falseStatement,
+                          Location l)
+               {
+                       this.expr = expr;
+                       TrueStatement = trueStatement;
+                       FalseStatement = falseStatement;
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       Report.Debug (1, "START IF BLOCK", loc);
+
+                       expr = Expression.ResolveBoolean (ec, expr, loc);
+                       if (expr == null){
+                               return false;
+                       }
+                       
+                       ec.StartFlowBranching (FlowBranchingType.BLOCK, loc);
+                       
+                       if (!TrueStatement.Resolve (ec)) {
+                               ec.KillFlowBranching ();
+                               return false;
+                       }
+
+                       ec.CurrentBranching.CreateSibling ();
+
+                       if ((FalseStatement != null) && !FalseStatement.Resolve (ec)) {
+                               ec.KillFlowBranching ();
+                               return false;
+                       }
+                                       
+                       ec.EndFlowBranching ();
+
+                       Report.Debug (1, "END IF BLOCK", loc);
+
+                       return true;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Label false_target = ig.DefineLabel ();
+                       Label end;
+                       bool is_true_ret, is_false_ret;
+
+                       //
+                       // Dead code elimination
+                       //
+                       if (expr is BoolConstant){
+                               bool take = ((BoolConstant) expr).Value;
+
+                               if (take){
+                                       if (FalseStatement != null){
+                                               Warning_DeadCodeFound (FalseStatement.loc);
+                                       }
+                                       return TrueStatement.Emit (ec);
+                               } else {
+                                       Warning_DeadCodeFound (TrueStatement.loc);
+                                       if (FalseStatement != null)
+                                               return FalseStatement.Emit (ec);
+                               }
+                       }
+                       
+                       EmitBoolExpression (ec, expr, false_target, false);
+
+                       is_true_ret = TrueStatement.Emit (ec);
+                       is_false_ret = is_true_ret;
+
+                       if (FalseStatement != null){
+                               bool branch_emitted = false;
+                               
+                               end = ig.DefineLabel ();
+                               if (!is_true_ret){
+                                       ig.Emit (OpCodes.Br, end);
+                                       branch_emitted = true;
+                               }
+
+                               ig.MarkLabel (false_target);
+                               is_false_ret = FalseStatement.Emit (ec);
+
+                               if (branch_emitted)
+                                       ig.MarkLabel (end);
+                       } else {
+                               ig.MarkLabel (false_target);
+                               is_false_ret = false;
+                       }
+
+                       return is_true_ret && is_false_ret;
+               }
+       }
+
+       public class Do : Statement {
+               public Expression expr;
+               public readonly Statement  EmbeddedStatement;
+               bool infinite, may_return;
+               
+               public Do (Statement statement, Expression boolExpr, Location l)
+               {
+                       expr = boolExpr;
+                       EmbeddedStatement = statement;
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       bool ok = true;
+
+                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
+
+                       if (!EmbeddedStatement.Resolve (ec))
+                               ok = false;
+
+                       expr = Expression.ResolveBoolean (ec, expr, loc);
+                       if (expr == null)
+                               ok = false;
+                       else if (expr is BoolConstant){
+                               bool res = ((BoolConstant) expr).Value;
+
+                               if (res)
+                                       infinite = true;
+                       }
+
+                       ec.CurrentBranching.Infinite = infinite;
+                       FlowReturns returns = ec.EndFlowBranching ();
+                       may_return = returns != FlowReturns.NEVER;
+
+                       return ok;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Label loop = ig.DefineLabel ();
+                       Label old_begin = ec.LoopBegin;
+                       Label old_end = ec.LoopEnd;
+                       bool  old_inloop = ec.InLoop;
+                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
+                       
+                       ec.LoopBegin = ig.DefineLabel ();
+                       ec.LoopEnd = ig.DefineLabel ();
+                       ec.InLoop = true;
+                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
+                               
+                       ig.MarkLabel (loop);
+                       EmbeddedStatement.Emit (ec);
+                       ig.MarkLabel (ec.LoopBegin);
+
+                       //
+                       // Dead code elimination
+                       //
+                       if (expr is BoolConstant){
+                               bool res = ((BoolConstant) expr).Value;
+
+                               if (res)
+                                       ec.ig.Emit (OpCodes.Br, loop); 
+                       } else
+                               EmitBoolExpression (ec, expr, loop, true);
+                       
+                       ig.MarkLabel (ec.LoopEnd);
+
+                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
+                       ec.LoopBegin = old_begin;
+                       ec.LoopEnd = old_end;
+                       ec.InLoop = old_inloop;
+
+                       if (infinite)
+                               return may_return == false;
+                       else
+                               return false;
+               }
+       }
+
+       public class While : Statement {
+               public Expression expr;
+               public readonly Statement Statement;
+               bool may_return, empty, infinite;
+               
+               public While (Expression boolExpr, Statement statement, Location l)
+               {
+                       this.expr = boolExpr;
+                       Statement = statement;
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       bool ok = true;
+
+                       expr = Expression.ResolveBoolean (ec, expr, loc);
+                       if (expr == null)
+                               return false;
+
+                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
+
+                       //
+                       // Inform whether we are infinite or not
+                       //
+                       if (expr is BoolConstant){
+                               BoolConstant bc = (BoolConstant) expr;
+
+                               if (bc.Value == false){
+                                       Warning_DeadCodeFound (Statement.loc);
+                                       empty = true;
+                               } else
+                                       infinite = true;
+                       } else {
+                               //
+                               // We are not infinite, so the loop may or may not be executed.
+                               //
+                               ec.CurrentBranching.CreateSibling ();
+                       }
+
+                       if (!Statement.Resolve (ec))
+                               ok = false;
+
+                       if (empty)
+                               ec.KillFlowBranching ();
+                       else {
+                               ec.CurrentBranching.Infinite = infinite;
+                               FlowReturns returns = ec.EndFlowBranching ();
+                               may_return = returns != FlowReturns.NEVER;
+                       }
+
+                       return ok;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       if (empty)
+                               return false;
+
+                       ILGenerator ig = ec.ig;
+                       Label old_begin = ec.LoopBegin;
+                       Label old_end = ec.LoopEnd;
+                       bool old_inloop = ec.InLoop;
+                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
+                       bool ret;
+                       
+                       ec.LoopBegin = ig.DefineLabel ();
+                       ec.LoopEnd = ig.DefineLabel ();
+                       ec.InLoop = true;
+                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
+
+                       //
+                       // Inform whether we are infinite or not
+                       //
+                       if (expr is BoolConstant){
+                               BoolConstant bc = (BoolConstant) expr;
+
+                               ig.MarkLabel (ec.LoopBegin);
+                               Statement.Emit (ec);
+                               ig.Emit (OpCodes.Br, ec.LoopBegin);
+                                       
+                               //
+                               // Inform that we are infinite (ie, `we return'), only
+                               // if we do not `break' inside the code.
+                               //
+                               ret = may_return == false;
+                               ig.MarkLabel (ec.LoopEnd);
+                       } else {
+                               Label while_loop = ig.DefineLabel ();
+
+                               ig.Emit (OpCodes.Br, ec.LoopBegin);
+                               ig.MarkLabel (while_loop);
+
+                               Statement.Emit (ec);
+                       
+                               ig.MarkLabel (ec.LoopBegin);
+
+                               EmitBoolExpression (ec, expr, while_loop, true);
+                               ig.MarkLabel (ec.LoopEnd);
+
+                               ret = false;
+                       }       
+
+                       ec.LoopBegin = old_begin;
+                       ec.LoopEnd = old_end;
+                       ec.InLoop = old_inloop;
+                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
+
+                       return ret;
+               }
+       }
+
+       public class For : Statement {
+               Expression Test;
+               readonly Statement InitStatement;
+               readonly Statement Increment;
+               readonly Statement Statement;
+               bool may_return, infinite, empty;
+               
+               public For (Statement initStatement,
+                           Expression test,
+                           Statement increment,
+                           Statement statement,
+                           Location l)
+               {
+                       InitStatement = initStatement;
+                       Test = test;
+                       Increment = increment;
+                       Statement = statement;
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       bool ok = true;
+
+                       if (InitStatement != null){
+                               if (!InitStatement.Resolve (ec))
+                                       ok = false;
+                       }
+
+                       if (Test != null){
+                               Test = Expression.ResolveBoolean (ec, Test, loc);
+                               if (Test == null)
+                                       ok = false;
+                               else if (Test is BoolConstant){
+                                       BoolConstant bc = (BoolConstant) Test;
+
+                                       if (bc.Value == false){
+                                               Warning_DeadCodeFound (Statement.loc);
+                                               empty = true;
+                                       } else
+                                               infinite = true;
+                               }
+                       } else
+                               infinite = true;
+
+                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
+                       if (!infinite)
+                               ec.CurrentBranching.CreateSibling ();
+
+                       if (!Statement.Resolve (ec))
+                               ok = false;
+
+                       if (Increment != null){
+                               if (!Increment.Resolve (ec))
+                                       ok = false;
+                       }
+
+                       if (empty)
+                               ec.KillFlowBranching ();
+                       else {
+                               ec.CurrentBranching.Infinite = infinite;
+                               FlowReturns returns = ec.EndFlowBranching ();
+                               may_return = returns != FlowReturns.NEVER;
+                       }
+
+                       return ok;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       if (empty)
+                               return false;
+
+                       ILGenerator ig = ec.ig;
+                       Label old_begin = ec.LoopBegin;
+                       Label old_end = ec.LoopEnd;
+                       bool old_inloop = ec.InLoop;
+                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
+                       Label loop = ig.DefineLabel ();
+                       Label test = ig.DefineLabel ();
+                       
+                       if (InitStatement != null)
+                               if (! (InitStatement is EmptyStatement))
+                                       InitStatement.Emit (ec);
+
+                       ec.LoopBegin = ig.DefineLabel ();
+                       ec.LoopEnd = ig.DefineLabel ();
+                       ec.InLoop = true;
+                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
+
+                       ig.Emit (OpCodes.Br, test);
+                       ig.MarkLabel (loop);
+                       Statement.Emit (ec);
+
+                       ig.MarkLabel (ec.LoopBegin);
+                       if (!(Increment is EmptyStatement))
+                               Increment.Emit (ec);
+
+                       ig.MarkLabel (test);
+                       //
+                       // If test is null, there is no test, and we are just
+                       // an infinite loop
+                       //
+                       if (Test != null){
+                               //
+                               // The Resolve code already catches the case for Test == BoolConstant (false)
+                               // so we know that this is true
+                               //
+                               if (Test is BoolConstant)
+                                       ig.Emit (OpCodes.Br, loop);
+                               else
+                                       EmitBoolExpression (ec, Test, loop, true);
+                       } else
+                               ig.Emit (OpCodes.Br, loop);
+                       ig.MarkLabel (ec.LoopEnd);
+
+                       ec.LoopBegin = old_begin;
+                       ec.LoopEnd = old_end;
+                       ec.InLoop = old_inloop;
+                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
+                       
+                       //
+                       // Inform whether we are infinite or not
+                       //
+                       if (Test != null){
+                               if (Test is BoolConstant){
+                                       BoolConstant bc = (BoolConstant) Test;
+
+                                       if (bc.Value)
+                                               return may_return == false;
+                               }
+                               return false;
+                       } else
+                               return may_return == false;
+               }
+       }
+       
+       public class StatementExpression : Statement {
+               ExpressionStatement expr;
+               
+               public StatementExpression (ExpressionStatement expr, Location l)
+               {
+                       this.expr = expr;
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       expr = expr.ResolveStatement (ec);
+                       return expr != null;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       expr.EmitStatement (ec);
+
+                       return false;
+               }
+
+               public override string ToString ()
+               {
+                       return "StatementExpression (" + expr + ")";
+               }
+       }
+
+       /// <summary>
+       ///   Implements the return statement
+       /// </summary>
+       public class Return : Statement {
+               public Expression Expr;
+               
+               public Return (Expression expr, Location l)
+               {
+                       Expr = expr;
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       if (Expr != null){
+                               Expr = Expr.Resolve (ec);
+                               if (Expr == null)
+                                       return false;
+                       }
+
+                       if (ec.InIterator){
+                               Report.Error (-206, loc, "Return statement not allowed inside iterators");
+                               return false;
+                       }
+                               
+                       FlowBranching.UsageVector vector = ec.CurrentBranching.CurrentUsageVector;
+
+                       if (ec.CurrentBranching.InTryBlock ())
+                               ec.CurrentBranching.AddFinallyVector (vector);
+                       else
+                               vector.CheckOutParameters (ec.CurrentBranching);
+
+                       vector.Returns = FlowReturns.ALWAYS;
+                       vector.Breaks = FlowReturns.ALWAYS;
+                       return true;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       if (ec.InFinally){
+                               Report.Error (157, loc, "Control can not leave the body of the finally block");
+                               return false;
+                       }
+                       
+                       if (ec.ReturnType == null){
+                               if (Expr != null){
+                                       Report.Error (127, loc, "Return with a value not allowed here");
+                                       return true;
+                               }
+                       } else {
+                               if (Expr == null){
+                                       Report.Error (126, loc, "An object of type `" +
+                                                     TypeManager.CSharpName (ec.ReturnType) + "' is " +
+                                                     "expected for the return statement");
+                                       return true;
+                               }
+
+                               if (Expr.Type != ec.ReturnType)
+                                       Expr = Convert.ImplicitConversionRequired (
+                                               ec, Expr, ec.ReturnType, loc);
+
+                               if (Expr == null)
+                                       return true;
+
+                               Expr.Emit (ec);
+
+                               if (ec.InTry || ec.InCatch)
+                                       ec.ig.Emit (OpCodes.Stloc, ec.TemporaryReturn ());
+                       }
+
+                       if (ec.InTry || ec.InCatch) {
+                               if (!ec.HasReturnLabel) {
+                                       ec.ReturnLabel = ec.ig.DefineLabel ();
+                                       ec.HasReturnLabel = true;
+                               }
+                               ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
+                       } else {
+                               ec.ig.Emit (OpCodes.Ret);
+                               ec.NeedExplicitReturn = false;
+                       }
+
+                       return true; 
+               }
+       }
+
+       public class Goto : Statement {
+               string target;
+               Block block;
+               LabeledStatement label;
+               
+               public override bool Resolve (EmitContext ec)
+               {
+                       label = block.LookupLabel (target);
+                       if (label == null){
+                               Report.Error (
+                                       159, loc,
+                                       "No such label `" + target + "' in this scope");
+                               return false;
+                       }
+
+                       // If this is a forward goto.
+                       if (!label.IsDefined)
+                               label.AddUsageVector (ec.CurrentBranching.CurrentUsageVector);
+
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+
+                       return true;
+               }
+               
+               public Goto (Block parent_block, string label, Location l)
+               {
+                       block = parent_block;
+                       loc = l;
+                       target = label;
+               }
+
+               public string Target {
+                       get {
+                               return target;
+                       }
+               }
+
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       Label l = label.LabelTarget (ec);
+                       ec.ig.Emit (OpCodes.Br, l);
+                       
+                       return false;
+               }
+       }
+
+       public class LabeledStatement : Statement {
+               public readonly Location Location;
+               string label_name;
+               bool defined;
+               bool referenced;
+               Label label;
+
+               ArrayList vectors;
+               
+               public LabeledStatement (string label_name, Location l)
+               {
+                       this.label_name = label_name;
+                       this.Location = l;
+               }
+
+               public Label LabelTarget (EmitContext ec)
+               {
+                       if (defined)
+                               return label;
+                       label = ec.ig.DefineLabel ();
+                       defined = true;
+
+                       return label;
+               }
+
+               public bool IsDefined {
+                       get {
+                               return defined;
+                       }
+               }
+
+               public bool HasBeenReferenced {
+                       get {
+                               return referenced;
+                       }
+               }
+
+               public void AddUsageVector (FlowBranching.UsageVector vector)
+               {
+                       if (vectors == null)
+                               vectors = new ArrayList ();
+
+                       vectors.Add (vector.Clone ());
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       if (vectors != null)
+                               ec.CurrentBranching.CurrentUsageVector.MergeJumpOrigins (vectors);
+                       else {
+                               ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.NEVER;
+                               ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.NEVER;
+                       }
+
+                       referenced = true;
+
+                       return true;
+               }
+
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       LabelTarget (ec);
+                       ec.ig.MarkLabel (label);
+
+                       return false;
+               }
+       }
+       
+
+       /// <summary>
+       ///   `goto default' statement
+       /// </summary>
+       public class GotoDefault : Statement {
+               
+               public GotoDefault (Location l)
+               {
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+                       return true;
+               }
+
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       if (ec.Switch == null){
+                               Report.Error (153, loc, "goto default is only valid in a switch statement");
+                               return false;
+                       }
+
+                       if (!ec.Switch.GotDefault){
+                               Report.Error (159, loc, "No default target on switch statement");
+                               return false;
+                       }
+                       ec.ig.Emit (OpCodes.Br, ec.Switch.DefaultTarget);
+                       return false;
+               }
+       }
+
+       /// <summary>
+       ///   `goto case' statement
+       /// </summary>
+       public class GotoCase : Statement {
+               Expression expr;
+               Label label;
+               
+               public GotoCase (Expression e, Location l)
+               {
+                       expr = e;
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       if (ec.Switch == null){
+                               Report.Error (153, loc, "goto case is only valid in a switch statement");
+                               return false;
+                       }
+
+                       expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return false;
+
+                       if (!(expr is Constant)){
+                               Report.Error (159, loc, "Target expression for goto case is not constant");
+                               return false;
+                       }
+
+                       object val = Expression.ConvertIntLiteral (
+                               (Constant) expr, ec.Switch.SwitchType, loc);
+
+                       if (val == null)
+                               return false;
+                                       
+                       SwitchLabel sl = (SwitchLabel) ec.Switch.Elements [val];
+
+                       if (sl == null){
+                               Report.Error (
+                                       159, loc,
+                                       "No such label 'case " + val + "': for the goto case");
+                               return false;
+                       }
+
+                       label = sl.ILLabelCode;
+
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.UNREACHABLE;
+                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.ALWAYS;
+                       return true;
+               }
+
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Br, label);
+                       return true;
+               }
+       }
+       
+       public class Throw : Statement {
+               Expression expr;
+               
+               public Throw (Expression expr, Location l)
+               {
+                       this.expr = expr;
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       if (expr != null){
+                               expr = expr.Resolve (ec);
+                               if (expr == null)
+                                       return false;
+
+                               ExprClass eclass = expr.eclass;
+
+                               if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
+                                     eclass == ExprClass.Value || eclass == ExprClass.IndexerAccess)) {
+                                       expr.Error_UnexpectedKind ("value, variable, property or indexer access ");
+                                       return false;
+                               }
+
+                               Type t = expr.Type;
+                               
+                               if ((t != TypeManager.exception_type) &&
+                                   !t.IsSubclassOf (TypeManager.exception_type) &&
+                                   !(expr is NullLiteral)) {
+                                       Report.Error (155, loc,
+                                                     "The type caught or thrown must be derived " +
+                                                     "from System.Exception");
+                                       return false;
+                               }
+                       }
+
+                       ec.CurrentBranching.CurrentUsageVector.Returns = FlowReturns.EXCEPTION;
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.EXCEPTION;
+                       return true;
+               }
+                       
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       if (expr == null){
+                               if (ec.InCatch)
+                                       ec.ig.Emit (OpCodes.Rethrow);
+                               else {
+                                       Report.Error (
+                                               156, loc,
+                                               "A throw statement with no argument is only " +
+                                               "allowed in a catch clause");
+                               }
+                               return false;
+                       }
+
+                       expr.Emit (ec);
+
+                       ec.ig.Emit (OpCodes.Throw);
+
+                       return true;
+               }
+       }
+
+       public class Break : Statement {
+               
+               public Break (Location l)
+               {
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       ec.CurrentBranching.MayLeaveLoop = true;
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+                       return true;
+               }
+
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       if (ec.InLoop == false && ec.Switch == null){
+                               Report.Error (139, loc, "No enclosing loop or switch to continue to");
+                               return false;
+                       }
+
+                       if (ec.InTry || ec.InCatch)
+                               ig.Emit (OpCodes.Leave, ec.LoopEnd);
+                       else
+                               ig.Emit (OpCodes.Br, ec.LoopEnd);
+
+                       return false;
+               }
+       }
+
+       public class Continue : Statement {
+               
+               public Continue (Location l)
+               {
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+                       return true;
+               }
+
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       Label begin = ec.LoopBegin;
+                       
+                       if (!ec.InLoop){
+                               Report.Error (139, loc, "No enclosing loop to continue to");
+                               return false;
+                       } 
+
+                       //
+                       // UGH: Non trivial.  This Br might cross a try/catch boundary
+                       // How can we tell?
+                       //
+                       // while () {
+                       //   try { ... } catch { continue; }
+                       // }
+                       //
+                       // From:
+                       // try {} catch { while () { continue; }}
+                       //
+                       if (ec.TryCatchLevel > ec.LoopBeginTryCatchLevel)
+                               ec.ig.Emit (OpCodes.Leave, begin);
+                       else if (ec.TryCatchLevel < ec.LoopBeginTryCatchLevel)
+                               throw new Exception ("Should never happen");
+                       else
+                               ec.ig.Emit (OpCodes.Br, begin);
+                       return false;
+               }
+       }
+
+       // <summary>
+       //   This is used in the control flow analysis code to specify whether the
+       //   current code block may return to its enclosing block before reaching
+       //   its end.
+       // </summary>
+       public enum FlowReturns {
+               // It can never return.
+               NEVER,
+
+               // This means that the block contains a conditional return statement
+               // somewhere.
+               SOMETIMES,
+
+               // The code always returns, ie. there's an unconditional return / break
+               // statement in it.
+               ALWAYS,
+
+               // The code always throws an exception.
+               EXCEPTION,
+
+               // The current code block is unreachable.  This happens if it's immediately
+               // following a FlowReturns.ALWAYS block.
+               UNREACHABLE
+       }
+
+       // <summary>
+       //   This is a special bit vector which can inherit from another bit vector doing a
+       //   copy-on-write strategy.  The inherited vector may have a smaller size than the
+       //   current one.
+       // </summary>
+       public class MyBitVector {
+               public readonly int Count;
+               public readonly MyBitVector InheritsFrom;
+
+               bool is_dirty;
+               BitArray vector;
+
+               public MyBitVector (int Count)
+                       : this (null, Count)
+               { }
+
+               public MyBitVector (MyBitVector InheritsFrom, int Count)
+               {
+                       this.InheritsFrom = InheritsFrom;
+                       this.Count = Count;
+               }
+
+               // <summary>
+               //   Checks whether this bit vector has been modified.  After setting this to true,
+               //   we won't use the inherited vector anymore, but our own copy of it.
+               // </summary>
+               public bool IsDirty {
+                       get {
+                               return is_dirty;
+                       }
+
+                       set {
+                               if (!is_dirty)
+                                       initialize_vector ();
+                       }
+               }
+
+               // <summary>
+               //   Get/set bit `index' in the bit vector.
+               // </summary>
+               public bool this [int index]
+               {
+                       get {
+                               if (index > Count)
+                                       throw new ArgumentOutOfRangeException ();
+
+                               // We're doing a "copy-on-write" strategy here; as long
+                               // as nobody writes to the array, we can use our parent's
+                               // copy instead of duplicating the vector.
+
+                               if (vector != null)
+                                       return vector [index];
+                               else if (InheritsFrom != null) {
+                                       BitArray inherited = InheritsFrom.Vector;
+
+                                       if (index < inherited.Count)
+                                               return inherited [index];
+                                       else
+                                               return false;
+                               } else
+                                       return false;
+                       }
+
+                       set {
+                               if (index > Count)
+                                       throw new ArgumentOutOfRangeException ();
+
+                               // Only copy the vector if we're actually modifying it.
+
+                               if (this [index] != value) {
+                                       initialize_vector ();
+
+                                       vector [index] = value;
+                               }
+                       }
+               }
+
+               // <summary>
+               //   If you explicitly convert the MyBitVector to a BitArray, you will get a deep
+               //   copy of the bit vector.
+               // </summary>
+               public static explicit operator BitArray (MyBitVector vector)
+               {
+                       vector.initialize_vector ();
+                       return vector.Vector;
+               }
+
+               // <summary>
+               //   Performs an `or' operation on the bit vector.  The `new_vector' may have a
+               //   different size than the current one.
+               // </summary>
+               public void Or (MyBitVector new_vector)
+               {
+                       BitArray new_array = new_vector.Vector;
+
+                       initialize_vector ();
+
+                       int upper;
+                       if (vector.Count < new_array.Count)
+                               upper = vector.Count;
+                       else
+                               upper = new_array.Count;
+
+                       for (int i = 0; i < upper; i++)
+                               vector [i] = vector [i] | new_array [i];
+               }
+
+               // <summary>
+               //   Perfonrms an `and' operation on the bit vector.  The `new_vector' may have
+               //   a different size than the current one.
+               // </summary>
+               public void And (MyBitVector new_vector)
+               {
+                       BitArray new_array = new_vector.Vector;
+
+                       initialize_vector ();
+
+                       int lower, upper;
+                       if (vector.Count < new_array.Count)
+                               lower = upper = vector.Count;
+                       else {
+                               lower = new_array.Count;
+                               upper = vector.Count;
+                       }
+
+                       for (int i = 0; i < lower; i++)
+                               vector [i] = vector [i] & new_array [i];
+
+                       for (int i = lower; i < upper; i++)
+                               vector [i] = false;
+               }
+
+               // <summary>
+               //   This does a deep copy of the bit vector.
+               // </summary>
+               public MyBitVector Clone ()
+               {
+                       MyBitVector retval = new MyBitVector (Count);
+
+                       retval.Vector = Vector;
+
+                       return retval;
+               }
+
+               BitArray Vector {
+                       get {
+                               if (vector != null)
+                                       return vector;
+                               else if (!is_dirty && (InheritsFrom != null))
+                                       return InheritsFrom.Vector;
+
+                               initialize_vector ();
+
+                               return vector;
+                       }
+
+                       set {
+                               initialize_vector ();
+
+                               for (int i = 0; i < Math.Min (vector.Count, value.Count); i++)
+                                       vector [i] = value [i];
+                       }
+               }
+
+               void initialize_vector ()
+               {
+                       if (vector != null)
+                               return;
+
+                       vector = new BitArray (Count, false);
+                       if (InheritsFrom != null)
+                               Vector = InheritsFrom.Vector;
+
+                       is_dirty = true;
+               }
+
+               public override string ToString ()
+               {
+                       StringBuilder sb = new StringBuilder ("MyBitVector (");
+
+                       BitArray vector = Vector;
+                       sb.Append (Count);
+                       sb.Append (",");
+                       if (!IsDirty)
+                               sb.Append ("INHERITED - ");
+                       for (int i = 0; i < vector.Count; i++) {
+                               if (i > 0)
+                                       sb.Append (",");
+                               sb.Append (vector [i]);
+                       }
+                       
+                       sb.Append (")");
+                       return sb.ToString ();
+               }
+       }
+
+       // <summary>
+       //   The type of a FlowBranching.
+       // </summary>
+       public enum FlowBranchingType {
+               // Normal (conditional or toplevel) block.
+               BLOCK,
+
+               // A loop block.
+               LOOP_BLOCK,
+
+               // Try/Catch block.
+               EXCEPTION,
+
+               // Switch block.
+               SWITCH,
+
+               // Switch section.
+               SWITCH_SECTION
+       }
+
+       // <summary>
+       //   A new instance of this class is created every time a new block is resolved
+       //   and if there's branching in the block's control flow.
+       // </summary>
+       public class FlowBranching {
+               // <summary>
+               //   The type of this flow branching.
+               // </summary>
+               public readonly FlowBranchingType Type;
+
+               // <summary>
+               //   The block this branching is contained in.  This may be null if it's not
+               //   a top-level block and it doesn't declare any local variables.
+               // </summary>
+               public readonly Block Block;
+
+               // <summary>
+               //   The parent of this branching or null if this is the top-block.
+               // </summary>
+               public readonly FlowBranching Parent;
+
+               // <summary>
+               //   Start-Location of this flow branching.
+               // </summary>
+               public readonly Location Location;
+
+               // <summary>
+               //   A list of UsageVectors.  A new vector is added each time control flow may
+               //   take a different path.
+               // </summary>
+               public UsageVector[] Siblings;
+
+               // <summary>
+               //   If this is an infinite loop.
+               // </summary>
+               public bool Infinite;
+
+               // <summary>
+               //   If we may leave the current loop.
+               // </summary>
+               public bool MayLeaveLoop;
+
+               //
+               // Private
+               //
+               VariableMap param_map, local_map;
+               ArrayList finally_vectors;
+
+               static int next_id = 0;
+               int id;
+
+               // <summary>
+               //   Performs an `And' operation on the FlowReturns status
+               //   (for instance, a block only returns ALWAYS if all its siblings
+               //   always return).
+               // </summary>
+               public static FlowReturns AndFlowReturns (FlowReturns a, FlowReturns b)
+               {
+                       if (b == FlowReturns.UNREACHABLE)
+                               return a;
+
+                       switch (a) {
+                       case FlowReturns.NEVER:
+                               if (b == FlowReturns.NEVER)
+                                       return FlowReturns.NEVER;
+                               else
+                                       return FlowReturns.SOMETIMES;
+
+                       case FlowReturns.SOMETIMES:
+                               return FlowReturns.SOMETIMES;
+
+                       case FlowReturns.ALWAYS:
+                               if ((b == FlowReturns.ALWAYS) || (b == FlowReturns.EXCEPTION))
+                                       return FlowReturns.ALWAYS;
+                               else
+                                       return FlowReturns.SOMETIMES;
+
+                       case FlowReturns.EXCEPTION:
+                               if (b == FlowReturns.EXCEPTION)
+                                       return FlowReturns.EXCEPTION;
+                               else if (b == FlowReturns.ALWAYS)
+                                       return FlowReturns.ALWAYS;
+                               else
+                                       return FlowReturns.SOMETIMES;
+                       }
+
+                       return b;
+               }
+
+               // <summary>
+               //   The vector contains a BitArray with information about which local variables
+               //   and parameters are already initialized at the current code position.
+               // </summary>
+               public class UsageVector {
+                       // <summary>
+                       //   If this is true, then the usage vector has been modified and must be
+                       //   merged when we're done with this branching.
+                       // </summary>
+                       public bool IsDirty;
+
+                       // <summary>
+                       //   The number of parameters in this block.
+                       // </summary>
+                       public readonly int CountParameters;
+
+                       // <summary>
+                       //   The number of locals in this block.
+                       // </summary>
+                       public readonly int CountLocals;
+
+                       // <summary>
+                       //   If not null, then we inherit our state from this vector and do a
+                       //   copy-on-write.  If null, then we're the first sibling in a top-level
+                       //   block and inherit from the empty vector.
+                       // </summary>
+                       public readonly UsageVector InheritsFrom;
+
+                       //
+                       // Private.
+                       //
+                       MyBitVector locals, parameters;
+                       FlowReturns real_returns, real_breaks;
+                       bool is_finally;
+
+                       static int next_id = 0;
+                       int id;
+
+                       //
+                       // Normally, you should not use any of these constructors.
+                       //
+                       public UsageVector (UsageVector parent, int num_params, int num_locals)
+                       {
+                               this.InheritsFrom = parent;
+                               this.CountParameters = num_params;
+                               this.CountLocals = num_locals;
+                               this.real_returns = FlowReturns.NEVER;
+                               this.real_breaks = FlowReturns.NEVER;
+
+                               if (parent != null) {
+                                       locals = new MyBitVector (parent.locals, CountLocals);
+                                       if (num_params > 0)
+                                               parameters = new MyBitVector (parent.parameters, num_params);
+                                       real_returns = parent.Returns;
+                                       real_breaks = parent.Breaks;
+                               } else {
+                                       locals = new MyBitVector (null, CountLocals);
+                                       if (num_params > 0)
+                                               parameters = new MyBitVector (null, num_params);
+                               }
+
+                               id = ++next_id;
+                       }
+
+                       public UsageVector (UsageVector parent)
+                               : this (parent, parent.CountParameters, parent.CountLocals)
+                       { }
+
+                       // <summary>
+                       //   This does a deep copy of the usage vector.
+                       // </summary>
+                       public UsageVector Clone ()
+                       {
+                               UsageVector retval = new UsageVector (null, CountParameters, CountLocals);
+
+                               retval.locals = locals.Clone ();
+                               if (parameters != null)
+                                       retval.parameters = parameters.Clone ();
+                               retval.real_returns = real_returns;
+                               retval.real_breaks = real_breaks;
+
+                               return retval;
+                       }
+
+                       public bool IsAssigned (VariableInfo var)
+                       {
+                               if (!var.IsParameter && AlwaysBreaks)
+                                       return true;
+
+                               return var.IsAssigned (var.IsParameter ? parameters : locals);
+                       }
+
+                       public void SetAssigned (VariableInfo var)
+                       {
+                               if (!var.IsParameter && AlwaysBreaks)
+                                       return;
+
+                               var.SetAssigned (var.IsParameter ? parameters : locals);
+                       }
+
+                       public bool IsFieldAssigned (VariableInfo var, string name)
+                       {
+                               if (!var.IsParameter && AlwaysBreaks)
+                                       return true;
+
+                               return var.IsFieldAssigned (var.IsParameter ? parameters : locals, name);
+                       }
+
+                       public void SetFieldAssigned (VariableInfo var, string name)
+                       {
+                               if (!var.IsParameter && AlwaysBreaks)
+                                       return;
+
+                               var.SetFieldAssigned (var.IsParameter ? parameters : locals, name);
+                       }
+
+                       // <summary>
+                       //   Specifies when the current block returns.
+                       //   If this is FlowReturns.UNREACHABLE, then control can never reach the
+                       //   end of the method (so that we don't need to emit a return statement).
+                       //   The same applies for FlowReturns.EXCEPTION, but in this case the return
+                       //   value will never be used.
+                       // </summary>
+                       public FlowReturns Returns {
+                               get {
+                                       return real_returns;
+                               }
+
+                               set {
+                                       real_returns = value;
+                               }
+                       }
+
+                       // <summary>
+                       //   Specifies whether control may return to our containing block
+                       //   before reaching the end of this block.  This happens if there
+                       //   is a break/continue/goto/return in it.
+                       //   This can also be used to find out whether the statement immediately
+                       //   following the current block may be reached or not.
+                       // </summary>
+                       public FlowReturns Breaks {
+                               get {
+                                       return real_breaks;
+                               }
+
+                               set {
+                                       real_breaks = value;
+                               }
+                       }
+
+                       public bool AlwaysBreaks {
+                               get {
+                                       return (Breaks == FlowReturns.ALWAYS) ||
+                                               (Breaks == FlowReturns.EXCEPTION) ||
+                                               (Breaks == FlowReturns.UNREACHABLE);
+                               }
+                       }
+
+                       public bool MayBreak {
+                               get {
+                                       return Breaks != FlowReturns.NEVER;
+                               }
+                       }
+
+                       public bool AlwaysReturns {
+                               get {
+                                       return (Returns == FlowReturns.ALWAYS) ||
+                                               (Returns == FlowReturns.EXCEPTION);
+                               }
+                       }
+
+                       public bool MayReturn {
+                               get {
+                                       return (Returns == FlowReturns.SOMETIMES) ||
+                                               (Returns == FlowReturns.ALWAYS);
+                               }
+                       }
+
+                       // <summary>
+                       //   Merge a child branching.
+                       // </summary>
+                       public FlowReturns MergeChildren (FlowBranching branching, UsageVector[] children)
+                       {
+                               MyBitVector new_locals = null;
+                               MyBitVector new_params = null;
+
+                               FlowReturns new_returns = FlowReturns.NEVER;
+                               FlowReturns new_breaks = FlowReturns.NEVER;
+                               bool new_returns_set = false, new_breaks_set = false;
+
+                               Report.Debug (2, "MERGING CHILDREN", branching, branching.Type,
+                                             this, children.Length);
+
+                               foreach (UsageVector child in children) {
+                                       Report.Debug (2, "  MERGING CHILD", child, child.is_finally);
+                                       
+                                       if (!child.is_finally) {
+                                               if (child.Breaks != FlowReturns.UNREACHABLE) {
+                                                       // If Returns is already set, perform an
+                                                       // `And' operation on it, otherwise just set just.
+                                                       if (!new_returns_set) {
+                                                               new_returns = child.Returns;
+                                                               new_returns_set = true;
+                                                       } else
+                                                               new_returns = AndFlowReturns (
+                                                                       new_returns, child.Returns);
+                                               }
+
+                                               // If Breaks is already set, perform an
+                                               // `And' operation on it, otherwise just set just.
+                                               if (!new_breaks_set) {
+                                                       new_breaks = child.Breaks;
+                                                       new_breaks_set = true;
+                                               } else
+                                                       new_breaks = AndFlowReturns (
+                                                               new_breaks, child.Breaks);
+                                       }
+
+                                       // Ignore unreachable children.
+                                       if (child.Returns == FlowReturns.UNREACHABLE)
+                                               continue;
+
+                                       // A local variable is initialized after a flow branching if it
+                                       // has been initialized in all its branches which do neither
+                                       // always return or always throw an exception.
+                                       //
+                                       // If a branch may return, but does not always return, then we
+                                       // can treat it like a never-returning branch here: control will
+                                       // only reach the code position after the branching if we did not
+                                       // return here.
+                                       //
+                                       // It's important to distinguish between always and sometimes
+                                       // returning branches here:
+                                       //
+                                       //    1   int a;
+                                       //    2   if (something) {
+                                       //    3      return;
+                                       //    4      a = 5;
+                                       //    5   }
+                                       //    6   Console.WriteLine (a);
+                                       //
+                                       // The if block in lines 3-4 always returns, so we must not look
+                                       // at the initialization of `a' in line 4 - thus it'll still be
+                                       // uninitialized in line 6.
+                                       //
+                                       // On the other hand, the following is allowed:
+                                       //
+                                       //    1   int a;
+                                       //    2   if (something)
+                                       //    3      a = 5;
+                                       //    4   else
+                                       //    5      return;
+                                       //    6   Console.WriteLine (a);
+                                       //
+                                       // Here, `a' is initialized in line 3 and we must not look at
+                                       // line 5 since it always returns.
+                                       // 
+                                       if (child.is_finally) {
+                                               if (new_locals == null)
+                                                       new_locals = locals.Clone ();
+                                               new_locals.Or (child.locals);
+
+                                               if (parameters != null) {
+                                                       if (new_params == null)
+                                                               new_params = parameters.Clone ();
+                                                       new_params.Or (child.parameters);
+                                               }
+                                       } else {
+                                               if (!child.AlwaysReturns && !child.AlwaysBreaks) {
+                                                       if (new_locals != null)
+                                                               new_locals.And (child.locals);
+                                                       else {
+                                                               new_locals = locals.Clone ();
+                                                               new_locals.Or (child.locals);
+                                                       }
+                                               } else if (children.Length == 1) {
+                                                       new_locals = locals.Clone ();
+                                                       new_locals.Or (child.locals);
+                                               }
+
+                                               // An `out' parameter must be assigned in all branches which do
+                                               // not always throw an exception.
+                                               if (parameters != null) {
+                                                       bool and_params = child.Breaks != FlowReturns.EXCEPTION;
+                                                       if (branching.Type == FlowBranchingType.EXCEPTION)
+                                                               and_params &= child.Returns != FlowReturns.NEVER;
+                                                       if (and_params) {
+                                                               if (new_params != null)
+                                                                       new_params.And (child.parameters);
+                                                               else {
+                                                                       new_params = parameters.Clone ();
+                                                                       new_params.Or (child.parameters);
+                                                               }
+                                                       } else if ((children.Length == 1) || (new_params == null)) {
+                                                               new_params = parameters.Clone ();
+                                                               new_params.Or (child.parameters);
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               Returns = new_returns;
+                               if ((branching.Type == FlowBranchingType.BLOCK) ||
+                                   (branching.Type == FlowBranchingType.EXCEPTION) ||
+                                   (new_breaks == FlowReturns.UNREACHABLE) ||
+                                   (new_breaks == FlowReturns.EXCEPTION))
+                                       Breaks = new_breaks;
+                               else if (branching.Type == FlowBranchingType.SWITCH_SECTION)
+                                       Breaks = new_returns;
+                               else if (branching.Type == FlowBranchingType.SWITCH){
+                                       if (new_breaks == FlowReturns.ALWAYS)
+                                               Breaks = FlowReturns.ALWAYS;
+                               }
+
+                               //
+                               // We've now either reached the point after the branching or we will
+                               // never get there since we always return or always throw an exception.
+                               //
+                               // If we can reach the point after the branching, mark all locals and
+                               // parameters as initialized which have been initialized in all branches
+                               // we need to look at (see above).
+                               //
+
+                               if (((new_breaks != FlowReturns.ALWAYS) &&
+                                    (new_breaks != FlowReturns.EXCEPTION) &&
+                                    (new_breaks != FlowReturns.UNREACHABLE)) ||
+                                   (children.Length == 1)) {
+                                       if (new_locals != null)
+                                               locals.Or (new_locals);
+
+                                       if (new_params != null)
+                                               parameters.Or (new_params);
+                               }
+
+                               Report.Debug (2, "MERGING CHILDREN DONE", branching.Type,
+                                             new_params, new_locals, new_returns, new_breaks,
+                                             branching.Infinite, branching.MayLeaveLoop, this);
+
+                               if (branching.Type == FlowBranchingType.SWITCH_SECTION) {
+                                       if ((new_breaks != FlowReturns.ALWAYS) &&
+                                           (new_breaks != FlowReturns.EXCEPTION) &&
+                                           (new_breaks != FlowReturns.UNREACHABLE))
+                                               Report.Error (163, branching.Location,
+                                                             "Control cannot fall through from one " +
+                                                             "case label to another");
+                               }
+
+                               if (branching.Infinite && !branching.MayLeaveLoop) {
+                                       Report.Debug (1, "INFINITE", new_returns, new_breaks,
+                                                     Returns, Breaks, this);
+
+                                       // We're actually infinite.
+                                       if (new_returns == FlowReturns.NEVER) {
+                                               Breaks = FlowReturns.UNREACHABLE;
+                                               return FlowReturns.UNREACHABLE;
+                                       }
+
+                                       // If we're an infinite loop and do not break, the code after
+                                       // the loop can never be reached.  However, if we may return
+                                       // from the loop, then we do always return (or stay in the loop
+                                       // forever).
+                                       if ((new_returns == FlowReturns.SOMETIMES) ||
+                                           (new_returns == FlowReturns.ALWAYS)) {
+                                               Returns = FlowReturns.ALWAYS;
+                                               return FlowReturns.ALWAYS;
+                                       }
+                               }
+
+                               if (branching.Type == FlowBranchingType.LOOP_BLOCK) {
+                                       Report.Debug (2, "MERGING LOOP BLOCK DONE", branching,
+                                                     branching.Infinite, branching.MayLeaveLoop,
+                                                     new_breaks, new_returns);
+
+                                       // If we may leave the loop, then we do not always return.
+                                       if (branching.MayLeaveLoop && (new_returns == FlowReturns.ALWAYS)) {
+                                               Returns = FlowReturns.SOMETIMES;
+                                               return FlowReturns.SOMETIMES;
+                                       }
+
+                                       // A `break' in a loop does not "break" in the outer block.
+                                       Breaks = FlowReturns.NEVER;
+                               }
+
+                               return new_returns;
+                       }
+
+                       // <summary>
+                       //   Tells control flow analysis that the current code position may be reached with
+                       //   a forward jump from any of the origins listed in `origin_vectors' which is a
+                       //   list of UsageVectors.
+                       //
+                       //   This is used when resolving forward gotos - in the following example, the
+                       //   variable `a' is uninitialized in line 8 becase this line may be reached via
+                       //   the goto in line 4:
+                       //
+                       //      1     int a;
+                       //
+                       //      3     if (something)
+                       //      4        goto World;
+                       //
+                       //      6     a = 5;
+                       //
+                       //      7  World:
+                       //      8     Console.WriteLine (a);
+                       //
+                       // </summary>
+                       public void MergeJumpOrigins (ICollection origin_vectors)
+                       {
+                               Report.Debug (1, "MERGING JUMP ORIGIN", this);
+
+                               real_breaks = FlowReturns.NEVER;
+                               real_returns = FlowReturns.NEVER;
+
+                               foreach (UsageVector vector in origin_vectors) {
+                                       Report.Debug (1, "  MERGING JUMP ORIGIN", vector);
+
+                                       locals.And (vector.locals);
+                                       if (parameters != null)
+                                               parameters.And (vector.parameters);
+                                       Breaks = AndFlowReturns (Breaks, vector.Breaks);
+                                       Returns = AndFlowReturns (Returns, vector.Returns);
+                               }
+
+                               Report.Debug (1, "MERGING JUMP ORIGIN DONE", this);
+                       }
+
+                       // <summary>
+                       //   This is used at the beginning of a finally block if there were
+                       //   any return statements in the try block or one of the catch blocks.
+                       // </summary>
+                       public void MergeFinallyOrigins (ICollection finally_vectors)
+                       {
+                               Report.Debug (1, "MERGING FINALLY ORIGIN", this);
+
+                               real_breaks = FlowReturns.NEVER;
+
+                               foreach (UsageVector vector in finally_vectors) {
+                                       Report.Debug (1, "  MERGING FINALLY ORIGIN", vector);
+
+                                       if (parameters != null)
+                                               parameters.And (vector.parameters);
+                                       Breaks = AndFlowReturns (Breaks, vector.Breaks);
+                               }
+
+                               is_finally = true;
+
+                               Report.Debug (1, "MERGING FINALLY ORIGIN DONE", this);
+                       }
+
+                       public void CheckOutParameters (FlowBranching branching)
+                       {
+                               if (parameters != null)
+                                       branching.CheckOutParameters (parameters, branching.Location);
+                       }
+
+                       // <summary>
+                       //   Performs an `or' operation on the locals and the parameters.
+                       // </summary>
+                       public void Or (UsageVector new_vector)
+                       {
+                               locals.Or (new_vector.locals);
+                               if (parameters != null)
+                                       parameters.Or (new_vector.parameters);
+                       }
+
+                       // <summary>
+                       //   Performs an `and' operation on the locals.
+                       // </summary>
+                       public void AndLocals (UsageVector new_vector)
+                       {
+                               locals.And (new_vector.locals);
+                       }
+
+                       // <summary>
+                       //   Returns a deep copy of the parameters.
+                       // </summary>
+                       public MyBitVector Parameters {
+                               get {
+                                       if (parameters != null)
+                                               return parameters.Clone ();
+                                       else
+                                               return null;
+                               }
+                       }
+
+                       // <summary>
+                       //   Returns a deep copy of the locals.
+                       // </summary>
+                       public MyBitVector Locals {
+                               get {
+                                       return locals.Clone ();
+                               }
+                       }
+
+                       //
+                       // Debugging stuff.
+                       //
+
+                       public override string ToString ()
+                       {
+                               StringBuilder sb = new StringBuilder ();
+
+                               sb.Append ("Vector (");
+                               sb.Append (id);
+                               sb.Append (",");
+                               sb.Append (Returns);
+                               sb.Append (",");
+                               sb.Append (Breaks);
+                               if (parameters != null) {
+                                       sb.Append (" - ");
+                                       sb.Append (parameters);
+                               }
+                               sb.Append (" - ");
+                               sb.Append (locals);
+                               sb.Append (")");
+
+                               return sb.ToString ();
+                       }
+               }
+
+               FlowBranching (FlowBranchingType type, Location loc)
+               {
+                       this.Block = null;
+                       this.Location = loc;
+                       this.Type = type;
+                       id = ++next_id;
+               }
+
+               // <summary>
+               //   Creates a new flow branching for `block'.
+               //   This is used from Block.Resolve to create the top-level branching of
+               //   the block.
+               // </summary>
+               public FlowBranching (Block block, Location loc)
+                       : this (FlowBranchingType.BLOCK, loc)
+               {
+                       Block = block;
+                       Parent = null;
+
+                       param_map = block.ParameterMap;
+                       local_map = block.LocalMap;
+
+                       UsageVector vector = new UsageVector (null, param_map.Length, local_map.Length);
+
+                       AddSibling (vector);
+               }
+
+               // <summary>
+               //   Creates a new flow branching which is contained in `parent'.
+               //   You should only pass non-null for the `block' argument if this block
+               //   introduces any new variables - in this case, we need to create a new
+               //   usage vector with a different size than our parent's one.
+               // </summary>
+               public FlowBranching (FlowBranching parent, FlowBranchingType type,
+                                     Block block, Location loc)
+                       : this (type, loc)
+               {
+                       Parent = parent;
+                       Block = block;
+
+                       UsageVector vector;
+                       if (Block != null) {
+                               param_map = Block.ParameterMap;
+                               local_map = Block.LocalMap;
+
+                               vector = new UsageVector (parent.CurrentUsageVector, param_map.Length,
+                                                         local_map.Length);
+                       } else {
+                               param_map = Parent.param_map;
+                               local_map = Parent.local_map;
+                               vector = new UsageVector (Parent.CurrentUsageVector);
+                       }
+
+                       AddSibling (vector);
+
+                       switch (Type) {
+                       case FlowBranchingType.EXCEPTION:
+                               finally_vectors = new ArrayList ();
+                               break;
+
+                       default:
+                               break;
+                       }
+               }
+
+               void AddSibling (UsageVector uv)
+               {
+                       if (Siblings != null) {
+                               UsageVector[] ns = new UsageVector [Siblings.Length + 1];
+                               for (int i = 0; i < Siblings.Length; ++i)
+                                       ns [i] = Siblings [i];
+                               Siblings = ns;
+                       } else {
+                               Siblings = new UsageVector [1];
+                       }
+                       Siblings [Siblings.Length - 1] = uv;
+               }
+
+               // <summary>
+               //   Returns the branching's current usage vector.
+               // </summary>
+               public UsageVector CurrentUsageVector
+               {
+                       get {
+                               return Siblings [Siblings.Length - 1];
+                       }
+               }
+
+               // <summary>
+               //   Creates a sibling of the current usage vector.
+               // </summary>
+               public void CreateSibling ()
+               {
+                       AddSibling (new UsageVector (Parent.CurrentUsageVector));
+
+                       Report.Debug (1, "CREATED SIBLING", CurrentUsageVector);
+               }
+
+               // <summary>
+               //   Creates a sibling for a `finally' block.
+               // </summary>
+               public void CreateSiblingForFinally ()
+               {
+                       if (Type != FlowBranchingType.EXCEPTION)
+                               throw new NotSupportedException ();
+
+                       CreateSibling ();
+
+                       CurrentUsageVector.MergeFinallyOrigins (finally_vectors);
+               }
+
+               // <summary>
+               //   Check whether all `out' parameters have been assigned.
+               // </summary>
+               public void CheckOutParameters (MyBitVector parameters, Location loc)
+               {
+                       if (InTryBlock ())
+                               return;
+
+                       for (int i = 0; i < param_map.Count; i++) {
+                               VariableInfo var = param_map [i];
+
+                               if (var == null)
+                                       continue;
+
+                               if (var.IsAssigned (parameters))
+                                       continue;
+
+                               Report.Error (177, loc, "The out parameter `" +
+                                             param_map.VariableNames [i] + "' must be " +
+                                             "assigned before control leave the current method.");
+                       }
+               }
+
+               // <summary>
+               //   Merge a child branching.
+               // </summary>
+               public FlowReturns MergeChild (FlowBranching child)
+               {
+                       FlowReturns returns = CurrentUsageVector.MergeChildren (child, child.Siblings);
+
+                       if ((child.Type != FlowBranchingType.LOOP_BLOCK) &&
+                           (child.Type != FlowBranchingType.SWITCH_SECTION))
+                               MayLeaveLoop |= child.MayLeaveLoop;
+
+                       return returns;
+               }
+               // <summary>
+               //   Does the toplevel merging.
+               // </summary>
+               public FlowReturns MergeTopBlock ()
+               {
+                       if ((Type != FlowBranchingType.BLOCK) || (Block == null))
+                               throw new NotSupportedException ();
+
+                       UsageVector vector = new UsageVector (null, param_map.Length, local_map.Length);
+
+                       Report.Debug (1, "MERGING TOP BLOCK", Location, vector);
+
+                       vector.MergeChildren (this, Siblings);
+
+                       if (Siblings.Length == 1)
+                               Siblings [0] = vector;
+                       else {
+                               Siblings = null;
+                               AddSibling (vector);
+                       }
+
+                       Report.Debug (1, "MERGING TOP BLOCK DONE", Location, vector);
+
+                       if (vector.Breaks != FlowReturns.EXCEPTION) {
+                               if (!vector.AlwaysBreaks)
+                                       CheckOutParameters (CurrentUsageVector.Parameters, Location);
+                               return vector.AlwaysBreaks ? FlowReturns.ALWAYS : vector.Returns;
+                       } else
+                               return FlowReturns.EXCEPTION;
+               }
+
+               public bool InTryBlock ()
+               {
+                       if (finally_vectors != null)
+                               return true;
+                       else if (Parent != null)
+                               return Parent.InTryBlock ();
+                       else
+                               return false;
+               }
+
+               public void AddFinallyVector (UsageVector vector)
+               {
+                       if (finally_vectors != null) {
+                               finally_vectors.Add (vector.Clone ());
+                               return;
+                       }
+
+                       if (Parent != null)
+                               Parent.AddFinallyVector (vector);
+                       else
+                               throw new NotSupportedException ();
+               }
+
+               public bool IsAssigned (VariableInfo vi)
+               {
+                       return CurrentUsageVector.IsAssigned (vi);
+               }
+
+               public bool IsFieldAssigned (VariableInfo vi, string field_name)
+               {
+                       if (CurrentUsageVector.IsAssigned (vi))
+                               return true;
+
+                       return CurrentUsageVector.IsFieldAssigned (vi, field_name);
+               }
+
+               public void SetAssigned (VariableInfo vi)
+               {
+                       CurrentUsageVector.SetAssigned (vi);
+               }
+
+               public void SetFieldAssigned (VariableInfo vi, string name)
+               {
+                       CurrentUsageVector.SetFieldAssigned (vi, name);
+               }
+
+               public bool IsReachable ()
+               {
+                       bool reachable;
+
+                       switch (Type) {
+                       case FlowBranchingType.SWITCH_SECTION:
+                               // The code following a switch block is reachable unless the switch
+                               // block always returns.
+                               reachable = !CurrentUsageVector.AlwaysReturns;
+                               break;
+
+                       case FlowBranchingType.LOOP_BLOCK:
+                               // The code following a loop is reachable unless the loop always
+                               // returns or it's an infinite loop without any `break's in it.
+                               reachable = !CurrentUsageVector.AlwaysReturns &&
+                                       (CurrentUsageVector.Breaks != FlowReturns.UNREACHABLE);
+                               break;
+
+                       default:
+                               // The code following a block or exception is reachable unless the
+                               // block either always returns or always breaks.
+                               if (MayLeaveLoop)
+                                       reachable = true;
+                               else
+                                       reachable = !CurrentUsageVector.AlwaysBreaks &&
+                                               !CurrentUsageVector.AlwaysReturns;
+                               break;
+                       }
+
+                       Report.Debug (1, "REACHABLE", this, Type, CurrentUsageVector.Returns,
+                                     CurrentUsageVector.Breaks, CurrentUsageVector, MayLeaveLoop,
+                                     reachable);
+
+                       return reachable;
+               }
+
+               public override string ToString ()
+               {
+                       StringBuilder sb = new StringBuilder ("FlowBranching (");
+
+                       sb.Append (id);
+                       sb.Append (",");
+                       sb.Append (Type);
+                       if (Block != null) {
+                               sb.Append (" - ");
+                               sb.Append (Block.ID);
+                               sb.Append (" - ");
+                               sb.Append (Block.StartLocation);
+                       }
+                       sb.Append (" - ");
+                       sb.Append (Siblings.Length);
+                       sb.Append (" - ");
+                       sb.Append (CurrentUsageVector);
+                       sb.Append (")");
+                       return sb.ToString ();
+               }
+       }
+
+       // <summary>
+       //   This is used by the flow analysis code to keep track of the type of local variables
+       //   and variables.
+       //
+       //   The flow code uses a BitVector to keep track of whether a variable has been assigned
+       //   or not.  This is easy for fundamental types (int, char etc.) or reference types since
+       //   you can only assign the whole variable as such.
+       //
+       //   For structs, we also need to keep track of all its fields.  To do this, we allocate one
+       //   bit for the struct itself (it's used if you assign/access the whole struct) followed by
+       //   one bit for each of its fields.
+       //
+       //   This class computes this `layout' for each type.
+       // </summary>
+       public class TypeInfo
+       {
+               public readonly Type Type;
+
+               // <summary>
+               //   Total number of bits a variable of this type consumes in the flow vector.
+               // </summary>
+               public readonly int TotalLength;
+
+               // <summary>
+               //   Number of bits the simple fields of a variable of this type consume
+               //   in the flow vector.
+               // </summary>
+               public readonly int Length;
+
+               // <summary>
+               //   This is only used by sub-structs.
+               // </summary>
+               public readonly int Offset;
+
+               // <summary>
+               //   If this is a struct.
+               // </summary>
+               public readonly bool IsStruct;       
+
+               // <summary>
+               //   If this is a struct, all fields which are structs theirselves.
+               // </summary>
+               public TypeInfo[] SubStructInfo;
+
+               protected readonly StructInfo struct_info;
+               private static Hashtable type_hash = new Hashtable ();
+
+               public static TypeInfo GetTypeInfo (Type type)
+               {
+                       TypeInfo info = (TypeInfo) type_hash [type];
+                       if (info != null)
+                               return info;
+
+                       info = new TypeInfo (type);
+                       type_hash.Add (type, info);
+                       return info;
+               }
+
+               public static TypeInfo GetTypeInfo (TypeContainer tc)
+               {
+                       TypeInfo info = (TypeInfo) type_hash [tc.TypeBuilder];
+                       if (info != null)
+                               return info;
+
+                       info = new TypeInfo (tc);
+                       type_hash.Add (tc.TypeBuilder, info);
+                       return info;
+               }
+
+               private TypeInfo (Type type)
+               {
+                       this.Type = type;
+
+                       struct_info = StructInfo.GetStructInfo (type);
+                       if (struct_info != null) {
+                               Length = struct_info.Length;
+                               TotalLength = struct_info.TotalLength;
+                               SubStructInfo = struct_info.StructFields;
+                               IsStruct = true;
+                       } else {
+                               Length = 0;
+                               TotalLength = 1;
+                               IsStruct = false;
+                       }
+               }
+
+               private TypeInfo (TypeContainer tc)
+               {
+                       this.Type = tc.TypeBuilder;
+
+                       struct_info = StructInfo.GetStructInfo (tc);
+                       if (struct_info != null) {
+                               Length = struct_info.Length;
+                               TotalLength = struct_info.TotalLength;
+                               SubStructInfo = struct_info.StructFields;
+                               IsStruct = true;
+                       } else {
+                               Length = 0;
+                               TotalLength = 1;
+                               IsStruct = false;
+                       }
+               }
+
+               protected TypeInfo (StructInfo struct_info, int offset)
+               {
+                       this.struct_info = struct_info;
+                       this.Offset = offset;
+                       this.Length = struct_info.Length;
+                       this.TotalLength = struct_info.TotalLength;
+                       this.SubStructInfo = struct_info.StructFields;
+                       this.Type = struct_info.Type;
+                       this.IsStruct = true;
+               }
+
+               public int GetFieldIndex (string name)
+               {
+                       if (struct_info == null)
+                               return 0;
+
+                       return struct_info [name];
+               }
+
+               public TypeInfo GetSubStruct (string name)
+               {
+                       if (struct_info == null)
+                               return null;
+
+                       return struct_info.GetStructField (name);
+               }
+
+               // <summary>
+               //   A struct's constructor must always assign all fields.
+               //   This method checks whether it actually does so.
+               // </summary>
+               public bool IsFullyInitialized (FlowBranching branching, VariableInfo vi, Location loc)
+               {
+                       if (struct_info == null)
+                               return true;
+
+                       bool ok = true;
+                       for (int i = 0; i < struct_info.Count; i++) {
+                               FieldInfo field = struct_info.Fields [i];
+
+                               if (!branching.IsFieldAssigned (vi, field.Name)) {
+                                       Report.Error (171, loc,
+                                                     "Field `" + TypeManager.CSharpName (Type) +
+                                                     "." + field.Name + "' must be fully initialized " +
+                                                     "before control leaves the constructor");
+                                       ok = false;
+                               }
+                       }
+
+                       return ok;
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("TypeInfo ({0}:{1}:{2}:{3})",
+                                             Type, Offset, Length, TotalLength);
+               }
+
+               protected class StructInfo {
+                       public readonly Type Type;
+                       public readonly FieldInfo[] Fields;
+                       public readonly TypeInfo[] StructFields;
+                       public readonly int Count;
+                       public readonly int CountPublic;
+                       public readonly int CountNonPublic;
+                       public readonly int Length;
+                       public readonly int TotalLength;
+                       public readonly bool HasStructFields;
+
+                       private static Hashtable field_type_hash = new Hashtable ();
+                       private Hashtable struct_field_hash;
+                       private Hashtable field_hash;
+
+                       protected bool InTransit = false;
+
+                       // Private constructor.  To save memory usage, we only need to create one instance
+                       // of this class per struct type.
+                       private StructInfo (Type type)
+                       {
+                               this.Type = type;
+
+                               field_type_hash.Add (type, this);
+
+                               if (type is TypeBuilder) {
+                                       TypeContainer tc = TypeManager.LookupTypeContainer (type);
+
+                                       ArrayList fields = tc.Fields;
+
+                                       ArrayList public_fields = new ArrayList ();
+                                       ArrayList non_public_fields = new ArrayList ();
+
+                                       if (fields != null) {
+                                               foreach (Field field in fields) {
+                                                       if ((field.ModFlags & Modifiers.STATIC) != 0)
+                                                               continue;
+                                                       if ((field.ModFlags & Modifiers.PUBLIC) != 0)
+                                                               public_fields.Add (field.FieldBuilder);
+                                                       else
+                                                               non_public_fields.Add (field.FieldBuilder);
+                                               }
+                                       }
+
+                                       CountPublic = public_fields.Count;
+                                       CountNonPublic = non_public_fields.Count;
+                                       Count = CountPublic + CountNonPublic;
+
+                                       Fields = new FieldInfo [Count];
+                                       public_fields.CopyTo (Fields, 0);
+                                       non_public_fields.CopyTo (Fields, CountPublic);
+                               } else {
+                                       FieldInfo[] public_fields = type.GetFields (
+                                               BindingFlags.Instance|BindingFlags.Public);
+                                       FieldInfo[] non_public_fields = type.GetFields (
+                                               BindingFlags.Instance|BindingFlags.NonPublic);
+
+                                       CountPublic = public_fields.Length;
+                                       CountNonPublic = non_public_fields.Length;
+                                       Count = CountPublic + CountNonPublic;
+
+                                       Fields = new FieldInfo [Count];
+                                       public_fields.CopyTo (Fields, 0);
+                                       non_public_fields.CopyTo (Fields, CountPublic);
+                               }
+
+                               struct_field_hash = new Hashtable ();
+                               field_hash = new Hashtable ();
+
+                               Length = 0;
+                               StructFields = new TypeInfo [Count];
+                               StructInfo[] sinfo = new StructInfo [Count];
+
+                               InTransit = true;
+
+                               for (int i = 0; i < Count; i++) {
+                                       FieldInfo field = (FieldInfo) Fields [i];
+
+                                       sinfo [i] = GetStructInfo (field.FieldType);
+                                       if (sinfo [i] == null)
+                                               field_hash.Add (field.Name, ++Length);
+                                       else if (sinfo [i].InTransit) {
+                                               Report.Error (523, String.Format (
+                                                                     "Struct member '{0}.{1}' of type '{2}' causes " +
+                                                                     "a cycle in the structure layout",
+                                                                     type, field.Name, sinfo [i].Type));
+                                               sinfo [i] = null;
+                                               return;
+                                       }
+                               }
+
+                               InTransit = false;
+
+                               TotalLength = Length + 1;
+                               for (int i = 0; i < Count; i++) {
+                                       FieldInfo field = (FieldInfo) Fields [i];
+
+                                       if (sinfo [i] == null)
+                                               continue;
+
+                                       field_hash.Add (field.Name, TotalLength);
+
+                                       HasStructFields = true;
+                                       StructFields [i] = new TypeInfo (sinfo [i], TotalLength);
+                                       struct_field_hash.Add (field.Name, StructFields [i]);
+                                       TotalLength += sinfo [i].TotalLength;
+                               }
+                       }
+
+                       public int this [string name] {
+                               get {
+                                       if (field_hash.Contains (name))
+                                               return (int) field_hash [name];
+                                       else
+                                               return 0;
+                               }
+                       }
+
+                       public TypeInfo GetStructField (string name)
+                       {
+                               return (TypeInfo) struct_field_hash [name];
+                       }
+
+                       public static StructInfo GetStructInfo (Type type)
+                       {
+                               if (!TypeManager.IsValueType (type) || TypeManager.IsEnumType (type) ||
+                                   TypeManager.IsBuiltinType (type))
+                                       return null;
+
+                               StructInfo info = (StructInfo) field_type_hash [type];
+                               if (info != null)
+                                       return info;
+
+                               return new StructInfo (type);
+                       }
+
+                       public static StructInfo GetStructInfo (TypeContainer tc)
+                       {
+                               StructInfo info = (StructInfo) field_type_hash [tc.TypeBuilder];
+                               if (info != null)
+                                       return info;
+
+                               return new StructInfo (tc.TypeBuilder);
+                       }
+               }
+       }
+
+       // <summary>
+       //   This is used by the flow analysis code to store information about a single local variable
+       //   or parameter.  Depending on the variable's type, we need to allocate one or more elements
+       //   in the BitVector - if it's a fundamental or reference type, we just need to know whether
+       //   it has been assigned or not, but for structs, we need this information for each of its fields.
+       // </summary>
+       public class VariableInfo {
+               public readonly string Name;
+               public readonly TypeInfo TypeInfo;
+
+               // <summary>
+               //   The bit offset of this variable in the flow vector.
+               // </summary>
+               public readonly int Offset;
+
+               // <summary>
+               //   The number of bits this variable needs in the flow vector.
+               //   The first bit always specifies whether the variable as such has been assigned while
+               //   the remaining bits contain this information for each of a struct's fields.
+               // </summary>
+               public readonly int Length;
+
+               // <summary>
+               //   If this is a parameter of local variable.
+               // </summary>
+               public readonly bool IsParameter;
+
+               public readonly LocalInfo LocalInfo;
+               public readonly int ParameterIndex;
+
+               readonly VariableInfo Parent;
+               VariableInfo[] sub_info;
+
+               protected VariableInfo (string name, Type type, int offset)
+               {
+                       this.Name = name;
+                       this.Offset = offset;
+                       this.TypeInfo = TypeInfo.GetTypeInfo (type);
+
+                       Length = TypeInfo.TotalLength;
+
+                       Initialize ();
+               }
+
+               protected VariableInfo (VariableInfo parent, TypeInfo type)
+               {
+                       this.Name = parent.Name;
+                       this.TypeInfo = type;
+                       this.Offset = parent.Offset + type.Offset;
+                       this.Parent = parent;
+                       this.Length = type.TotalLength;
+
+                       this.IsParameter = parent.IsParameter;
+                       this.LocalInfo = parent.LocalInfo;
+                       this.ParameterIndex = parent.ParameterIndex;
+
+                       Initialize ();
+               }
+
+               protected void Initialize ()
+               {
+                       TypeInfo[] sub_fields = TypeInfo.SubStructInfo;
+                       if (sub_fields != null) {
+                               sub_info = new VariableInfo [sub_fields.Length];
+                               for (int i = 0; i < sub_fields.Length; i++) {
+                                       if (sub_fields [i] != null)
+                                               sub_info [i] = new VariableInfo (this, sub_fields [i]);
+                               }
+                       } else
+                               sub_info = new VariableInfo [0];
+               }
+
+               public VariableInfo (LocalInfo local_info, int offset)
+                       : this (local_info.Name, local_info.VariableType, offset)
+               {
+                       this.LocalInfo = local_info;
+                       this.IsParameter = false;
+               }
+
+               public VariableInfo (string name, Type type, int param_idx, int offset)
+                       : this (name, type, offset)
+               {
+                       this.ParameterIndex = param_idx;
+                       this.IsParameter = true;
+               }
+
+               public bool IsAssigned (EmitContext ec)
+               {
+                       return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (this);
+               }
+
+               public bool IsAssigned (EmitContext ec, Location loc)
+               {
+                       if (IsAssigned (ec))
+                               return true;
+
+                       Report.Error (165, loc,
+                                     "Use of unassigned local variable `" + Name + "'");
+                       ec.CurrentBranching.SetAssigned (this);
+                       return false;
+               }
+
+               public bool IsAssigned (MyBitVector vector)
+               {
+                       if (vector [Offset])
+                               return true;
+
+                       for (VariableInfo parent = Parent; parent != null; parent = parent.Parent)
+                               if (vector [parent.Offset])
+                                       return true;
+
+                       // Return unless this is a struct.
+                       if (!TypeInfo.IsStruct)
+                               return false;
+
+                       // Ok, so each field must be assigned.
+                       for (int i = 0; i < TypeInfo.Length; i++) {
+                               if (!vector [Offset + i + 1])
+                                       return false;
+                       }
+
+                       // Ok, now check all fields which are structs.
+                       for (int i = 0; i < sub_info.Length; i++) {
+                               VariableInfo sinfo = sub_info [i];
+                               if (sinfo == null)
+                                       continue;
+
+                               if (!sinfo.IsAssigned (vector))
+                                       return false;
+                       }
+
+                       vector [Offset] = true;
+                       return true;
+               }
+
+               public void SetAssigned (EmitContext ec)
+               {
+                       if (ec.DoFlowAnalysis)
+                               ec.CurrentBranching.SetAssigned (this);
+               }
+
+               public void SetAssigned (MyBitVector vector)
+               {
+                       vector [Offset] = true;
+               }
+
+               public bool IsFieldAssigned (EmitContext ec, string name, Location loc)
+               {
+                       if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsFieldAssigned (this, name))
+                               return true;
+
+                       Report.Error (170, loc,
+                                     "Use of possibly unassigned field `" + name + "'");
+                       ec.CurrentBranching.SetFieldAssigned (this, name);
+                       return false;
+               }
+
+               public bool IsFieldAssigned (MyBitVector vector, string field_name)
+               {
+                       int field_idx = TypeInfo.GetFieldIndex (field_name);
+
+                       if (field_idx == 0)
+                               return true;
+
+                       return vector [Offset + field_idx];
+               }
+
+               public void SetFieldAssigned (EmitContext ec, string name)
+               {
+                       if (ec.DoFlowAnalysis)
+                               ec.CurrentBranching.SetFieldAssigned (this, name);
+               }
+
+               public void SetFieldAssigned (MyBitVector vector, string field_name)
+               {
+                       int field_idx = TypeInfo.GetFieldIndex (field_name);
+
+                       if (field_idx == 0)
+                               return;
+
+                       vector [Offset + field_idx] = true;
+               }
+
+               public VariableInfo GetSubStruct (string name)
+               {
+                       TypeInfo type = TypeInfo.GetSubStruct (name);
+
+                       if (type == null)
+                               return null;
+
+                       return new VariableInfo (this, type);
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("VariableInfo ({0}:{1}:{2}:{3}:{4})",
+                                             Name, TypeInfo, Offset, Length, IsParameter);
+               }
+       }
+
+       // <summary>
+       //   This is used by the flow code to hold the `layout' of the flow vector for
+       //   all locals and all parameters (ie. we create one instance of this class for the
+       //   locals and another one for the params).
+       // </summary>
+       public class VariableMap {
+               // <summary>
+               //   The number of variables in the map.
+               // </summary>
+               public readonly int Count;
+
+               // <summary>
+               //   Total length of the flow vector for this map.
+               // <summary>
+               public readonly int Length;
+
+               // <summary>
+               //   Type and name of all the variables.
+               //   Note that this is null for variables for which we do not need to compute
+               //   assignment info.
+               // </summary>
+               public readonly Type[] VariableTypes;
+               public readonly string[] VariableNames;
+
+               VariableInfo[] map;
+
+               public VariableMap (InternalParameters ip)
+               {
+                       Count = ip != null ? ip.Count : 0;
+                       map = new VariableInfo [Count];
+                       VariableNames = new string [Count];
+                       VariableTypes = new Type [Count];
+                       Length = 0;
+
+                       for (int i = 0; i < Count; i++) {
+                               Parameter.Modifier mod = ip.ParameterModifier (i);
+
+                               if ((mod & Parameter.Modifier.OUT) == 0)
+                                       continue;
+
+                               VariableNames [i] = ip.ParameterName (i);
+                               VariableTypes [i] = TypeManager.GetElementType (ip.ParameterType (i));
+
+                               map [i] = new VariableInfo (VariableNames [i], VariableTypes [i], i, Length);
+                               Length += map [i].Length;
+                       }
+               }
+
+               public VariableMap (LocalInfo[] locals)
+                       : this (null, locals)
+               { }
+
+               public VariableMap (VariableMap parent, LocalInfo[] locals)
+               {
+                       int offset = 0, start = 0;
+                       if (parent != null) {
+                               offset = parent.Length;
+                               start = parent.Count;
+                       }
+
+                       Count = locals.Length + start;
+                       map = new VariableInfo [Count];
+                       VariableNames = new string [Count];
+                       VariableTypes = new Type [Count];
+                       Length = offset;
+
+                       if (parent != null) {
+                               parent.map.CopyTo (map, 0);
+                               parent.VariableNames.CopyTo (VariableNames, 0);
+                               parent.VariableTypes.CopyTo (VariableTypes, 0);
+                       }
+
+                       for (int i = start; i < Count; i++) {
+                               LocalInfo li = locals [i-start];
+
+                               if (li.VariableType == null)
+                                       continue;
+
+                               VariableNames [i] = li.Name;
+                               VariableTypes [i] = li.VariableType;
+
+                               map [i] = li.VariableInfo = new VariableInfo (li, Length);
+                               Length += map [i].Length;
+                       }
+               }
+
+               // <summary>
+               //   Returns the VariableInfo for variable @index or null if we don't need to
+               //   compute assignment info for this variable.
+               // </summary>
+               public VariableInfo this [int index] {
+                       get {
+                               return map [index];
+                       }
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("VariableMap ({0}:{1})", Count, Length);
+               }
+       }
+
+       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
+               // be stored in the EmitContext
+               //
+               //
+               public LocalBuilder LocalBuilder;
+               public FieldBuilder FieldBuilder;
+
+               public Type VariableType;
+               public readonly string Name;
+               public readonly Location Location;
+               public readonly Block Block;
+
+               public VariableInfo VariableInfo;
+
+               public bool Used;
+               public bool Assigned;
+               public bool ReadOnly;
+               public bool IsFixed;
+               
+               public LocalInfo (Expression type, string name, Block block, Location l)
+               {
+                       Type = type;
+                       Name = name;
+                       Block = block;
+                       LocalBuilder = null;
+                       Location = l;
+               }
+
+               public LocalInfo (TypeContainer tc, Block block, Location l)
+               {
+                       VariableType = tc.TypeBuilder;
+                       Block = block;
+                       LocalBuilder = null;
+                       Location = l;
+               }
+
+               public bool IsThisAssigned (EmitContext ec, Location loc)
+               {
+                       VariableInfo vi = Block.GetVariableInfo (this);
+                       if (vi == null)
+                               throw new Exception ();
+
+                       if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (vi))
+                               return true;
+
+                       return vi.TypeInfo.IsFullyInitialized (ec.CurrentBranching, vi, loc);
+               }
+
+               public bool Resolve (DeclSpace decl)
+               {
+                       if (VariableType == null)
+                               VariableType = decl.ResolveType (Type, false, Location);
+
+                       if (VariableType == null)
+                               return false;
+
+                       return true;
+               }
+
+               public void MakePinned ()
+               {
+                       TypeManager.MakePinned (LocalBuilder);
+                       IsFixed = true;
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("LocalInfo ({0},{1},{2},{3})",
+                                             Name, Type, VariableInfo, Location);
+               }
+       }
+               
+       /// <summary>
+       ///   Block represents a C# block.
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   This class is used in a number of places: either to represent
+       ///   explicit blocks that the programmer places or implicit blocks.
+       ///
+       ///   Implicit blocks are used as labels or to introduce variable
+       ///   declarations.
+       /// </remarks>
+       public class Block : Statement {
+               public readonly Block     Parent;
+               public readonly Location  StartLocation;
+               public Location           EndLocation = Location.Null;
+
+               [Flags]
+               public enum Flags : byte {
+                       Implicit  = 1,
+                       Unchecked = 2
+               }
+               Flags flags;
+
+               public bool Implicit {
+                       get {
+                               return (flags & Flags.Implicit) != 0;
+                       }
+               }
+
+               public bool Unchecked {
+                       get {
+                               return (flags & Flags.Unchecked) != 0;
+                       }
+                       set {
+                               flags |= Flags.Unchecked;
+                       }
+               }
+
+               //
+               // The statements in this block
+               //
+               ArrayList statements;
+
+               //
+               // An array of Blocks.  We keep track of children just
+               // to generate the local variable declarations.
+               //
+               // Statements and child statements are handled through the
+               // statements.
+               //
+               ArrayList children;
+               
+               //
+               // Labels.  (label, block) pairs.
+               //
+               Hashtable labels;
+
+               //
+               // Keeps track of (name, type) pairs
+               //
+               Hashtable variables;
+
+               //
+               // Keeps track of constants
+               Hashtable constants;
+
+               //
+               // If this is a switch section, the enclosing switch block.
+               //
+               Block switch_block;
+
+               bool used = false;
+
+               static int id;
+
+               int this_id;
+               
+               public Block (Block parent)
+                       : this (parent, (Flags) 0, Location.Null, Location.Null)
+               { }
+
+               public Block (Block parent, Flags flags)
+                       : this (parent, flags, Location.Null, Location.Null)
+               { }
+
+               public Block (Block parent, Flags flags, Parameters parameters)
+                       : this (parent, flags, parameters, Location.Null, Location.Null)
+               { }
+
+               public Block (Block parent, Location start, Location end)
+                       : this (parent, (Flags) 0, start, end)
+               { }
+
+               public Block (Block parent, Parameters parameters, Location start, Location end)
+                       : this (parent, (Flags) 0, parameters, start, end)
+               { }
+
+               public Block (Block parent, Flags flags, Location start, Location end)
+                       : this (parent, flags, Parameters.EmptyReadOnlyParameters, start, end)
+               { }
+
+               public Block (Block parent, Flags flags, Parameters parameters,
+                             Location start, Location end)
+               {
+                       if (parent != null)
+                               parent.AddChild (this);
+                       
+                       this.Parent = parent;
+                       this.flags = flags;
+                       this.parameters = parameters;
+                       this.StartLocation = start;
+                       this.EndLocation = end;
+                       this.loc = start;
+                       this_id = id++;
+                       statements = new ArrayList ();
+               }
+
+               public Block CreateSwitchBlock (Location start)
+               {
+                       Block new_block = new Block (this, start, start);
+                       new_block.switch_block = this;
+                       return new_block;
+               }
+
+               public int ID {
+                       get {
+                               return this_id;
+                       }
+               }
+
+               void AddChild (Block b)
+               {
+                       if (children == null)
+                               children = new ArrayList ();
+                       
+                       children.Add (b);
+               }
+
+               public void SetEndLocation (Location loc)
+               {
+                       EndLocation = loc;
+               }
+
+               /// <summary>
+               ///   Adds a label to the current block. 
+               /// </summary>
+               ///
+               /// <returns>
+               ///   false if the name already exists in this block. true
+               ///   otherwise.
+               /// </returns>
+               ///
+               public bool AddLabel (string name, LabeledStatement target)
+               {
+                       if (switch_block != null)
+                               return switch_block.AddLabel (name, target);
+
+                       if (labels == null)
+                               labels = new Hashtable ();
+                       if (labels.Contains (name))
+                               return false;
+                       
+                       labels.Add (name, target);
+                       return true;
+               }
+
+               public LabeledStatement LookupLabel (string name)
+               {
+                       if (switch_block != null)
+                               return switch_block.LookupLabel (name);
+
+                       if (labels != null){
+                               if (labels.Contains (name))
+                                       return ((LabeledStatement) labels [name]);
+                       }
+
+                       if (Parent != null)
+                               return Parent.LookupLabel (name);
+
+                       return null;
+               }
+
+               LocalInfo this_variable = null;
+
+               // <summary>
+               //   Returns the "this" instance variable of this block.
+               //   See AddThisVariable() for more information.
+               // </summary>
+               public LocalInfo ThisVariable {
+                       get {
+                               if (this_variable != null)
+                                       return this_variable;
+                               else if (Parent != null)
+                                       return Parent.ThisVariable;
+                               else
+                                       return null;
+                       }
+               }
+
+               Hashtable child_variable_names;
+
+               // <summary>
+               //   Marks a variable with name @name as being used in a child block.
+               //   If a variable name has been used in a child block, it's illegal to
+               //   declare a variable with the same name in the current block.
+               // </summary>
+               public void AddChildVariableName (string name)
+               {
+                       if (child_variable_names == null)
+                               child_variable_names = new Hashtable ();
+
+                       if (!child_variable_names.Contains (name))
+                               child_variable_names.Add (name, true);
+               }
+
+               // <summary>
+               //   Marks all variables from block @block and all its children as being
+               //   used in a child block.
+               // </summary>
+               public void AddChildVariableNames (Block block)
+               {
+                       if (block.Variables != null) {
+                               foreach (string name in block.Variables.Keys)
+                                       AddChildVariableName (name);
+                       }
+
+                       if (block.children != null) {
+                               foreach (Block child in block.children)
+                                       AddChildVariableNames (child);
+                       }
+
+                       if (block.child_variable_names != null) {
+                               foreach (string name in block.child_variable_names.Keys)
+                                       AddChildVariableName (name);
+                       }
+               }
+
+               // <summary>
+               //   Checks whether a variable name has already been used in a child block.
+               // </summary>
+               public bool IsVariableNameUsedInChildBlock (string name)
+               {
+                       if (child_variable_names == null)
+                               return false;
+
+                       return child_variable_names.Contains (name);
+               }
+
+               // <summary>
+               //   This is used by non-static `struct' constructors which do not have an
+               //   initializer - in this case, the constructor must initialize all of the
+               //   struct's fields.  To do this, we add a "this" variable and use the flow
+               //   analysis code to ensure that it's been fully initialized before control
+               //   leaves the constructor.
+               // </summary>
+               public LocalInfo AddThisVariable (TypeContainer tc, Location l)
+               {
+                       if (this_variable != null)
+                               return this_variable;
+
+                       if (variables == null)
+                               variables = new Hashtable ();
+
+                       this_variable = new LocalInfo (tc, this, l);
+
+                       variables.Add ("this", this_variable);
+
+                       return this_variable;
+               }
+
+               public LocalInfo AddVariable (Expression type, string name, Parameters pars, Location l)
+               {
+                       if (variables == null)
+                               variables = new Hashtable ();
+
+                       LocalInfo vi = GetLocalInfo (name);
+                       if (vi != null) {
+                               if (vi.Block != this)
+                                       Report.Error (136, l, "A local variable named `" + name + "' " +
+                                                     "cannot be declared in this scope since it would " +
+                                                     "give a different meaning to `" + name + "', which " +
+                                                     "is already used in a `parent or current' scope to " +
+                                                     "denote something else");
+                               else
+                                       Report.Error (128, l, "A local variable `" + name + "' is already " +
+                                                     "defined in this scope");
+                               return null;
+                       }
+
+                       if (IsVariableNameUsedInChildBlock (name)) {
+                               Report.Error (136, l, "A local variable named `" + name + "' " +
+                                             "cannot be declared in this scope since it would " +
+                                             "give a different meaning to `" + name + "', which " +
+                                             "is already used in a `child' scope to denote something " +
+                                             "else");
+                               return null;
+                       }
+
+                       if (pars != null) {
+                               int idx = 0;
+                               Parameter p = pars.GetParameterByName (name, out idx);
+                               if (p != null) {
+                                       Report.Error (136, l, "A local variable named `" + name + "' " +
+                                                     "cannot be declared in this scope since it would " +
+                                                     "give a different meaning to `" + name + "', which " +
+                                                     "is already used in a `parent or current' scope to " +
+                                                     "denote something else");
+                                       return null;
+                               }
+                       }
+                       
+                       vi = new LocalInfo (type, name, this, l);
+
+                       variables.Add (name, vi);
+
+                       if (variables_initialized)
+                               throw new Exception ();
+
+                       // Console.WriteLine ("Adding {0} to {1}", name, ID);
+                       return vi;
+               }
+
+               public bool AddConstant (Expression type, string name, Expression value, Parameters pars, Location l)
+               {
+                       if (AddVariable (type, name, pars, l) == null)
+                               return false;
+                       
+                       if (constants == null)
+                               constants = new Hashtable ();
+
+                       constants.Add (name, value);
+                       return true;
+               }
+
+               public Hashtable Variables {
+                       get {
+                               return variables;
+                       }
+               }
+
+               public LocalInfo GetLocalInfo (string name)
+               {
+                       if (variables != null) {
+                               object temp;
+                               temp = variables [name];
+
+                               if (temp != null){
+                                       return (LocalInfo) temp;
+                               }
+                       }
+
+                       if (Parent != null)
+                               return Parent.GetLocalInfo (name);
+
+                       return null;
+               }
+
+               public VariableInfo GetVariableInfo (LocalInfo li)
+               {
+                       return li.VariableInfo;
+               }
+
+               public Expression GetVariableType (string name)
+               {
+                       LocalInfo vi = GetLocalInfo (name);
+
+                       if (vi != null)
+                               return vi.Type;
+
+                       return null;
+               }
+
+               public Expression GetConstantExpression (string name)
+               {
+                       if (constants != null) {
+                               object temp;
+                               temp = constants [name];
+                               
+                               if (temp != null)
+                                       return (Expression) temp;
+                       }
+                       
+                       if (Parent != null)
+                               return Parent.GetConstantExpression (name);
+
+                       return null;
+               }
+               
+               /// <summary>
+               ///   True if the variable named @name is a constant
+               ///  </summary>
+               public bool IsConstant (string name)
+               {
+                       Expression e = null;
+                       
+                       e = GetConstantExpression (name);
+                       
+                       return e != null;
+               }
+               
+               /// <summary>
+               ///   Use to fetch the statement associated with this label
+               /// </summary>
+               public Statement this [string name] {
+                       get {
+                               return (Statement) labels [name];
+                       }
+               }
+
+               Parameters parameters = null;
+               public Parameters Parameters {
+                       get {
+                               if (Parent != null)
+                                       return Parent.Parameters;
+
+                               return parameters;
+                       }
+               }
+
+               /// <returns>
+               ///   A list of labels that were not used within this block
+               /// </returns>
+               public string [] GetUnreferenced ()
+               {
+                       // FIXME: Implement me
+                       return null;
+               }
+
+               public void AddStatement (Statement s)
+               {
+                       statements.Add (s);
+                       used = true;
+               }
+
+               public bool Used {
+                       get {
+                               return used;
+                       }
+               }
+
+               public void Use ()
+               {
+                       used = true;
+               }
+
+               VariableMap param_map, local_map;
+               bool variables_initialized = false;
+
+               public VariableMap ParameterMap {
+                       get {
+                               if (!variables_initialized)
+                                       throw new Exception ();
+
+                               return param_map;
+                       }
+               }
+
+               public VariableMap LocalMap {
+                       get {
+                               if (!variables_initialized)
+                                       throw new Exception ();
+
+                               return local_map;
+                       }
+               }
+
+               /// <summary>
+               ///   Emits the variable declarations and labels.
+               /// </summary>
+               /// <remarks>
+               ///   tc: is our typecontainer (to resolve type references)
+               ///   ig: is the code generator:
+               ///   toplevel: the toplevel block.  This is used for checking 
+               ///             that no two labels with the same name are used.
+               /// </remarks>
+               public void EmitMeta (EmitContext ec, InternalParameters ip, Block toplevel)
+               {
+                       DeclSpace ds = ec.DeclSpace;
+                       ILGenerator ig = ec.ig;
+
+                       //
+                       // Compute the VariableMap's.
+                       //
+                       // Unfortunately, we don't know the type when adding variables with
+                       // AddVariable(), so we need to compute this info here.
+                       //
+
+                       LocalInfo[] locals;
+                       if (variables != null) {
+                               foreach (LocalInfo li in variables.Values)
+                                       li.Resolve (ec.DeclSpace);
+
+                               locals = new LocalInfo [variables.Count];
+                               variables.Values.CopyTo (locals, 0);
+                       } else
+                               locals = new LocalInfo [0];
+
+                       if (Parent != null)
+                               local_map = new VariableMap (Parent.LocalMap, locals);
+                       else
+                               local_map = new VariableMap (locals);
+
+                       param_map = new VariableMap (ip);
+                       variables_initialized = true;
+
+                       bool old_check_state = ec.ConstantCheckState;
+                       ec.ConstantCheckState = (flags & Flags.Unchecked) == 0;
+                       bool remap_locals = ec.RemapToProxy;
+                               
+                       //
+                       // Process this block variables
+                       //
+                       if (variables != null){
+                               foreach (DictionaryEntry de in variables){
+                                       string name = (string) de.Key;
+                                       LocalInfo vi = (LocalInfo) de.Value;
+                                       
+                                       if (vi.VariableType == null)
+                                               continue;
+
+                                       Type variable_type = vi.VariableType;
+
+                                       if (variable_type.IsPointer){
+                                               //
+                                               // Am not really convinced that this test is required (Microsoft does it)
+                                               // but the fact is that you would not be able to use the pointer variable
+                                               // *anyways*
+                                               //
+                                               if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (variable_type),
+                                                                                  vi.Location))
+                                                       continue;
+                                       }
+
+                                       if (remap_locals)
+                                               vi.FieldBuilder = ec.MapVariable (name, vi.VariableType);
+                                       else
+                                               vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
+
+                                       if (constants == null)
+                                               continue;
+
+                                       Expression cv = (Expression) constants [name];
+                                       if (cv == null)
+                                               continue;
+
+                                       ec.CurrentBlock = this;
+                                       Expression e = cv.Resolve (ec);
+                                       if (e == null)
+                                               continue;
+
+                                       if (!(e is Constant)){
+                                               Report.Error (133, vi.Location,
+                                                             "The expression being assigned to `" +
+                                                             name + "' must be constant (" + e + ")");
+                                               continue;
+                                       }
+
+                                       constants.Remove (name);
+                                       constants.Add (name, e);
+                               }
+                       }
+                       ec.ConstantCheckState = old_check_state;
+
+                       //
+                       // Now, handle the children
+                       //
+                       if (children != null){
+                               foreach (Block b in children)
+                                       b.EmitMeta (ec, ip, toplevel);
+                       }
+               }
+
+               public void UsageWarning ()
+               {
+                       string name;
+                       
+                       if (variables != null){
+                               foreach (DictionaryEntry de in variables){
+                                       LocalInfo vi = (LocalInfo) de.Value;
+                                       
+                                       if (vi.Used)
+                                               continue;
+                                       
+                                       name = (string) de.Key;
+                                               
+                                       if (vi.Assigned){
+                                               Report.Warning (
+                                                       219, vi.Location, "The variable `" + name +
+                                                       "' is assigned but its value is never used");
+                                       } else {
+                                               Report.Warning (
+                                                       168, vi.Location, "The variable `" +
+                                                       name +
+                                                       "' is declared but never used");
+                                       } 
+                               }
+                       }
+
+                       if (children != null)
+                               foreach (Block b in children)
+                                       b.UsageWarning ();
+               }
+
+               bool has_ret = false;
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       Block prev_block = ec.CurrentBlock;
+                       bool ok = true;
+
+                       ec.CurrentBlock = this;
+                       ec.StartFlowBranching (this);
+
+                       Report.Debug (1, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
+
+                       ArrayList new_statements = new ArrayList ();
+                       bool unreachable = false, warning_shown = false;
+
+                       foreach (Statement s in statements){
+                               if (unreachable && !(s is LabeledStatement)) {
+                                       if (!warning_shown && !(s is EmptyStatement)) {
+                                               warning_shown = true;
+                                               Warning_DeadCodeFound (s.loc);
+                                       }
+
+                                       continue;
+                               }
+
+                               if (s.Resolve (ec) == false) {
+                                       ok = false;
+                                       continue;
+                               }
+
+                               if (s is LabeledStatement)
+                                       unreachable = false;
+                               else
+                                       unreachable = ! ec.CurrentBranching.IsReachable ();
+
+                               new_statements.Add (s);
+                       }
+
+                       statements = new_statements;
+
+                       Report.Debug (1, "RESOLVE BLOCK DONE", StartLocation, ec.CurrentBranching);
+
+                       FlowReturns returns = ec.EndFlowBranching ();
+                       ec.CurrentBlock = prev_block;
+
+                       // If we're a non-static `struct' constructor which doesn't have an
+                       // initializer, then we must initialize all of the struct's fields.
+                       if ((this_variable != null) && (returns != FlowReturns.EXCEPTION) &&
+                           !this_variable.IsThisAssigned (ec, loc))
+                               ok = false;
+
+                       if ((labels != null) && (RootContext.WarningLevel >= 2)) {
+                               foreach (LabeledStatement label in labels.Values)
+                                       if (!label.HasBeenReferenced)
+                                               Report.Warning (164, label.Location,
+                                                               "This label has not been referenced");
+                       }
+
+                       if ((returns == FlowReturns.ALWAYS) ||
+                           (returns == FlowReturns.EXCEPTION) ||
+                           (returns == FlowReturns.UNREACHABLE))
+                               has_ret = true;
+
+                       return ok;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       foreach (Statement s in statements)
+                               s.Emit (ec);
+
+                       return has_ret;
+               }
+
+               public override bool Emit (EmitContext ec)
+               {
+                       Block prev_block = ec.CurrentBlock;
+
+                       ec.CurrentBlock = this;
+
+                       bool emit_debug_info = (CodeGen.SymbolWriter != null);
+                       bool is_lexical_block = !Implicit && (Parent != null);
+
+                       if (emit_debug_info) {
+                               if (is_lexical_block)
+                                       ec.ig.BeginScope ();
+
+                               if (variables != null) {
+                                       foreach (DictionaryEntry de in variables) {
+                                               string name = (string) de.Key;
+                                               LocalInfo vi = (LocalInfo) de.Value;
+
+                                               if (vi.LocalBuilder == null)
+                                                       continue;
+
+                                               vi.LocalBuilder.SetLocalSymInfo (name);
+                                       }
+                               }
+                       }
+
+                       ec.Mark (StartLocation, true);
+                       bool retval = DoEmit (ec);
+                       ec.Mark (EndLocation, true); 
+
+                       if (emit_debug_info && is_lexical_block)
+                               ec.ig.EndScope ();
+
+                       ec.CurrentBlock = prev_block;
+
+                       return retval;
+               }
+       }
+
+       public class SwitchLabel {
+               Expression label;
+               object converted;
+               public Location loc;
+               public Label ILLabel;
+               public Label ILLabelCode;
+
+               //
+               // if expr == null, then it is the default case.
+               //
+               public SwitchLabel (Expression expr, Location l)
+               {
+                       label = expr;
+                       loc = l;
+               }
+
+               public Expression Label {
+                       get {
+                               return label;
+                       }
+               }
+
+               public object Converted {
+                       get {
+                               return converted;
+                       }
+               }
+
+               //
+               // Resolves the expression, reduces it to a literal if possible
+               // and then converts it to the requested type.
+               //
+               public bool ResolveAndReduce (EmitContext ec, Type required_type)
+               {
+                       ILLabel = ec.ig.DefineLabel ();
+                       ILLabelCode = ec.ig.DefineLabel ();
+
+                       if (label == null)
+                               return true;
+                       
+                       Expression e = label.Resolve (ec);
+
+                       if (e == null)
+                               return false;
+
+                       if (!(e is Constant)){
+                               Report.Error (150, loc, "A constant value is expected, got: " + e);
+                               return false;
+                       }
+
+                       if (e is StringConstant || e is NullLiteral){
+                               if (required_type == TypeManager.string_type){
+                                       converted = e;
+                                       ILLabel = ec.ig.DefineLabel ();
+                                       return true;
+                               }
+                       }
+
+                       converted = Expression.ConvertIntLiteral ((Constant) e, required_type, loc);
+                       if (converted == null)
+                               return false;
+
+                       return true;
+               }
+       }
+
+       public class SwitchSection {
+               // An array of SwitchLabels.
+               public readonly ArrayList Labels;
+               public readonly Block Block;
+               
+               public SwitchSection (ArrayList labels, Block block)
+               {
+                       Labels = labels;
+                       Block = block;
+               }
+       }
+       
+       public class Switch : Statement {
+               public readonly ArrayList Sections;
+               public Expression Expr;
+
+               /// <summary>
+               ///   Maps constants whose type type SwitchType to their  SwitchLabels.
+               /// </summary>
+               public Hashtable Elements;
+
+               /// <summary>
+               ///   The governing switch type
+               /// </summary>
+               public Type SwitchType;
+
+               //
+               // Computed
+               //
+               bool got_default;
+               Label default_target;
+               Expression new_expr;
+
+               //
+               // The types allowed to be implicitly cast from
+               // on the governing type
+               //
+               static Type [] allowed_types;
+               
+               public Switch (Expression e, ArrayList sects, Location l)
+               {
+                       Expr = e;
+                       Sections = sects;
+                       loc = l;
+               }
+
+               public bool GotDefault {
+                       get {
+                               return got_default;
+                       }
+               }
+
+               public Label DefaultTarget {
+                       get {
+                               return default_target;
+                       }
+               }
+
+               //
+               // Determines the governing type for a switch.  The returned
+               // expression might be the expression from the switch, or an
+               // expression that includes any potential conversions to the
+               // integral types or to string.
+               //
+               Expression SwitchGoverningType (EmitContext ec, Type t)
+               {
+                       if (t == TypeManager.int32_type ||
+                           t == TypeManager.uint32_type ||
+                           t == TypeManager.char_type ||
+                           t == TypeManager.byte_type ||
+                           t == TypeManager.sbyte_type ||
+                           t == TypeManager.ushort_type ||
+                           t == TypeManager.short_type ||
+                           t == TypeManager.uint64_type ||
+                           t == TypeManager.int64_type ||
+                           t == TypeManager.string_type ||
+                               t == TypeManager.bool_type ||
+                               t.IsSubclassOf (TypeManager.enum_type))
+                               return Expr;
+
+                       if (allowed_types == null){
+                               allowed_types = new Type [] {
+                                       TypeManager.sbyte_type,
+                                       TypeManager.byte_type,
+                                       TypeManager.short_type,
+                                       TypeManager.ushort_type,
+                                       TypeManager.int32_type,
+                                       TypeManager.uint32_type,
+                                       TypeManager.int64_type,
+                                       TypeManager.uint64_type,
+                                       TypeManager.char_type,
+                                       TypeManager.bool_type,
+                                       TypeManager.string_type
+                               };
+                       }
+
+                       //
+                       // Try to find a *user* defined implicit conversion.
+                       //
+                       // If there is no implicit conversion, or if there are multiple
+                       // conversions, we have to report an error
+                       //
+                       Expression converted = null;
+                       foreach (Type tt in allowed_types){
+                               Expression e;
+                               
+                               e = Convert.ImplicitUserConversion (ec, Expr, tt, loc);
+                               if (e == null)
+                                       continue;
+
+                               if (converted != null){
+                                       Report.Error (-12, loc, "More than one conversion to an integral " +
+                                                     " type exists for type `" +
+                                                     TypeManager.CSharpName (Expr.Type)+"'");
+                                       return null;
+                               } else
+                                       converted = e;
+                       }
+                       return converted;
+               }
+
+               void error152 (string n)
+               {
+                       Report.Error (
+                               152, "The label `" + n + ":' " +
+                               "is already present on this switch statement");
+               }
+               
+               //
+               // Performs the basic sanity checks on the switch statement
+               // (looks for duplicate keys and non-constant expressions).
+               //
+               // It also returns a hashtable with the keys that we will later
+               // use to compute the switch tables
+               //
+               bool CheckSwitch (EmitContext ec)
+               {
+                       Type compare_type;
+                       bool error = false;
+                       Elements = new Hashtable ();
+                               
+                       got_default = false;
+
+                       if (TypeManager.IsEnumType (SwitchType)){
+                               compare_type = TypeManager.EnumToUnderlying (SwitchType);
+                       } else
+                               compare_type = SwitchType;
+                       
+                       foreach (SwitchSection ss in Sections){
+                               foreach (SwitchLabel sl in ss.Labels){
+                                       if (!sl.ResolveAndReduce (ec, SwitchType)){
+                                               error = true;
+                                               continue;
+                                       }
+
+                                       if (sl.Label == null){
+                                               if (got_default){
+                                                       error152 ("default");
+                                                       error = true;
+                                               }
+                                               got_default = true;
+                                               continue;
+                                       }
+                                       
+                                       object key = sl.Converted;
+
+                                       if (key is Constant)
+                                               key = ((Constant) key).GetValue ();
+
+                                       if (key == null)
+                                               key = NullLiteral.Null;
+                                       
+                                       string lname = null;
+                                       if (compare_type == TypeManager.uint64_type){
+                                               ulong v = (ulong) key;
+
+                                               if (Elements.Contains (v))
+                                                       lname = v.ToString ();
+                                               else
+                                                       Elements.Add (v, sl);
+                                       } else if (compare_type == TypeManager.int64_type){
+                                               long v = (long) key;
+
+                                               if (Elements.Contains (v))
+                                                       lname = v.ToString ();
+                                               else
+                                                       Elements.Add (v, sl);
+                                       } else if (compare_type == TypeManager.uint32_type){
+                                               uint v = (uint) key;
+
+                                               if (Elements.Contains (v))
+                                                       lname = v.ToString ();
+                                               else
+                                                       Elements.Add (v, sl);
+                                       } else if (compare_type == TypeManager.char_type){
+                                               char v = (char) key;
+                                               
+                                               if (Elements.Contains (v))
+                                                       lname = v.ToString ();
+                                               else
+                                                       Elements.Add (v, sl);
+                                       } else if (compare_type == TypeManager.byte_type){
+                                               byte v = (byte) key;
+                                               
+                                               if (Elements.Contains (v))
+                                                       lname = v.ToString ();
+                                               else
+                                                       Elements.Add (v, sl);
+                                       } else if (compare_type == TypeManager.sbyte_type){
+                                               sbyte v = (sbyte) key;
+                                               
+                                               if (Elements.Contains (v))
+                                                       lname = v.ToString ();
+                                               else
+                                                       Elements.Add (v, sl);
+                                       } else if (compare_type == TypeManager.short_type){
+                                               short v = (short) key;
+                                               
+                                               if (Elements.Contains (v))
+                                                       lname = v.ToString ();
+                                               else
+                                                       Elements.Add (v, sl);
+                                       } else if (compare_type == TypeManager.ushort_type){
+                                               ushort v = (ushort) key;
+                                               
+                                               if (Elements.Contains (v))
+                                                       lname = v.ToString ();
+                                               else
+                                                       Elements.Add (v, sl);
+                                       } else if (compare_type == TypeManager.string_type){
+                                               if (key is NullLiteral){
+                                                       if (Elements.Contains (NullLiteral.Null))
+                                                               lname = "null";
+                                                       else
+                                                               Elements.Add (NullLiteral.Null, null);
+                                               } else {
+                                                       string s = (string) key;
+
+                                                       if (Elements.Contains (s))
+                                                               lname = s;
+                                                       else
+                                                               Elements.Add (s, sl);
+                                               }
+                                       } else if (compare_type == TypeManager.int32_type) {
+                                               int v = (int) key;
+
+                                               if (Elements.Contains (v))
+                                                       lname = v.ToString ();
+                                               else
+                                                       Elements.Add (v, sl);
+                                       } else if (compare_type == TypeManager.bool_type) {
+                                               bool v = (bool) key;
+
+                                               if (Elements.Contains (v))
+                                                       lname = v.ToString ();
+                                               else
+                                                       Elements.Add (v, sl);
+                                       }
+                                       else
+                                       {
+                                               throw new Exception ("Unknown switch type!" +
+                                                                    SwitchType + " " + compare_type);
+                                       }
+
+                                       if (lname != null){
+                                               error152 ("case + " + lname);
+                                               error = true;
+                                       }
+                               }
+                       }
+                       if (error)
+                               return false;
+                       
+                       return true;
+               }
+
+               void EmitObjectInteger (ILGenerator ig, object k)
+               {
+                       if (k is int)
+                               IntConstant.EmitInt (ig, (int) k);
+                       else if (k is Constant) {
+                               EmitObjectInteger (ig, ((Constant) k).GetValue ());
+                       } 
+                       else if (k is uint)
+                               IntConstant.EmitInt (ig, unchecked ((int) (uint) k));
+                       else if (k is long)
+                       {
+                               if ((long) k >= int.MinValue && (long) k <= int.MaxValue)
+                               {
+                                       IntConstant.EmitInt (ig, (int) (long) k);
+                                       ig.Emit (OpCodes.Conv_I8);
+                               }
+                               else
+                                       LongConstant.EmitLong (ig, (long) k);
+                       }
+                       else if (k is ulong)
+                       {
+                               if ((ulong) k < (1L<<32))
+                               {
+                                       IntConstant.EmitInt (ig, (int) (long) k);
+                                       ig.Emit (OpCodes.Conv_U8);
+                               }
+                               else
+                               {
+                                       LongConstant.EmitLong (ig, unchecked ((long) (ulong) k));
+                               }
+                       }
+                       else if (k is char)
+                               IntConstant.EmitInt (ig, (int) ((char) k));
+                       else if (k is sbyte)
+                               IntConstant.EmitInt (ig, (int) ((sbyte) k));
+                       else if (k is byte)
+                               IntConstant.EmitInt (ig, (int) ((byte) k));
+                       else if (k is short)
+                               IntConstant.EmitInt (ig, (int) ((short) k));
+                       else if (k is ushort)
+                               IntConstant.EmitInt (ig, (int) ((ushort) k));
+                       else if (k is bool)
+                               IntConstant.EmitInt (ig, ((bool) k) ? 1 : 0);
+                       else
+                               throw new Exception ("Unhandled case");
+               }
+               
+               // structure used to hold blocks of keys while calculating table switch
+               class KeyBlock : IComparable
+               {
+                       public KeyBlock (long _nFirst)
+                       {
+                               nFirst = nLast = _nFirst;
+                       }
+                       public long nFirst;
+                       public long nLast;
+                       public ArrayList rgKeys = null;
+                       public int Length
+                       {
+                               get { return (int) (nLast - nFirst + 1); }
+                       }
+                       public static long TotalLength (KeyBlock kbFirst, KeyBlock kbLast)
+                       {
+                               return kbLast.nLast - kbFirst.nFirst + 1;
+                       }
+                       public int CompareTo (object obj)
+                       {
+                               KeyBlock kb = (KeyBlock) obj;
+                               int nLength = Length;
+                               int nLengthOther = kb.Length;
+                               if (nLengthOther == nLength)
+                                       return (int) (kb.nFirst - nFirst);
+                               return nLength - nLengthOther;
+                       }
+               }
+
+               /// <summary>
+               /// This method emits code for a lookup-based switch statement (non-string)
+               /// Basically it groups the cases into blocks that are at least half full,
+               /// and then spits out individual lookup opcodes for each block.
+               /// It emits the longest blocks first, and short blocks are just
+               /// handled with direct compares.
+               /// </summary>
+               /// <param name="ec"></param>
+               /// <param name="val"></param>
+               /// <returns></returns>
+               bool TableSwitchEmit (EmitContext ec, LocalBuilder val)
+               {
+                       int cElements = Elements.Count;
+                       object [] rgKeys = new object [cElements];
+                       Elements.Keys.CopyTo (rgKeys, 0);
+                       Array.Sort (rgKeys);
+
+                       // initialize the block list with one element per key
+                       ArrayList rgKeyBlocks = new ArrayList ();
+                       foreach (object key in rgKeys)
+                               rgKeyBlocks.Add (new KeyBlock (System.Convert.ToInt64 (key)));
+
+                       KeyBlock kbCurr;
+                       // iteratively merge the blocks while they are at least half full
+                       // there's probably a really cool way to do this with a tree...
+                       while (rgKeyBlocks.Count > 1)
+                       {
+                               ArrayList rgKeyBlocksNew = new ArrayList ();
+                               kbCurr = (KeyBlock) rgKeyBlocks [0];
+                               for (int ikb = 1; ikb < rgKeyBlocks.Count; ikb++)
+                               {
+                                       KeyBlock kb = (KeyBlock) rgKeyBlocks [ikb];
+                                       if ((kbCurr.Length + kb.Length) * 2 >=  KeyBlock.TotalLength (kbCurr, kb))
+                                       {
+                                               // merge blocks
+                                               kbCurr.nLast = kb.nLast;
+                                       }
+                                       else
+                                       {
+                                               // start a new block
+                                               rgKeyBlocksNew.Add (kbCurr);
+                                               kbCurr = kb;
+                                       }
+                               }
+                               rgKeyBlocksNew.Add (kbCurr);
+                               if (rgKeyBlocks.Count == rgKeyBlocksNew.Count)
+                                       break;
+                               rgKeyBlocks = rgKeyBlocksNew;
+                       }
+
+                       // initialize the key lists
+                       foreach (KeyBlock kb in rgKeyBlocks)
+                               kb.rgKeys = new ArrayList ();
+
+                       // fill the key lists
+                       int iBlockCurr = 0;
+                       if (rgKeyBlocks.Count > 0) {
+                               kbCurr = (KeyBlock) rgKeyBlocks [0];
+                               foreach (object key in rgKeys)
+                               {
+                                       bool fNextBlock = (key is UInt64) ? (ulong) key > (ulong) kbCurr.nLast :
+                                               System.Convert.ToInt64 (key) > kbCurr.nLast;
+                                       if (fNextBlock)
+                                               kbCurr = (KeyBlock) rgKeyBlocks [++iBlockCurr];
+                                       kbCurr.rgKeys.Add (key);
+                               }
+                       }
+
+                       // sort the blocks so we can tackle the largest ones first
+                       rgKeyBlocks.Sort ();
+
+                       // okay now we can start...
+                       ILGenerator ig = ec.ig;
+                       Label lblEnd = ig.DefineLabel ();       // at the end ;-)
+                       Label lblDefault = ig.DefineLabel ();
+
+                       Type typeKeys = null;
+                       if (rgKeys.Length > 0)
+                               typeKeys = rgKeys [0].GetType ();       // used for conversions
+
+                       for (int iBlock = rgKeyBlocks.Count - 1; iBlock >= 0; --iBlock)
+                       {
+                               KeyBlock kb = ((KeyBlock) rgKeyBlocks [iBlock]);
+                               lblDefault = (iBlock == 0) ? DefaultTarget : ig.DefineLabel ();
+                               if (kb.Length <= 2)
+                               {
+                                       foreach (object key in kb.rgKeys)
+                                       {
+                                               ig.Emit (OpCodes.Ldloc, val);
+                                               EmitObjectInteger (ig, key);
+                                               SwitchLabel sl = (SwitchLabel) Elements [key];
+                                               ig.Emit (OpCodes.Beq, sl.ILLabel);
+                                       }
+                               }
+                               else
+                               {
+                                       // TODO: if all the keys in the block are the same and there are
+                                       //       no gaps/defaults then just use a range-check.
+                                       if (SwitchType == TypeManager.int64_type ||
+                                               SwitchType == TypeManager.uint64_type)
+                                       {
+                                               // TODO: optimize constant/I4 cases
+
+                                               // check block range (could be > 2^31)
+                                               ig.Emit (OpCodes.Ldloc, val);
+                                               EmitObjectInteger (ig, System.Convert.ChangeType (kb.nFirst, typeKeys));
+                                               ig.Emit (OpCodes.Blt, lblDefault);
+                                               ig.Emit (OpCodes.Ldloc, val);
+                                               EmitObjectInteger (ig, System.Convert.ChangeType (kb.nFirst, typeKeys));
+                                               ig.Emit (OpCodes.Bgt, lblDefault);
+
+                                               // normalize range
+                                               ig.Emit (OpCodes.Ldloc, val);
+                                               if (kb.nFirst != 0)
+                                               {
+                                                       EmitObjectInteger (ig, System.Convert.ChangeType (kb.nFirst, typeKeys));
+                                                       ig.Emit (OpCodes.Sub);
+                                               }
+                                               ig.Emit (OpCodes.Conv_I4);      // assumes < 2^31 labels!
+                                       }
+                                       else
+                                       {
+                                               // normalize range
+                                               ig.Emit (OpCodes.Ldloc, val);
+                                               int nFirst = (int) kb.nFirst;
+                                               if (nFirst > 0)
+                                               {
+                                                       IntConstant.EmitInt (ig, nFirst);
+                                                       ig.Emit (OpCodes.Sub);
+                                               }
+                                               else if (nFirst < 0)
+                                               {
+                                                       IntConstant.EmitInt (ig, -nFirst);
+                                                       ig.Emit (OpCodes.Add);
+                                               }
+                                       }
+
+                                       // first, build the list of labels for the switch
+                                       int iKey = 0;
+                                       int cJumps = kb.Length;
+                                       Label [] rgLabels = new Label [cJumps];
+                                       for (int iJump = 0; iJump < cJumps; iJump++)
+                                       {
+                                               object key = kb.rgKeys [iKey];
+                                               if (System.Convert.ToInt64 (key) == kb.nFirst + iJump)
+                                               {
+                                                       SwitchLabel sl = (SwitchLabel) Elements [key];
+                                                       rgLabels [iJump] = sl.ILLabel;
+                                                       iKey++;
+                                               }
+                                               else
+                                                       rgLabels [iJump] = lblDefault;
+                                       }
+                                       // emit the switch opcode
+                                       ig.Emit (OpCodes.Switch, rgLabels);
+                               }
+
+                               // mark the default for this block
+                               if (iBlock != 0)
+                                       ig.MarkLabel (lblDefault);
+                       }
+
+                       // TODO: find the default case and emit it here,
+                       //       to prevent having to do the following jump.
+                       //       make sure to mark other labels in the default section
+
+                       // the last default just goes to the end
+                       ig.Emit (OpCodes.Br, lblDefault);
+
+                       // now emit the code for the sections
+                       bool fFoundDefault = false;
+                       bool fAllReturn = true;
+                       foreach (SwitchSection ss in Sections)
+                       {
+                               foreach (SwitchLabel sl in ss.Labels)
+                               {
+                                       ig.MarkLabel (sl.ILLabel);
+                                       ig.MarkLabel (sl.ILLabelCode);
+                                       if (sl.Label == null)
+                                       {
+                                               ig.MarkLabel (lblDefault);
+                                               fFoundDefault = true;
+                                       }
+                               }
+                               bool returns = ss.Block.Emit (ec);
+                               fAllReturn &= returns;
+                               //ig.Emit (OpCodes.Br, lblEnd);
+                       }
+                       
+                       if (!fFoundDefault) {
+                               ig.MarkLabel (lblDefault);
+                               fAllReturn = false;
+                       }
+                       ig.MarkLabel (lblEnd);
+
+                       return fAllReturn;
+               }
+               //
+               // This simple emit switch works, but does not take advantage of the
+               // `switch' opcode. 
+               // TODO: remove non-string logic from here
+               // TODO: binary search strings?
+               //
+               bool SimpleSwitchEmit (EmitContext ec, LocalBuilder val)
+               {
+                       ILGenerator ig = ec.ig;
+                       Label end_of_switch = ig.DefineLabel ();
+                       Label next_test = ig.DefineLabel ();
+                       Label null_target = ig.DefineLabel ();
+                       bool default_found = false;
+                       bool first_test = true;
+                       bool pending_goto_end = false;
+                       bool all_return = true;
+                       bool null_found;
+                       
+                       ig.Emit (OpCodes.Ldloc, val);
+                       
+                       if (Elements.Contains (NullLiteral.Null)){
+                               ig.Emit (OpCodes.Brfalse, null_target);
+                       } else
+                               ig.Emit (OpCodes.Brfalse, default_target);
+                       
+                       ig.Emit (OpCodes.Ldloc, val);
+                       ig.Emit (OpCodes.Call, TypeManager.string_isinterneted_string);
+                       ig.Emit (OpCodes.Stloc, val);
+               
+                       int section_count = Sections.Count;
+                       for (int section = 0; section < section_count; section++){
+                               SwitchSection ss = (SwitchSection) Sections [section];
+                               Label sec_begin = ig.DefineLabel ();
+
+                               if (pending_goto_end)
+                                       ig.Emit (OpCodes.Br, end_of_switch);
+
+                               int label_count = ss.Labels.Count;
+                               null_found = false;
+                               for (int label = 0; label < label_count; label++){
+                                       SwitchLabel sl = (SwitchLabel) ss.Labels [label];
+                                       ig.MarkLabel (sl.ILLabel);
+                                       
+                                       if (!first_test){
+                                               ig.MarkLabel (next_test);
+                                               next_test = ig.DefineLabel ();
+                                       }
+                                       //
+                                       // If we are the default target
+                                       //
+                                       if (sl.Label == null){
+                                               ig.MarkLabel (default_target);
+                                               default_found = true;
+                                       } else {
+                                               object lit = sl.Converted;
+
+                                               if (lit is NullLiteral){
+                                                       null_found = true;
+                                                       if (label_count == 1)
+                                                               ig.Emit (OpCodes.Br, next_test);
+                                                       continue;
+                                                                             
+                                               }
+                                               StringConstant str = (StringConstant) lit;
+                                               
+                                               ig.Emit (OpCodes.Ldloc, val);
+                                               ig.Emit (OpCodes.Ldstr, str.Value);
+                                               if (label_count == 1)
+                                                       ig.Emit (OpCodes.Bne_Un, next_test);
+                                               else {
+                                                       if (label+1 == label_count)
+                                                               ig.Emit (OpCodes.Bne_Un, next_test);
+                                                       else
+                                                               ig.Emit (OpCodes.Beq, sec_begin);
+                                               }
+                                       }
+                               }
+                               if (null_found)
+                                       ig.MarkLabel (null_target);
+                               ig.MarkLabel (sec_begin);
+                               foreach (SwitchLabel sl in ss.Labels)
+                                       ig.MarkLabel (sl.ILLabelCode);
+
+                               bool returns = ss.Block.Emit (ec);
+                               if (returns)
+                                       pending_goto_end = false;
+                               else {
+                                       all_return = false;
+                                       pending_goto_end = true;
+                               }
+                               first_test = false;
+                       }
+                       if (!default_found){
+                               ig.MarkLabel (default_target);
+                               all_return = false;
+                       }
+                       ig.MarkLabel (next_test);
+                       ig.MarkLabel (end_of_switch);
+
+                       return all_return;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       Expr = Expr.Resolve (ec);
+                       if (Expr == null)
+                               return false;
+
+                       new_expr = SwitchGoverningType (ec, Expr.Type);
+                       if (new_expr == null){
+                               Report.Error (151, loc, "An integer type or string was expected for switch");
+                               return false;
+                       }
+
+                       // Validate switch.
+                       SwitchType = new_expr.Type;
+
+                       if (!CheckSwitch (ec))
+                               return false;
+
+                       Switch old_switch = ec.Switch;
+                       ec.Switch = this;
+                       ec.Switch.SwitchType = SwitchType;
+
+                       ec.StartFlowBranching (FlowBranchingType.SWITCH, loc);
+
+                       bool first = true;
+                       foreach (SwitchSection ss in Sections){
+                               if (!first)
+                                       ec.CurrentBranching.CreateSibling ();
+                               else
+                                       first = false;
+
+                               if (ss.Block.Resolve (ec) != true)
+                                       return false;
+                       }
+
+
+                       if (!got_default)
+                               ec.CurrentBranching.CreateSibling ();
+
+                       ec.EndFlowBranching ();
+                       ec.Switch = old_switch;
+
+                       return true;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       // Store variable for comparission purposes
+                       LocalBuilder value = ec.ig.DeclareLocal (SwitchType);
+                       new_expr.Emit (ec);
+                       ec.ig.Emit (OpCodes.Stloc, value);
+
+                       ILGenerator ig = ec.ig;
+
+                       default_target = ig.DefineLabel ();
+
+                       //
+                       // Setup the codegen context
+                       //
+                       Label old_end = ec.LoopEnd;
+                       Switch old_switch = ec.Switch;
+                       
+                       ec.LoopEnd = ig.DefineLabel ();
+                       ec.Switch = this;
+
+                       // Emit Code.
+                       bool all_return;
+                       if (SwitchType == TypeManager.string_type)
+                               all_return = SimpleSwitchEmit (ec, value);
+                       else
+                               all_return = TableSwitchEmit (ec, value);
+
+                       // Restore context state. 
+                       ig.MarkLabel (ec.LoopEnd);
+
+                       //
+                       // Restore the previous context
+                       //
+                       ec.LoopEnd = old_end;
+                       ec.Switch = old_switch;
+                       
+                       return all_return;
+               }
+       }
+
+       public class Lock : Statement {
+               Expression expr;
+               Statement Statement;
+                       
+               public Lock (Expression expr, Statement stmt, Location l)
+               {
+                       this.expr = expr;
+                       Statement = stmt;
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       expr = expr.Resolve (ec);
+                       return Statement.Resolve (ec) && expr != null;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       Type type = expr.Type;
+                       bool val;
+                       
+                       if (type.IsValueType){
+                               Report.Error (185, loc, "lock statement requires the expression to be " +
+                                             " a reference type (type is: `" +
+                                             TypeManager.CSharpName (type) + "'");
+                               return false;
+                       }
+
+                       ILGenerator ig = ec.ig;
+                       LocalBuilder temp = ig.DeclareLocal (type);
+                               
+                       expr.Emit (ec);
+                       ig.Emit (OpCodes.Dup);
+                       ig.Emit (OpCodes.Stloc, temp);
+                       ig.Emit (OpCodes.Call, TypeManager.void_monitor_enter_object);
+
+                       // try
+                       Label end = ig.BeginExceptionBlock ();
+                       bool old_in_try = ec.InTry;
+                       ec.InTry = true;
+                       Label finish = ig.DefineLabel ();
+                       val = Statement.Emit (ec);
+                       ec.InTry = old_in_try;
+                       // ig.Emit (OpCodes.Leave, finish);
+
+                       ig.MarkLabel (finish);
+                       
+                       // finally
+                       ig.BeginFinallyBlock ();
+                       ig.Emit (OpCodes.Ldloc, temp);
+                       ig.Emit (OpCodes.Call, TypeManager.void_monitor_exit_object);
+                       ig.EndExceptionBlock ();
+                       
+                       return val;
+               }
+       }
+
+       public class Unchecked : Statement {
+               public readonly Block Block;
+               
+               public Unchecked (Block b)
+               {
+                       Block = b;
+                       b.Unchecked = true;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       bool previous_state = ec.CheckState;
+                       bool previous_state_const = ec.ConstantCheckState;
+
+                       ec.CheckState = false;
+                       ec.ConstantCheckState = false;
+                       bool ret = Block.Resolve (ec);
+                       ec.CheckState = previous_state;
+                       ec.ConstantCheckState = previous_state_const;
+
+                       return ret;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       bool previous_state = ec.CheckState;
+                       bool previous_state_const = ec.ConstantCheckState;
+                       bool val;
+                       
+                       ec.CheckState = false;
+                       ec.ConstantCheckState = false;
+                       val = Block.Emit (ec);
+                       ec.CheckState = previous_state;
+                       ec.ConstantCheckState = previous_state_const;
+
+                       return val;
+               }
+       }
+
+       public class Checked : Statement {
+               public readonly Block Block;
+               
+               public Checked (Block b)
+               {
+                       Block = b;
+                       b.Unchecked = false;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       bool previous_state = ec.CheckState;
+                       bool previous_state_const = ec.ConstantCheckState;
+                       
+                       ec.CheckState = true;
+                       ec.ConstantCheckState = true;
+                       bool ret = Block.Resolve (ec);
+                       ec.CheckState = previous_state;
+                       ec.ConstantCheckState = previous_state_const;
+
+                       return ret;
+               }
+
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       bool previous_state = ec.CheckState;
+                       bool previous_state_const = ec.ConstantCheckState;
+                       bool val;
+                       
+                       ec.CheckState = true;
+                       ec.ConstantCheckState = true;
+                       val = Block.Emit (ec);
+                       ec.CheckState = previous_state;
+                       ec.ConstantCheckState = previous_state_const;
+
+                       return val;
+               }
+       }
+
+       public class Unsafe : Statement {
+               public readonly Block Block;
+
+               public Unsafe (Block b)
+               {
+                       Block = b;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       bool previous_state = ec.InUnsafe;
+                       bool val;
+                       
+                       ec.InUnsafe = true;
+                       val = Block.Resolve (ec);
+                       ec.InUnsafe = previous_state;
+
+                       return val;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       bool previous_state = ec.InUnsafe;
+                       bool val;
+                       
+                       ec.InUnsafe = true;
+                       val = Block.Emit (ec);
+                       ec.InUnsafe = previous_state;
+
+                       return val;
+               }
+       }
+
+       // 
+       // Fixed statement
+       //
+       public class Fixed : Statement {
+               Expression type;
+               ArrayList declarators;
+               Statement statement;
+               Type expr_type;
+               FixedData[] data;
+
+               struct FixedData {
+                       public bool is_object;
+                       public LocalInfo vi;
+                       public Expression expr;
+                       public Expression converted;
+               }                       
+
+               public Fixed (Expression type, ArrayList decls, Statement stmt, Location l)
+               {
+                       this.type = type;
+                       declarators = decls;
+                       statement = stmt;
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       if (!ec.InUnsafe){
+                               Expression.UnsafeError (loc);
+                               return false;
+                       }
+                       
+                       expr_type = ec.DeclSpace.ResolveType (type, false, loc);
+                       if (expr_type == null)
+                               return false;
+
+                       if (ec.RemapToProxy){
+                               Report.Error (-210, loc, "Fixed statement not allowed in iterators");
+                               return false;
+                       }
+                       
+                       data = new FixedData [declarators.Count];
+
+                       if (!expr_type.IsPointer){
+                               Report.Error (209, loc, "Variables in a fixed statement must be pointers");
+                               return false;
+                       }
+                       
+                       int i = 0;
+                       foreach (Pair p in declarators){
+                               LocalInfo vi = (LocalInfo) p.First;
+                               Expression e = (Expression) p.Second;
+
+                               vi.VariableInfo = null;
+
+                               //
+                               // The rules for the possible declarators are pretty wise,
+                               // but the production on the grammar is more concise.
+                               //
+                               // So we have to enforce these rules here.
+                               //
+                               // We do not resolve before doing the case 1 test,
+                               // because the grammar is explicit in that the token &
+                               // is present, so we need to test for this particular case.
+                               //
+
+                               //
+                               // Case 1: & object.
+                               //
+                               if (e is Unary && ((Unary) e).Oper == Unary.Operator.AddressOf){
+                                       Expression child = ((Unary) e).Expr;
+
+                                       vi.MakePinned ();
+                                       if (child is ParameterReference || child is LocalVariableReference){
+                                               Report.Error (
+                                                       213, loc, 
+                                                       "No need to use fixed statement for parameters or " +
+                                                       "local variable declarations (address is already " +
+                                                       "fixed)");
+                                               return false;
+                                       }
+
+                                       ec.InFixedInitializer = true;
+                                       e = e.Resolve (ec);
+                                       ec.InFixedInitializer = false;
+                                       if (e == null)
+                                               return false;
+
+                                       child = ((Unary) e).Expr;
+                                       
+                                       if (!TypeManager.VerifyUnManaged (child.Type, loc))
+                                               return false;
+
+                                       data [i].is_object = true;
+                                       data [i].expr = e;
+                                       data [i].converted = null;
+                                       data [i].vi = vi;
+                                       i++;
+
+                                       continue;
+                               }
+
+                               ec.InFixedInitializer = true;
+                               e = e.Resolve (ec);
+                               ec.InFixedInitializer = false;
+                               if (e == null)
+                                       return false;
+
+                               //
+                               // Case 2: Array
+                               //
+                               if (e.Type.IsArray){
+                                       Type array_type = TypeManager.GetElementType (e.Type);
+                                       
+                                       vi.MakePinned ();
+                                       //
+                                       // Provided that array_type is unmanaged,
+                                       //
+                                       if (!TypeManager.VerifyUnManaged (array_type, loc))
+                                               return false;
+
+                                       //
+                                       // and T* is implicitly convertible to the
+                                       // pointer type given in the fixed statement.
+                                       //
+                                       ArrayPtr array_ptr = new ArrayPtr (e, loc);
+                                       
+                                       Expression converted = Convert.ImplicitConversionRequired (
+                                               ec, array_ptr, vi.VariableType, loc);
+                                       if (converted == null)
+                                               return false;
+
+                                       data [i].is_object = false;
+                                       data [i].expr = e;
+                                       data [i].converted = converted;
+                                       data [i].vi = vi;
+                                       i++;
+
+                                       continue;
+                               }
+
+                               //
+                               // Case 3: string
+                               //
+                               if (e.Type == TypeManager.string_type){
+                                       data [i].is_object = false;
+                                       data [i].expr = e;
+                                       data [i].converted = null;
+                                       data [i].vi = vi;
+                                       i++;
+                               }
+                       }
+
+                       return statement.Resolve (ec);
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       bool is_ret = false;
+                       LocalBuilder [] clear_list = new LocalBuilder [data.Length];
+                       
+                       for (int i = 0; i < data.Length; i++) {
+                               LocalInfo vi = data [i].vi;
+
+                               //
+                               // Case 1: & object.
+                               //
+                               if (data [i].is_object) {
+                                       //
+                                       // Store pointer in pinned location
+                                       //
+                                       data [i].expr.Emit (ec);
+                                       ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+                                       clear_list [i] = vi.LocalBuilder;
+                                       continue;
+                               }
+
+                               //
+                               // Case 2: Array
+                               //
+                               if (data [i].expr.Type.IsArray){
+                                       //
+                                       // Store pointer in pinned location
+                                       //
+                                       data [i].converted.Emit (ec);
+                                       
+                                       ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+                                       clear_list [i] = vi.LocalBuilder;
+                                       continue;
+                               }
+
+                               //
+                               // Case 3: string
+                               //
+                               if (data [i].expr.Type == TypeManager.string_type){
+                                       LocalBuilder pinned_string = ig.DeclareLocal (TypeManager.string_type);
+                                       TypeManager.MakePinned (pinned_string);
+                                       clear_list [i] = pinned_string;
+                                       
+                                       data [i].expr.Emit (ec);
+                                       ig.Emit (OpCodes.Stloc, pinned_string);
+
+                                       Expression sptr = new StringPtr (pinned_string, loc);
+                                       Expression converted = Convert.ImplicitConversionRequired (
+                                               ec, sptr, vi.VariableType, loc);
+                                       
+                                       if (converted == null)
+                                               continue;
+
+                                       converted.Emit (ec);
+                                       ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+                               }
+                       }
+
+                       is_ret = statement.Emit (ec);
+
+                       if (is_ret)
+                               return is_ret;
+                       //
+                       // Clear the pinned variable
+                       //
+                       for (int i = 0; i < data.Length; i++) {
+                               LocalInfo vi = data [i].vi;
+
+                               if (data [i].is_object || data [i].expr.Type.IsArray) {
+                                       ig.Emit (OpCodes.Ldc_I4_0);
+                                       ig.Emit (OpCodes.Conv_U);
+                                       ig.Emit (OpCodes.Stloc, clear_list [i]);
+                               } else if (data [i].expr.Type == TypeManager.string_type){
+                                       ig.Emit (OpCodes.Ldnull);
+                                       ig.Emit (OpCodes.Stloc, clear_list [i]);
+                               }
+                       }
+
+                       return is_ret;
+               }
+       }
+       
+       public class Catch {
+               public readonly string Name;
+               public readonly Block  Block;
+               public readonly Location Location;
+
+               Expression type_expr;
+               Type type;
+               
+               public Catch (Expression type, string name, Block block, Location l)
+               {
+                       type_expr = type;
+                       Name = name;
+                       Block = block;
+                       Location = l;
+               }
+
+               public Type CatchType {
+                       get {
+                               return type;
+                       }
+               }
+
+               public bool IsGeneral {
+                       get {
+                               return type_expr == null;
+                       }
+               }
+
+               public bool Resolve (EmitContext ec)
+               {
+                       if (type_expr != null) {
+                               type = ec.DeclSpace.ResolveType (type_expr, false, Location);
+                               if (type == null)
+                                       return false;
+
+                               if (type != TypeManager.exception_type && !type.IsSubclassOf (TypeManager.exception_type)){
+                                       Report.Error (155, Location,
+                                                     "The type caught or thrown must be derived " +
+                                                     "from System.Exception");
+                                       return false;
+                               }
+                       } else
+                               type = null;
+
+                       if (!Block.Resolve (ec))
+                               return false;
+
+                       return true;
+               }
+       }
+
+       public class Try : Statement {
+               public readonly Block Fini, Block;
+               public readonly ArrayList Specific;
+               public readonly Catch General;
+               
+               //
+               // specific, general and fini might all be null.
+               //
+               public Try (Block block, ArrayList specific, Catch general, Block fini, Location l)
+               {
+                       if (specific == null && general == null){
+                               Console.WriteLine ("CIR.Try: Either specific or general have to be non-null");
+                       }
+                       
+                       this.Block = block;
+                       this.Specific = specific;
+                       this.General = general;
+                       this.Fini = fini;
+                       loc = l;
+               }
+
+               public override bool Resolve (EmitContext ec)
+               {
+                       bool ok = true;
+                       
+                       ec.StartFlowBranching (FlowBranchingType.EXCEPTION, Block.StartLocation);
+
+                       Report.Debug (1, "START OF TRY BLOCK", Block.StartLocation);
+
+                       bool old_in_try = ec.InTry;
+                       ec.InTry = true;
+
+                       if (!Block.Resolve (ec))
+                               ok = false;
+
+                       ec.InTry = old_in_try;
+
+                       FlowBranching.UsageVector vector = ec.CurrentBranching.CurrentUsageVector;
+
+                       Report.Debug (1, "START OF CATCH BLOCKS", vector);
+
+                       foreach (Catch c in Specific){
+                               ec.CurrentBranching.CreateSibling ();
+                               Report.Debug (1, "STARTED SIBLING FOR CATCH", ec.CurrentBranching);
+
+                               if (c.Name != null) {
+                                       LocalInfo vi = c.Block.GetLocalInfo (c.Name);
+                                       if (vi == null)
+                                               throw new Exception ();
+
+                                       vi.VariableInfo = null;
+                               }
+
+                               bool old_in_catch = ec.InCatch;
+                               ec.InCatch = true;
+
+                               if (!c.Resolve (ec))
+                                       ok = false;
+
+                               ec.InCatch = old_in_catch;
+
+                               FlowBranching.UsageVector current = ec.CurrentBranching.CurrentUsageVector;
+
+                               if (!current.AlwaysReturns && !current.AlwaysBreaks)
+                                       vector.AndLocals (current);
+                               else
+                                       vector.Or (current);
+                       }
+
+                       Report.Debug (1, "END OF CATCH BLOCKS", ec.CurrentBranching);
+
+                       if (General != null){
+                               ec.CurrentBranching.CreateSibling ();
+                               Report.Debug (1, "STARTED SIBLING FOR GENERAL", ec.CurrentBranching);
+
+                               bool old_in_catch = ec.InCatch;
+                               ec.InCatch = true;
+
+                               if (!General.Resolve (ec))
+                                       ok = false;
+
+                               ec.InCatch = old_in_catch;
+
+                               FlowBranching.UsageVector current = ec.CurrentBranching.CurrentUsageVector;
+
+                               if (!current.AlwaysReturns && !current.AlwaysBreaks)
+                                       vector.AndLocals (current);
+                               else    
+                                       vector.Or (current);
+                       }
+
+                       Report.Debug (1, "END OF GENERAL CATCH BLOCKS", ec.CurrentBranching);
+
+                       if (Fini != null) {
+                               if (ok)
+                                       ec.CurrentBranching.CreateSiblingForFinally ();
+                               Report.Debug (1, "STARTED SIBLING FOR FINALLY", ec.CurrentBranching, vector);
+
+                               bool old_in_finally = ec.InFinally;
+                               ec.InFinally = true;
+
+                               if (!Fini.Resolve (ec))
+                                       ok = false;
+
+                               ec.InFinally = old_in_finally;
+                       }
+
+                       FlowReturns returns = ec.EndFlowBranching ();
+
+                       FlowBranching.UsageVector f_vector = ec.CurrentBranching.CurrentUsageVector;
+
+                       Report.Debug (1, "END OF FINALLY", ec.CurrentBranching, returns, vector, f_vector);
+
+                       if ((returns == FlowReturns.SOMETIMES) || (returns == FlowReturns.ALWAYS)) {
+                               ec.CurrentBranching.CheckOutParameters (f_vector.Parameters, loc);
+                       }
+
+                       ec.CurrentBranching.CurrentUsageVector.Or (vector);
+
+                       Report.Debug (1, "END OF TRY", ec.CurrentBranching);
+
+                       if (returns != FlowReturns.ALWAYS) {
+                               // Unfortunately, System.Reflection.Emit automatically emits a leave
+                               // to the end of the finally block.  This is a problem if `returns'
+                               // is true since we may jump to a point after the end of the method.
+                               // As a workaround, emit an explicit ret here.
+                               ec.NeedExplicitReturn = true;
+                       }
+
+                       return ok;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Label end;
+                       Label finish = ig.DefineLabel ();;
+                       bool returns;
+
+                       ec.TryCatchLevel++;
+                       end = ig.BeginExceptionBlock ();
+                       bool old_in_try = ec.InTry;
+                       ec.InTry = true;
+                       returns = Block.Emit (ec);
+                       ec.InTry = old_in_try;
+
+                       //
+                       // System.Reflection.Emit provides this automatically:
+                       // ig.Emit (OpCodes.Leave, finish);
+
+                       bool old_in_catch = ec.InCatch;
+                       ec.InCatch = true;
+                       DeclSpace ds = ec.DeclSpace;
+
+                       foreach (Catch c in Specific){
+                               LocalInfo vi;
+                               
+                               ig.BeginCatchBlock (c.CatchType);
+
+                               if (c.Name != null){
+                                       vi = c.Block.GetLocalInfo (c.Name);
+                                       if (vi == null)
+                                               throw new Exception ("Variable does not exist in this block");
+
+                                       ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+                               } else
+                                       ig.Emit (OpCodes.Pop);
+                               
+                               if (!c.Block.Emit (ec))
+                                       returns = false;
+                       }
+
+                       if (General != null){
+                               ig.BeginCatchBlock (TypeManager.object_type);
+                               ig.Emit (OpCodes.Pop);
+                               if (!General.Block.Emit (ec))
+                                       returns = false;
+                       }
+                       ec.InCatch = old_in_catch;
+
+                       ig.MarkLabel (finish);
+                       if (Fini != null){
+                               ig.BeginFinallyBlock ();
+                               bool old_in_finally = ec.InFinally;
+                               ec.InFinally = true;
+                               Fini.Emit (ec);
+                               ec.InFinally = old_in_finally;
+                       }
+                       
+                       ig.EndExceptionBlock ();
+                       ec.TryCatchLevel--;
+
+                       return returns;
+               }
+       }
+
+       public class Using : Statement {
+               object expression_or_block;
+               Statement Statement;
+               ArrayList var_list;
+               Expression expr;
+               Type expr_type;
+               Expression conv;
+               Expression [] converted_vars;
+               ExpressionStatement [] assign;
+               
+               public Using (object expression_or_block, Statement stmt, Location l)
+               {
+                       this.expression_or_block = expression_or_block;
+                       Statement = stmt;
+                       loc = l;
+               }
+
+               //
+               // Resolves for the case of using using a local variable declaration.
+               //
+               bool ResolveLocalVariableDecls (EmitContext ec)
+               {
+                       bool need_conv = false;
+                       expr_type = ec.DeclSpace.ResolveType (expr, false, loc);
+                       int i = 0;
+
+                       if (expr_type == null)
+                               return false;
+
+                       //
+                       // The type must be an IDisposable or an implicit conversion
+                       // must exist.
+                       //
+                       converted_vars = new Expression [var_list.Count];
+                       assign = new ExpressionStatement [var_list.Count];
+                       if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type)){
+                               foreach (DictionaryEntry e in var_list){
+                                       Expression var = (Expression) e.Key;
+
+                                       var = var.ResolveLValue (ec, new EmptyExpression ());
+                                       if (var == null)
+                                               return false;
+                                       
+                                       converted_vars [i] = Convert.ImplicitConversionRequired (
+                                               ec, var, TypeManager.idisposable_type, loc);
+
+                                       if (converted_vars [i] == null)
+                                               return false;
+                                       i++;
+                               }
+                               need_conv = true;
+                       }
+
+                       i = 0;
+                       foreach (DictionaryEntry e in var_list){
+                               LocalVariableReference var = (LocalVariableReference) e.Key;
+                               Expression new_expr = (Expression) e.Value;
+                               Expression a;
+
+                               a = new Assign (var, new_expr, loc);
+                               a = a.Resolve (ec);
+                               if (a == null)
+                                       return false;
+
+                               if (!need_conv)
+                                       converted_vars [i] = var;
+                               assign [i] = (ExpressionStatement) a;
+                               i++;
+                       }
+
+                       return true;
+               }
+
+               bool ResolveExpression (EmitContext ec)
+               {
+                       if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type)){
+                               conv = Convert.ImplicitConversionRequired (
+                                       ec, expr, TypeManager.idisposable_type, loc);
+
+                               if (conv == null)
+                                       return false;
+                       }
+
+                       return true;
+               }
+               
+               //
+               // Emits the code for the case of using using a local variable declaration.
+               //
+               bool EmitLocalVariableDecls (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       int i = 0;
+
+                       bool old_in_try = ec.InTry;
+                       ec.InTry = true;
+                       for (i = 0; i < assign.Length; i++) {
+                               assign [i].EmitStatement (ec);
+                               
+                               ig.BeginExceptionBlock ();
+                       }
+                       Statement.Emit (ec);
+                       ec.InTry = old_in_try;
+
+                       bool old_in_finally = ec.InFinally;
+                       ec.InFinally = true;
+                       var_list.Reverse ();
+                       foreach (DictionaryEntry e in var_list){
+                               LocalVariableReference var = (LocalVariableReference) e.Key;
+                               Label skip = ig.DefineLabel ();
+                               i--;
+                               
+                               ig.BeginFinallyBlock ();
+                               
+                               var.Emit (ec);
+                               ig.Emit (OpCodes.Brfalse, skip);
+                               converted_vars [i].Emit (ec);
+                               ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+                               ig.MarkLabel (skip);
+                               ig.EndExceptionBlock ();
+                       }
+                       ec.InFinally = old_in_finally;
+
+                       return false;
+               }
+
+               bool EmitExpression (EmitContext ec)
+               {
+                       //
+                       // Make a copy of the expression and operate on that.
+                       //
+                       ILGenerator ig = ec.ig;
+                       LocalBuilder local_copy = ig.DeclareLocal (expr_type);
+                       if (conv != null)
+                               conv.Emit (ec);
+                       else
+                               expr.Emit (ec);
+                       ig.Emit (OpCodes.Stloc, local_copy);
+
+                       bool old_in_try = ec.InTry;
+                       ec.InTry = true;
+                       ig.BeginExceptionBlock ();
+                       Statement.Emit (ec);
+                       ec.InTry = old_in_try;
+                       
+                       Label skip = ig.DefineLabel ();
+                       bool old_in_finally = ec.InFinally;
+                       ig.BeginFinallyBlock ();
+                       ig.Emit (OpCodes.Ldloc, local_copy);
+                       ig.Emit (OpCodes.Brfalse, skip);
+                       ig.Emit (OpCodes.Ldloc, local_copy);
+                       ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+                       ig.MarkLabel (skip);
+                       ec.InFinally = old_in_finally;
+                       ig.EndExceptionBlock ();
+
+                       return false;
+               }
+               
+               public override bool Resolve (EmitContext ec)
+               {
+                       if (expression_or_block is DictionaryEntry){
+                               expr = (Expression) ((DictionaryEntry) expression_or_block).Key;
+                               var_list = (ArrayList)((DictionaryEntry)expression_or_block).Value;
+
+                               if (!ResolveLocalVariableDecls (ec))
+                                       return false;
+
+                       } else if (expression_or_block is Expression){
+                               expr = (Expression) expression_or_block;
+
+                               expr = expr.Resolve (ec);
+                               if (expr == null)
+                                       return false;
+
+                               expr_type = expr.Type;
+
+                               if (!ResolveExpression (ec))
+                                       return false;
+                       }                       
+
+                       return Statement.Resolve (ec);
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       if (expression_or_block is DictionaryEntry)
+                               return EmitLocalVariableDecls (ec);
+                       else if (expression_or_block is Expression)
+                               return EmitExpression (ec);
+
+                       return false;
+               }
+       }
+
+       /// <summary>
+       ///   Implementation of the foreach C# statement
+       /// </summary>
+       public class Foreach : Statement {
+               Expression type;
+               LocalVariableReference variable;
+               Expression expr;
+               Statement statement;
+               ForeachHelperMethods hm;
+               Expression empty, conv;
+               Type array_type, element_type;
+               Type var_type;
+               
+               public Foreach (Expression type, LocalVariableReference var, Expression expr,
+                               Statement stmt, Location l)
+               {
+                       this.type = type;
+                       this.variable = var;
+                       this.expr = expr;
+                       statement = stmt;
+                       loc = l;
+               }
+               
+               public override bool Resolve (EmitContext ec)
+               {
+                       expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return false;
+
+                       var_type = ec.DeclSpace.ResolveType (type, false, loc);
+                       if (var_type == null)
+                               return false;
+                       
+                       //
+                       // We need an instance variable.  Not sure this is the best
+                       // way of doing this.
+                       //
+                       // FIXME: When we implement propertyaccess, will those turn
+                       // out to return values in ExprClass?  I think they should.
+                       //
+                       if (!(expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.Value ||
+                             expr.eclass == ExprClass.PropertyAccess || expr.eclass == ExprClass.IndexerAccess)){
+                               error1579 (expr.Type);
+                               return false;
+                       }
+
+                       if (expr.Type.IsArray) {
+                               array_type = expr.Type;
+                               element_type = TypeManager.GetElementType (array_type);
+
+                               empty = new EmptyExpression (element_type);
+                       } else {
+                               hm = ProbeCollectionType (ec, expr.Type);
+                               if (hm == null){
+                                       error1579 (expr.Type);
+                                       return false;
+                               }
+
+                               array_type = expr.Type;
+                               element_type = hm.element_type;
+
+                               empty = new EmptyExpression (hm.element_type);
+                       }
+
+                       ec.StartFlowBranching (FlowBranchingType.LOOP_BLOCK, loc);
+                       ec.CurrentBranching.CreateSibling ();
+
+                       //
+                       //
+                       // FIXME: maybe we can apply the same trick we do in the
+                       // array handling to avoid creating empty and conv in some cases.
+                       //
+                       // Although it is not as important in this case, as the type
+                       // will not likely be object (what the enumerator will return).
+                       //
+                       conv = Convert.ExplicitConversion (ec, empty, var_type, loc);
+                       if (conv == null)
+                               return false;
+
+                       if (variable.ResolveLValue (ec, empty) == null)
+                               return false;
+
+                       if (!statement.Resolve (ec))
+                               return false;
+
+                       FlowReturns returns = ec.EndFlowBranching ();
+
+                       return true;
+               }
+               
+               //
+               // Retrieves a `public bool MoveNext ()' method from the Type `t'
+               //
+               static MethodInfo FetchMethodMoveNext (Type t)
+               {
+                       MemberList move_next_list;
+                       
+                       move_next_list = TypeContainer.FindMembers (
+                               t, MemberTypes.Method,
+                               BindingFlags.Public | BindingFlags.Instance,
+                               Type.FilterName, "MoveNext");
+                       if (move_next_list.Count == 0)
+                               return null;
+
+                       foreach (MemberInfo m in move_next_list){
+                               MethodInfo mi = (MethodInfo) m;
+                               Type [] args;
+                               
+                               args = TypeManager.GetArgumentTypes (mi);
+                               if (args != null && args.Length == 0){
+                                       if (mi.ReturnType == TypeManager.bool_type)
+                                               return mi;
+                               }
+                       }
+                       return null;
+               }
+               
+               //
+               // Retrieves a `public T get_Current ()' method from the Type `t'
+               //
+               static MethodInfo FetchMethodGetCurrent (Type t)
+               {
+                       MemberList move_next_list;
+                       
+                       move_next_list = TypeContainer.FindMembers (
+                               t, MemberTypes.Method,
+                               BindingFlags.Public | BindingFlags.Instance,
+                               Type.FilterName, "get_Current");
+                       if (move_next_list.Count == 0)
+                               return null;
+
+                       foreach (MemberInfo m in move_next_list){
+                               MethodInfo mi = (MethodInfo) m;
+                               Type [] args;
+
+                               args = TypeManager.GetArgumentTypes (mi);
+                               if (args != null && args.Length == 0)
+                                       return mi;
+                       }
+                       return null;
+               }
+
+               // 
+               // This struct records the helper methods used by the Foreach construct
+               //
+               class ForeachHelperMethods {
+                       public EmitContext ec;
+                       public MethodInfo get_enumerator;
+                       public MethodInfo move_next;
+                       public MethodInfo get_current;
+                       public Type element_type;
+                       public Type enumerator_type;
+                       public bool is_disposable;
+
+                       public ForeachHelperMethods (EmitContext ec)
+                       {
+                               this.ec = ec;
+                               this.element_type = TypeManager.object_type;
+                               this.enumerator_type = TypeManager.ienumerator_type;
+                               this.is_disposable = true;
+                       }
+               }
+               
+               static bool GetEnumeratorFilter (MemberInfo m, object criteria)
+               {
+                       if (m == null)
+                               return false;
+                       
+                       if (!(m is MethodInfo))
+                               return false;
+                       
+                       if (m.Name != "GetEnumerator")
+                               return false;
+
+                       MethodInfo mi = (MethodInfo) m;
+                       Type [] args = TypeManager.GetArgumentTypes (mi);
+                       if (args != null){
+                               if (args.Length != 0)
+                                       return false;
+                       }
+                       ForeachHelperMethods hm = (ForeachHelperMethods) criteria;
+                       EmitContext ec = hm.ec;
+
+                       //
+                       // Check whether GetEnumerator is accessible to us
+                       //
+                       MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
+
+                       Type declaring = mi.DeclaringType;
+                       if (prot == MethodAttributes.Private){
+                               if (declaring != ec.ContainerType)
+                                       return false;
+                       } else if (prot == MethodAttributes.FamANDAssem){
+                               // If from a different assembly, false
+                               if (!(mi is MethodBuilder))
+                                       return false;
+                               //
+                               // Are we being invoked from the same class, or from a derived method?
+                               //
+                               if (ec.ContainerType != declaring){
+                                       if (!ec.ContainerType.IsSubclassOf (declaring))
+                                               return false;
+                               }
+                       } else if (prot == MethodAttributes.FamORAssem){
+                               if (!(mi is MethodBuilder ||
+                                     ec.ContainerType == declaring ||
+                                     ec.ContainerType.IsSubclassOf (declaring)))
+                                       return false;
+                       } if (prot == MethodAttributes.Family){
+                               if (!(ec.ContainerType == declaring ||
+                                     ec.ContainerType.IsSubclassOf (declaring)))
+                                       return false;
+                       }
+
+                       if ((mi.ReturnType == TypeManager.ienumerator_type) && (declaring == TypeManager.string_type))
+                               //
+                               // Apply the same optimization as MS: skip the GetEnumerator
+                               // returning an IEnumerator, and use the one returning a 
+                               // CharEnumerator instead. This allows us to avoid the 
+                               // try-finally block and the boxing.
+                               //
+                               return false;
+
+                       //
+                       // Ok, we can access it, now make sure that we can do something
+                       // with this `GetEnumerator'
+                       //
+
+                       if (mi.ReturnType == TypeManager.ienumerator_type ||
+                           TypeManager.ienumerator_type.IsAssignableFrom (mi.ReturnType) ||
+                           (!RootContext.StdLib && TypeManager.ImplementsInterface (mi.ReturnType, TypeManager.ienumerator_type))) {
+                               if (declaring != TypeManager.string_type) {
+                                       hm.move_next = TypeManager.bool_movenext_void;
+                                       hm.get_current = TypeManager.object_getcurrent_void;
+                                       return true;
+                               }
+                       }
+
+                       //
+                       // Ok, so they dont return an IEnumerable, we will have to
+                       // find if they support the GetEnumerator pattern.
+                       //
+                       Type return_type = mi.ReturnType;
+
+                       hm.move_next = FetchMethodMoveNext (return_type);
+                       if (hm.move_next == null)
+                               return false;
+                       hm.get_current = FetchMethodGetCurrent (return_type);
+                       if (hm.get_current == null)
+                               return false;
+
+                       hm.element_type = hm.get_current.ReturnType;
+                       hm.enumerator_type = return_type;
+                       hm.is_disposable = !hm.enumerator_type.IsSealed ||
+                               TypeManager.ImplementsInterface (
+                                       hm.enumerator_type, TypeManager.idisposable_type);
+
+                       return true;
+               }
+               
+               /// <summary>
+               ///   This filter is used to find the GetEnumerator method
+               ///   on which IEnumerator operates
+               /// </summary>
+               static MemberFilter FilterEnumerator;
+               
+               static Foreach ()
+               {
+                       FilterEnumerator = new MemberFilter (GetEnumeratorFilter);
+               }
+
+                void error1579 (Type t)
+                {
+                        Report.Error (1579, loc,
+                                      "foreach statement cannot operate on variables of type `" +
+                                      t.FullName + "' because that class does not provide a " +
+                                      " GetEnumerator method or it is inaccessible");
+                }
+
+               static bool TryType (Type t, ForeachHelperMethods hm)
+               {
+                       MemberList mi;
+                       
+                       mi = TypeContainer.FindMembers (t, MemberTypes.Method,
+                                                       BindingFlags.Public | BindingFlags.NonPublic |
+                                                       BindingFlags.Instance,
+                                                       FilterEnumerator, hm);
+
+                       if (mi.Count == 0)
+                               return false;
+
+                       hm.get_enumerator = (MethodInfo) mi [0];
+                       return true;    
+               }
+               
+               //
+               // Looks for a usable GetEnumerator in the Type, and if found returns
+               // the three methods that participate: GetEnumerator, MoveNext and get_Current
+               //
+               ForeachHelperMethods ProbeCollectionType (EmitContext ec, Type t)
+               {
+                       ForeachHelperMethods hm = new ForeachHelperMethods (ec);
+
+                       if (TryType (t, hm))
+                               return hm;
+
+                       //
+                       // Now try to find the method in the interfaces
+                       //
+                       while (t != null){
+                               Type [] ifaces = t.GetInterfaces ();
+
+                               foreach (Type i in ifaces){
+                                       if (TryType (i, hm))
+                                               return hm;
+                               }
+                               
+                               //
+                               // Since TypeBuilder.GetInterfaces only returns the interface
+                               // types for this type, we have to keep looping, but once
+                               // we hit a non-TypeBuilder (ie, a Type), then we know we are
+                               // done, because it returns all the types
+                               //
+                               if ((t is TypeBuilder))
+                                       t = t.BaseType;
+                               else
+                                       break;
+                       } 
+
+                       return null;
+               }
+
+               //
+               // FIXME: possible optimization.
+               // We might be able to avoid creating `empty' if the type is the sam
+               //
+               bool EmitCollectionForeach (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       LocalBuilder enumerator, disposable;
+
+                       enumerator = ig.DeclareLocal (hm.enumerator_type);
+                       if (hm.is_disposable)
+                               disposable = ig.DeclareLocal (TypeManager.idisposable_type);
+                       else
+                               disposable = null;
+                       
+                       //
+                       // Instantiate the enumerator
+                       //
+                       if (expr.Type.IsValueType){
+                               if (expr is IMemoryLocation){
+                                       IMemoryLocation ml = (IMemoryLocation) expr;
+
+                                       ml.AddressOf (ec, AddressOp.Load);
+                               } else
+                                       throw new Exception ("Expr " + expr + " of type " + expr.Type +
+                                                            " does not implement IMemoryLocation");
+                               ig.Emit (OpCodes.Call, hm.get_enumerator);
+                       } else {
+                               expr.Emit (ec);
+                               ig.Emit (OpCodes.Callvirt, hm.get_enumerator);
+                       }
+                       ig.Emit (OpCodes.Stloc, enumerator);
+
+                       //
+                       // Protect the code in a try/finalize block, so that
+                       // if the beast implement IDisposable, we get rid of it
+                       //
+                       Label l;
+                       bool old_in_try = ec.InTry;
+
+                       if (hm.is_disposable) {
+                               l = ig.BeginExceptionBlock ();
+                               ec.InTry = true;
+                       }
+                       
+                       Label end_try = ig.DefineLabel ();
+                       
+                       ig.MarkLabel (ec.LoopBegin);
+                       ig.Emit (OpCodes.Ldloc, enumerator);
+                       ig.Emit (OpCodes.Callvirt, hm.move_next);
+                       ig.Emit (OpCodes.Brfalse, end_try);
+                       ig.Emit (OpCodes.Ldloc, enumerator);
+                       ig.Emit (OpCodes.Callvirt, hm.get_current);
+
+                       variable.EmitAssign (ec, conv);
+                       statement.Emit (ec);
+                       ig.Emit (OpCodes.Br, ec.LoopBegin);
+                       ig.MarkLabel (end_try);
+                       ec.InTry = old_in_try;
+                       
+                       // The runtime provides this for us.
+                       // ig.Emit (OpCodes.Leave, end);
+
+                       //
+                       // Now the finally block
+                       //
+                       if (hm.is_disposable) {
+                               Label end_finally = ig.DefineLabel ();
+                               bool old_in_finally = ec.InFinally;
+                               ec.InFinally = true;
+                               ig.BeginFinallyBlock ();
+                       
+                               ig.Emit (OpCodes.Ldloc, enumerator);
+                               ig.Emit (OpCodes.Isinst, TypeManager.idisposable_type);
+                               ig.Emit (OpCodes.Stloc, disposable);
+                               ig.Emit (OpCodes.Ldloc, disposable);
+                               ig.Emit (OpCodes.Brfalse, end_finally);
+                               ig.Emit (OpCodes.Ldloc, disposable);
+                               ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
+                               ig.MarkLabel (end_finally);
+                               ec.InFinally = old_in_finally;
+
+                               // The runtime generates this anyways.
+                               // ig.Emit (OpCodes.Endfinally);
+
+                               ig.EndExceptionBlock ();
+                       }
+
+                       ig.MarkLabel (ec.LoopEnd);
+                       return false;
+               }
+
+               //
+               // FIXME: possible optimization.
+               // We might be able to avoid creating `empty' if the type is the sam
+               //
+               bool EmitArrayForeach (EmitContext ec)
+               {
+                       int rank = array_type.GetArrayRank ();
+                       ILGenerator ig = ec.ig;
+
+                       LocalBuilder copy = ig.DeclareLocal (array_type);
+                       
+                       //
+                       // Make our copy of the array
+                       //
+                       expr.Emit (ec);
+                       ig.Emit (OpCodes.Stloc, copy);
+                       
+                       if (rank == 1){
+                               LocalBuilder counter = ig.DeclareLocal (TypeManager.int32_type);
+
+                               Label loop, test;
+                               
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               ig.Emit (OpCodes.Stloc, counter);
+                               test = ig.DefineLabel ();
+                               ig.Emit (OpCodes.Br, test);
+
+                               loop = ig.DefineLabel ();
+                               ig.MarkLabel (loop);
+
+                               ig.Emit (OpCodes.Ldloc, copy);
+                               ig.Emit (OpCodes.Ldloc, counter);
+
+                               //
+                               // Load the value, we load the value using the underlying type,
+                               // then we use the variable.EmitAssign to load using the proper cast.
+                               //
+                               ArrayAccess.EmitLoadOpcode (ig, element_type);
+                               variable.EmitAssign (ec, conv);
+
+                               statement.Emit (ec);
+
+                               ig.MarkLabel (ec.LoopBegin);
+                               ig.Emit (OpCodes.Ldloc, counter);
+                               ig.Emit (OpCodes.Ldc_I4_1);
+                               ig.Emit (OpCodes.Add);
+                               ig.Emit (OpCodes.Stloc, counter);
+
+                               ig.MarkLabel (test);
+                               ig.Emit (OpCodes.Ldloc, counter);
+                               ig.Emit (OpCodes.Ldloc, copy);
+                               ig.Emit (OpCodes.Ldlen);
+                               ig.Emit (OpCodes.Conv_I4);
+                               ig.Emit (OpCodes.Blt, loop);
+                       } else {
+                               LocalBuilder [] dim_len   = new LocalBuilder [rank];
+                               LocalBuilder [] dim_count = new LocalBuilder [rank];
+                               Label [] loop = new Label [rank];
+                               Label [] test = new Label [rank];
+                               int dim;
+                               
+                               for (dim = 0; dim < rank; dim++){
+                                       dim_len [dim] = ig.DeclareLocal (TypeManager.int32_type);
+                                       dim_count [dim] = ig.DeclareLocal (TypeManager.int32_type);
+                                       test [dim] = ig.DefineLabel ();
+                                       loop [dim] = ig.DefineLabel ();
+                               }
+                                       
+                               for (dim = 0; dim < rank; dim++){
+                                       ig.Emit (OpCodes.Ldloc, copy);
+                                       IntLiteral.EmitInt (ig, dim);
+                                       ig.Emit (OpCodes.Callvirt, TypeManager.int_getlength_int);
+                                       ig.Emit (OpCodes.Stloc, dim_len [dim]);
+                               }
+
+                               for (dim = 0; dim < rank; dim++){
+                                       ig.Emit (OpCodes.Ldc_I4_0);
+                                       ig.Emit (OpCodes.Stloc, dim_count [dim]);
+                                       ig.Emit (OpCodes.Br, test [dim]);
+                                       ig.MarkLabel (loop [dim]);
+                               }
+
+                               ig.Emit (OpCodes.Ldloc, copy);
+                               for (dim = 0; dim < rank; dim++)
+                                       ig.Emit (OpCodes.Ldloc, dim_count [dim]);
+
+                               //
+                               // FIXME: Maybe we can cache the computation of `get'?
+                               //
+                               Type [] args = new Type [rank];
+                               MethodInfo get;
+
+                               for (int i = 0; i < rank; i++)
+                                       args [i] = TypeManager.int32_type;
+
+                               ModuleBuilder mb = CodeGen.ModuleBuilder;
+                               get = mb.GetArrayMethod (
+                                       array_type, "Get",
+                                       CallingConventions.HasThis| CallingConventions.Standard,
+                                       var_type, args);
+                               ig.Emit (OpCodes.Call, get);
+                               variable.EmitAssign (ec, conv);
+                               statement.Emit (ec);
+                               ig.MarkLabel (ec.LoopBegin);
+                               for (dim = rank - 1; dim >= 0; dim--){
+                                       ig.Emit (OpCodes.Ldloc, dim_count [dim]);
+                                       ig.Emit (OpCodes.Ldc_I4_1);
+                                       ig.Emit (OpCodes.Add);
+                                       ig.Emit (OpCodes.Stloc, dim_count [dim]);
+
+                                       ig.MarkLabel (test [dim]);
+                                       ig.Emit (OpCodes.Ldloc, dim_count [dim]);
+                                       ig.Emit (OpCodes.Ldloc, dim_len [dim]);
+                                       ig.Emit (OpCodes.Blt, loop [dim]);
+                               }
+                       }
+                       ig.MarkLabel (ec.LoopEnd);
+                       
+                       return false;
+               }
+               
+               protected override bool DoEmit (EmitContext ec)
+               {
+                       bool ret_val;
+                       
+                       ILGenerator ig = ec.ig;
+                       
+                       Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd;
+                       bool old_inloop = ec.InLoop;
+                       int old_loop_begin_try_catch_level = ec.LoopBeginTryCatchLevel;
+                       ec.LoopBegin = ig.DefineLabel ();
+                       ec.LoopEnd = ig.DefineLabel ();
+                       ec.InLoop = true;
+                       ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
+                       
+                       if (hm != null)
+                               ret_val = EmitCollectionForeach (ec);
+                       else
+                               ret_val = EmitArrayForeach (ec);
+                       
+                       ec.LoopBegin = old_begin;
+                       ec.LoopEnd = old_end;
+                       ec.InLoop = old_inloop;
+                       ec.LoopBeginTryCatchLevel = old_loop_begin_try_catch_level;
+
+                       return ret_val;
+               }
+       }
+}
diff --git a/mcs/gmcs/statementCollection.cs b/mcs/gmcs/statementCollection.cs
new file mode 100755 (executable)
index 0000000..9e5141d
--- /dev/null
@@ -0,0 +1,166 @@
+//
+// System.CodeDOM CodeStatementCollection Class implementation
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc.
+//
+
+namespace Mono.CSharp {
+
+       using System.Collections;
+       using System;
+       
+       public class StatementCollection : IList, ICollection, IEnumerable {
+
+               ArrayList statements;
+               
+               //
+               // Constructors
+               //
+               public StatementCollection ()
+               {
+                       statements = new ArrayList ();
+               }
+
+               //
+               // Properties
+               //
+               public int Count {
+                       get {
+                               return statements.Count;
+                       }
+               }
+
+               //
+               // Methods
+               //
+               public void Add (Statement value)
+               {
+                       statements.Add (value);
+               }
+
+               public void AddRange (Statement [] values)
+               {
+                       foreach (Statement ca in values) 
+                               statements.Add (ca);
+
+               }
+
+               public void Clear ()
+               {
+                       statements.Clear ();
+               }
+
+               private class Enumerator : IEnumerator {
+                       private StatementCollection collection;
+                       private int currentIndex = -1;
+
+                       internal Enumerator (StatementCollection collection)
+                       {
+                               this.collection = collection;
+                       }
+
+                       public object Current {
+                               get {
+                                       if (currentIndex == collection.Count)
+                                               throw new InvalidOperationException ();
+                                       return collection [currentIndex];
+                               }
+                       }
+
+                       public bool MoveNext ()
+                       {
+                               if (currentIndex > collection.Count)
+                                       throw new InvalidOperationException ();
+                               return ++currentIndex < collection.Count;
+                       }
+
+                       public void Reset ()
+                       {
+                               currentIndex = -1;
+                       }
+               }
+               
+               public IEnumerator GetEnumerator ()
+               {
+                       return new StatementCollection.Enumerator (this);
+               }
+
+               //
+               // IList method implementations
+               //
+               public int Add (object value)
+               {
+                       return statements.Add (value);
+               }
+
+               public bool Contains (Object value)
+               {
+                       return statements.Contains (value);
+               }
+
+               public int IndexOf (Object value)
+               {
+                       return statements.IndexOf (value);
+               }
+
+               public void Insert (int index, Object value)
+               {
+                       statements [index] = value;
+               }
+
+               public object this[int index] {
+                       get {
+                               return statements [index];
+                       }
+
+                       set {
+                               statements [index] = value;
+                       }
+               }
+
+               public void Remove (object value)
+               {
+                       statements.Remove (value);
+               }
+
+               public void RemoveAt (int index)
+               {
+                       statements.RemoveAt (index);
+               }
+
+               //
+               // ICollection method implementations
+               //
+               public void CopyTo (Array array, int index)
+               {
+                       statements.CopyTo (array, index);
+               }
+
+               public object SyncRoot {
+                       get {
+                               return statements.SyncRoot;
+                       }
+               }
+
+               public bool IsReadOnly {
+                       get {
+                               return false;
+                       }
+               }
+
+               public bool IsSynchronized {
+                       get {
+                               return statements.IsSynchronized;
+                       }
+               }
+
+               public bool IsFixedSize {
+                       get {
+                               return false;
+                       }
+               }
+       }
+}
diff --git a/mcs/gmcs/support.cs b/mcs/gmcs/support.cs
new file mode 100755 (executable)
index 0000000..c93be32
--- /dev/null
@@ -0,0 +1,258 @@
+//
+// support.cs: Support routines to work around the fact that System.Reflection.Emit
+// can not introspect types that are being constructed
+//
+// Author:
+//   Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+
+using System;
+using System.Text;
+using System.Reflection;
+using System.Collections;
+using System.Reflection.Emit;
+using System.Globalization;
+
+namespace Mono.CSharp {
+
+       public interface ParameterData {
+               Type ParameterType (int pos);
+               int  Count { get; }
+               string ParameterName (int pos);
+               string ParameterDesc (int pos);
+               Parameter.Modifier ParameterModifier (int pos);
+       }
+
+       public class ReflectionParameters : ParameterData {
+               ParameterInfo [] pi;
+               bool last_arg_is_params = false;
+               
+               public ReflectionParameters (ParameterInfo [] pi)
+               {
+                       object [] attrs;
+                       
+                       this.pi = pi;
+                       int count = pi.Length-1;
+
+                       if (count >= 0) {
+                               attrs = pi [count].GetCustomAttributes (TypeManager.param_array_type, true);
+
+                               if (attrs == null)
+                                       return;
+                               
+                               if (attrs.Length == 0)
+                                       return;
+
+                               last_arg_is_params = true;
+                       }
+               }
+                      
+               public Type ParameterType (int pos)
+               {
+                       if (last_arg_is_params && pos >= pi.Length - 1)
+                               return pi [pi.Length - 1].ParameterType;
+                       else {
+                               Type t = pi [pos].ParameterType;
+
+                               return t;
+                       }
+               }
+
+               public string ParameterName (int pos)
+               {
+                       if (last_arg_is_params && pos >= pi.Length - 1)
+                               return pi [pi.Length - 1].Name;
+                       else 
+                               return pi [pos].Name;
+               }
+
+               public string ParameterDesc (int pos)
+               {
+                       StringBuilder sb = new StringBuilder ();
+
+                       if (pi [pos].IsIn)
+                               sb.Append ("in ");
+
+                       Type partype = ParameterType (pos);
+                       if (partype.IsByRef){
+                               partype = TypeManager.GetElementType (partype);
+                               if (pi [pos].IsOut)
+                                       sb.Append ("out ");
+                               else
+                                       sb.Append ("ref ");
+                       } 
+
+                       if (pos >= pi.Length - 1 && last_arg_is_params)
+                               sb.Append ("params ");
+                       
+                       sb.Append (TypeManager.CSharpName (partype));
+
+                       return sb.ToString ();
+                       
+               }
+
+               public Parameter.Modifier ParameterModifier (int pos)
+               {
+                       int len = pi.Length;
+
+                       if (pos >= len - 1)
+                               if (last_arg_is_params)
+                                       return Parameter.Modifier.PARAMS;
+                       
+                       Type t = pi [pos].ParameterType;
+                       if (t.IsByRef){
+                               if ((pi [pos].Attributes & ParameterAttributes.Out) != 0)
+                                       return Parameter.Modifier.ISBYREF | Parameter.Modifier.OUT;
+                               else
+                                       return Parameter.Modifier.ISBYREF | Parameter.Modifier.REF;
+                       }
+                       
+                       return Parameter.Modifier.NONE;
+               }
+
+               public int Count {
+                       get {
+                               return pi.Length;
+                       }
+               }
+               
+       }
+
+       public class InternalParameters : ParameterData {
+               Type [] param_types;
+
+               public readonly Parameters Parameters;
+               
+               public InternalParameters (Type [] param_types, Parameters parameters)
+               {
+                       this.param_types = param_types;
+                       this.Parameters = parameters;
+               }
+
+               public InternalParameters (DeclSpace ds, Parameters parameters)
+                       : this (parameters.GetParameterInfo (ds), parameters)
+               {
+               }
+
+               public int Count {
+                       get {
+                               if (param_types == null)
+                                       return 0;
+
+                               return param_types.Length;
+                       }
+               }
+
+               Parameter GetParameter (int pos)
+               {
+                       Parameter [] fixed_pars = Parameters.FixedParameters;
+                       if (fixed_pars != null){
+                               int len = fixed_pars.Length;
+                               if (pos < len)
+                                       return Parameters.FixedParameters [pos];
+                       }
+
+                       return Parameters.ArrayParameter;
+               }
+
+               public Type ParameterType (int pos)
+               {
+                       if (param_types == null)
+                               return null;
+
+                       return GetParameter (pos).ExternalType ();
+               }
+
+
+               public string ParameterName (int pos)
+               {
+                       return GetParameter (pos).Name;
+               }
+
+               public string ParameterDesc (int pos)
+               {
+                       string tmp = String.Empty;
+                       Parameter p = GetParameter (pos);
+
+                       //
+                       // We need to and for REF/OUT, because if either is set the
+                       // extra flag ISBYREF will be set as well
+                       //
+                       if ((p.ModFlags & Parameter.Modifier.REF) != 0)
+                               tmp = "ref ";
+                       else if ((p.ModFlags & Parameter.Modifier.OUT) != 0)
+                               tmp = "out ";
+                       else if (p.ModFlags == Parameter.Modifier.PARAMS)
+                               tmp = "params ";
+
+                       Type t = ParameterType (pos);
+
+                       return tmp + TypeManager.CSharpName (t);
+               }
+
+               public Parameter.Modifier ParameterModifier (int pos)
+               {
+                       Parameter.Modifier mod = GetParameter (pos).ModFlags;
+
+                       if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
+                               mod |= Parameter.Modifier.ISBYREF;
+
+                       return mod;
+               }
+               
+       }
+
+       class PtrHashtable : Hashtable {
+               class PtrComparer : IComparer {
+                       public int Compare (object x, object y)
+                       {
+                               if (x == y)
+                                       return 0;
+                               else
+                                       return 1;
+                       }
+               }
+               
+               public PtrHashtable ()
+               {
+                       comparer = new PtrComparer ();
+               }
+       }
+
+       //
+       // Compares member infos based on their name and
+       // also allows one argument to be a string
+       //
+       class MemberInfoCompare : IComparer {
+
+               public int Compare (object a, object b)
+               {
+                       if (a == null || b == null){
+                               Console.WriteLine ("Invalid information passed");
+                               throw new Exception ();
+                       }
+                       
+                       if (a is string)
+                               return String.Compare ((string) a, ((MemberInfo)b).Name);
+
+                       if (b is string)
+                               return String.Compare (((MemberInfo)a).Name, (string) b);
+
+                       return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
+               }
+       }
+
+       struct Pair {
+               public object First;
+               public object Second;
+               
+               public Pair (object f, object s)
+               {
+                       First = f;
+                       Second = s;
+               }
+       }
+
+}
diff --git a/mcs/gmcs/symbolwriter.cs b/mcs/gmcs/symbolwriter.cs
new file mode 100644 (file)
index 0000000..a6577e4
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// symbolwriter.cs: The symbol writer
+//
+// Author:
+//   Martin Baulig (martin@ximian.com)
+//
+// (C) 2003 Ximian, Inc.
+//
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics.SymbolStore;
+
+namespace Mono.CSharp {
+       public class SymbolWriter {
+               ISymbolWriter symwriter;
+               MethodInfo define_namespace;
+               MethodInfo open_method;
+
+               protected SymbolWriter (ISymbolWriter symwriter)
+               {
+                       this.symwriter = symwriter;
+               }
+
+               bool Initialize ()
+               {
+                       Type type = symwriter.GetType ();
+                       define_namespace = type.GetMethod ("DefineNamespace", new Type[] {
+                               typeof (string), typeof (ISymbolDocumentWriter),
+                               typeof (string []), typeof (int) });
+                       if (define_namespace == null)
+                               return false;
+
+                       open_method = type.GetMethod ("OpenMethod", new Type[] {
+                               typeof (ISymbolDocumentWriter), typeof (int), typeof (int),
+                               typeof (int), typeof (int), typeof (MethodBase), typeof (int) });
+                       if (open_method == null)
+                               return false;
+
+                       Location.DefineSymbolDocuments (this);
+                       Namespace.DefineNamespaces (this);
+
+                       return true;
+               }
+
+               public ISymbolDocumentWriter DefineDocument (string path)
+               {
+                       return symwriter.DefineDocument (
+                               path, SymLanguageType.CSharp, SymLanguageVendor.Microsoft,
+                               SymDocumentType.Text);
+               }
+
+               public int DefineNamespace (string name, SourceFile file, string[] using_list, int parent)
+               {
+                       return (int) define_namespace.Invoke (symwriter, new object[] {
+                               name, file.SymbolDocument, using_list, parent });
+               }
+
+               public void OpenMethod (TypeContainer parent, MethodBase method, Location start, Location end)
+               {
+                       int ns_id = parent.Namespace.SymbolFileID;
+                       open_method.Invoke (symwriter, new object[] {
+                               start.SymbolDocument, start.Row, 0, end.Row, 0, method, ns_id });
+               }
+
+               public void CloseMethod ()
+               {
+                       symwriter.CloseMethod ();
+               }
+
+               public static SymbolWriter GetSymbolWriter (ModuleBuilder module)
+               {
+                       ISymbolWriter symwriter = module.GetSymWriter ();
+
+                       if (symwriter == null)
+                               return null;
+
+                       SymbolWriter writer = new SymbolWriter (symwriter);
+                       if (!writer.Initialize ())
+                               return null;
+
+                       return writer;
+               }
+       }
+}
diff --git a/mcs/gmcs/tree.cs b/mcs/gmcs/tree.cs
new file mode 100755 (executable)
index 0000000..57e4740
--- /dev/null
@@ -0,0 +1,109 @@
+//
+// tree.cs: keeps a tree representation of the generated code
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+//
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.IO;
+
+namespace Mono.CSharp
+{
+
+       public interface ITreeDump {
+               int  Dump (Tree tree, StreamWriter output);
+               void ParseOptions (string options);
+       }
+
+       // <summary>
+       //   
+       //   We store here all the toplevel types that we have parsed,
+       //   this is the root of all information we have parsed.
+       // 
+       // </summary>
+       
+       public class Tree {
+               TypeContainer root_types;
+
+               // <summary>
+               //  Keeps track of namespaces defined in the source code
+               // </summary>
+               Hashtable namespaces;
+
+               // <summary>
+               //   Keeps track of all the types definied (classes, structs, ifaces, enums)
+               // </summary>
+               Hashtable decls;
+               
+               public Tree ()
+               {
+                       root_types = new TypeContainer (null, "", new Location (-1));
+
+                       decls = new Hashtable ();
+                       namespaces = new Hashtable ();
+               }
+
+               public void RecordDecl (string name, DeclSpace ds)
+               {
+                       if (decls.Contains (name)){
+                               Report.Error (
+                                       101, ds.Location,
+                                       "There is already a definition for `" + name + "'");
+                               DeclSpace other = (DeclSpace) decls [name];
+                               Report.Error (0,
+                                       other.Location, "(Location of symbol related to previous error)");
+                               return;
+                       }
+                       decls.Add (name, ds);
+               }
+               
+               public NamespaceEntry RecordNamespace (NamespaceEntry parent, SourceFile file, string name)
+               {
+                       NamespaceEntry ns = new NamespaceEntry (parent, file, name);
+
+                       if (namespaces.Contains (file)){
+                               Hashtable ns_ns = (Hashtable) namespaces [file];
+
+                               if (ns_ns.Contains (ns.Name))
+                                       return (NamespaceEntry) ns_ns [ns.Name];
+                               ns_ns.Add (ns.Name, ns);
+                       } else {
+                               Hashtable new_table = new Hashtable ();
+                               namespaces [file] = new_table;
+
+                               new_table.Add (ns.Name, ns);
+                       }
+
+                       return ns;
+               }
+
+               //
+               // FIXME: Why are we using Types?
+               //
+                public TypeContainer Types {
+                        get {
+                                return root_types;
+                        }
+                }
+
+               public Hashtable Decls {
+                       get {
+                               return decls;
+                       }
+               }
+
+               public Hashtable Namespaces {
+                       get {
+                               return namespaces;
+                       }
+               }
+       }
+}
diff --git a/mcs/gmcs/typemanager.cs b/mcs/gmcs/typemanager.cs
new file mode 100755 (executable)
index 0000000..326e22f
--- /dev/null
@@ -0,0 +1,2739 @@
+//
+// typemanager.cs: C# type manager
+//
+// Author: Miguel de Icaza (miguel@gnu.org)
+//         Ravi Pratap     (ravi@ximian.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+//
+
+//
+// We will eventually remove the SIMPLE_SPEEDUP, and should never change 
+// the behavior of the compilation.  This can be removed if we rework
+// the code to get a list of namespaces available.
+//
+#define SIMPLE_SPEEDUP
+
+using System;
+using System.IO;
+using System.Globalization;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Runtime.CompilerServices;
+using System.Diagnostics;
+
+namespace Mono.CSharp {
+
+public class TypeManager {
+       //
+       // A list of core types that the compiler requires or uses
+       //
+       static public Type object_type;
+       static public Type value_type;
+       static public Type string_type;
+       static public Type int32_type;
+       static public Type uint32_type;
+       static public Type int64_type;
+       static public Type uint64_type;
+       static public Type float_type;
+       static public Type double_type;
+       static public Type char_type;
+       static public Type char_ptr_type;
+       static public Type short_type;
+       static public Type decimal_type;
+       static public Type bool_type;
+       static public Type sbyte_type;
+       static public Type byte_type;
+       static public Type ushort_type;
+       static public Type enum_type;
+       static public Type delegate_type;
+       static public Type multicast_delegate_type;
+       static public Type void_type;
+       static public Type enumeration_type;
+       static public Type array_type;
+       static public Type runtime_handle_type;
+       static public Type icloneable_type;
+       static public Type type_type;
+       static public Type ienumerator_type;
+       static public Type ienumerable_type;
+       static public Type idisposable_type;
+       static public Type default_member_type;
+       static public Type iasyncresult_type;
+       static public Type asynccallback_type;
+       static public Type intptr_type;
+       static public Type monitor_type;
+       static public Type runtime_field_handle_type;
+       static public Type attribute_type;
+       static public Type attribute_usage_type;
+       static public Type dllimport_type;
+       static public Type unverifiable_code_type;
+       static public Type methodimpl_attr_type;
+       static public Type marshal_as_attr_type;
+       static public Type param_array_type;
+       static public Type guid_attr_type;
+       static public Type void_ptr_type;
+       static public Type indexer_name_type;
+       static public Type exception_type;
+       static public Type invalid_operation_exception_type;
+       static public object obsolete_attribute_type;
+       static public object conditional_attribute_type;
+       static public Type in_attribute_type;
+
+       //
+       // An empty array of types
+       //
+       static public Type [] NoTypes;
+
+
+       // 
+       // Expressions representing the internal types.  Used during declaration
+       // definition.
+       //
+       static public Expression system_object_expr, system_string_expr; 
+       static public Expression system_boolean_expr, system_decimal_expr;
+       static public Expression system_single_expr, system_double_expr;
+       static public Expression system_sbyte_expr, system_byte_expr;
+       static public Expression system_int16_expr, system_uint16_expr;
+       static public Expression system_int32_expr, system_uint32_expr;
+       static public Expression system_int64_expr, system_uint64_expr;
+       static public Expression system_char_expr, system_void_expr;
+       static public Expression system_asynccallback_expr;
+       static public Expression system_iasyncresult_expr;
+
+       //
+       // This is only used when compiling corlib
+       //
+       static public Type system_int32_type;
+       static public Type system_array_type;
+       static public Type system_type_type;
+       static public Type system_assemblybuilder_type;
+       static public MethodInfo system_int_array_get_length;
+       static public MethodInfo system_int_array_get_rank;
+       static public MethodInfo system_object_array_clone;
+       static public MethodInfo system_int_array_get_length_int;
+       static public MethodInfo system_int_array_get_lower_bound_int;
+       static public MethodInfo system_int_array_get_upper_bound_int;
+       static public MethodInfo system_void_array_copyto_array_int;
+
+       
+       //
+       // Internal, not really used outside
+       //
+       static Type runtime_helpers_type;
+       
+       //
+       // These methods are called by code generated by the compiler
+       //
+       static public MethodInfo string_concat_string_string;
+       static public MethodInfo string_concat_string_string_string;
+       static public MethodInfo string_concat_string_string_string_string;
+       static public MethodInfo string_concat_object_object;
+       static public MethodInfo string_isinterneted_string;
+       static public MethodInfo system_type_get_type_from_handle;
+       static public MethodInfo object_getcurrent_void;
+       static public MethodInfo bool_movenext_void;
+       static public MethodInfo ienumerable_getenumerator_void;
+       static public MethodInfo void_reset_void;
+       static public MethodInfo void_dispose_void;
+       static public MethodInfo void_monitor_enter_object;
+       static public MethodInfo void_monitor_exit_object;
+       static public MethodInfo void_initializearray_array_fieldhandle;
+       static public MethodInfo int_getlength_int;
+       static public MethodInfo delegate_combine_delegate_delegate;
+       static public MethodInfo delegate_remove_delegate_delegate;
+       static public MethodInfo int_get_offset_to_string_data;
+       static public MethodInfo int_array_get_length;
+       static public MethodInfo int_array_get_rank;
+       static public MethodInfo object_array_clone;
+       static public MethodInfo int_array_get_length_int;
+       static public MethodInfo int_array_get_lower_bound_int;
+       static public MethodInfo int_array_get_upper_bound_int;
+       static public MethodInfo void_array_copyto_array_int;
+       
+       //
+       // The attribute constructors.
+       //
+       static public ConstructorInfo object_ctor;
+       static public ConstructorInfo cons_param_array_attribute;
+       static public ConstructorInfo void_decimal_ctor_five_args;
+       static public ConstructorInfo unverifiable_code_ctor;
+       static public ConstructorInfo invalid_operation_ctor;
+       
+       // <remarks>
+       //   Holds the Array of Assemblies that have been loaded
+       //   (either because it is the default or the user used the
+       //   -r command line option)
+       // </remarks>
+       static Assembly [] assemblies;
+
+       // <remarks>
+       //  Keeps a list of module builders. We used this to do lookups
+       //  on the modulebuilder using GetType -- needed for arrays
+       // </remarks>
+       static ModuleBuilder [] modules;
+
+       // <remarks>
+       //   This is the type_cache from the assemblies to avoid
+       //   hitting System.Reflection on every lookup.
+       // </summary>
+       static Hashtable types;
+
+       // <remarks>
+       //  This is used to hotld the corresponding TypeContainer objects
+       //  since we need this in FindMembers
+       // </remarks>
+       static Hashtable typecontainers;
+
+       // <remarks>
+       //   Keeps track of those types that are defined by the
+       //   user's program
+       // </remarks>
+       static ArrayList user_types;
+
+       static PtrHashtable builder_to_declspace;
+
+       // <remarks>
+       //   Tracks the interfaces implemented by typebuilders.  We only
+       //   enter those who do implement or or more interfaces
+       // </remarks>
+       static PtrHashtable builder_to_ifaces;
+
+       // <remarks>
+       //   Maps MethodBase.RuntimeTypeHandle to a Type array that contains
+       //   the arguments to the method
+       // </remarks>
+       static Hashtable method_arguments;
+
+       // <remarks>
+       //   Maps PropertyBuilder to a Type array that contains
+       //   the arguments to the indexer
+       // </remarks>
+       static Hashtable indexer_arguments;
+
+       // <remarks>
+       //   Maybe `method_arguments' should be replaced and only
+       //   method_internal_params should be kept?
+       // <remarks>
+       static Hashtable method_internal_params;
+
+       // <remarks>
+       //  Keeps track of attribute types
+       // </remarks>
+
+       static Hashtable builder_to_attr;
+
+       // <remarks>
+       //  Keeps track of methods
+       // </remarks>
+
+       static Hashtable builder_to_method;
+
+       struct Signature {
+               public string name;
+               public Type [] args;
+       }
+
+       /// <summary>
+       ///   A filter for Findmembers that uses the Signature object to
+       ///   extract objects
+       /// </summary>
+       static bool SignatureFilter (MemberInfo mi, object criteria)
+       {
+               Signature sig = (Signature) criteria;
+
+               if (!(mi is MethodBase))
+                       return false;
+               
+               if (mi.Name != sig.name)
+                       return false;
+
+               int count = sig.args.Length;
+               
+               if (mi is MethodBuilder || mi is ConstructorBuilder){
+                       Type [] candidate_args = GetArgumentTypes ((MethodBase) mi);
+
+                       if (candidate_args.Length != count)
+                               return false;
+                       
+                       for (int i = 0; i < count; i++)
+                               if (candidate_args [i] != sig.args [i])
+                                       return false;
+                       
+                       return true;
+               } else {
+                       ParameterInfo [] pars = ((MethodBase) mi).GetParameters ();
+
+                       if (pars.Length != count)
+                               return false;
+
+                       for (int i = 0; i < count; i++)
+                               if (pars [i].ParameterType != sig.args [i])
+                                       return false;
+                       return true;
+               }
+       }
+
+       // A delegate that points to the filter above.
+       static MemberFilter signature_filter;
+
+       //
+       // These are expressions that represent some of the internal data types, used
+       // elsewhere
+       //
+       static void InitExpressionTypes ()
+       {
+               system_object_expr  = new TypeLookupExpression ("System.Object");
+               system_string_expr  = new TypeLookupExpression ("System.String");
+               system_boolean_expr = new TypeLookupExpression ("System.Boolean");
+               system_decimal_expr = new TypeLookupExpression ("System.Decimal");
+               system_single_expr  = new TypeLookupExpression ("System.Single");
+               system_double_expr  = new TypeLookupExpression ("System.Double");
+               system_sbyte_expr   = new TypeLookupExpression ("System.SByte");
+               system_byte_expr    = new TypeLookupExpression ("System.Byte");
+               system_int16_expr   = new TypeLookupExpression ("System.Int16");
+               system_uint16_expr  = new TypeLookupExpression ("System.UInt16");
+               system_int32_expr   = new TypeLookupExpression ("System.Int32");
+               system_uint32_expr  = new TypeLookupExpression ("System.UInt32");
+               system_int64_expr   = new TypeLookupExpression ("System.Int64");
+               system_uint64_expr  = new TypeLookupExpression ("System.UInt64");
+               system_char_expr    = new TypeLookupExpression ("System.Char");
+               system_void_expr    = new TypeLookupExpression ("System.Void");
+               system_asynccallback_expr = new TypeLookupExpression ("System.AsyncCallback");
+               system_iasyncresult_expr = new TypeLookupExpression ("System.IAsyncResult");
+       }
+       
+       static TypeManager ()
+       {
+               assemblies = new Assembly [0];
+               modules = null;
+               user_types = new ArrayList ();
+               
+               types = new Hashtable ();
+               typecontainers = new Hashtable ();
+               
+               builder_to_declspace = new PtrHashtable ();
+               builder_to_attr = new PtrHashtable ();
+               builder_to_method = new PtrHashtable ();
+               method_arguments = new PtrHashtable ();
+               method_internal_params = new PtrHashtable ();
+               indexer_arguments = new PtrHashtable ();
+               builder_to_ifaces = new PtrHashtable ();
+               
+               NoTypes = new Type [0];
+
+               signature_filter = new MemberFilter (SignatureFilter);
+               InitExpressionTypes ();
+       }
+
+       public static void HandleDuplicate (string name, Type t)
+       {
+               Type prev = (Type) types [name];
+               TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
+               
+               if (tc != null){
+                       //
+                       // This probably never happens, as we catch this before
+                       //
+                       Report.Error (-17, "The type `" + name + "' has already been defined.");
+                       return;
+               }
+               
+               Location l;
+               tc = builder_to_declspace [t] as TypeContainer;
+               if (tc != null){
+                       Report.Warning (
+                                       1595, "The type `" + name + "' is defined in an existing assembly;"+
+                                       " Using the new definition from: " + tc.Location);
+               } else {
+                       Report.Warning (
+                                       1595, "The type `" + name + "' is defined in an existing assembly;");
+               }
+               
+               Report.Warning (1595, "Previously defined in: " + prev.Assembly.FullName);
+               
+               types.Remove (name);
+               types.Add (name, t);
+       }
+       
+       public static void AddUserType (string name, TypeBuilder t, Type [] ifaces)
+       {
+               try {
+                       types.Add (name, t);
+               } catch {
+                       HandleDuplicate (name, t); 
+               }
+               user_types.Add (t);
+                       
+               if (ifaces != null)
+                       builder_to_ifaces [t] = ifaces;
+       }
+
+       //
+       // This entry point is used by types that we define under the covers
+       // 
+       public static void RegisterBuilder (TypeBuilder tb, Type [] ifaces)
+       {
+               if (ifaces != null)
+                       builder_to_ifaces [tb] = ifaces;
+       }
+       
+       public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, Type [] ifaces)
+       {
+               builder_to_declspace.Add (t, tc);
+               typecontainers.Add (name, tc);
+               AddUserType (name, t, ifaces);
+       }
+
+       public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
+       {
+               try {
+                       types.Add (name, t);
+               } catch {
+                       HandleDuplicate (name, t);
+               }
+               
+               builder_to_declspace.Add (t, del);
+       }
+       
+       public static void AddEnumType (string name, TypeBuilder t, Enum en)
+       {
+               try {
+                       types.Add (name, t);
+               } catch {
+                       HandleDuplicate (name, t);
+               }
+               builder_to_declspace.Add (t, en);
+       }
+
+       public static void AddUserInterface (string name, TypeBuilder t, Interface i, Type [] ifaces)
+       {
+               AddUserType (name, t, ifaces);
+               builder_to_declspace.Add (t, i);
+       }
+
+       public static void AddMethod (MethodBuilder builder, MethodData method)
+       {
+               builder_to_method.Add (builder, method);
+       }
+
+       public static void RegisterAttrType (Type t, TypeContainer tc)
+       {
+               builder_to_attr.Add (t, tc);
+       }
+
+       /// <summary>
+       ///   Returns the DeclSpace whose Type is `t' or null if there is no
+       ///   DeclSpace for `t' (ie, the Type comes from a library)
+       /// </summary>
+       public static DeclSpace LookupDeclSpace (Type t)
+       {
+               return builder_to_declspace [t] as DeclSpace;
+       }
+
+       /// <summary>
+       ///   Returns the TypeContainer whose Type is `t' or null if there is no
+       ///   TypeContainer for `t' (ie, the Type comes from a library)
+       /// </summary>
+       public static TypeContainer LookupTypeContainer (Type t)
+       {
+               return builder_to_declspace [t] as TypeContainer;
+       }
+       
+       public static IMemberContainer LookupMemberContainer (Type t)
+       {
+               if (t is TypeBuilder) {
+                       IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
+                       if (container != null)
+                               return container;
+               }
+
+               return TypeHandle.GetTypeHandle (t);
+       }
+
+       public static Interface LookupInterface (Type t)
+       {
+               return builder_to_declspace [t] as Interface;
+       }
+
+       public static Delegate LookupDelegate (Type t)
+       {
+               return builder_to_declspace [t] as Delegate;
+       }
+
+       public static Enum LookupEnum (Type t)
+       {
+               return builder_to_declspace [t] as Enum;
+       }
+       
+       public static TypeContainer LookupAttr (Type t)
+       {
+               return (TypeContainer) builder_to_attr [t];
+       }
+       
+       /// <summary>
+       ///   Registers an assembly to load types from.
+       /// </summary>
+       public static void AddAssembly (Assembly a)
+       {
+               int top = assemblies.Length;
+               Assembly [] n = new Assembly [top + 1];
+
+               assemblies.CopyTo (n, 0);
+               
+               n [top] = a;
+               assemblies = n;
+       }
+
+       /// <summary>
+       ///  Registers a module builder to lookup types from
+       /// </summary>
+       public static void AddModule (ModuleBuilder mb)
+       {
+               int top = modules != null ? modules.Length : 0;
+               ModuleBuilder [] n = new ModuleBuilder [top + 1];
+
+               if (modules != null)
+                       modules.CopyTo (n, 0);
+               n [top] = mb;
+               modules = n;
+       }
+
+       static Hashtable references = new Hashtable ();
+       
+       //
+       // Gets the reference to T version of the Type (T&)
+       //
+       public static Type GetReferenceType (Type t)
+       {
+               string tname = t.FullName + "&";
+               
+               Type ret = t.Assembly.GetType (tname);
+
+               //
+               // If the type comes from the assembly we are building
+               // We need the Hashtable, because .NET 1.1 will return different instance types
+               // every time we call ModuleBuilder.GetType.
+               //
+               if (ret == null){
+                       if (references [t] == null)
+                               references [t] = CodeGen.ModuleBuilder.GetType (tname);
+                       ret = (Type) references [t];
+               }
+
+               return ret;
+       }
+
+       static Hashtable pointers = new Hashtable ();
+
+       //
+       // Gets the pointer to T version of the Type  (T*)
+       //
+       public static Type GetPointerType (Type t)
+       {
+               string tname = t.FullName + "*";
+               
+               Type ret = t.Assembly.GetType (tname);
+               
+               //
+               // If the type comes from the assembly we are building
+               // We need the Hashtable, because .NET 1.1 will return different instance types
+               // every time we call ModuleBuilder.GetType.
+               //
+               if (ret == null){
+                       if (pointers [t] == null)
+                               pointers [t] = CodeGen.ModuleBuilder.GetType (tname);
+                       
+                       ret = (Type) pointers [t];
+               }
+
+               return ret;
+       }
+       
+       //
+       // Low-level lookup, cache-less
+       //
+       static Type LookupTypeReflection (string name)
+       {
+               Type t;
+
+               foreach (Assembly a in assemblies){
+                       t = a.GetType (name);
+                       if (t == null)
+                               continue;
+
+                       TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask;
+                       if (ta == TypeAttributes.NotPublic ||
+                           ta == TypeAttributes.NestedPrivate ||
+                           ta == TypeAttributes.NestedAssembly ||
+                           ta == TypeAttributes.NestedFamANDAssem)
+                               continue;
+                       return t;
+               }
+
+               foreach (ModuleBuilder mb in modules) {
+                       t = mb.GetType (name);
+                       if (t != null) 
+                               return t;
+               }
+                        
+               return null;
+       }
+
+       static Hashtable negative_hits = new Hashtable ();
+       
+       //
+       // This function is used when you want to avoid the lookups, and want to go
+       // directly to the source.  This will use the cache.
+       //
+       // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
+       // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
+       // way to test things other than doing a fullname compare
+       //
+       public static Type LookupTypeDirect (string name)
+       {
+               Type t = (Type) types [name];
+               if (t != null)
+                       return t;
+
+               t = LookupTypeReflection (name);
+               if (t == null)
+                       return null;
+
+               types [name] = t;
+               return t;
+       }
+
+       /// <summary>
+       ///   Returns the Type associated with @name, takes care of the fact that
+       ///   reflection expects nested types to be separated from the main type
+       ///   with a "+" instead of a "."
+       /// </summary>
+       public static Type LookupType (string name)
+       {
+               Type t;
+
+               //
+               // First lookup in user defined and cached values
+               //
+
+               t = (Type) types [name];
+               if (t != null)
+                       return t;
+
+               // Two thirds of the failures are caught here.
+               if (negative_hits.Contains (name))
+                       return null;
+
+               string [] elements = name.Split ('.');
+               int count = elements.Length;
+
+               for (int n = 1; n <= count; n++){
+                       string top_level_type = String.Join (".", elements, 0, n);
+
+                       // One third of the failures are caught here.
+                       if (negative_hits.Contains (top_level_type))
+                               continue;
+                       
+                       t = (Type) types [top_level_type];
+                       if (t == null){
+                               t = LookupTypeReflection (top_level_type);
+                               if (t == null){
+                                       negative_hits [top_level_type] = true;
+                                       continue;
+                               }
+                       }
+                       
+                       if (count == n){
+                               types [name] = t;
+                               return t;
+                       } 
+
+                       //
+                       // We know that System.Object does not have children, and since its the parent of 
+                       // all the objects, it always gets probbed for inner classes. 
+                       //
+                       if (top_level_type == "System.Object")
+                               return null;
+                       
+                       string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
+                       //Console.WriteLine ("Looking up: " + newt + " " + name);
+                       t = LookupTypeReflection (newt);
+                       if (t == null)
+                               negative_hits [name] = true;
+                       else
+                               types [name] = t;
+                       return t;
+               }
+               negative_hits [name] = true;
+               return null;
+       }
+
+       /// <summary>
+       ///   Computes the namespaces that we import from the assemblies we reference.
+       /// </summary>
+       public static void ComputeNamespaces ()
+       {
+               MethodInfo assembly_get_namespaces = typeof (Assembly).GetMethod ("GetNamespaces");
+
+               //
+               // First add the assembly namespaces
+               //
+               if (assembly_get_namespaces != null){
+                       int count = assemblies.Length;
+                       int total;
+
+                       for (int i = 0; i < count; i++){
+                               Assembly a = assemblies [i];
+                               string [] namespaces = (string []) assembly_get_namespaces.Invoke (a, null);
+                               foreach (string ns in namespaces){
+                                       if (ns == "")
+                                               continue;
+                                       Namespace.LookupNamespace (ns, true);
+                               }
+                       }
+               } else {
+                       foreach (Assembly a in assemblies){
+                               foreach (Type t in a.GetTypes ()){
+                                       string ns = t.Namespace;
+
+                                       // t.Namespace returns null for <PrivateImplDetails>
+                                       if (ns == ""|| ns == null)
+                                               continue;
+                                       Namespace.LookupNamespace (ns, true);
+                               }
+                       }
+               }
+       }
+
+       public static bool NamespaceClash (string name, Location loc)
+       {
+               if (Namespace.LookupNamespace (name, false) == null)
+                       return false;
+
+               Report.Error (519, loc, String.Format ("`{0}' clashes with a predefined namespace", name));
+               return true;
+       }
+
+       /// <summary>
+       ///   Returns the C# name of a type if possible, or the full type name otherwise
+       /// </summary>
+       static public string CSharpName (Type t)
+       {
+               return Regex.Replace (t.FullName, 
+                       @"^System\." +
+                       @"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
+                       @"Single|Double|Char|Decimal|Byte|SByte|Object|" +
+                       @"Boolean|String|Void)" +
+                       @"(\W+|\b)", 
+                       new MatchEvaluator (CSharpNameMatch));
+       }       
+       
+       static String CSharpNameMatch (Match match) 
+       {
+               string s = match.Groups [1].Captures [0].Value;
+               return s.ToLower ().
+               Replace ("int32", "int").
+               Replace ("uint32", "uint").
+               Replace ("int16", "short").
+               Replace ("uint16", "ushort").
+               Replace ("int64", "long").
+               Replace ("uint64", "ulong").
+               Replace ("single", "float").
+               Replace ("boolean", "bool")
+               + match.Groups [2].Captures [0].Value;
+       }
+
+        /// <summary>
+        ///   Returns the signature of the method
+        /// </summary>
+        static public string CSharpSignature (MethodBase mb)
+        {
+                string sig = "(";
+
+               //
+               // FIXME: We should really have a single function to do
+               // everything instead of the following 5 line pattern
+               //
+                ParameterData iparams = LookupParametersByBuilder (mb);
+
+               if (iparams == null){
+                       ParameterInfo [] pi = mb.GetParameters ();
+                       iparams = new ReflectionParameters (pi);
+               }
+               
+                for (int i = 0; i < iparams.Count; i++) {
+                        if (i > 0) {
+                                sig += ", ";
+                        }
+                        sig += iparams.ParameterDesc(i);
+                }
+                sig += ")";
+
+                return mb.DeclaringType.Name + "." + mb.Name + sig;
+        }
+
+       /// <summary>
+       ///   Looks up a type, and aborts if it is not found.  This is used
+       ///   by types required by the compiler
+       /// </summary>
+       static Type CoreLookupType (string name)
+       {
+               Type t = LookupTypeDirect (name);
+
+               if (t == null){
+                       Report.Error (518, "The predefined type `" + name + "' is not defined or imported");
+                       Environment.Exit (0);
+               }
+
+               return t;
+       }
+
+       /// <summary>
+       ///   Returns the MethodInfo for a method named `name' defined
+       ///   in type `t' which takes arguments of types `args'
+       /// </summary>
+       static MethodInfo GetMethod (Type t, string name, Type [] args, bool report_errors)
+       {
+               MemberList list;
+               Signature sig;
+
+               sig.name = name;
+               sig.args = args;
+               
+               list = FindMembers (t, MemberTypes.Method, instance_and_static | BindingFlags.Public,
+                                   signature_filter, sig);
+               if (list.Count == 0) {
+                       if (report_errors)
+                               Report.Error (-19, "Can not find the core function `" + name + "'");
+                       return null;
+               }
+
+               MethodInfo mi = list [0] as MethodInfo;
+               if (mi == null) {
+                       if (report_errors)
+                               Report.Error (-19, "Can not find the core function `" + name + "'");
+                       return null;
+               }
+
+               return mi;
+       }
+
+       static MethodInfo GetMethod (Type t, string name, Type [] args)
+       {
+               return GetMethod (t, name, args, true);
+       }
+
+
+       /// <summary>
+       ///    Returns the ConstructorInfo for "args"
+       /// </summary>
+       static ConstructorInfo GetConstructor (Type t, Type [] args)
+       {
+               MemberList list;
+               Signature sig;
+
+               sig.name = ".ctor";
+               sig.args = args;
+               
+               list = FindMembers (t, MemberTypes.Constructor,
+                                   instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
+                                   signature_filter, sig);
+               if (list.Count == 0){
+                       Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
+                       return null;
+               }
+
+               ConstructorInfo ci = list [0] as ConstructorInfo;
+               if (ci == null){
+                       Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
+                       return null;
+               }
+
+               return ci;
+       }
+
+       public static void InitEnumUnderlyingTypes ()
+       {
+
+               int32_type    = CoreLookupType ("System.Int32");
+               int64_type    = CoreLookupType ("System.Int64");
+               uint32_type   = CoreLookupType ("System.UInt32"); 
+               uint64_type   = CoreLookupType ("System.UInt64"); 
+               byte_type     = CoreLookupType ("System.Byte");
+               sbyte_type    = CoreLookupType ("System.SByte");
+               short_type    = CoreLookupType ("System.Int16");
+               ushort_type   = CoreLookupType ("System.UInt16");
+       }
+       
+       /// <remarks>
+       ///   The types have to be initialized after the initial
+       ///   population of the type has happened (for example, to
+       ///   bootstrap the corlib.dll
+       /// </remarks>
+       public static void InitCoreTypes ()
+       {
+               object_type   = CoreLookupType ("System.Object");
+               value_type    = CoreLookupType ("System.ValueType");
+
+               InitEnumUnderlyingTypes ();
+
+               char_type     = CoreLookupType ("System.Char");
+               string_type   = CoreLookupType ("System.String");
+               float_type    = CoreLookupType ("System.Single");
+               double_type   = CoreLookupType ("System.Double");
+               char_ptr_type = CoreLookupType ("System.Char*");
+               decimal_type  = CoreLookupType ("System.Decimal");
+               bool_type     = CoreLookupType ("System.Boolean");
+               enum_type     = CoreLookupType ("System.Enum");
+
+               multicast_delegate_type = CoreLookupType ("System.MulticastDelegate");
+               delegate_type           = CoreLookupType ("System.Delegate");
+
+               array_type    = CoreLookupType ("System.Array");
+               void_type     = CoreLookupType ("System.Void");
+               type_type     = CoreLookupType ("System.Type");
+
+               runtime_field_handle_type = CoreLookupType ("System.RuntimeFieldHandle");
+               runtime_helpers_type = CoreLookupType ("System.Runtime.CompilerServices.RuntimeHelpers");
+               default_member_type  = CoreLookupType ("System.Reflection.DefaultMemberAttribute");
+               runtime_handle_type  = CoreLookupType ("System.RuntimeTypeHandle");
+               asynccallback_type   = CoreLookupType ("System.AsyncCallback");
+               iasyncresult_type    = CoreLookupType ("System.IAsyncResult");
+               ienumerator_type     = CoreLookupType ("System.Collections.IEnumerator");
+               ienumerable_type     = CoreLookupType ("System.Collections.IEnumerable");
+               idisposable_type     = CoreLookupType ("System.IDisposable");
+               icloneable_type      = CoreLookupType ("System.ICloneable");
+               monitor_type         = CoreLookupType ("System.Threading.Monitor");
+               intptr_type          = CoreLookupType ("System.IntPtr");
+
+               attribute_type       = CoreLookupType ("System.Attribute");
+               attribute_usage_type = CoreLookupType ("System.AttributeUsageAttribute");
+               dllimport_type       = CoreLookupType ("System.Runtime.InteropServices.DllImportAttribute");
+               methodimpl_attr_type = CoreLookupType ("System.Runtime.CompilerServices.MethodImplAttribute");
+               marshal_as_attr_type = CoreLookupType ("System.Runtime.InteropServices.MarshalAsAttribute");
+               param_array_type     = CoreLookupType ("System.ParamArrayAttribute");
+               in_attribute_type    = CoreLookupType ("System.Runtime.InteropServices.InAttribute");
+
+               //
+               // Sigh. Remove this before the release.  Wonder what versions of Mono
+               // people are running.
+               //
+               guid_attr_type        = LookupType ("System.Runtime.InteropServices.GuidAttribute");
+
+               unverifiable_code_type= CoreLookupType ("System.Security.UnverifiableCodeAttribute");
+
+               void_ptr_type         = CoreLookupType ("System.Void*");
+
+               indexer_name_type     = CoreLookupType ("System.Runtime.CompilerServices.IndexerNameAttribute");
+
+               exception_type        = CoreLookupType ("System.Exception");
+               invalid_operation_exception_type = CoreLookupType ("System.InvalidOperationException");
+
+               //
+               // Attribute types
+               //
+               obsolete_attribute_type = CoreLookupType ("System.ObsoleteAttribute");
+               conditional_attribute_type = CoreLookupType ("System.Diagnostics.ConditionalAttribute");
+
+               //
+               // When compiling corlib, store the "real" types here.
+               //
+               if (!RootContext.StdLib) {
+                       system_int32_type = typeof (System.Int32);
+                       system_array_type = typeof (System.Array);
+                       system_type_type = typeof (System.Type);
+                       system_assemblybuilder_type = typeof (System.Reflection.Emit.AssemblyBuilder);
+
+                       Type [] void_arg = {  };
+                       system_int_array_get_length = GetMethod (
+                               system_array_type, "get_Length", void_arg);
+                       system_int_array_get_rank = GetMethod (
+                               system_array_type, "get_Rank", void_arg);
+                       system_object_array_clone = GetMethod (
+                               system_array_type, "Clone", void_arg);
+
+                       Type [] system_int_arg = { system_int32_type };
+                       system_int_array_get_length_int = GetMethod (
+                               system_array_type, "GetLength", system_int_arg);
+                       system_int_array_get_upper_bound_int = GetMethod (
+                               system_array_type, "GetUpperBound", system_int_arg);
+                       system_int_array_get_lower_bound_int = GetMethod (
+                               system_array_type, "GetLowerBound", system_int_arg);
+
+                       Type [] system_array_int_arg = { system_array_type, system_int32_type };
+                       system_void_array_copyto_array_int = GetMethod (
+                               system_array_type, "CopyTo", system_array_int_arg);
+
+                       Type [] system_3_type_arg = {
+                               system_type_type, system_type_type, system_type_type };
+                       Type [] system_4_type_arg = {
+                               system_type_type, system_type_type, system_type_type, system_type_type };
+
+                       MethodInfo set_corlib_type_builders = GetMethod (
+                               system_assemblybuilder_type, "SetCorlibTypeBuilders",
+                               system_4_type_arg, false);
+
+                       if (set_corlib_type_builders != null) {
+                               object[] args = new object [4];
+                               args [0] = object_type;
+                               args [1] = value_type;
+                               args [2] = enum_type;
+                               args [3] = void_type;
+                               
+                               set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
+                       } else {
+                               // Compatibility for an older version of the class libs.
+                               set_corlib_type_builders = GetMethod (
+                                       system_assemblybuilder_type, "SetCorlibTypeBuilders",
+                                       system_3_type_arg, true);
+
+                               if (set_corlib_type_builders == null) {
+                                       Report.Error (-26, "Corlib compilation is not supported in Microsoft.NET due to bugs in it");
+                                       return;
+                               }
+
+                               object[] args = new object [3];
+                               args [0] = object_type;
+                               args [1] = value_type;
+                               args [2] = enum_type;
+                               
+                               set_corlib_type_builders.Invoke (CodeGen.AssemblyBuilder, args);
+                       }
+               }
+       }
+
+       //
+       // The helper methods that are used by the compiler
+       //
+       public static void InitCodeHelpers ()
+       {
+               //
+               // Now load the default methods that we use.
+               //
+               Type [] string_string = { string_type, string_type };
+               string_concat_string_string = GetMethod (
+                       string_type, "Concat", string_string);
+               Type [] string_string_string = { string_type, string_type, string_type };
+               string_concat_string_string_string = GetMethod (
+                       string_type, "Concat", string_string_string);
+               Type [] string_string_string_string = { string_type, string_type, string_type, string_type };
+               string_concat_string_string_string_string = GetMethod (
+                       string_type, "Concat", string_string_string_string);
+
+               Type [] object_object = { object_type, object_type };
+               string_concat_object_object = GetMethod (
+                       string_type, "Concat", object_object);
+
+               Type [] string_ = { string_type };
+               string_isinterneted_string = GetMethod (
+                       string_type, "IsInterned", string_);
+               
+               Type [] runtime_type_handle = { runtime_handle_type };
+               system_type_get_type_from_handle = GetMethod (
+                       type_type, "GetTypeFromHandle", runtime_type_handle);
+
+               Type [] delegate_delegate = { delegate_type, delegate_type };
+               delegate_combine_delegate_delegate = GetMethod (
+                               delegate_type, "Combine", delegate_delegate);
+
+               delegate_remove_delegate_delegate = GetMethod (
+                               delegate_type, "Remove", delegate_delegate);
+
+               //
+               // Void arguments
+               //
+               Type [] void_arg = {  };
+               object_getcurrent_void = GetMethod (
+                       ienumerator_type, "get_Current", void_arg);
+               bool_movenext_void = GetMethod (
+                       ienumerator_type, "MoveNext", void_arg);
+               void_reset_void = GetMethod (
+                       ienumerator_type, "Reset", void_arg);
+               void_dispose_void = GetMethod (
+                       idisposable_type, "Dispose", void_arg);
+               int_get_offset_to_string_data = GetMethod (
+                       runtime_helpers_type, "get_OffsetToStringData", void_arg);
+               int_array_get_length = GetMethod (
+                       array_type, "get_Length", void_arg);
+               int_array_get_rank = GetMethod (
+                       array_type, "get_Rank", void_arg);
+               ienumerable_getenumerator_void = GetMethod (
+                       ienumerable_type, "GetEnumerator", void_arg);
+               
+               //
+               // Int32 arguments
+               //
+               Type [] int_arg = { int32_type };
+               int_array_get_length_int = GetMethod (
+                       array_type, "GetLength", int_arg);
+               int_array_get_upper_bound_int = GetMethod (
+                       array_type, "GetUpperBound", int_arg);
+               int_array_get_lower_bound_int = GetMethod (
+                       array_type, "GetLowerBound", int_arg);
+
+               //
+               // System.Array methods
+               //
+               object_array_clone = GetMethod (
+                       array_type, "Clone", void_arg);
+               Type [] array_int_arg = { array_type, int32_type };
+               void_array_copyto_array_int = GetMethod (
+                       array_type, "CopyTo", array_int_arg);
+               
+               //
+               // object arguments
+               //
+               Type [] object_arg = { object_type };
+               void_monitor_enter_object = GetMethod (
+                       monitor_type, "Enter", object_arg);
+               void_monitor_exit_object = GetMethod (
+                       monitor_type, "Exit", object_arg);
+
+               Type [] array_field_handle_arg = { array_type, runtime_field_handle_type };
+               
+               void_initializearray_array_fieldhandle = GetMethod (
+                       runtime_helpers_type, "InitializeArray", array_field_handle_arg);
+
+               //
+               // Array functions
+               //
+               int_getlength_int = GetMethod (
+                       array_type, "GetLength", int_arg);
+
+               //
+               // Decimal constructors
+               //
+               Type [] dec_arg = { int32_type, int32_type, int32_type, bool_type, byte_type };
+               void_decimal_ctor_five_args = GetConstructor (
+                       decimal_type, dec_arg);
+               
+               //
+               // Attributes
+               //
+               cons_param_array_attribute = GetConstructor (
+                       param_array_type, void_arg);
+
+               unverifiable_code_ctor = GetConstructor (
+                       unverifiable_code_type, void_arg);
+
+               //
+               // InvalidOperationException
+               //
+               invalid_operation_ctor = GetConstructor (
+                       invalid_operation_exception_type, void_arg);
+
+
+               // Object
+               object_ctor = GetConstructor (object_type, void_arg);
+
+       }
+
+       const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
+
+       static Hashtable type_hash = new Hashtable ();
+
+       /// <remarks>
+       ///   This is the "old", non-cache based FindMembers() function.  We cannot use
+       ///   the cache here because there is no member name argument.
+       /// </remarks>
+       public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+                                             MemberFilter filter, object criteria)
+       {
+               DeclSpace decl = (DeclSpace) builder_to_declspace [t];
+
+               //
+               // `builder_to_declspace' contains all dynamic types.
+               //
+               if (decl != null) {
+                       MemberList list;
+                       Timer.StartTimer (TimerType.FindMembers);
+                       list = decl.FindMembers (mt, bf, filter, criteria);
+                       Timer.StopTimer (TimerType.FindMembers);
+                       return list;
+               }
+
+               //
+               // We have to take care of arrays specially, because GetType on
+               // a TypeBuilder array will return a Type, not a TypeBuilder,
+               // and we can not call FindMembers on this type.
+               //
+               if (t.IsSubclassOf (TypeManager.array_type))
+                       return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
+
+               //
+               // Since FindMembers will not lookup both static and instance
+               // members, we emulate this behaviour here.
+               //
+               if ((bf & instance_and_static) == instance_and_static){
+                       MemberInfo [] i_members = t.FindMembers (
+                               mt, bf & ~BindingFlags.Static, filter, criteria);
+
+                       int i_len = i_members.Length;
+                       if (i_len == 1){
+                               MemberInfo one = i_members [0];
+
+                               //
+                               // If any of these are present, we are done!
+                               //
+                               if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
+                                       return new MemberList (i_members);
+                       }
+                               
+                       MemberInfo [] s_members = t.FindMembers (
+                               mt, bf & ~BindingFlags.Instance, filter, criteria);
+
+                       int s_len = s_members.Length;
+                       if (i_len > 0 || s_len > 0)
+                               return new MemberList (i_members, s_members);
+                       else {
+                               if (i_len > 0)
+                                       return new MemberList (i_members);
+                               else
+                                       return new MemberList (s_members);
+                       }
+               }
+
+               return new MemberList (t.FindMembers (mt, bf, filter, criteria));
+       }
+
+
+       /// <summary>
+       ///   This method is only called from within MemberLookup.  It tries to use the member
+       ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
+       ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
+       ///   our return value will already contain all inherited members and the caller don't need
+       ///   to check base classes and interfaces anymore.
+       /// </summary>
+       private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+                                                           string name, out bool used_cache)
+       {
+                bool not_loaded_corlib = (t.Assembly == CodeGen.AssemblyBuilder);
+                
+               //
+               // We have to take care of arrays specially, because GetType on
+               // a TypeBuilder array will return a Type, not a TypeBuilder,
+               // and we can not call FindMembers on this type.
+               //
+               if (t == TypeManager.array_type || t.IsSubclassOf (TypeManager.array_type)) {
+                       used_cache = true;
+                       return TypeHandle.ArrayType.MemberCache.FindMembers (
+                               mt, bf, name, FilterWithClosure_delegate, null);
+               }
+
+               //
+               // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
+               // and we can ask the DeclSpace for the MemberCache.
+               //
+               if (t is TypeBuilder) {
+                       DeclSpace decl = (DeclSpace) builder_to_declspace [t];
+                       MemberCache cache = decl.MemberCache;
+
+                       //
+                       // If this DeclSpace has a MemberCache, use it.
+                       //
+
+                       if (cache != null) {
+                               used_cache = true;
+                               return cache.FindMembers (
+                                       mt, bf, name, FilterWithClosure_delegate, null);
+                       }
+
+                       // If there is no MemberCache, we need to use the "normal" FindMembers.
+
+                       MemberList list;
+                       Timer.StartTimer (TimerType.FindMembers);
+                       list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
+                                                FilterWithClosure_delegate, name);
+                       Timer.StopTimer (TimerType.FindMembers);
+                       used_cache = false;
+                       return list;
+               }
+
+               //
+               // This call will always succeed.  There is exactly one TypeHandle instance per
+               // type, TypeHandle.GetTypeHandle() will either return it or create a new one
+               // if it didn't already exist.
+               //
+               TypeHandle handle = TypeHandle.GetTypeHandle (t);
+
+               used_cache = true;
+               return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
+       }
+
+       public static bool IsBuiltinType (Type t)
+       {
+               if (t == object_type || t == string_type || t == int32_type || t == uint32_type ||
+                   t == int64_type || t == uint64_type || t == float_type || t == double_type ||
+                   t == char_type || t == short_type || t == decimal_type || t == bool_type ||
+                   t == sbyte_type || t == byte_type || t == ushort_type || t == void_type)
+                       return true;
+               else
+                       return false;
+       }
+
+       //
+       // This is like IsBuiltinType, but lacks decimal_type, we should also clean up
+       // the pieces in the code where we use IsBuiltinType and special case decimal_type.
+       // 
+       public static bool IsCLRType (Type t)
+       {
+               if (t == object_type || t == int32_type || t == uint32_type ||
+                   t == int64_type || t == uint64_type || t == float_type || t == double_type ||
+                   t == char_type || t == short_type || t == bool_type ||
+                   t == sbyte_type || t == byte_type || t == ushort_type)
+                       return true;
+               else
+                       return false;
+       }
+
+       public static bool IsDelegateType (Type t)
+       {
+               if (t.IsSubclassOf (TypeManager.delegate_type))
+                       return true;
+               else
+                       return false;
+       }
+       
+       public static bool IsEnumType (Type t)
+       {
+               if (t == TypeManager.enum_type || t.IsSubclassOf (TypeManager.enum_type))
+                       return true;
+               else
+                       return false;
+       }
+
+       //
+       // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
+       //
+       public static bool IsUnmanagedType (Type t)
+       {
+               if (IsBuiltinType (t) && t != TypeManager.string_type)
+                       return true;
+
+               if (IsEnumType (t))
+                       return true;
+
+               if (t.IsPointer)
+                       return true;
+
+               if (IsValueType (t)){
+                       if (t is TypeBuilder){
+                               TypeContainer tc = LookupTypeContainer (t);
+
+                               foreach (Field f in tc.Fields){
+                                       if (f.FieldBuilder.IsStatic)
+                                               continue;
+                                       if (!IsUnmanagedType (f.FieldBuilder.FieldType))
+                                               return false;
+                               }
+                       } else {
+                               FieldInfo [] fields = t.GetFields ();
+
+                               foreach (FieldInfo f in fields){
+                                       if (f.IsStatic)
+                                               continue;
+                                       if (!IsUnmanagedType (f.FieldType))
+                                               return false;
+                               }
+                       }
+                       return true;
+               }
+
+               return false;
+       }
+               
+       public static bool IsValueType (Type t)
+       {
+               if (t.IsSubclassOf (TypeManager.value_type) && (t != TypeManager.enum_type))
+                       return true;
+               else
+                       return false;
+       }
+       
+       public static bool IsInterfaceType (Type t)
+       {
+               Interface iface = builder_to_declspace [t] as Interface;
+
+               if (iface != null)
+                       return true;
+               else
+                       return false;
+       }
+
+       //
+       // Checks whether `type' is a subclass or nested child of `parent'.
+       //
+       public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
+       {
+               do {
+                       if ((type == parent) || type.IsSubclassOf (parent))
+                               return true;
+
+                       // Handle nested types.
+                       type = type.DeclaringType;
+               } while (type != null);
+
+               return false;
+       }
+
+       //
+       // Checks whether `type' is a nested child of `parent'.
+       //
+       public static bool IsNestedChildOf (Type type, Type parent)
+       {
+               if (type == parent)
+                       return false;
+
+               type = type.DeclaringType;
+               while (type != null) {
+                       if (type == parent)
+                               return true;
+
+                       type = type.DeclaringType;
+               }
+
+               return false;
+       }
+
+        //
+        // Do the right thing when returning the element type of
+        // an array type based on whether we 
+        //
+        public static Type GetElementType (Type t)
+        {
+                if (RootContext.StdLib)
+                        return t.GetElementType ();
+                else
+                        return TypeToCoreType (t.GetElementType ());
+        }
+
+       /// <summary>
+       ///   Returns the User Defined Types
+       /// </summary>
+       public static ArrayList UserTypes {
+               get {
+                       return user_types;
+               }
+       }
+
+       public static Hashtable TypeContainers {
+               get {
+                       return typecontainers;
+               }
+       }
+
+       static Hashtable attr_to_allowmult;
+
+       public static void RegisterAttributeAllowMultiple (Type attr_type, bool allow)
+       {
+               if (attr_to_allowmult == null)
+                       attr_to_allowmult = new PtrHashtable ();
+
+               if (attr_to_allowmult.Contains (attr_type))
+                       return;
+
+               attr_to_allowmult.Add (attr_type, allow);
+                              
+       }
+
+       public static bool AreMultipleAllowed (Type attr_type)
+       {
+               if (!(attr_type is TypeBuilder)) {
+                       System.Attribute [] attrs = System.Attribute.GetCustomAttributes (attr_type);
+
+                       foreach (System.Attribute tmp in attrs)
+                               if (tmp is AttributeUsageAttribute) {
+                                        return ((AttributeUsageAttribute) tmp).AllowMultiple;
+                                }
+
+                       return false;
+               }
+               
+               if (attr_to_allowmult == null)
+                       return false;
+
+               return (bool) attr_to_allowmult [attr_type];
+       }
+
+       static Hashtable builder_to_constant;
+
+       public static void RegisterConstant (FieldBuilder fb, Const c)
+       {
+               if (builder_to_constant == null)
+                       builder_to_constant = new PtrHashtable ();
+
+               if (builder_to_constant.Contains (fb))
+                       return;
+
+               builder_to_constant.Add (fb, c);
+       }
+
+       public static Const LookupConstant (FieldBuilder fb)
+       {
+               if (builder_to_constant == null)
+                       return null;
+               
+               return (Const) builder_to_constant [fb];
+       }
+       
+       /// <summary>
+       ///   Gigantic work around for missing features in System.Reflection.Emit follows.
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   Since System.Reflection.Emit can not return MethodBase.GetParameters
+       ///   for anything which is dynamic, and we need this in a number of places,
+       ///   we register this information here, and use it afterwards.
+       /// </remarks>
+       static public bool RegisterMethod (MethodBase mb, InternalParameters ip, Type [] args)
+       {
+               if (args == null)
+                       args = NoTypes;
+                               
+               method_arguments.Add (mb, args);
+               method_internal_params.Add (mb, ip);
+               
+               return true;
+       }
+       
+       static public InternalParameters LookupParametersByBuilder (MethodBase mb)
+       {
+               if (! (mb is ConstructorBuilder || mb is MethodBuilder))
+                       return null;
+               
+               if (method_internal_params.Contains (mb))
+                       return (InternalParameters) method_internal_params [mb];
+               else
+                       throw new Exception ("Argument for Method not registered" + mb);
+       }
+
+       /// <summary>
+       ///    Returns the argument types for a method based on its methodbase
+       ///
+       ///    For dynamic methods, we use the compiler provided types, for
+       ///    methods from existing assemblies we load them from GetParameters,
+       ///    and insert them into the cache
+       /// </summary>
+       static public Type [] GetArgumentTypes (MethodBase mb)
+       {
+               if (method_arguments.Contains (mb))
+                       return (Type []) method_arguments [mb];
+               else {
+                       ParameterInfo [] pi = mb.GetParameters ();
+                       int c = pi.Length;
+                       Type [] types = new Type [c];
+                       
+                       for (int i = 0; i < c; i++)
+                               types [i] = pi [i].ParameterType;
+
+                       method_arguments.Add (mb, types);
+                       return types;
+               }
+       }
+
+       /// <summary>
+       ///    Returns the argument types for an indexer based on its PropertyInfo
+       ///
+       ///    For dynamic indexers, we use the compiler provided types, for
+       ///    indexers from existing assemblies we load them from GetParameters,
+       ///    and insert them into the cache
+       /// </summary>
+       static public Type [] GetArgumentTypes (PropertyInfo indexer)
+       {
+               if (indexer_arguments.Contains (indexer))
+                       return (Type []) indexer_arguments [indexer];
+               else if (indexer is PropertyBuilder)
+                       // If we're a PropertyBuilder and not in the
+                       // `indexer_arguments' hash, then we're a property and
+                       // not an indexer.
+                       return NoTypes;
+               else {
+                       ParameterInfo [] pi = indexer.GetIndexParameters ();
+                       // Property, not an indexer.
+                       if (pi == null)
+                               return NoTypes;
+                       int c = pi.Length;
+                       Type [] types = new Type [c];
+                       
+                       for (int i = 0; i < c; i++)
+                               types [i] = pi [i].ParameterType;
+
+                       indexer_arguments.Add (indexer, types);
+                       return types;
+               }
+       }
+       
+       // <remarks>
+       //  This is a workaround the fact that GetValue is not
+       //  supported for dynamic types
+       // </remarks>
+       static Hashtable fields = new Hashtable ();
+       static public bool RegisterFieldValue (FieldBuilder fb, object value)
+       {
+               if (fields.Contains (fb))
+                       return false;
+
+               fields.Add (fb, value);
+
+               return true;
+       }
+
+       static public object GetValue (FieldBuilder fb)
+       {
+               return fields [fb];
+       }
+
+       static Hashtable fieldbuilders_to_fields = new Hashtable ();
+       static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f)
+       {
+               if (fieldbuilders_to_fields.Contains (fb))
+                       return false;
+
+               fieldbuilders_to_fields.Add (fb, f);
+               return true;
+       }
+
+       static public FieldBase GetField (FieldInfo fb)
+       {
+               return (FieldBase) fieldbuilders_to_fields [fb];
+       }
+       
+       static Hashtable events;
+
+       static public bool RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove)
+       {
+               if (events == null)
+                       events = new Hashtable ();
+
+               if (events.Contains (eb))
+                       return false;
+
+               events.Add (eb, new Pair (add, remove));
+
+               return true;
+       }
+
+       static public MethodInfo GetAddMethod (EventInfo ei)
+       {
+               if (ei is MyEventBuilder) {
+                       Pair pair = (Pair) events [ei];
+
+                       return (MethodInfo) pair.First;
+               } else
+                       return ei.GetAddMethod ();
+       }
+
+       static public MethodInfo GetRemoveMethod (EventInfo ei)
+       {
+               if (ei is MyEventBuilder) {
+                       Pair pair = (Pair) events [ei];
+
+                       return (MethodInfo) pair.Second;
+               } else
+                       return ei.GetRemoveMethod ();
+       }
+
+       static Hashtable priv_fields_events;
+
+       static public bool RegisterPrivateFieldOfEvent (EventInfo einfo, FieldBuilder builder)
+       {
+               if (priv_fields_events == null)
+                       priv_fields_events = new Hashtable ();
+
+               if (priv_fields_events.Contains (einfo))
+                       return false;
+
+               priv_fields_events.Add (einfo, builder);
+
+               return true;
+       }
+
+       static public MemberInfo GetPrivateFieldOfEvent (EventInfo ei)
+       {
+               if (priv_fields_events == null)
+                       return null;
+               else
+                       return (MemberInfo) priv_fields_events [ei];
+       }
+               
+       static Hashtable properties;
+       
+       static public bool RegisterProperty (PropertyBuilder pb, MethodBase get, MethodBase set)
+       {
+               if (properties == null)
+                       properties = new Hashtable ();
+
+               if (properties.Contains (pb))
+                       return false;
+
+               properties.Add (pb, new Pair (get, set));
+
+               return true;
+       }
+
+       static public bool RegisterIndexer (PropertyBuilder pb, MethodBase get,
+                                            MethodBase set, Type[] args)
+       {
+               if (!RegisterProperty (pb, get,set))
+                       return false;
+
+               indexer_arguments.Add (pb, args);
+
+               return true;
+       }
+
+       /// <summary>
+       ///   Given an array of interface types, expand and eliminate repeated ocurrences
+       ///   of an interface.  
+       /// </summary>
+       ///
+       /// <remarks>
+       ///   This expands in context like: IA; IB : IA; IC : IA, IB; the interface "IC" to
+       ///   be IA, IB, IC.
+       /// </remarks>
+       public static Type [] ExpandInterfaces (Type [] base_interfaces)
+       {
+               ArrayList new_ifaces = new ArrayList ();
+               
+               foreach (Type iface in base_interfaces){
+                       if (!new_ifaces.Contains (iface))
+                               new_ifaces.Add (iface);
+                       
+                       Type [] implementing = TypeManager.GetInterfaces (iface);
+                       
+                       foreach (Type imp in implementing){
+                               if (!new_ifaces.Contains (imp))
+                                       new_ifaces.Add (imp);
+                       }
+               }
+               Type [] ret = new Type [new_ifaces.Count];
+               new_ifaces.CopyTo (ret, 0);
+               return ret;
+       }
+               
+       /// <summary>
+       ///   This function returns the interfaces in the type `t'.  Works with
+       ///   both types and TypeBuilders.
+       /// </summary>
+       public static Type [] GetInterfaces (Type t)
+       {
+               //
+               // The reason for catching the Array case is that Reflection.Emit
+               // will not return a TypeBuilder for Array types of TypeBuilder types,
+               // but will still throw an exception if we try to call GetInterfaces
+               // on the type.
+               //
+               // Since the array interfaces are always constant, we return those for
+               // the System.Array
+               //
+               
+               if (t.IsArray)
+                       t = TypeManager.array_type;
+               
+               if (t is TypeBuilder){
+                       Type [] parent_ifaces;
+                       
+                       if (t.BaseType == null)
+                               parent_ifaces = NoTypes;
+                       else
+                               parent_ifaces = GetInterfaces (t.BaseType);
+                       Type [] type_ifaces = (Type []) builder_to_ifaces [t];
+                       if (type_ifaces == null)
+                               type_ifaces = NoTypes;
+
+                       int parent_count = parent_ifaces.Length;
+                       Type [] result = new Type [parent_count + type_ifaces.Length];
+                       parent_ifaces.CopyTo (result, 0);
+                       type_ifaces.CopyTo (result, parent_count);
+
+                       return result;
+               } else
+                       return t.GetInterfaces ();
+       }
+       
+       /// <remarks>
+       ///  The following is used to check if a given type implements an interface.
+       ///  The cache helps us reduce the expense of hitting Type.GetInterfaces everytime.
+       /// </remarks>
+       public static bool ImplementsInterface (Type t, Type iface)
+       {
+               Type [] interfaces;
+
+               //
+               // FIXME OPTIMIZATION:
+               // as soon as we hit a non-TypeBuiler in the interface
+               // chain, we could return, as the `Type.GetInterfaces'
+               // will return all the interfaces implement by the type
+               // or its parents.
+               //
+               do {
+                       interfaces = GetInterfaces (t);
+
+                       if (interfaces != null){
+                               foreach (Type i in interfaces){
+                                       if (i == iface)
+                                               return true;
+                               }
+                       }
+                       
+                       t = t.BaseType;
+               } while (t != null);
+               
+               return false;
+       }
+
+       // This is a custom version of Convert.ChangeType() which works
+       // with the TypeBuilder defined types when compiling corlib.
+       public static object ChangeType (object value, Type conversionType, out bool error)
+       {
+               if (!(value is IConvertible)){
+                       error = true;
+                       return null;
+               }
+               
+               IConvertible convertValue = (IConvertible) value;
+               CultureInfo ci = CultureInfo.CurrentCulture;
+               NumberFormatInfo provider = ci.NumberFormat;
+
+               //
+               // We must use Type.Equals() here since `conversionType' is
+               // the TypeBuilder created version of a system type and not
+               // the system type itself.  You cannot use Type.GetTypeCode()
+               // on such a type - it'd always return TypeCode.Object.
+               //
+               error = false;
+               try {
+                       if (conversionType.Equals (typeof (Boolean)))
+                               return (object)(convertValue.ToBoolean (provider));
+                       else if (conversionType.Equals (typeof (Byte)))
+                               return (object)(convertValue.ToByte (provider));
+                       else if (conversionType.Equals (typeof (Char)))
+                               return (object)(convertValue.ToChar (provider));
+                       else if (conversionType.Equals (typeof (DateTime)))
+                               return (object)(convertValue.ToDateTime (provider));
+                       else if (conversionType.Equals (typeof (Decimal)))
+                               return (object)(convertValue.ToDecimal (provider));
+                       else if (conversionType.Equals (typeof (Double)))
+                               return (object)(convertValue.ToDouble (provider));
+                       else if (conversionType.Equals (typeof (Int16)))
+                               return (object)(convertValue.ToInt16 (provider));
+                       else if (conversionType.Equals (typeof (Int32)))
+                               return (object)(convertValue.ToInt32 (provider));
+                       else if (conversionType.Equals (typeof (Int64)))
+                               return (object)(convertValue.ToInt64 (provider));
+                       else if (conversionType.Equals (typeof (SByte)))
+                               return (object)(convertValue.ToSByte (provider));
+                       else if (conversionType.Equals (typeof (Single)))
+                               return (object)(convertValue.ToSingle (provider));
+                       else if (conversionType.Equals (typeof (String)))
+                               return (object)(convertValue.ToString (provider));
+                       else if (conversionType.Equals (typeof (UInt16)))
+                               return (object)(convertValue.ToUInt16 (provider));
+                       else if (conversionType.Equals (typeof (UInt32)))
+                               return (object)(convertValue.ToUInt32 (provider));
+                       else if (conversionType.Equals (typeof (UInt64)))
+                               return (object)(convertValue.ToUInt64 (provider));
+                       else if (conversionType.Equals (typeof (Object)))
+                               return (object)(value);
+                       else 
+                               error = true;
+               } catch {
+                       error = true;
+               }
+               return null;
+       }
+
+       //
+       // This is needed, because enumerations from assemblies
+       // do not report their underlyingtype, but they report
+       // themselves
+       //
+       public static Type EnumToUnderlying (Type t)
+       {
+               if (t == TypeManager.enum_type)
+                       return t;
+
+               t = t.UnderlyingSystemType;
+               if (!TypeManager.IsEnumType (t))
+                       return t;
+       
+               if (t is TypeBuilder) {
+                       // slow path needed to compile corlib
+                       if (t == TypeManager.bool_type ||
+                                       t == TypeManager.byte_type ||
+                                       t == TypeManager.sbyte_type ||
+                                       t == TypeManager.char_type ||
+                                       t == TypeManager.short_type ||
+                                       t == TypeManager.ushort_type ||
+                                       t == TypeManager.int32_type ||
+                                       t == TypeManager.uint32_type ||
+                                       t == TypeManager.int64_type ||
+                                       t == TypeManager.uint64_type)
+                               return t;
+                       throw new Exception ("Unhandled typecode in enum " + " from " + t.AssemblyQualifiedName);
+               }
+               TypeCode tc = Type.GetTypeCode (t);
+
+               switch (tc){
+               case TypeCode.Boolean:
+                       return TypeManager.bool_type;
+               case TypeCode.Byte:
+                       return TypeManager.byte_type;
+               case TypeCode.SByte:
+                       return TypeManager.sbyte_type;
+               case TypeCode.Char:
+                       return TypeManager.char_type;
+               case TypeCode.Int16:
+                       return TypeManager.short_type;
+               case TypeCode.UInt16:
+                       return TypeManager.ushort_type;
+               case TypeCode.Int32:
+                       return TypeManager.int32_type;
+               case TypeCode.UInt32:
+                       return TypeManager.uint32_type;
+               case TypeCode.Int64:
+                       return TypeManager.int64_type;
+               case TypeCode.UInt64:
+                       return TypeManager.uint64_type;
+               }
+               throw new Exception ("Unhandled typecode in enum " + tc + " from " + t.AssemblyQualifiedName);
+       }
+
+       //
+       // When compiling corlib and called with one of the core types, return
+       // the corresponding typebuilder for that type.
+       //
+       public static Type TypeToCoreType (Type t)
+       {
+               if (RootContext.StdLib || (t is TypeBuilder))
+                       return t;
+
+               TypeCode tc = Type.GetTypeCode (t);
+
+               switch (tc){
+               case TypeCode.Boolean:
+                       return TypeManager.bool_type;
+               case TypeCode.Byte:
+                       return TypeManager.byte_type;
+               case TypeCode.SByte:
+                       return TypeManager.sbyte_type;
+               case TypeCode.Char:
+                       return TypeManager.char_type;
+               case TypeCode.Int16:
+                       return TypeManager.short_type;
+               case TypeCode.UInt16:
+                       return TypeManager.ushort_type;
+               case TypeCode.Int32:
+                       return TypeManager.int32_type;
+               case TypeCode.UInt32:
+                       return TypeManager.uint32_type;
+               case TypeCode.Int64:
+                       return TypeManager.int64_type;
+               case TypeCode.UInt64:
+                       return TypeManager.uint64_type;
+               case TypeCode.String:
+                       return TypeManager.string_type;
+               default:
+                       if (t == typeof (void))
+                               return TypeManager.void_type;
+                       if (t == typeof (object))
+                               return TypeManager.object_type;
+                       if (t == typeof (System.Type))
+                               return TypeManager.type_type;
+                       return t;
+               }
+       }
+
+       /// <summary>
+       ///   Utility function that can be used to probe whether a type
+       ///   is managed or not.  
+       /// </summary>
+       public static bool VerifyUnManaged (Type t, Location loc)
+       {
+               if (t.IsValueType || t.IsPointer){
+                       //
+                       // FIXME: this is more complex, we actually need to
+                       // make sure that the type does not contain any
+                       // classes itself
+                       //
+                       return true;
+               }
+
+               if (!RootContext.StdLib && (t == TypeManager.decimal_type))
+                       // We need this explicit check here to make it work when
+                       // compiling corlib.
+                       return true;
+
+               Report.Error (
+                       208, loc,
+                       "Cannot take the address or size of a variable of a managed type ('" +
+                       CSharpName (t) + "')");
+               return false;   
+       }
+       
+       /// <summary>
+       ///   Returns the name of the indexer in a given type.
+       /// </summary>
+       /// <remarks>
+       ///   The default is not always `Item'.  The user can change this behaviour by
+       ///   using the DefaultMemberAttribute in the class.
+       ///
+       ///   For example, the String class indexer is named `Chars' not `Item' 
+       /// </remarks>
+       public static string IndexerPropertyName (Type t)
+       {
+               if (t is TypeBuilder) {
+                       if (t.IsInterface) {
+                               Interface i = LookupInterface (t);
+
+                               if ((i == null) || (i.IndexerName == null))
+                                       return "Item";
+
+                               return i.IndexerName;
+                       } else {
+                               TypeContainer tc = LookupTypeContainer (t);
+
+                               if ((tc == null) || (tc.IndexerName == null))
+                                       return "Item";
+
+                               return tc.IndexerName;
+                       }
+               }
+               
+               System.Attribute attr = System.Attribute.GetCustomAttribute (
+                       t, TypeManager.default_member_type);
+               if (attr != null){
+                       DefaultMemberAttribute dma = (DefaultMemberAttribute) attr;
+                       return dma.MemberName;
+               }
+
+               return "Item";
+       }
+
+       public static void MakePinned (LocalBuilder builder)
+       {
+               //
+               // FIXME: Flag the "LocalBuilder" type as being
+               // pinned.  Figure out API.
+               //
+       }
+
+
+       //
+       // Returns whether the array of memberinfos contains the given method
+       //
+       static bool ArrayContainsMethod (MemberInfo [] array, MethodBase new_method)
+       {
+               Type [] new_args = TypeManager.GetArgumentTypes (new_method);
+               
+               foreach (MethodBase method in array){
+                       if (method.Name != new_method.Name)
+                               continue;
+                       
+                       Type [] old_args = TypeManager.GetArgumentTypes (method);
+                       int old_count = old_args.Length;
+                       int i;
+                       
+                       if (new_args.Length != old_count)
+                               continue;
+                       
+                       for (i = 0; i < old_count; i++){
+                               if (old_args [i] != new_args [i])
+                                       break;
+                       }
+                       if (i != old_count)
+                               continue;
+
+                       return true;
+               }
+               return false;
+       }
+       
+       //
+       // We copy methods from `new_members' into `target_list' if the signature
+       // for the method from in the new list does not exist in the target_list
+       //
+       // The name is assumed to be the same.
+       //
+       public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
+       {
+               if (target_list == null){
+                       target_list = new ArrayList ();
+
+                       foreach (MemberInfo mi in new_members){
+                               if (mi is MethodBase)
+                                       target_list.Add (mi);
+                       }
+                       return target_list;
+               }
+               
+               MemberInfo [] target_array = new MemberInfo [target_list.Count];
+               target_list.CopyTo (target_array, 0);
+               
+               foreach (MemberInfo mi in new_members){
+                       MethodBase new_method = (MethodBase) mi;
+                       
+                       if (!ArrayContainsMethod (target_array, new_method))
+                               target_list.Add (new_method);
+               }
+               return target_list;
+       }
+
+       [Flags]
+       public enum MethodFlags {
+               IsObsolete = 1,
+               IsObsoleteError = 2,
+               ShouldIgnore = 3
+       }
+       
+       //
+       // Returns the TypeManager.MethodFlags for this method.
+       // This emits an error 619 / warning 618 if the method is obsolete.
+       // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
+       //
+       static public MethodFlags GetMethodFlags (MethodBase mb, Location loc)
+       {
+               MethodFlags flags = 0;
+               
+               if (mb.DeclaringType is TypeBuilder){
+                       MethodData method = (MethodData) builder_to_method [mb];
+                       if (method == null) {
+                               // FIXME: implement Obsolete attribute on Property,
+                               //        Indexer and Event.
+                               return 0;
+                       }
+
+                       return method.GetMethodFlags (loc);
+               }
+
+               object [] attrs = mb.GetCustomAttributes (true);
+               foreach (object ta in attrs){
+                       if (!(ta is System.Attribute)){
+                               Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
+                               continue;
+                       }
+                       System.Attribute a = (System.Attribute) ta;
+                       if (a.TypeId == TypeManager.obsolete_attribute_type){
+                               ObsoleteAttribute oa = (ObsoleteAttribute) a;
+
+                               string method_desc = TypeManager.CSharpSignature (mb);
+
+                               if (oa.IsError) {
+                                       Report.Error (619, loc, "Method `" + method_desc +
+                                                     "' is obsolete: `" + oa.Message + "'");
+                                       return MethodFlags.IsObsoleteError;
+                               } else
+                                       Report.Warning (618, loc, "Method `" + method_desc +
+                                                       "' is obsolete: `" + oa.Message + "'");
+
+                               flags |= MethodFlags.IsObsolete;
+
+                               continue;
+                       }
+                       
+                       //
+                       // Skip over conditional code.
+                       //
+                       if (a.TypeId == TypeManager.conditional_attribute_type){
+                               ConditionalAttribute ca = (ConditionalAttribute) a;
+
+                               if (RootContext.AllDefines [ca.ConditionString] == null)
+                                       flags |= MethodFlags.ShouldIgnore;
+                       }
+               }
+
+               return flags;
+       }
+       
+#region MemberLookup implementation
+       
+       //
+       // Name of the member
+       //
+       static string   closure_name;
+
+       //
+       // Whether we allow private members in the result (since FindMembers
+       // uses NonPublic for both protected and private), we need to distinguish.
+       //
+       static bool     closure_private_ok;
+
+       //
+       // Who is invoking us and which type is being queried currently.
+       //
+       static Type     closure_invocation_type;
+       static Type     closure_queried_type;
+       static Type     closure_qualifier_type;
+
+       //
+       // The assembly that defines the type is that is calling us
+       //
+       static Assembly closure_invocation_assembly;
+
+       static internal bool FilterNone (MemberInfo m, object filter_criteria)
+       {
+               return true;
+       }
+       
+       //
+       // This filter filters by name + whether it is ok to include private
+       // members in the search
+       //
+       static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
+       {
+               //
+               // Hack: we know that the filter criteria will always be in the `closure'
+               // fields. 
+               //
+
+               if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
+                       return false;
+
+               if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
+                   (m.DeclaringType == closure_invocation_type))
+                       return true;
+
+               //
+               // Ugly: we need to find out the type of `m', and depending
+               // on this, tell whether we accept or not
+               //
+               if (m is MethodBase){
+                       MethodBase mb = (MethodBase) m;
+                       MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
+
+                       if (ma == MethodAttributes.Private)
+                               return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
+                                       IsNestedChildOf (closure_invocation_type, m.DeclaringType);
+
+                       //
+                       // FamAndAssem requires that we not only derivate, but we are on the
+                       // same assembly.  
+                       //
+                       if (ma == MethodAttributes.FamANDAssem){
+                               if (closure_invocation_assembly != mb.DeclaringType.Assembly)
+                                       return false;
+                       }
+
+                       // Assembly and FamORAssem succeed if we're in the same assembly.
+                       if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
+                               if (closure_invocation_assembly == mb.DeclaringType.Assembly)
+                                       return true;
+                       }
+
+                       // We already know that we aren't in the same assembly.
+                       if (ma == MethodAttributes.Assembly)
+                               return false;
+
+                       // Family and FamANDAssem require that we derive.
+                       if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
+                               if (closure_invocation_type == null)
+                                       return false;
+
+                               if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
+                                       return false;
+
+                               // Although a derived class can access protected members of its base class
+                               // it cannot do so through an instance of the base class (CS1540).
+                               if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
+                                   (closure_qualifier_type != null) &&
+                                   closure_invocation_type.IsSubclassOf (closure_qualifier_type))
+                                       return false;
+
+                               return true;
+                       }
+
+                       // Public.
+                       return true;
+               }
+
+               if (m is FieldInfo){
+                       FieldInfo fi = (FieldInfo) m;
+                       FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
+
+                       if (fa == FieldAttributes.Private)
+                               return closure_private_ok || (closure_invocation_type == m.DeclaringType) ||
+                                       IsNestedChildOf (closure_invocation_type, m.DeclaringType);
+
+                       //
+                       // FamAndAssem requires that we not only derivate, but we are on the
+                       // same assembly.  
+                       //
+                       if (fa == FieldAttributes.FamANDAssem){
+                               if (closure_invocation_assembly != fi.DeclaringType.Assembly)
+                                       return false;
+                       }
+
+                       // Assembly and FamORAssem succeed if we're in the same assembly.
+                       if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
+                               if (closure_invocation_assembly == fi.DeclaringType.Assembly)
+                                       return true;
+                       }
+
+                       // We already know that we aren't in the same assembly.
+                       if (fa == FieldAttributes.Assembly)
+                               return false;
+
+                       // Family and FamANDAssem require that we derive.
+                       if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
+                               if (closure_invocation_type == null)
+                                       return false;
+
+                               if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
+                                       return false;
+
+                               // Although a derived class can access protected members of its base class
+                               // it cannot do so through an instance of the base class (CS1540).
+                               if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
+                                   (closure_qualifier_type != null) &&
+                                   closure_invocation_type.IsSubclassOf (closure_qualifier_type))
+                                       return false;
+
+                               return true;
+                       }
+
+                       // Public.
+                       return true;
+               }
+
+               //
+               // EventInfos and PropertyInfos, return true because they lack permission
+               // informaiton, so we need to check later on the methods.
+               //
+               return true;
+       }
+
+       static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
+       static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
+
+       //
+       // Looks up a member called `name' in the `queried_type'.  This lookup
+       // is done by code that is contained in the definition for `invocation_type'
+       // through a qualifier of type `qualifier_type' (or null if there is no qualifier).
+       //
+       // `invocation_type' is used to check whether we're allowed to access the requested
+       // member wrt its protection level.
+       //
+       // When called from MemberAccess, `qualifier_type' is the type which is used to access
+       // the requested member (`class B { A a = new A (); a.foo = 5; }'; here invocation_type
+       // is B and qualifier_type is A).  This is used to do the CS1540 check.
+       //
+       // When resolving a SimpleName, `qualifier_type' is null.
+       //
+       // The `qualifier_type' is used for the CS1540 check; it's normally either null or
+       // the same than `queried_type' - except when we're being called from BaseAccess;
+       // in this case, `invocation_type' is the current type and `queried_type' the base
+       // type, so this'd normally trigger a CS1540.
+       //
+       // The binding flags are `bf' and the kind of members being looked up are `mt'
+       //
+       // The return value always includes private members which code in `invocation_type'
+       // is allowed to access (using the specified `qualifier_type' if given); only use
+       // BindingFlags.NonPublic to bypass the permission check.
+       //
+       // Returns an array of a single element for everything but Methods/Constructors
+       // that might return multiple matches.
+       //
+       public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
+                                                 Type queried_type,  MemberTypes mt,
+                                                 BindingFlags original_bf, string name)
+       {
+               Timer.StartTimer (TimerType.MemberLookup);
+
+               MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
+                                                       queried_type, mt, original_bf, name);
+
+               Timer.StopTimer (TimerType.MemberLookup);
+
+               return retval;
+       }
+
+       static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
+                                              Type queried_type, MemberTypes mt,
+                                              BindingFlags original_bf, string name)
+       {
+               BindingFlags bf = original_bf;
+               
+               ArrayList method_list = null;
+               Type current_type = queried_type;
+               bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
+               bool skip_iface_check = true, used_cache = false;
+               bool always_ok_flag = false;
+
+               closure_name = name;
+               closure_invocation_type = invocation_type;
+               closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
+               closure_qualifier_type = qualifier_type;
+
+               //
+               // If we are a nested class, we always have access to our container
+               // type names
+               //
+               if (invocation_type != null){
+                       string invocation_name = invocation_type.FullName;
+                       if (invocation_name.IndexOf ('+') != -1){
+                               string container = queried_type.FullName + "+";
+                               int container_length = container.Length;
+
+                               if (invocation_name.Length > container_length){
+                                       string shared = invocation_name.Substring (0, container_length);
+                               
+                                       if (shared == container)
+                                               always_ok_flag = true;
+                               }
+                       }
+               }
+               
+               do {
+                       MemberList list;
+
+                       //
+                       // `NonPublic' is lame, because it includes both protected and
+                       // private methods, so we need to control this behavior by
+                       // explicitly tracking if a private method is ok or not.
+                       //
+                       // The possible cases are:
+                       //    public, private and protected (internal does not come into the
+                       //    equation)
+                       //
+                       if ((invocation_type != null) &&
+                           ((invocation_type == current_type) ||
+                            IsNestedChildOf (invocation_type, current_type)) ||
+                           always_ok_flag)
+                               bf = original_bf | BindingFlags.NonPublic;
+                       else
+                               bf = original_bf;
+
+                       closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0;
+                       closure_queried_type = current_type;
+
+                       Timer.StopTimer (TimerType.MemberLookup);
+
+                       list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
+
+                       Timer.StartTimer (TimerType.MemberLookup);
+
+                       //
+                       // When queried for an interface type, the cache will automatically check all
+                       // inherited members, so we don't need to do this here.  However, this only
+                       // works if we already used the cache in the first iteration of this loop.
+                       //
+                       // If we used the cache in any further iteration, we can still terminate the
+                       // loop since the cache always looks in all parent classes.
+                       //
+
+                       if (used_cache)
+                               searching = false;
+                       else
+                               skip_iface_check = false;
+
+                       if (current_type == TypeManager.object_type)
+                               searching = false;
+                       else {
+                               current_type = current_type.BaseType;
+                               
+                               //
+                               // This happens with interfaces, they have a null
+                               // basetype.  Look members up in the Object class.
+                               //
+                               if (current_type == null)
+                                       current_type = TypeManager.object_type;
+                       }
+                       
+                       if (list.Count == 0)
+                               continue;
+
+                       //
+                       // Events and types are returned by both `static' and `instance'
+                       // searches, which means that our above FindMembers will
+                       // return two copies of the same.
+                       //
+                       if (list.Count == 1 && !(list [0] is MethodBase)){
+                               return (MemberInfo []) list;
+                       }
+
+                       //
+                       // Multiple properties: we query those just to find out the indexer
+                       // name
+                       //
+                       if (list [0] is PropertyInfo)
+                               return (MemberInfo []) list;
+
+                       //
+                       // We found an event: the cache lookup returns both the event and
+                       // its private field.
+                       //
+                       if (list [0] is EventInfo) {
+                               if ((list.Count == 2) && (list [1] is FieldInfo))
+                                       return new MemberInfo [] { list [0] };
+
+                               // Oooops
+                               return null;
+                       }
+
+                       //
+                       // We found methods, turn the search into "method scan"
+                       // mode.
+                       //
+
+                       method_list = CopyNewMethods (method_list, list);
+                       mt &= (MemberTypes.Method | MemberTypes.Constructor);
+               } while (searching);
+
+               if (method_list != null && method_list.Count > 0) {
+                        return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
+                }
+               //
+               // This happens if we already used the cache in the first iteration, in this case
+               // the cache already looked in all interfaces.
+               //
+               if (skip_iface_check)
+                       return null;
+
+               //
+               // Interfaces do not list members they inherit, so we have to
+               // scan those.
+               // 
+               if (!queried_type.IsInterface)
+                       return null;
+
+               if (queried_type.IsArray)
+                       queried_type = TypeManager.array_type;
+               
+               Type [] ifaces = GetInterfaces (queried_type);
+               if (ifaces == null)
+                       return null;
+               
+               foreach (Type itype in ifaces){
+                       MemberInfo [] x;
+
+                       x = MemberLookup (null, null, itype, mt, bf, name);
+                       if (x != null)
+                               return x;
+               }
+                                       
+               return null;
+       }
+
+       //
+       // This is used to extract properties and event declarations from a type
+       //
+       static MemberInfo [] SpecialContainerLookup (Type t, bool is_static)
+       {
+               BindingFlags bf = BindingFlags.DeclaredOnly | (is_static ? BindingFlags.Static : BindingFlags.Instance);
+
+               bf |= BindingFlags.Public | BindingFlags.NonPublic;
+               
+               if (t is TypeBuilder) {
+                       DeclSpace decl = (DeclSpace) builder_to_declspace [t];
+
+                       return (MemberInfo []) decl.FindMembers (
+                               MemberTypes.Property | MemberTypes.Event,
+                               bf, FilterNone_delegate, null);
+               } else {
+                       return t.FindMembers (MemberTypes.Property | MemberTypes.Event,
+                                             bf, FilterNone_delegate, null);
+
+               }
+       }
+       
+       public static bool IsSpecialMethod (MethodBase mb)
+       {
+               Type t = mb.DeclaringType;
+               
+               MemberInfo [] matches = TypeManager.SpecialContainerLookup (t, mb.IsStatic);
+               if (matches == null)
+                       return false;
+               
+               foreach (MemberInfo mi in matches){
+                       if (mi is PropertyBuilder){
+                               Pair p = (Pair) properties [mi];
+
+                               if (p.First == mb || p.Second == mb)
+                                       return true;
+                       } else if (mi is PropertyInfo){
+                               MethodInfo [] methods = ((PropertyInfo) mi).GetAccessors (true);
+                               
+                               foreach (MethodInfo m in methods){
+                                       if (m == mb)
+                                               return true;
+                               }
+                       } else if (mi is MyEventBuilder){
+                               Pair p = (Pair) events [mi];
+
+                               if (p.First == mb || p.Second == mb)
+                                       return true;
+                       } else if (mi is EventInfo){
+                               EventInfo ei = ((EventInfo) mi);
+                               
+                               if (ei.GetAddMethod (true) == mb)
+                                       return true;
+                               
+                               if (ei.GetRemoveMethod (true) == mb)
+                                       return true;
+                               
+                               if (ei.GetRaiseMethod (true) == mb)
+                                       return true;
+                       }
+               }
+
+               //
+               // Now check if it is an operator method
+               //
+               string s = mb.Name;
+
+               if (s.StartsWith ("op_")){
+                       foreach (string name in Unary.oper_names){
+                               if (s == name)
+                                       return true;
+                       }
+
+                       foreach (string name in Binary.oper_names){
+                               if (s == name)
+                                       return true;
+                       }
+               }
+               
+               return false;
+       }
+               
+#endregion
+       
+}
+
+/// <summary>
+///   There is exactly one instance of this class per type.
+/// </summary>
+public sealed class TypeHandle : IMemberContainer {
+       public readonly TypeHandle BaseType;
+
+       readonly int id = ++next_id;
+       static int next_id = 0;
+
+       /// <summary>
+       ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
+       ///   a TypeHandle yet, a new instance of it is created.  This static method
+       ///   ensures that we'll only have one TypeHandle instance per type.
+       /// </summary>
+       public static TypeHandle GetTypeHandle (Type t)
+       {
+               TypeHandle handle = (TypeHandle) type_hash [t];
+               if (handle != null)
+                       return handle;
+
+               handle = new TypeHandle (t);
+               type_hash.Add (t, handle);
+               return handle;
+       }
+
+       /// <summary>
+       ///   Returns the TypeHandle for TypeManager.object_type.
+       /// </summary>
+       public static IMemberContainer ObjectType {
+               get {
+                       if (object_type != null)
+                               return object_type;
+
+                       object_type = GetTypeHandle (TypeManager.object_type);
+
+                       return object_type;
+               }
+       }
+
+       /// <summary>
+       ///   Returns the TypeHandle for TypeManager.array_type.
+       /// </summary>
+       public static IMemberContainer ArrayType {
+               get {
+                       if (array_type != null)
+                               return array_type;
+
+                       array_type = GetTypeHandle (TypeManager.array_type);
+
+                       return array_type;
+               }
+       }
+
+       private static PtrHashtable type_hash = new PtrHashtable ();
+
+       private static TypeHandle object_type = null;
+       private static TypeHandle array_type = null;
+
+       private Type type;
+       private bool is_interface;
+       private MemberCache member_cache;
+
+       private TypeHandle (Type type)
+       {
+               this.type = type;
+               if (type.BaseType != null)
+                       BaseType = GetTypeHandle (type.BaseType);
+               else if ((type != TypeManager.object_type) && (type != typeof (object)))
+                       is_interface = true;
+               this.member_cache = new MemberCache (this);
+       }
+
+       // IMemberContainer methods
+
+       public string Name {
+               get {
+                       return type.FullName;
+               }
+       }
+
+       public Type Type {
+               get {
+                       return type;
+               }
+       }
+
+       public IMemberContainer Parent {
+               get {
+                       return BaseType;
+               }
+       }
+
+       public bool IsInterface {
+               get {
+                       return is_interface;
+               }
+       }
+
+       public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
+       {
+               if (mt == MemberTypes.Event)
+                       return new MemberList (type.GetEvents (bf | BindingFlags.DeclaredOnly));
+               else
+                       return new MemberList (type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
+                                                                null, null));
+       }
+
+       // IMemberFinder methods
+
+       public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
+                                      MemberFilter filter, object criteria)
+       {
+               return member_cache.FindMembers (mt, bf, name, filter, criteria);
+       }
+
+       public MemberCache MemberCache {
+               get {
+                       return member_cache;
+               }
+       }
+
+       public override string ToString ()
+       {
+               if (BaseType != null)
+                       return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
+               else
+                       return "TypeHandle (" + id + "," + Name + ")";
+       }
+}
+
+}